Jesse A. Green / notebook

Live demo: the DocCompiler guide library as a static, read-only snapshot (October 2026). No backend, no accounts, nothing to submit.

Full Stack FastAPI Template — User Guide

Generated June 2026 from fastapi/full-stack-fastapi-template at 38302d7

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

The Full Stack FastAPI Template is a production-ready starter kit for building web applications with a Python backend and a React frontend. You clone (or generate) it once, and you get a complete, working application: a JWT-authenticated REST API, a database with migrations, a single-page admin dashboard, email-based password recovery, automated tests, and a Docker Compose setup that runs everything together.

Rather than wiring FastAPI, SQLModel, PostgreSQL, React, and Traefik together yourself, you start from a stack that is already integrated, tested in CI, and ready to customize into your own product.

Note

This is a template, not a library you install. The goal is to give you a running codebase to build on top of — you own and edit every file after you generate your project.


1. Quick Start

Get the full application running locally in a few minutes. You need Docker (Docker Engine with Compose) installed.

# 1. Get the code (use it as-is for now)
git clone https://github.com/fastapi/full-stack-fastapi-template.git my-app
cd my-app

# 2. Start the whole stack (backend, frontend, database, proxy, mail catcher)
docker compose watch

The first start takes a minute while the backend waits for the database and seeds the first admin user. Once it is up, open these URLs in your browser:

Service URL What it is
Frontend dashboard http://localhost:5173 The React single-page app
Backend API http://localhost:8000 The FastAPI JSON API
Interactive API docs (Swagger UI) http://localhost:8000/docs Try every endpoint in the browser
Alternative API docs (ReDoc) http://localhost:8000/redoc Reference-style API docs
Adminer (database UI) http://localhost:8080 Browse and edit the database
Traefik dashboard http://localhost:8090 See how the proxy routes traffic
Mailcatcher http://localhost:1080 Read emails the app "sends" locally

Log in to the dashboard with the default superuser credentials that ship in the .env file:

Email:    [email removed]
Password: changethis

Caution

The default .env ships with placeholder secrets set to changethis (SECRET_KEY, POSTGRES_PASSWORD, FIRST_SUPERUSER_PASSWORD). They are fine for a quick local spin, but you must change them before deploying anywhere. See Generating secure secrets.

Tip

docker compose watch keeps your running containers in sync with your source code — when you edit a backend or frontend file, the change is synced into the container automatically. To follow logs while it runs, open a second terminal and run docker compose logs (or docker compose logs backend for one service).


2. Starting Your Own Project

You have two ways to turn this template into your own project: clone it directly (simplest) or generate it with Copier (customizes names and secrets for you as it copies). Both leave you with a normal Git repository you fully own.

Clone or fork (simplest)

You can just fork or clone the repository and use it as-is. To start a private project from it (GitHub does not let you make a fork private), clone it under your own name and re-point the remote:

# Clone into a directory named for your project
git clone git@github.com:fastapi/full-stack-fastapi-template.git my-full-stack
cd my-full-stack

# Point "origin" at your own (new, empty) repository
git remote set-url origin git@github.com:your-org/my-full-stack.git

# Keep the template as "upstream" so you can pull future updates
git remote add upstream git@github.com:fastapi/full-stack-fastapi-template.git

# Push to your repository
git push -u origin master

Generate with Copier (customized)

Copier copies all the files, asks you a few configuration questions, and fills your .env files with your answers (including auto-generating secure secrets).

# Install copier (pipx recommended)
pipx install copier

# Generate a new project into ./my-awesome-project
copier copy https://github.com/fastapi/full-stack-fastapi-template my-awesome-project --trust

If you have pipx you can skip the install and run it directly:

pipx run copier copy https://github.com/fastapi/full-stack-fastapi-template my-awesome-project --trust

Important

The --trust flag is required. The template runs a post-generation script (.copier/update_dotenv.py) that writes your answers into the .env files; Copier will not execute it without --trust.

2.1 Copier input variables

When you generate with Copier, you are asked for the following. You can change any of them later by editing the .env file, so don't overthink them now.

Variable Default Purpose
project_name FastAPI Project Project name shown to API users (in API docs and emails)
stack_name fastapi-project Name used for Docker Compose labels — no spaces or periods
secret_key changethis Secret key used to sign tokens — generate a real one
first_superuser [email removed] Email of the first admin user
first_superuser_password changethis Password of the first admin user — change it
smtp_host (empty) SMTP server host for sending email (optional, set later)
smtp_user (empty) SMTP username (optional)
smtp_password (empty) SMTP password (optional)
emails_from_email [email removed] "From" address for outgoing email
postgres_password changethis PostgreSQL password — generate a real one
sentry_dsn (empty) Sentry DSN for error tracking (optional)

2.2 Pulling updates from the template later

Because you added the template as upstream, you can pull its later improvements into your project:

# Download the latest template changes without committing them
git pull --no-commit upstream master

# Resolve any conflicts in your editor, then finish the merge
git merge --continue

Tip

--no-commit lets you review everything the template changed before it lands in your history — useful because you will have edited many of the same files.


3. What You Get — The Application Tour

Once you log in, the template gives you a working dashboard built around two example resources: users (people who can log in) and items (a simple owned resource you replace with your own data model). Everything here is real, working code you can study and adapt.

3.1 Authentication

The app ships with a complete authentication flow, all backed by JWT access tokens:

  • Log in (/login) — email + password, returns an access token stored in the browser.
  • Sign up (/signup) — self-service registration for new users.
  • Forgot password (/recover-password) — enter your email to receive a reset link.
  • Reset password (/reset-password) — set a new password using the emailed token.

Note

Password recovery emails are only sent when SMTP is configured. During local development they are captured by Mailcatcher instead — open http://localhost:1080 to read them. See Email in development.

3.2 The dashboard

After logging in you land on the dashboard, which uses a collapsible sidebar for navigation. The pages available are:

Page Route What you can do
Dashboard / Landing page greeting the logged-in user
Items /items Create, view, edit, and delete your items in a paginated table
Admin /admin (Superusers) Manage all users — add, edit, delete
User Settings /settings Update your profile, change password, change appearance, delete account

3.3 Managing items

The Items page is the template's example of a full create-read-update-delete (CRUD) feature, wired end to end from the database to the UI:

  • Click Add Item to create one (title required, description optional).
  • Each item appears in a sortable, paginated table.
  • Use the per-row actions menu to edit or delete an item.
  • Regular users see only their own items; superusers see everyone's.

This is the feature you will most likely copy and rename when you build your own resource. See the Admin Guide for how the item model, API routes, and frontend pages fit together.

3.4 Managing users (admin)

Superusers get an Admin page to manage every account:

  • Add User — create a user with an email, name, password, and optional superuser/active flags.
  • Edit User — change a user's details or reset their password.
  • Delete User — remove a user (and, via cascade, their items).

Note

The first superuser is created automatically from FIRST_SUPERUSER / FIRST_SUPERUSER_PASSWORD in your .env the first time the stack starts. From there, that superuser can create other users through the Admin page or the API.

3.5 User settings

Every logged-in user can manage their own account from Settings:

  • My profile — update full name and email.
  • Password — change your password (requires your current password).
  • Appearance — switch between light and dark mode (the app ships with dark mode by default).
  • Danger zone — permanently delete your own account.

3.6 Dark mode

The interface supports light and dark themes out of the box, defaulting to dark. Your choice is remembered in the browser between visits.


4. Configuration

All configuration lives in a single .env file at the root of the project. The backend, frontend build, database, and proxy all read from it. After changing any value, restart the stack with docker compose watch.

4.1 The essentials

These are the values you are most likely to set when starting out:

Variable Default What it does
PROJECT_NAME Full Stack FastAPI Project Name shown in API docs and emails
STACK_NAME full-stack-fastapi-project Docker Compose project/label name (no spaces/dots)
DOMAIN localhost Base domain; becomes your real domain in production
FRONTEND_HOST http://localhost:5173 Where the frontend lives (used in email links)
ENVIRONMENT local One of local, staging, production
FIRST_SUPERUSER [email removed] Email of the auto-created admin
FIRST_SUPERUSER_PASSWORD changethis Password of the auto-created admin

4.2 Database, email, and secrets

Variable Default What it does
POSTGRES_SERVER localhost Database host (db inside Docker Compose)
POSTGRES_PORT 5432 Database port
POSTGRES_DB app Database name
POSTGRES_USER postgres Database user
POSTGRES_PASSWORD changethis Database password — change this
SECRET_KEY changethis Signs login tokens — change this
BACKEND_CORS_ORIGINS local hosts Comma-separated list of browser origins allowed to call the API
SMTP_HOST (empty) SMTP server for sending email (leave empty to disable email)
SMTP_USER / SMTP_PASSWORD (empty) SMTP credentials
SMTP_PORT 587 SMTP port
SMTP_TLS / SMTP_SSL True / False SMTP encryption mode
EMAILS_FROM_EMAIL [email removed] "From" address for outgoing email
SENTRY_DSN (empty) Sentry error-tracking DSN (optional)

Tip

Email features (password recovery, new-account notifications) turn on automatically once both SMTP_HOST and EMAILS_FROM_EMAIL are set. Until then, the API simply skips sending — nothing breaks.

For the complete list of every setting, including advanced backend-only options like token lifetimes, see the Admin Guide → Configuration Reference.

4.3 Generate secure secrets

Three values ship as changethis and must be replaced before any real deployment: SECRET_KEY, POSTGRES_PASSWORD, and FIRST_SUPERUSER_PASSWORD. Generate a strong random value for each:

python -c "import secrets; print(secrets.token_urlsafe(32))"
Xy7d9F2kQ1mN8pZ3rT6vW0bJ4hL5sG... (example — yours will differ)

Run it once per secret and paste the result into .env.

Warning

If you set ENVIRONMENT to staging or production while any of these three is still changethis, the backend refuses to start and raises an error. This is a deliberate safety check, not a bug.


5. Developing on the Template

This is starter code — you are meant to edit it. The stack is designed so you can run each part either inside Docker or directly on your machine, whichever is faster for the change you are making.

5.1 Run a service locally instead of in Docker

Each service uses the same port whether it runs in Docker or locally, so you can stop the container and start a local dev server in its place with no other changes.

For the frontend (live reload, fastest for UI work):

docker compose stop frontend
cd frontend
bun install
bun run dev

For the backend (live reload via FastAPI):

docker compose stop backend
cd backend
uv sync
source .venv/bin/activate
fastapi dev app/main.py

Note

The backend uses uv for Python dependencies and the frontend uses Bun (Node.js also works). Both are the recommended tools but only needed if you run a service outside Docker.

5.2 Where the code lives

You want to change... Edit...
Data models / database tables backend/app/models.py
API endpoints backend/app/api/routes/
Database read/write helpers backend/app/crud.py
Backend settings backend/app/core/config.py (values in .env)
Frontend pages frontend/src/routes/
Reusable UI components frontend/src/components/
Frontend hooks frontend/src/hooks/

5.3 Keeping the frontend API client in sync

The frontend talks to the backend through an automatically generated TypeScript client (in frontend/src/client/). Whenever you change the backend API, regenerate the client so the frontend stays type-safe:

# From the project root, with the backend running
bash ./scripts/generate-client.sh

Then commit the regenerated files. This means you never hand-write API calls — adding a backend endpoint and regenerating gives you a ready-to-use typed function on the frontend.

Tip

Forgetting to regenerate after a backend change is the most common source of frontend type errors. If TypeScript complains about a missing service or field, run the generator first.

5.4 Reading emails in development

When running with Docker Compose locally, the backend is automatically pointed at Mailcatcher instead of a real mail server. Any email the app "sends" (password recovery, new-account notices) is captured and shown at http://localhost:1080. No real email leaves your machine.

5.5 Running the tests

The backend ships with a Pytest suite and the frontend with Playwright end-to-end tests.

Backend tests:

docker compose exec backend bash scripts/tests-start.sh

Frontend end-to-end tests (stack must be running):

cd frontend
bunx playwright test
# Watch the tests run in an interactive UI
bunx playwright test --ui

6. Building an API-Only App

If you only need the backend (no dashboard), you can remove the frontend cleanly:

  • [ ] Delete the ./frontend directory.
  • [ ] Remove the frontend service from compose.yml.
  • [ ] Remove the frontend and playwright services from compose.override.yml.

That's it — you now have an API-only application. The FRONTEND environment variables can be left in place; they simply have no effect.


7. Troubleshooting

Error: The value of SECRET_KEY is "changethis"...

Cause: You set ENVIRONMENT to staging or production while SECRET_KEY, POSTGRES_PASSWORD, or FIRST_SUPERUSER_PASSWORD is still the placeholder changethis. Solution: Generate real values (see 4.3) and put them in .env. Prevention: Always change the three secrets before changing ENVIRONMENT.

Error: Incorrect email or password

Cause: The credentials sent to /login/access-token don't match an active user. Solution: Use the FIRST_SUPERUSER / FIRST_SUPERUSER_PASSWORD from your .env, or sign up a new account. Prevention: Remember email login is case- and whitespace-sensitive.

The stack starts but the dashboard can't reach the API

Cause: Your browser's origin isn't in BACKEND_CORS_ORIGINS, so the API rejects the request. Solution: Add your frontend URL to BACKEND_CORS_ORIGINS in .env (comma separated) and restart. Prevention: Keep this list in sync whenever you change DOMAIN or FRONTEND_HOST.

The backend takes a long time to start (or restarts repeatedly)

Cause: The backend waits for PostgreSQL to be ready before it starts (up to five minutes), retrying once per second. Solution: Watch docker compose logs db and docker compose logs backend; a healthy database resolves it. Prevention: Make sure your POSTGRES_* values are consistent across .env.

Frontend type errors after a backend change

Cause: The generated API client is stale. Solution: Run bash ./scripts/generate-client.sh and commit the result. Prevention: Regenerate the client every time the backend API changes.

Password recovery "works" but no email arrives

Cause: Email is only sent when SMTP_HOST and EMAILS_FROM_EMAIL are both set; locally, email goes to Mailcatcher. Solution: Check http://localhost:1080 in development, or configure SMTP for production. Prevention: Confirm both SMTP values are present before expecting real delivery.

docker compose watch isn't picking up my changes

Cause: watch syncs source into the container, but some changes (like new dependencies) require a rebuild. Solution: Stop and re-run docker compose watch; for dependency changes the backend image rebuilds automatically. Prevention: Restart the stack after editing pyproject.toml or package.json.


8. Frequently Asked Questions

Q: Do I install this from npm or pip? No. It is a project template you clone or generate with Copier, then own and edit. There is no package to install.

Q: Which database does it use? PostgreSQL. The connection is assembled from the POSTGRES_* variables in .env.

Q: How long do login sessions last? Access tokens are valid for 8 days by default. This is configurable in the backend (see the Admin Guide).

Q: Can I use a different frontend or no frontend at all? Yes. The backend is fully independent; see Building an API-Only App. You can also point the frontend at a remote backend by setting VITE_API_URL.

Q: How do I add my own data model (instead of "items")? Add a model in backend/app/models.py, create API routes under backend/app/api/routes/, create an Alembic migration, then regenerate the frontend client and build a page under frontend/src/routes/. The existing "items" feature is a complete worked example to copy.

Q: How do I change the database schema? Edit backend/app/models.py, then create and apply an Alembic migration. The Admin Guide covers the exact commands.

Q: Where do the API docs come from? FastAPI generates them automatically from your code. Visit /docs (Swagger UI) or /redoc while the backend is running.

Q: Is it ready for production? The template is built for it — it includes Traefik with automatic HTTPS, multi-stage Docker builds, and GitHub Actions CI/CD. You still must set real secrets and a domain. See the Admin Guide → Deployment.

Q: How do I get future improvements from the template? Add it as a Git upstream remote and git pull --no-commit upstream master (see 2.2).

Q: What's the difference between a regular user and a superuser? Superusers can manage all users and see all items; regular users can only manage their own account and their own items.