146 lines
6.2 KiB
Markdown
146 lines
6.2 KiB
Markdown
# The Great Bear — Microbrewery Website
|
|
|
|
Full-stack site for The Great Bear microbrewery (SCO 32, Sector 26, Chandigarh), built from the
|
|
Stitch "Industrial Hospitality" design.
|
|
|
|
| Layer | Tech |
|
|
| --------- | ----------------------------------------------------------- |
|
|
| Frontend | [TanStack Start](https://tanstack.com/start) (React 19, Vite 8, Tailwind CSS 4, SSR) |
|
|
| Backend | [PocketBase](https://pocketbase.io) v0.40 — CMS content, form intake, admin UI |
|
|
| Runtime | Single Docker image running both services |
|
|
| Proxy | Caddy (automatic HTTPS) on the target host |
|
|
| Deploys | `deploy.sh` (build + push) → Ansible playbook (pull + run) |
|
|
|
|
## Pages
|
|
|
|
- `/` — hero, stats, featured brews, experiences, testimonials, quick table booking
|
|
- `/our-brews` — flagship banner, core lineup, seasonal releases, tasting-flight builder
|
|
- `/menu` — filterable gastropub menu with beer pairings
|
|
- `/visit` — reservation form, contact info, map
|
|
|
|
All structured content (brews, menu, testimonials, stats, contact info) is served from
|
|
PocketBase and editable in the admin UI. If PocketBase is unreachable, the site falls back to
|
|
bundled seed content so it never renders empty.
|
|
|
|
## Repository layout
|
|
|
|
```
|
|
app/ TanStack Start application
|
|
src/routes/ Pages (/, /our-brews, /menu, /visit)
|
|
src/components/ Shared UI + client forms
|
|
src/lib/ Server functions & PocketBase client
|
|
src/data/content.json Single source of truth for seed + fallback content
|
|
public/images/ Design assets (downloaded from the Stitch export)
|
|
pb/migrations/ PocketBase schema (snapshot migration, auto-applied)
|
|
scripts/
|
|
run-all.mjs Container supervisor: PocketBase + site server
|
|
seed.mjs Idempotent content seeder (create-if-missing by uid)
|
|
create-collections.sh Dev helper used to build the schema migration
|
|
ansible/ Deployment playbook (roles: app, caddy)
|
|
Dockerfile Multi-stage image build
|
|
deploy.sh Build & push image to the private registry
|
|
```
|
|
|
|
## Local development
|
|
|
|
Frontend only (renders from bundled seed content; forms return errors):
|
|
|
|
```bash
|
|
cd app
|
|
npm install
|
|
npm run dev # http://localhost:3000
|
|
```
|
|
|
|
Full stack with PocketBase (recommended — from the repo root):
|
|
|
|
```bash
|
|
# Terminal 1 — PocketBase on :8090 (data in ./pb_data, schema auto-applied
|
|
# from pb/migrations on first boot)
|
|
./.tmp-pb/pocketbase serve --http=127.0.0.1:8090 --dir=./pb_data --migrationsDir=./pb/migrations
|
|
|
|
# Terminal 2 — one-time setup: create a local admin and seed the content
|
|
./.tmp-pb/pocketbase superuser upsert dev@greatbear.in devpass12345 --dir=./pb_data --migrationsDir=./pb/migrations
|
|
PB_URL=http://127.0.0.1:8090 PB_SUPERUSER_EMAIL=dev@greatbear.in PB_SUPERUSER_PASSWORD=devpass12345 \
|
|
node scripts/seed.mjs
|
|
|
|
# Terminal 2 — the site (talks to PocketBase on 127.0.0.1:8090 automatically)
|
|
cd app && npm run dev
|
|
```
|
|
|
|
- PocketBase admin UI: `http://127.0.0.1:8090/_/` (dev@greatbear.in) — edits show up on the
|
|
site on the next page load
|
|
- Dev data lives in `./pb_data` (git-ignored); delete it for a factory reset
|
|
- The PB binary in `.tmp-pb/` was fetched during setup — if it's missing, grab a release from
|
|
https://github.com/pocketbase/pocketbase/releases (or run PocketBase however you like; only
|
|
the port matters)
|
|
|
|
`npm run build` produces `.output/server/index.mjs`, started with `npm start`. To run the
|
|
**production image** locally instead:
|
|
|
|
```bash
|
|
docker build -t greatbear:dev .
|
|
docker run --rm -p 3000:3000 -p 8090:8090 \
|
|
-e PB_SUPERUSER_EMAIL=dev@greatbear.in -e PB_SUPERUSER_PASSWORD=devpass12345 \
|
|
-v greatbear_dev_data:/data greatbear:dev
|
|
```
|
|
|
|
## Deploying
|
|
|
|
### 1. Build and push the image
|
|
|
|
```bash
|
|
cp .env.example .env # then fill in registry credentials
|
|
./deploy.sh
|
|
```
|
|
|
|
Tags pushed: `registry.tanshu.com/tanshu/greatbear:latest` and `:<git-sha>`.
|
|
|
|
### 2. Deploy with Ansible
|
|
|
|
Requirements on the controller: `ansible` + `community.docker` collection
|
|
(`ansible-galaxy collection install community.docker`), SSH access to the host.
|
|
|
|
Requirements on the host (`www.greatbear.in`): Docker and Caddy already installed.
|
|
|
|
```bash
|
|
cd ansible
|
|
# edit group_vars/greatbear/vars.yml if needed (or encrypt it with ansible-vault)
|
|
ansible-playbook site.yml # add -i inventory/hosts.yml if not using ansible.cfg
|
|
```
|
|
|
|
The playbook:
|
|
|
|
1. Logs into the registry on the host, pulls the image, and (re)creates the `greatbear`
|
|
container with ports bound to loopback (`127.0.0.1:3000`, `127.0.0.1:8090`) and a named
|
|
volume `greatbear_pb_data:/data` for the database.
|
|
2. Waits for PocketBase + site health checks.
|
|
3. Writes `/etc/caddy/caddy.d/greatbear.conf` with both site blocks and reloads Caddy:
|
|
|
|
- `www.greatbear.in` → `127.0.0.1:3000` (the site)
|
|
- `admin.greatbear.in` → `127.0.0.1:8090` (PocketBase API + admin UI)
|
|
|
|
DNS records for both domains must point at the host; Caddy obtains TLS certificates
|
|
automatically on first request.
|
|
|
|
## PocketBase admin
|
|
|
|
- URL: `https://admin.greatbear.in/_/`
|
|
- First container start bootstraps the superuser from `PB_SUPERUSER_EMAIL` /
|
|
`PB_SUPERUSER_PASSWORD` (set in `ansible/group_vars/greatbear/vars.yml`, idempotent).
|
|
|
|
Content collections: `brews`, `menu_categories`, `menu_items`, `experiences`, `testimonials`,
|
|
`stats`, `pairings`, `settings`. Reservation/contact submissions land in `reservations`
|
|
(public create only — readable by admins).
|
|
|
|
The seed only creates records that are missing (matched by `uid`), so edits made in the admin
|
|
are never overwritten by redeploys. Schema changes belong in `pb/migrations/`.
|
|
|
|
## Container environment
|
|
|
|
| Variable | Default | Purpose |
|
|
| ----------------------- | ------------------------ | -------------------------------------- |
|
|
| `PORT` | `3000` | Site server port |
|
|
| `PB_URL` | `http://127.0.0.1:8090` | PocketBase URL used by the site server |
|
|
| `PB_SUPERUSER_EMAIL` | — | Initial admin (bootstrapped at start) |
|
|
| `PB_SUPERUSER_PASSWORD` | — | Initial admin password |
|