Boilerplate Repository Guide¶
Overview¶
The boilerplate repository serves as the initial project structure for all new gyms. It provides a fully configured Next.js 16 application with authentication, database management, Docker-based environments, and a consistent developer workflow — ready to clone and build on.
Single starting point
Every new gym should begin by cloning this repository. It ensures consistent architecture, tooling, and conventions across all OTS gyms.
Tech Stack¶
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router) |
| Language | TypeScript 5 |
| Styling | Tailwind CSS 4 |
| Database | PostgreSQL 18 |
| ORM | Prisma 7 |
| State Management | Zustand 5 |
| Forms | React Hook Form 7 + Zod resolvers |
| Auth | Client-side Zustand (localStorage) |
| Containerization | Docker |
| Deployment | Vercel |
What you get¶
- Modern web stack: Next.js 16 (App Router) + TypeScript 5 + Tailwind CSS 4
- Database: Prisma 7 + PostgreSQL 18
- Fast onboarding: one-command bootstrap via
npm run initialize - Data workflows: seed with
npm run db:seed, or sync environments vianpm run db -- sync ... - Deploy-ready:
npm run vercel-buildruns Prisma generate + migrations + build - Demo auth: client-side Zustand persisted to
localStorage(useful for gyms; not production-grade auth)
Getting Started¶
Prerequisites¶
- Node.js 22+
- Docker (Docker Desktop or Docker Engine)
- A
GITHUB_TOKENenvironment variable exported in your shell (a GitHub Personal Access Token withread:packagesscope). The.npmrcuses it to install private packages from the@turing-rlgymGitHub Packages registry. Without it,npm install(and Docker builds) will fail. - A
.envfile at the project root (template below; see also Environment Variables)
Example:
.env required
The application reads configuration from .env. Use the template below for local development. If you need remote database credentials (for syncing or APP_ENV != local), request them from your team lead.
1) Create .env¶
Create a .env file at the project root:
APP_ENV=local
GYM_SLUG=boiler-plate
# Required for remote DB access (syncing or APP_ENV != local)
REMOTE_DB_USER=your_remote_db_user
REMOTE_DB_PASS=your_remote_db_password
Notes:
- Local development uses
APP_ENV=localand expects Postgres onlocalhost:5432. - Remote credentials (
REMOTE_DB_USER,REMOTE_DB_PASS) are only required if you plan to sync from/to a remote environment, or connect directly to a remote DB (APP_ENV != local). For remote environments, the database name is derived fromGYM_SLUG(e.g.${GYM_SLUG}_prod). - If you change
GYM_SLUG, make sure your local DB build/run workflow matches it (see the boilerplate repo’sdocker/README.md).
2) Bootstrap everything (local Docker database)¶
One command to rule them all
Run the single initialization command below — it installs dependencies, generates the Prisma client, builds + starts a local Postgres container, runs the initial migration, and launches the dev server. This path is for APP_ENV=local. If you'd rather connect to a remote database instead, skip ahead to Connect to a Remote Database.
This command runs six steps in sequence:
npm install— installs all Node.js dependencies.npx prisma generate— generates the type-safe Prisma Client from the schema.npm run docker:build:db— builds a local PostgreSQL image (Dockerfile target:db).npm run docker:run:db— starts the local PostgreSQL container on port5432.npx prisma migrate dev --name init— creates and applies the initial database migration.npm run dev— starts the Next.js development server athttp://localhost:3000.
3) Put data in your database¶
After initialization, populate your local database. Choose the path that matches your situation:
If this is a brand-new project with no existing data, seed the database with sample flights:
If the project is already under active development and a remote database has data, pull it into your local container:
Configure .env first
Make sure your .env file has GYM_SLUG, REMOTE_DB_USER, and REMOTE_DB_PASS configured before syncing. Missing variables will cause authentication errors.
For the full DB sync guide (promotion chain, verification, data-only vs full), see scripts/README.md.
Connect to a Remote Database (without Docker)¶
If the project already has a remote database set up, you don't need Docker or npm run initialize at all. Simply change APP_ENV in your .env file to the desired remote environment and start the dev server:
# 1. In .env, set APP_ENV to one of: data, development, staging, production
# 2. Then run:
npm install
npx prisma generate
npm run dev
The app will connect directly to the corresponding remote database — no local container required. Use this when you want to develop against an existing remote dataset without any Docker setup.
APP_ENV=local is the only value that requires a local Docker DB
Setting APP_ENV=local connects to the local Docker database (what npm run initialize sets up). All other values (data, development, staging, production) connect to remote databases using the credentials in .env.
Scripts Reference¶
All scripts are defined in package.json and grouped by purpose below.
These commands build Docker images from the project's multi-stage Dockerfile. The build uses a GITHUB_TOKEN secret so npm ci can install private packages listed in .npmrc.
Image names are derived from GYM_SLUG
Docker image tags are derived from .env GYM_SLUG (for example: ${GYM_SLUG}-app:dev, ${GYM_SLUG}-db). You do not need to manually rename scripts when cloning the boilerplate.
| Command | What it builds | Dockerfile target |
|---|---|---|
npm run docker:build |
Development image with hot-reload support and full source code mounted (${GYM_SLUG}-app:dev) |
dev |
npm run docker:build:prod |
Production-optimized image with a standalone Next.js build (${GYM_SLUG}-app:runner) |
runner |
npm run docker:build:db |
Local PostgreSQL 18 image (${GYM_SLUG}-db) |
db |
npm run docker:build:dist |
Self-contained distribution image (${GYM_SLUG}-app:dist) + a build-time DB snapshot |
dist |
The dev target copies the full source and runs npm run dev. The runner target builds the app, then creates a minimal container with only the standalone output — no node_modules, no source code.
These commands start containers from previously built images.
| Command | Image | Notes |
|---|---|---|
npm run docker:run |
${GYM_SLUG}-app:dev |
Dev app container (mounts your repo). Sets APP_ENV=local inside the container. |
npm run docker:run:prod |
${GYM_SLUG}-app:runner |
Production runner container. Uses APP_ENV from your .env to choose the database connection. |
npm run docker:run:db |
${GYM_SLUG}-db |
Local PostgreSQL container on localhost:5432. Container name is ${GYM_SLUG}-db. |
npm run docker:run:dist |
${GYM_SLUG}-app:dist |
Dist image with embedded Postgres initialized from a build-time snapshot (no credentials at runtime). |
npm run docker:export:dist |
${GYM_SLUG}-app:dist |
Exports the dist image to ${GYM_SLUG}-app-dist.tar.gz. |
Volume mounts in dev mode
The docker:run (dev) command mounts three volumes:
$(pwd):/app— your local project directory is synced into the container./app/node_modules— an anonymous volume prevents the container'snode_modulesfrom being overwritten by your host./app/.next— an anonymous volume keeps the Next.js cache inside the container.
This means you can edit files locally and see changes reflected immediately without rebuilding.
These commands manage the Prisma schema and the PostgreSQL database. For deep-dive DB sync behavior, see scripts/README.md.
| Command | Purpose | When to use |
|---|---|---|
npx prisma generate |
Regenerates the Prisma Client (prisma/generated/). |
After any change to .prisma files. |
npx prisma db push |
Pushes schema changes directly to the DB (no migration file). | Local development only. Fast iteration — may drop data. |
npx prisma migrate deploy |
Applies pending migrations from prisma/migrations/. |
Staging / production deployments (also runs during npm run vercel-build). |
npx prisma studio |
Opens Prisma Studio at http://localhost:5555. |
Inspecting/editing data without writing queries. |
npm run db:seed |
Populates the database with sample flight data. | After a fresh DB setup or reset. |
npm run db -- sync --from <env> |
Sync a source environment into a target (default target: local). |
Pulling remote data locally; promoting data through envs. |
db:push may drop data
The npx prisma db push command applies schema changes directly without generating a migration file. This is convenient for local iteration but can cause data loss. Never use it against staging or production databases — use npx prisma migrate deploy instead.
Environment Variables¶
The application uses APP_ENV to determine which database to connect to at runtime. The connection URL is built dynamically by lib/build-database-url.ts using the variables in .env.
Never commit .env files
The .env file contains database credentials and secrets. It must remain in .gitignore and should never be committed to the repository.
| Variable | Purpose |
|---|---|
APP_ENV |
Controls the active environment: local, data, development, staging, production. |
GYM_SLUG |
Gym slug used to derive DB names (e.g. ${GYM_SLUG}_dev, ${GYM_SLUG}_prod) and local DB (${GYM_SLUG}-db). |
REMOTE_DB_USER |
Shared database username for remote environments. |
REMOTE_DB_PASS |
Shared database password for remote environments. |
How APP_ENV routes the connection
When APP_ENV=local, the app connects to the local Docker database at postgresql://postgres:postgres@localhost:5432/${GYM_SLUG}-db.
For all other environments, it builds a remote connection from REMOTE_DB_USER, REMOTE_DB_PASS, and a DB name derived from GYM_SLUG + an environment suffix (e.g. ${GYM_SLUG}_stg).
Project Structure¶
├── app/ Next.js App Router (pages, layouts, API routes)
│ ├── api/flights/ Flight data API (GET with filters, pagination, sorting)
│ ├── api/admin/ Admin endpoints (health check, data management)
│ └── auth/ Auth pages (login, register, forgot-password)
├── components/
│ ├── auth/ Auth forms (LoginForm, RegisterForm, ForgotPasswordForm, LogoutButton)
│ ├── flights/ Flight UI (FlightsSection, FlightsTable, FlightsFilters, FlightsPagination)
│ ├── landing/ Landing page components (Header, Footer, NavigationBar, Content)
│ └── ui/ Reusable primitives (Button, Card, Modal, TextInput)
├── data/initializers/ Default state values and seed data
├── lib/ Shared utilities (auth, database, helpers)
├── prisma/
│ ├── schema/models/ Prisma model definitions (.prisma files)
│ ├── generated/ Auto-generated Prisma Client (do NOT edit)
│ ├── migrations/ SQL migration files
│ └── seed.ts Database seeding script (flights)
├── scripts/ Shell scripts for database sync workflows
├── store/ Zustand stores (modal, users, auth)
├── types/ Shared TypeScript type definitions
├── docker/ Docker helper scripts (snapshot + dist entrypoint)
├── Dockerfile Multi-stage build (dev, builder, runner, db, snapshot, dist)
├── prisma.config.ts Prisma configuration (schema path, datasource URL)
└── package.json Dependencies and all npm scripts
For deeper documentation on specific areas, see the README in each directory of the boilerplate repository:
prisma/README.md— database models, schema conventions, and seeding.scripts/README.md— database sync scripts and environment workflows.store/README.md— state management patterns, Zustand conventions, and store walkthroughs.docker/README.md— Docker images, targets, and dist snapshot workflow.
Common Workflows¶
I just cloned the repo and the project is new¶
I just cloned the repo and the project is already under development¶
Configure .env first
Make sure .env is configured (at minimum GYM_SLUG, REMOTE_DB_USER, REMOTE_DB_PASS) before syncing. See Environment Variables.
npm run initialize
npm run db -- sync --from dev # or data, dev, stg, prod — whichever has the data you need
I'm starting my day and need to run the project¶
npm run docker:run:db # start the local PostgreSQL container
npm run dev # start the Next.js dev server at http://localhost:3000
I want to test the production Docker image locally¶
npm run docker:build:prod
# Set APP_ENV in .env (data, development, staging, or production), then:
npm run docker:run:prod
I need production data locally¶
Configure .env first
Make sure .env is configured (at minimum GYM_SLUG, REMOTE_DB_USER, REMOTE_DB_PASS) before syncing. See Environment Variables.
I want to inspect the database visually¶
I want to work against a remote database without Docker¶
# In .env, set APP_ENV to the desired environment (data, development, staging, or production)
npm install
npx prisma generate
npm run dev
I changed a Prisma model¶
I need to apply migrations to a remote database¶
Admin only
Applying migrations to remote databases should only be done by authorized team members.
Troubleshooting¶
npm installfails (401/403): confirmGITHUB_TOKENis exported and hasread:packagesaccess (required for private@turing-rlgym/*packages from GitHub Packages).- Docker errors: make sure Docker Desktop (or the Docker daemon) is running, then retry
npm run initialize. - Port
5432already in use: stop any local Postgres using that port, or adjust the port mapping in your DB run command (seedocker/README.md). - Remote DB auth/hostname errors: verify
GYM_SLUG,REMOTE_DB_USER,REMOTE_DB_PASS, and your network access to the remote database host. - App running in Docker +
APP_ENV=local:localhost:5432inside the app container is not the DB container. Recommended: run the app on your host (npm run dev) and keep Postgres in Docker, or connect to a remote DB (APP_ENV != local) / configure container networking.