ShipKit docs

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 .env

The .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 setup

That 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
AppPortWhat it is
apps/api3001Elysia REST API, OpenAPI reference at /openapi
apps/web3002Product UI: marketing, auth screens, dashboard
apps/admin3003Auth-gated admin panel
apps/docs3004This 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 dev

Run 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:

UnsetEffect
PolarNo checkout; everyone resolves to the free plan and the gates still work
ResendNo mail; magic-link sign-in stays hidden
S3 / R2Uploads throw a named error listing the variables
AI keysAI routes unavailable
Sentry, PostHogNothing reported, nothing tracked

The environment reference lists all of them.

Next

On this page