Local development
Run the monorepo, work with Docker services, and debug common issues.
The developer quickstart gets you running. This page covers the development environment in more detail.
Services and ports
| Service | Command | URL / port |
|---|---|---|
| Admin | pnpm dev:admin | http://localhost:3000 |
| Storefront | pnpm dev:store | http://localhost:3001 |
| Docs | pnpm dev:docs | http://localhost:3002 |
| PostgreSQL | pnpm db:dev:up | localhost:5432 |
| Mailpit SMTP | pnpm mail:up | localhost:2525 |
| Mailpit UI | pnpm mail:up | http://localhost:8025 |
| SeaweedFS S3 | pnpm storage:up | http://localhost:8333 |
| SeaweedFS UI | pnpm storage:up | http://localhost:8888 |
| Inngest dev server | Started by pnpm dev:admin | localhost:8310 |
| Drizzle Studio | Started by pnpm dev:admin | https://local.drizzle.studio |
| Test database | pnpm db:test:up | localhost:5433 |
pnpm dev runs every app with a dev script, plus Inngest and Drizzle Studio.
Environment files
Each app validates its own environment:
apps/admin/.env
apps/storefront/.env
packages/db/.envUse the .env.example files as templates. The admin and storefront must share
the same BETTER_AUTH_SECRET and DATABASE_URL.
Database workflow
pnpm db:dev:up # start PostgreSQL
pnpm db:migrate # apply committed migrations
pnpm -F admin db:seeddb:seed creates demo data and is intended for local development only. It
requires Bun because the admin scripts run with Bun.
To inspect data, run pnpm db:studio or connect with any PostgreSQL client.
Running a single workspace
Turborepo filters:
pnpm dev:admin
pnpm dev:store
pnpm dev:docs
pnpm build:admin
pnpm build:store
pnpm build:sdk
pnpm check:admin
pnpm check:storeFor an arbitrary workspace, use pnpm -F <workspace> <script>.
Inngest
The admin app serves the Inngest endpoint at /api/inngest. The local dev
server is started by pnpm dev:admin on port 8310.
- Open the Inngest dev UI to inspect runs and replay events.
- If port
8288is unavailable on Windows (Hyper-V/WSL), the repo defaults the dev server to8310; keepINNGEST_DEVin sync if you override it. - Background jobs that send email, SMS, or generate PDFs need the dev server running.
Email and storage
- Email: Mailpit captures all messages. Open http://localhost:8025 to read OTPs, invitations, and order confirmations.
- Storage: SeaweedFS is available locally; RustFS is an alternative. Only run one storage service at a time. Cloudinary is the default provider.
Useful reset commands:
pnpm mail:reset
pnpm storage:reset
pnpm db:dev:reset # backs up first
pnpm db:dev:reset:forceMaking a change
- Create a focused branch.
- Make the change in the smallest relevant workspace.
- Add or update tests.
- Run
pnpm checkandpnpm check-types. - Run the relevant test suite.
- Update docs if behavior changed.
- Commit with a descriptive message.
Debugging
- Env validation fails on startup: compare
.envwith.env.example; the error names the missing variable. - Database connection refused:
pnpm db:dev:upand check port5432. - Storefront shows no products: publish a product and verify
ORGANIZATION_SLUGandAPI_KEY. - Emails do not arrive: start Mailpit and check
SMTP_*values. - PDFs fail: check the Puppeteer runtime and storage credentials.
- Docs API pages are stale: run
pnpm docs:sync-api.