fastreact - FastAPI + React full-stack webapp
Build a production-shaped full-stack web app from a mockup to a running Docker Compose stack.
Backend: FastAPI, uv, SQLModel, Postgres, Alembic, JWT + Google OAuth, boto3 (S3).
Frontend: Vite, React, TypeScript, shadcn/ui + Tailwind, TanStack Router (file-based) / Query / Table, Zod, Axios.
Infra: Docker Compose (postgres + backend + frontend), seeded test users, agent-browser E2E.
When to use
- "Spin up / bootstrap / create a full-stack webapp", "FastAPI + React", "Python backend + React frontend".
- An admin panel, client portal, dashboard, or internal tool with auth + RBAC + file upload + S3.
- API-first backend with a typed SPA; local docker dev with seeded users.
Scope
This skill handles scaffolding, conventions, and local setup for a FastAPI+React+Postgres+S3 webapp.
It does NOT: deploy to cloud, generate raster brand art itself (delegates to
), or design HTML pages itself (delegates to
). For pure UI-token/Tailwind work use
. Never put secrets in tracked files; always a gitignored
.
Workflow (numbered)
1. Mockup first (design before code)
Lock the look before writing app code. Save artifacts under the injected
path (fall back to a temp dir only when no
path was injected) in a
subdir, where
is a kebab-case name for the app/feature.
- Brand/logo (raster): use ( / ) for the mark + favicons. Engine: Codex via ChatGPT, falls back to Gemini. To stay faithful to an existing logo, pass it as a reference image ( or the cip ).
- HTML page mockups: use for the screens (login, dashboard, tables, detail) plus an gallery and ONE source-of-truth (color tokens, type scale, spacing, components). marketing-design defers HTML/dashboards to opendesign.
- Get approval on direction (style, screens) with concise preview options before building.
- Treat the approved + screens as the contract: the frontend MUST match them.
Details:
references/design-mockup-workflow.md
.
2. Scaffold the project
Run the scaffolder (idempotent, never overwrites existing files):
bash
bash scripts/scaffold.sh <project-dir> <app-name>
It creates
,
,
,
,
,
.
Then write the real
(gitignored) with DB + JWT + AWS/S3 + Google OAuth + seed creds.
Structure + conventions:
references/project-structure.md
.
3. Build the backend (API-first)
Implement under
:
thin routers,
stateless logic,
I/O seams,
SQLModel tables,
Pydantic contracts,
config/db/security/exceptions/permissions,
DI,
,
. One Alembic migration per change. Auth = bcrypt + JWT (HS256) + optional Google OAuth (domain allowlist). S3 = boto3 wrapper in
. Verify:
uv sync && uv run python -c "import app.main" && uv run pytest
.
Auth/RBAC/S3 patterns:
.
4. Build the frontend (feature slices)
(TanStack file-based:
layout,
,
);
(schemas.ts + queries.ts + components/);
src/components/{ui,layout}
;
(api-client, query-client, permissions, utils);
(Zod). Port the approved
into
+ Tailwind tokens (map shadcn HSL vars to the brand palette). Match the mockups exactly. Verify:
npx tsc --noEmit && npm run build
.
5. Run locally with Docker Compose
builds + starts postgres, then backend (migrate + seed on entrypoint), then frontend (nginx). Pick host ports that are free (
; common conflicts with other local stacks).
,
,
(down -v resets DB). Local setup + entrypoint:
references/local-setup.md
.
6. Seed + verify end-to-end
Seed deterministic test users per role. Verify the real flow in the browser via
(scaffold
from its compose-spa example: readyz gate, form login, persistent profile per role) - login → core feature → RBAC - and curl the API (incl. real S3 upload/delete). For frontend layout work, run desktop and mobile viewport checks against the Docker stack and verify no horizontal overflow, hidden action controls, stale bundles, or console errors. The
CLI works as a lighter alternative when traces aren't needed. Loop on fixes until the stack is healthy and the flow passes.
Reusable assets
- - generates the project skeleton (run it; do not hand-create dirs).
references/project-structure.md
- exact backend + frontend trees + naming conventions.
references/local-setup.md
- docker-compose, Dockerfiles, entrypoint, Makefile, ports, seed.
- - JWT + Google OAuth, role model, permission deps, S3 key scheme.
references/design-mockup-workflow.md
- marketing-design + opendesign then theme port.
- - the bugs that recur in this stack. READ before frontend↔backend integration.
- - AWS deploy: EC2+compose, SSM/Ansible, RDS, ALB, ECR, OIDC; security floor + pre-apply checklist.
Hard rules (this stack bites here; see references/gotchas.md)
- FormData uploads: never set
Content-Type: multipart/form-data
manually; in the axios request interceptor delete the default JSON header when so the browser sets the boundary. The backend param name MUST match the FormData key (/).
- Zod and the backend contract: read the backend Pydantic schema before writing the Zod schema. IDs are ints (use if the UI wants strings); use not when the key is always present but may be null. A parse mismatch surfaces as "could not load".
- TanStack route nesting: a that has children (, ) MUST be a layout that renders ; put the page body in . Otherwise the child route renders the parent's page.
- Brand lockup grid: if the wordmark stacks under the icon via CSS grid, the wrapper needs so the / become grid items, else the tagline renders inline.
- Ports: other local stacks squat 5173/5432/8000/8080; pick free host ports in compose and set CORS + to match the chosen frontend origin/backend port.
- Secrets: is gitignored; scan staged files for key patterns (, ) before any push.
- Tables and search: every table needs loading, empty, filtered-empty, and error states, plus a body frame that keeps pagination pinned. Client-side search is only acceptable when the full result set is loaded and small; otherwise add backend , filter, sort, limit, and offset params.
- Admin filters: use a compact toolbar with search plus select/dropdown filters for role, company, status, and action. Avoid long flat pill rows that wrap badly on mobile.
- Avatar consistency: expose from auth/user schemas when available, capture Google , and render one shared Avatar primitive everywhere (topbar, profile, user tables, audit rows). Fallback initials must use one deterministic color function.
- Responsive verification: after login, table, profile, or shell changes, run local browser E2E in desktop and mobile widths before shipping. Check screenshots, not just typecheck/build.