Quickstart
The setup guide is QUICKSTART.md at the root of the repository, the one copy kept up to date. It
takes a fresh clone to a running app in about ten minutes, then covers the first administrator,
documents and AI jobs, the accounts and keys you need next, deployment and the launch checklist.
This page is its outline; where the two differ, QUICKSTART.md is right.
Install and run
Section titled “Install and run”You need Bun 1.4 or newer, and Docker with Compose and a running daemon for the local Postgres, or
an existing Postgres 17 with pgvector instead of Docker. Python 3.13 and uv are only for the AI
service, Rust only for the Tauri shells. Node.js is optional, but if it is installed it must be
22.17 or newer: Vite runs under it.
Start from a release, not from the kit’s main: UPGRADING.md’s first block checks out the
release you name (name the newest: git tag -l "kit/*" --sort=-v:refname lists them) and files the
kit’s tags under kit/, which later upgrades merge from. Then:
bun installbun run setup # every .env from its template, with generated secretsbun run doctor # read-only: prerequisites and configurationbun run db:up # Postgres 17 in Docker on 127.0.0.1:5433bun run db:migratebun run dev:app # API on :3000, app on http://localhost:5173On Windows, run them in PowerShell; QUICKSTART.md, Step 0, says what to do once in a clone checked
out with CRLF line endings, and how stopping the API differs there.
Without Docker, point DATABASE_URL in the root .env at a development database on your own
Postgres, run bun run doctor -- --database=external instead of bun run doctor, and skip
db:up. The doctor then skips its Docker checks; it does not install or configure Postgres.
Create that database with createdb -T template0 --locale=C <name>. Homebrew’s postgresql@17 is
keg-only, so on a Mac createdb and psql are not on your PATH until you run
brew link --force postgresql@17 or add $(brew --prefix postgresql@17)/bin to it. Every id is
text, and under a language collation, the default a Homebrew or distribution Postgres gives a new
database, an index probe on a text key costs about 7 µs against 0.7 µs under C. C sorts by byte
value, so a list users see sorted by name names an ICU collation in its query
(order by name collate "und-x-icu"). Once the database answers, the doctor prints its collation
and warns when it is not C. A Docker database db:up creates from this release on is in the builtin
C.UTF-8 locale; a volume created before keeps en_US.utf8, and gets that warning. Give the
database’s role CREATEDB (createuser --createdb <role>, or ALTER ROLE <role> CREATEDB): the
database suites and test:e2e:full create scratch databases beside yours, and doctor warns
without it.
Rename the kit before setup if you already have a product name, on the branch UPGRADING.md names
so later releases merge cleanly (QUICKSTART.md, Step 1, item 2). setup never replaces a value
you set, so it is safe to run again. It also gives the marketing site and the docs their local
SITE_URL, so bun run build works on a fresh clone.
The AI service that runs document jobs starts in its own terminal, with the SERVICE_TOKEN
setup shared between it and the API:
cd services/ai && uv sync && uv run uvicorn ai.main:app --reload --port 8000Configuration explains every variable, and Commands lists every command. When you add your first feature, follow the worked feature example.
For data that belongs to one organization’s workspace, follow Your first tenant-scoped feature.
First steps in the app
Section titled “First steps in the app”- Sign up at
/signupwith email and password. In development the verification email prints to the API terminal.REQUIRE_EMAIL_VERIFICATIONdecides whether a session is issued before the address is verified (default: only in production). - Create an organization. It is the tenant and billing entity that owns members, invitations
and teams.
/appoffers it in one click, already named after you, until you have one. New sessions start in your first organization. The organization’s menu at the top of the sidebar changes it and opens its settings. - Invite people from Members in the settings dialog (
/app/organization/members). Invitations are emailed as links that expire after 7 days. Give each person the owner, admin or member role. - Create a workspace from
/app. Workspaces hold the product data. Each one belongs to the organization and optionally to a team.
First platform administrator
Section titled “First platform administrator”Platform administrators are users whose role is admin. This role is independent of organization
roles. Promote the account you created during signup, then manage others from /admin/users:
bun run admin:create -- --email you@example.com --name 'You' --yes--yes confirms promotion of the existing account and leaves its password unchanged. For a new
email, the script creates the account and reads its password from ADMIN_PASSWORD or an interactive
prompt. The password is never read from a command-line argument, because arguments stay in shell
history and are visible in ps.
Demo data
Section titled “Demo data”bun run seed fills a fresh database with a demo organization: a team, two workspaces, three
documents, six finished jobs with their credit-ledger rows and an audit trail. The owner is
demo@example.com / demo-password-1234 (SEED_PASSWORD overrides the password). The script is
idempotent and refuses to run with NODE_ENV=production. The documents’ files go to storage the way
an upload does, so they download, and Extract, Summarize and Index run on them.
What a deploy publishes
Section titled “What a deploy publishes”A deploy publishes your product, so check what it still says about the kit before the first one:
- The marketing site. Its copy and its OG images are the kit’s until you rewrite them. The
changelog and the blog start with one draft sample each (
draft: true), whichbun run dev:siteshows and no build publishes; write your own entries inapps/site/src/content/changelogandblog. The kit’s own release notes areCHANGELOG.mdand never reach your site. - The legal pages are templates. A production build for a real origin refuses them while a
**[placeholder]**or the “review with counsel” note is left, and names each file;ALLOW_LEGAL_PLACEHOLDERS=1publishes them anyway, for a staging deployment. - The docs. A docs build serves your product’s documentation by default,
apps/docs/src/content/product: a two-page start and the interactive API reference. This manual isapps/docs/src/content/docs;bun run dev:manualserves it locally, and no build includes it unless it setsDOCS_CONTENT=kit.
bun run rename prints the full list as the end of its checklist.
Where things live
Section titled “Where things live”apps/ web/ SvelteKit application: auth, orgs/teams, workspaces, billing, admin (thin client) api/ Hono on Bun: Better Auth, oRPC router (RPC + REST/OpenAPI), webhooks site/ Astro: marketing, pricing, blog, SEO docs/ Astro Starlight: your product's docs, and this manual (`bun run dev:manual`) native/ Tauri 2: desktop + mobile shells around apps/web's static build (no IPC)packages/ api-contract/ oRPC + Zod contract: the API's single source of truth api-client/ typed client for the contract (browser, SSR, Tauri, Bun scripts) auth/ Better Auth server instance (API) and Svelte client factory (frontends) db/ Drizzle schema (generated auth tables + ours), migrations, Bun.SQL client billing/ plan catalog + Stripe client email/ provider abstraction (Resend / console) + templates env/ validated server environment (t3-env + Zod) storage/ document bytes: local disk with signed URLs, or S3/R2/MinIO ui/ shared Svelte 5 components (shadcn-svelte/bits-ui + thin form wrappers) + Tailwind tokens tsconfig/ shared TypeScript configsservices/ ai/ FastAPI service (uv): internal, called by the API onlyinfra/ compose.yml self-hosted stack: postgres · api · web · ai · caddy compose.dev.yml Postgres for local development caddy/ subdomains.Caddyfile (public) · single-origin.Caddyfile (tailnet/LAN) docker/ Dockerfile.static (Astro sites → Caddy)Internal packages are consumed from source. There is no build step. Shared dependency versions are
pinned once in the root package.json catalog and referenced with catalog:.