Skip to content
Public template

About

Production-Ready FastAPI + Next.js Template with Auth, Observability, and Agent Scaffold

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

90 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

{{PROJECT_NAME}} Full-Stack Template

Polyglot monorepo starter: FastAPI + Next.js + Rust, with JWT auth, audit logging, async SQLAlchemy, Celery workers, Docker Compose, Prometheus, and Grafana dashboards. Rust can run as a standalone service or be compiled into Python extensions (PyO3) and WASM modules (wasm-bindgen) for direct import.

What's Included

  • Backend (FastAPI): Auth & audit routes, async SQLAlchemy + Alembic, Redis-backed rate limiting, Prometheus metrics, structured logging, Celery worker/beat scaffolding.
  • Frontend (Next.js + TypeScript): Auth flows (login/register/profile), protected dashboard shell, typed API client, Tailwind styles.
  • Rust: Binary service scaffold (apps/rust-svc), PyO3 extension stub (packages/py-core), wasm-bindgen stub (packages/wasm-core), shared TS types (packages/ts-shared).
  • Agent scaffold: Stub LLM provider with /api/v1/agents/run endpoint and frontend demo page to submit prompts.
  • Ops: Docker Compose for Postgres, Redis, backend, frontend, Prometheus, Grafana; health/readiness endpoints; Makefile helpers; Moon task runner for cross-language cached builds.

Frontend Session Recovery

The API client refreshes an expired access token when an authenticated request returns 401. Concurrent requests share one in-flight refresh; each original request is retried at most once with the new token. Login, registration, and refresh requests never trigger automatic refresh. Token rotation updates both stored tokens, and logout or a newer login prevents an older in-flight refresh from restoring the previous session.

Network errors, timeouts, rate limits, and server failures preserve stored credentials and the loaded user while surfacing the error. Rejected refresh tokens or an unauthorized retry invalidate the session and clear both tokens. A 403 from /me also clears the session (the API uses it for inactive users); permission errors on other endpoints do not. A wrong current password can return 401 without invalidating the session.

Project Structure

.
├── apps/
│   ├── api/          # FastAPI service (Python/uv)
│   ├── web/          # Next.js app (TypeScript/pnpm)
│   └── rust-svc/     # Rust binary service
├── packages/
│   ├── py-core/      # PyO3 crate → native .so for apps/api
│   ├── wasm-core/    # wasm-bindgen crate → WASM for apps/web
│   └── ts-shared/    # Shared TypeScript types
├── nginx/
├── prometheus/
├── grafana/
├── Cargo.toml        # Cargo workspace root
├── pyproject.toml    # uv workspace root
├── pnpm-workspace.yaml
├── docker-compose.yml
└── Makefile

Getting Started

Prerequisites

Install these once on your machine before anything else:

Tool Version Install
Rust + cargo stable curl https://sh.rustup.rs -sSf | sh
Python ≥ 3.12 python.org or brew install python
uv latest curl -LsSf https://astral.sh/uv/install.sh | sh
Node.js ≥ 22 brew install node or nodejs.org
pnpm 9.14.4 (pinned in root package.json) corepack enable or npm install -g pnpm@9.14.4
Moon latest curl -fsSL https://moonrepo.dev/install/moon.sh | bash
Docker Desktop latest docker.com — needed for the full-stack path

Optional (only needed when you start using the Rust extension stubs):

pip install maturin        # PyO3 → Python .so  (packages/py-core)
cargo install wasm-pack    # Rust → WASM         (packages/wasm-core)

Verify your environment:

cargo --version && python3 --version && uv --version
node --version && pnpm --version && moon --version

Step 1 — Personalise the template

Replace placeholders across the repo:

# macOS / Linux
grep -rl '{{PROJECT_NAME}}' . | xargs sed -i '' 's/{{PROJECT_NAME}}/My App/g'
grep -rl '{{PROJECT_NAME_SLUG}}' . | xargs sed -i '' 's/{{PROJECT_NAME_SLUG}}/my-app/g'
grep -rl 'project-name-slug' . | xargs sed -i '' 's/project-name-slug/my-app/g'

Step 2 — Configure environment files

cp apps/api/.env.example apps/api/.env
cp apps/web/.env.example apps/web/.env

Minimum values to set in apps/api/.env:

DATABASE_URL=postgresql+asyncpg://postgres:postgres@localhost:5432/myapp
JWT_SECRET_KEY=<generate below>
REDIS_URL=redis://localhost:6379/0

Generate a JWT secret:

python3 -c "import secrets; print(secrets.token_urlsafe(32))"

Set in apps/web/.env (or .env.local for local-only override):

NEXT_PUBLIC_API_URL=http://localhost:8000

Step 3 — Install dependencies

make install
# Runs: uv sync (Python) + pnpm install (Node) + cargo fetch (Rust)

Run pnpm from the repository root to install both apps/web and packages/ts-shared. pnpm-lock.yaml is the only JavaScript lockfile; use pnpm install --frozen-lockfile for reproducible installs.

Verify the build graph works:

moon run :build
# rust-svc compiles; api wheel builds; py-core/wasm-core/web skip gracefully
# until maturin/wasm-pack/pnpm-install are complete

Path A — Local dev (no Docker)

You still need Postgres and Redis running. The quickest way is Docker for just those two:

docker compose up -d postgres redis

Then run migrations and start the servers:

# 1. Apply database migrations
cd apps/api && uv run alembic upgrade head && cd ../..

# 2. (Optional) Load fixture data
make seed     # creates admin@example.com / ChangeMe123!

# 3. Start API (port 8000) + web (port 3000) in parallel
make dev

Open:

Path B — Full stack with Docker

Builds and starts the default services (Postgres, Redis, API, Celery, Web, nginx, Prometheus, Grafana, pgAdmin):

docker compose up -d --build

rust-svc is an unfinished binary scaffold: it prints a startup message and exits, so it is excluded from default startup by the opt-in rust profile in both docker-compose.yml and docker-compose.prod.yml. Before enabling it, implement a persistent HTTP server listening on 0.0.0.0:8080 with a /health endpoint. Then include it with docker compose --profile rust up -d --build (or docker compose -f docker-compose.prod.yml --profile rust up -d --build for production). Explicitly targeting rust-svc also enables it regardless of profiles.

Wait ~30 s for migrations and health checks, then:

# (Optional) Seed fixture data inside the running container
make seed

Open:

Path C — Docker dev mode (hot reload)

Runs API and web with source mounted for live reload, nginx for TLS:

# First time only — installs deps into named Docker volumes
make docker-dev-prepare

# Start api + web + nginx with hot reload
make docker-dev-up

Cross-Language Builds (Moon)

Moon manages build ordering across languages automatically:

moon run :build     # builds everything in dependency order (cached)
moon run :test      # tests everything
moon run web:build  # builds web after wasm-core + ts-shared
moon run api:build  # builds api after py-core

Build graph:

api:build   ← py-core:build   (Rust → Python .so via maturin)
web:build   ← wasm-core:build (Rust → WASM via wasm-pack)
web:build   ← ts-shared:build (TypeScript types)

Developer Tooling

  • Lint/format: make lint and make format (runs ruff/black/isort for Python, eslint/prettier for TypeScript).
  • Type checks: make api-typecheck (mypy), make web-typecheck (Next.js route types + TypeScript for the pnpm workspace).
  • Frontend build: make web-build (shared TypeScript package, then Next.js).
  • Git hooks: make pre-commit-install, then run on demand with make pre-commit.
  • Sample data: make seed loads fixture users (admin@example.com / ChangeMe123!) and basic audit events.

Environment Variables

Canonical examples: apps/api/.env.example and apps/web/.env.example

Variable Where Notes
DATABASE_URL api Postgres connection string
JWT_SECRET_KEY api Generate with secrets.token_urlsafe(32)
REDIS_URL api For Celery + rate limiting
NEXT_PUBLIC_API_URL web http://localhost:8000 (local), https://localhost (Docker)
LLM_PROVIDER / LLM_MODEL / LLM_API_KEY api Optional — for the agent scaffold

Scaling & Sessions

  • Backend workers: Single Uvicorn process by default. For horizontal scale, run multiple replicas behind nginx and set UVICORN_WORKERS. Keep Alembic migrations as a one-shot job.
  • Celery: Scale celery-worker replicas independently. celery-beat must stay singleton.
  • Sessions/state: Stateless JWT auth — safe to scale horizontally. Redis handles rate limiting.
  • Redis persistence: Disabled by default. Enable AOF/RDB or use a managed Redis for durable state.

Testing

make api-test       # pytest
make web-test       # Playwright e2e
make rust-test      # Cargo workspace tests
moon run :test      # all projects (cached)

Install the test browser once with pnpm --filter frontend exec playwright install chromium. make web-test builds the frontend first; Playwright then starts the production server automatically (or reuses an existing local server on port 3000). When invoking pnpm --filter frontend test:e2e directly, run make web-build first. Set PLAYWRIGHT_BASE_URL to test an already-running deployment instead.

Run make api-install before the Playwright suite: cross-origin authentication tests launch an isolated API fixture from the workspace .venv, without requiring Postgres or Redis. Set PLAYWRIGHT_API_PYTHON to use another API-ready interpreter.

Continuous integration

.github/workflows/ci.yml installs the pnpm workspace with the root lockfile and runs production dependency audits, API lint/tests, frontend lint, workspace type checks, shared-package and Next.js builds, and Chromium Playwright tests against the production build. Playwright starts and stops the Next.js production server and uploads its report and traces for seven days. The Rust job checks formatting, runs Clippy with warnings denied, and tests every Cargo workspace member using Cargo.lock.

Next Steps

  • Add your domains: extend apps/api/src/domain and apps/api/src/api/v1
  • Expand apps/web/src pages/components for your use case
  • Add Rust logic to packages/py-core (PyO3) or packages/wasm-core (WASM) and import it
  • Extend the CI checks as you add services and configure deployment for your environment

About

Production-Ready FastAPI + Next.js Template with Auth, Observability, and Agent Scaffold

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages