Production-ready, SEO-first website foundation with three bounded surfaces:
| Surface | Folder | Role |
|---|---|---|
| Frontend | apps/Frontend |
Static public site (Astro, pre-rendered HTML) |
| Administration FE | apps/Administration-FE |
Authenticated staff workspace (Astro + React) |
| Backend | apps/Backend |
Contract-first API (FastAPI, PostgreSQL, S3-compatible storage) |
Ordinary public browsing does not require the Backend at runtime. Administration FE and publish flows do.
- Frontend / Administration FE: Astro 5, React 19 (Administration FE only), TypeScript
- Backend: FastAPI, Python 3.12, PostgreSQL 16
- Object storage: S3-compatible (MinIO locally)
- Deployment: Docker Compose + k3s under
deployment/
README.md # This file
apps/
├── Frontend/
├── Administration-FE/
└── Backend/
deployment/
├── compose/ # Docker Compose, .env, Caddy gateway
└── k8s/ # Kustomize manifests for Flycatch k3s
specs/001-website-foundation/ # Feature spec, plan, contracts, quickstart
specs/002-auth-rbac/ # JWT auth + RBAC spec, plan, contracts, quickstart
docs/ # Conventions and onboarding (implementation phase)
Foundation payload schemas live in specs/001-website-foundation/contracts/ (OpenAPI 3.1). Staff auth, RBAC, management, and publish live in specs/002-auth-rbac/contracts/.
- Backend MUST implement these contracts. Staff auth is JWT access + refresh (
Authorization: Bearer), not cookies or CSRF. - Frontend MUST generate or validate build-time types from the content, settings, SEO, and publish schemas.
- Administration FE MUST generate types from
admin-auth.v2,admin-rbac.v1,admin-management.v2, andpublish.v2— no hand-written token or permission DTOs. Tokens stay in memory only.
See 001 contracts and 002 contracts.
Shared local and preview setup for Frontend, Administration FE, Backend, PostgreSQL, and object storage. Step-by-step first boot (including staff users) is also in docs/onboarding.md.
- Docker and Docker Compose
- Node.js 22 LTS, pnpm, Python 3.12 (for local app development)
Compose does not create staff accounts or apply migrations. There is no default login and no public sign-up.
-
Copy environment config and set secrets (
JWT_SECRETand the otherchange-mevalues):cp deployment/compose/.env.example deployment/compose/.env
Do not commit
deployment/compose/.env. Variable names are documented indeployment/compose/.env.example. -
Build and start all services from the repository root:
docker compose -f deployment/compose/docker-compose.yml --env-file deployment/compose/.env up -d --build
From
deployment/compose/you can usedocker compose up -d --buildinstead. -
After Postgres and MinIO are healthy, migrate, seed, and bootstrap two staff users:
docker compose -f deployment/compose/docker-compose.yml --env-file deployment/compose/.env exec backend alembic upgrade head docker compose -f deployment/compose/docker-compose.yml --env-file deployment/compose/.env exec backend flycatch-seed-records docker compose -f deployment/compose/docker-compose.yml --env-file deployment/compose/.env exec backend flycatch-bootstrap \ --user-1-email admin1@example.com \ --user-2-email admin2@example.com \ --user-2-role editor
Passwords are prompted (minimum 12 characters) unless you pass
--user-1-passwordand--user-2-password. User 1 is always roleadministrator. Re-running bootstrap with the same emails is idempotent and does not reset passwords.Example emails above are documentation only — use any addresses you control. Pytest uses different editor email/password fixtures; those are not created by Compose.
-
Sign in at
http://localhost:8080/admin. Later staff:flycatch-provision-admin --email someone@example.com --role editor(--roleis required:administratororeditor). -
Rebuild app images after Frontend or Administration FE changes:
docker compose -f deployment/compose/docker-compose.yml --env-file deployment/compose/.env up -d --build
Stop the stack with
docker compose -f deployment/compose/docker-compose.yml --env-file deployment/compose/.env down. Add-vonly if you intend to wipe Postgres and MinIO volumes.
Gateway (default http://localhost:8080, GATEWAY_PORT in .env):
| Path | Service |
|---|---|
/ |
Frontend |
/admin |
Administration FE |
/api |
Backend |
| File | Purpose |
|---|---|
deployment/compose/docker-compose.yml |
All foundation services |
deployment/compose/.env.example |
Shared environment configuration |
deployment/k8s/base/Caddyfile |
Path-based gateway routing (compose + k8s) |
deployment/k8s/ |
Kubernetes manifests for the Flycatch k3s cluster |
While Docker Compose runs all services together, you can also run them individually during development.
Make sure to install dependencies for the respective services first.
The public website (Astro).
cd apps/Frontend
pnpm install
pnpm run devRuns at: http://localhost:4321
The admin dashboard (Astro + React).
cd apps/Administration-FE
npm install
npm run devRuns at: http://localhost:4173
The API server (FastAPI). Ensure you have PostgreSQL running.
cd apps/Backend
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
fastapi dev src/flycatch_api/main.pyRuns at: http://localhost:8000 (FastAPI default)
| Document | Description |
|---|---|
| spec.md | Feature specification |
| plan.md | Implementation plan |
| quickstart.md | End-to-end validation scenarios |
| data-model.md | Entities and validation rules |
| research.md | Technology decisions |
Before promotion, verify: static Frontend build, OpenAPI validation, consumer contract alignment, accessibility (WCAG 2.2 AA), SEO conventions, i18n (no hard-coded strings), security headers, and Playwright journeys (public no-JS + admin draft/publish).
Details in quickstart.md.