Getting started
Clone to a running stack, and the two things that go wrong on the way.
Prerequisites
- Bun 1.3 or newer
- Docker, or your own Postgres and Redis
Clone and install
git clone <repo> my-app && cd my-app
bun install
cp .env.example .envThe .env at the repo root is the only one. Bun and Next auto-load a
.env from the process's own working directory, and Turbo runs each app with
its cwd set to that app, so every entrypoint imports
@workspace/env/load-root-env, which walks up to find this file. Per-app .env
files are not read, and making one will confuse you later.
Bring the stack up
bun run setupThat is docker compose up -d --wait, then db:push, then db:seed. Compose
starts pgvector/pgvector:pg16 and redis:7-alpine, waits for both
healthchecks, and creates the two Postgres extensions the schema needs through
scripts/init-db.sql.
Those extensions are why the image is pgvector/pgvector rather than stock
postgres. If you skip compose and point at your own Postgres, create them
yourself as a superuser first:
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pg_trgm;Without them db:push fails with type "vector" does not exist and says
nothing about extensions.
Run it
bun run dev| App | Port | What it is |
|---|---|---|
apps/api | 3001 | Elysia REST API, OpenAPI reference at /openapi |
apps/web | 3002 | Product UI: marketing, auth screens, dashboard |
apps/admin | 3003 | Auth-gated admin panel |
apps/docs | 3004 | This site |
Sign in with the seeded account: admin@example.com / Admin123!. The seed
also creates three sample projects, so the dashboard and the projects page show
something on the first run.
NEXT_PUBLIC_APP_URL points at the API origin in local development
(http://localhost:3001), not at the web app. Better Auth and the Eden treaty
client both build their paths from it, and locally the auth handler lives on
the API. In production, where one proxy fronts everything, it is the single
public origin instead.
This is the most common way a first run goes wrong, which is why
.env.example says so at the top of the file.
The worker
bun run dev does not start it. Nothing in the UI depends on it, so it stays
out of the default loop:
bun run --filter=@workspace/worker devRun it when you are working on emails, webhooks or anything queued. See background jobs.
What works with no configuration at all
Auth, the database, the admin, the dashboard and the generated resources. Every integration is inert until its variables are set, and the app boots without any of them:
| Unset | Effect |
|---|---|
| Polar | No checkout; everyone resolves to the free plan and the gates still work |
| Resend | No mail; magic-link sign-in stays hidden |
| S3 / R2 | Uploads throw a named error listing the variables |
| AI keys | AI routes unavailable |
| Sentry, PostHog | Nothing reported, nothing tracked |
The environment reference lists all of them.