Toast
Contributor

Local Dev Setup

Get your development environment running from scratch.

This guide walks you through setting up a local Toast development environment. For the short version, see the CONTRIBUTING.md checklist.

Prerequisites

  • Node.js 24+ — check with node --version
  • pnpm — installed via corepack (corepack enable)
  • Docker — required for PostgreSQL and MinIO (object storage)
  • Git — for cloning and hooks

Quick Start

git clone https://github.com/TryGhost/Toast.git
cd Toast
pnpm install
pnpm dx

pnpm dx is the single command that handles everything: starts Docker containers, runs database migrations, seeds data, and launches all dev servers.

What pnpm dx Does

On first run, pnpm dx detects it's a fresh checkout and runs the bootstrap sequence:

  1. Port detection — checks if default ports (5432, 9000, 3000, 5173) are available
  2. Environment setup — creates .env from .env.example, prompting for custom ports if needed
  3. Docker Compose — starts PostgreSQL 16 and MinIO (S3-compatible object storage)
  4. Database migrations — applies all Drizzle ORM migrations
  5. Database seeding — creates a default site and admin user
  6. Dev servers — starts the API server (port 3000) and admin panel (port 5173) via Turborepo

On subsequent runs, it skips the bootstrap and goes straight to starting Docker and dev servers.

Non-Interactive Mode

For CI or scripting, skip all prompts:

DX_AUTO=1 pnpm dx

Or manually create .env before running:

cp .env.example .env
# Edit ports if needed
pnpm dx

TipTap Pro Token

The editor uses TipTap Pro extensions. If pnpm install fails with ERR_PNPM_FETCH_404 for @tiptap-pro/* packages, set the token first:

export TIPTAP_PRO_TOKEN=<token-from-tiptap-cloud>
pnpm install

Get the token from TipTap Cloud → Pro Extensions.

TipTap Runtime Features

TipTap has a two-layer model:

  • TIPTAP_PRO_TOKEN — install/build auth only (package registry access)
  • Runtime capabilities — controlled by env pairs:
    • Collaboration: VITE_TIPTAP_COLLAB_APP_ID + TIPTAP_COLLAB_SECRET
    • AI: VITE_TIPTAP_AI_APP_ID + TIPTAP_AI_SECRET

The admin panel checks /api/capabilities at runtime to gate features — it never reads env vars directly.

Verify Setup

After pnpm dx completes, verify everything is running:

# API health check
curl http://localhost:3000/healthz        # {"status":"ok"}
curl http://localhost:3000/healthz/ready  # {"status":"ok","database":"connected"}

The admin panel runs at http://localhost:5173. Default login:

  • Email: admin@ghost.org
  • Password: admin

Docker Services

docker-compose.dev.yml manages two services:

ServiceImageDefault PortPurpose
dbpostgres:16-alpine5432Primary database
miniominio/minio9000 / 9001S3-compatible file storage

A minio-setup init container creates the default toast-uploads bucket on first start.

Port Conflicts

If port 5432 is already in use (e.g., a system PostgreSQL), you have two options:

  1. Interactive — run pnpm dx and choose custom ports when prompted
  2. Manual — edit .env to set DB_PORT=5433 and update DATABASE_URL accordingly

Git Worktrees

When working on multiple branches simultaneously, use worktrees instead of stashing:

# Create a worktree with auto-allocated ports
pnpm worktree:create my-feature-branch

# Check which ports your worktree uses
pnpm worktree:context --json

# List all worktrees and their ports
pnpm worktree:list --json

# Detect and fix port collisions
pnpm worktree:ports:check
pnpm worktree:ports:fix

Each worktree gets its own .env with unique ports so multiple branches can run dev servers simultaneously without conflicts.

Important: In a worktree, never assume default ports from docs. Always run pnpm worktree:context --json first.

Common Commands

TaskCommand
Start everythingpnpm dx
Run testspnpm test
Run a single testpnpm test path/to/file.test.ts
Integration testspnpm test:integration
Type checkpnpm typecheck
Lint + fixpnpm lint:fix
Format + fixpnpm format:fix
Full quality checkpnpm check
Strict check (no fix)pnpm check:strict
Generate DB migrationpnpm db:generate
Apply migrationspnpm db:migrate
Reset databasepnpm db:reset
Browse DB (Drizzle Kit)pnpm db:studio

Editor Setup

Install the Biome VS Code extension for real-time lint feedback. The ESLint extension is also recommended for the custom guard rules.

See Linting & Formatting Strategy for the full rule set.

Troubleshooting

pnpm install fails with 404 errors

You need a TipTap Pro token. See TipTap Pro Token above.

Docker containers won't start

Check that Docker Desktop is running and no other containers are using the same ports:

docker ps                                          # List running containers
docker compose -f docker-compose.dev.yml down      # Stop Toast containers
docker compose -f docker-compose.dev.yml up -d     # Restart

Database connection errors

Verify the database is healthy:

docker compose -f docker-compose.dev.yml ps     # Check container status
pnpm db:migrate                                 # Re-run migrations
pnpm db:reset                                   # Nuclear option: reset and re-seed

Port already in use

If a dev server fails to start because a port is taken:

lsof -i :3000               # Find what's using the port
pnpm worktree:ports:check    # Check for worktree port collisions

On this page