Skip to content
BoringStack
Star

Quickstart

7 min read

Verified 2026-09

From nothing to a working dev stack in about three minutes. Docker and Docker Compose v2 are the only prerequisites for booting: Compose runs every runtime, so you need no local Postgres and no local Node. You do need Bun to develop once it is up, because every root script (bun run check, bun run regen, bun run rename:project) runs on it.

After boot you have a register/login UI at http://localhost:7331, the API at http://localhost:7330/api/* (OpenAPI spec served at /swagger), Postgres with migrations applied, Valkey for cache and BullMQ, and a generated TypeScript client wired into apps/ui that fails to compile the moment the API contract drifts. Optional overlays via env flags: Mailpit, Bull Board, observability, GlitchTip, image update notifications.

  • Docker + Docker Compose v2 (docker compose version reports v2.x or newer).
  • About 4 GB of free RAM.
  • git. Optionally gh, authenticated, to get a GitHub-hosted repo.
  • Bun 1.4.2 to develop. Not needed to boot.

Paste this into your coding agent:

Set up boringstack.xyz for me

It reads /agents.md, which carries the install command, the health checks, the machine-readable config surface at /scaffold-manifest.json, and the invariants that keep generated code passing CI. Nothing else needs to be in the prompt.

Terminal window
curl -fsSL https://boringstack.xyz/install.sh | sh -s -- --project acme

Five phases, announced as they go: preflight (Compose v2, free ports, memory), scaffold, rename, boot, health check. It never prompts, so it works the same from a terminal, a CI job or an agent. Useful flags:

FlagEffect
--dry-runPrint the resolved plan and exit without writing.
--jsonOne JSON object per phase on stdout; human output on stderr.
--no-bootScaffold and rename only; skip Docker.
--no-renameKeep the BoringStack identifiers.
--ghcr-owner, --domain, --dir, --refOverride the defaults.

Each phase exits with its own code (3 preflight, 4 scaffold, 5 rename, 6 boot, 7 health), and every failure prints the fix.

The monorepo is a GitHub template repository, so gh can create your copy without touching a browser:

Terminal window
gh repo create <your-repo> \
--template boringstack-xyz/boringstack --private --clone
cd <your-repo>

Without gh, clone and detach from upstream so this is your project rather than a fork:

Terminal window
git clone --depth 1 \
https://github.com/boringstack-xyz/boringstack <your-repo>
cd <your-repo> && rm -rf .git && git init

Then rebrand. The script is idempotent and self-verifying: it fails if any upstream identifier survives the rewrite, and DRY_RUN=1 previews the edits.

Terminal window
./scripts/rename-project.sh <project> <ghcr-owner> <domain>

API, UI, docs, Compose and bootstrap infrastructure all live in this one tree: apps/api/ (Bun + Elysia + Drizzle), apps/ui/ (Vite + React SPA), apps/docs/ (this site), infra/compose/ (the Docker Compose stack) and infra/bootstrap/ (optional OpenTofu VPS bootstrap).

From the repo root:

Terminal window
./setup.sh --up

setup.sh bootstraps infra/compose/compose/.env, generates a GLITCHTIP_SECRET_KEY, makes the compose scripts executable, and with --up runs ./dev.sh up -d --build.

Or do the same thing by hand:

Terminal window
cd infra/compose/compose
cp .env.example .env
chmod +x dev.sh ../scripts/*.sh
./dev.sh up -d --build

First boot pulls base images, builds the api/ui dev images, and runs migrations. If you set SUPERUSER_EMAIL and SUPERUSER_PASSWORD in compose/.env, an admin user is also created. About three minutes on a fast laptop.

Open http://localhost:7331.

If you set SUPERUSER_EMAIL and SUPERUSER_PASSWORD in compose/.env before booting, sign in with those credentials. That path runs scripts/db/seed-superuser.ts, which is the only thing that sets is_platform_admin. It skips an email that already exists rather than promoting it, so give it an address you have not registered.

Otherwise click “Sign up” and register. That makes you the owner of your own account, since every signup creates a personal account, an owner membership and a Free plan row in one transaction. It does not make you a platform admin, whatever order you register in. You land on a dashboard that’s intentionally empty. Start building from here.

The dashboard is intentionally empty so you start shipping immediately. BoringStack supports two workflows for adding features, both agent-friendly. Pick one per session; switch any time.

In Claude Code or Cursor, run /add-full-feature and describe the slice you want to ship. The skill at .claude/skills/add-full-feature.md coordinates the api half, then the OpenAPI regen, then the ui half. Good for small changes where you trust the agent to stay scoped.

Run bun run spec:init once per project to wire the spec loop (creates .specs/next.md, the /spec slash command, and a TypeScript gate that blocks source writes until you approve a slice). Then in the agent:

  1. /spec explore <idea>.
  2. /spec slice.
  3. You approve the slice.
  4. /spec build.

The gate at tools/spec-loop/hooks/gate.ts is the discipline: useful when the agent’s tendency to over-build is the failure mode you’re worried about.

The spec loop is opt-in. A fresh bun run spec:init writes four files (.specs/next.md, .claude/commands/spec.md, .claude/settings.json, .cursor/hooks.json). Skip it and Path A is the default. See Spec loop for the deep dive.

  • postgres (port 5432): app database; schemas auth, billing, audit, app, notifications.
  • valkey (port 6379): cache and BullMQ queues.
  • api-migrate (one-shot): runs db:push and the optional superuser seed, then exits.
  • api-dev (port 7330): Bun + Elysia API with hot reload via bind mount.
  • ui-dev (port 7331): Vite dev server; proxies /api/* to api-dev.

Traefik runs only in the prod profile. In prod it terminates TLS and path-routes /api/* plus /health to the api container, everything else to the ui container, all on one domain.

  • Regenerate cross-app contracts: bun run regen from the repo root. The api must be on :7330 for the OpenAPI fetch to succeed.
  • Everything ships wired in dev. Cache (Valkey), real-time SSE notifications, Web Push (VAPID keys auto-generated on first boot), Bull-board, Mailpit, observability, and error tracking are all on by default. Inspect them at: Grafana http://localhost:3010, GlitchTip http://glitchtip.localhost, Bull-board http://bullmq.localhost, Mailpit http://localhost:8025. See Profiles & overlays for the full default matrix and the off switches.
  • Production deploy: Deployment covers GHCR images, TLS, firewall, and backups.

From infra/compose/compose/, ./dev.sh down stops everything and keeps the volumes on disk. To wipe data as well, run ./scripts/compose-down-clean.sh from infra/compose/; it prompts before deleting, or set CONFIRM=yes to skip the prompt.

For account-owned feature work, follow the verified agent workflow and account-resource recipe. The commands give both engineers and agents structured evidence from isolated integration services. Existing installations should also read the security upgrade runbook.