Skip to content

Local development

In development every external service is optional. Without Mailgun, emails are kept in a console outbox; without Stripe, billing is simulated; without Microsoft Entra, a developer sign-in is offered.

  1. Install dependencies from the repository root:

    Terminal window
    npm install
  2. Start Postgres and keep it running in its own terminal:

    Terminal window
    npm run dev:db

    This starts an embedded Postgres on port 54329 with data in apps/api/.pgdata, creates the pdfeditor database, and matches the default DATABASE_URL (postgres://postgres:postgres@localhost:54329/pdfeditor). Set DEV_DB_PORT to use another port (and change DATABASE_URL to match).

  3. Configure (optional). Copy apps/api/.env.example to apps/api/.env. Everything has a development default, so you can skip this at first.

  4. Start the API and web app:

    Terminal window
    npm run dev

    The API listens on http://localhost:3001 and applies migrations on start. The web app runs on http://localhost:5173 and proxies /api to the API (set API_URL to proxy elsewhere). Its startup line shows the billing mode, email transport and whether Microsoft sign-in is on.

  5. Create an account. Open http://localhost:5173/signup. The confirmation email isn’t sent anywhere: its link is printed in the API log and kept in the dev outbox (below).

  6. Choose a plan. With simulated billing, Choose plan opens a Simulated checkout page where you confirm without paying.

Helper What it does
GET /api/dev/emails Emails captured by the console transport, newest first (the last 200). Filter with ?to=someone@example.com. Open it at http://localhost:5173/api/dev/emails.
Development sign-in When DEV_LOGIN is on (the default outside production), the sign-in page has a Development sign-in panel listing existing users. Click one to sign in as them, with no password or Microsoft account.
GET /api/dev/users The users that the development sign-in lists.
Simulated billing BILLING_MODE=fake (the default without STRIPE_SECRET_KEY): checkout and extra packs complete on a local page and set up a 30-day period. The billing portal isn’t available.

All /api/dev/* routes return 404 in production, and the development sign-in is always off there.

Terminal window
npm run dev -w @pdfeditor/docs # this site, http://localhost:4322
npm run dev -w @pdfeditor/marketing # the marketing site, http://localhost:4321
npm test # shared + API tests
npm run lint

To create a super admin locally, see Creating the first super admin.