Skip to content
BoringStack
GitHub

Quickstart

5 min read

Local boot

Click Use this template on the BoringStack monorepo, clone your new repo, run ./setup.sh --up, and Compose starts Postgres, Valkey, api-dev (migrations + OpenAPI), and ui-dev (Vite on :3001 with generated client). Optional overlays: Mailpit, Bull Board, observability, GlitchTip.

1

click Use this template

Docker

only prerequisite

0

local Node or Bun installs

01

Use this template

Click "Use this template" on GitHub, then clone the new repo created under your org.

02

Run setup

`./setup.sh --up` seeds compose/.env and boots the dev stack.

03

Sign in

Open http://localhost:3001; use SUPERUSER_* from compose/.env or register.

04

Ship changes

From repo root: `bun run regen` then `bun run check` before you push.

You now have Postgres, Valkey, the API, and the UI running locally with hot reload.

  • Docker + Docker Compose v2 (docker compose version reports v2.x or newer).
  • About 4 GB of free RAM.
  • No local Node or Bun needed for the default path; everything runs in containers.

The BoringStack monorepo is a GitHub template repository. On the boringstack-xyz/boringstack page, click Use this template → Create a new repository to make a fresh copy under your org with full ownership and no fork relationship.

Then clone the repo you just created:

Terminal window
git clone https://github.com/<your-org>/<your-repo>.git
cd <your-repo>

API, UI, docs, Compose, and bootstrap infrastructure all live in this one tree. Run bun run rename:project from the root any time to rebrand the BoringStack identifiers across the codebase.

Monorepo layout
boringstack/
  • apps/api/Bun + Elysia + Drizzle API
  • apps/ui/Vite + React SPA
  • apps/docs/boringstack.xyz site source
  • infra/compose/
    • compose/
      • docker-compose.ymlbuild.context → ../../../apps/api | apps/ui
      • dev.shdev stack entrypoint
  • infra/bootstrap/optional OpenTofu VPS bootstrap
Boot locally
$ ./setup.sh --up

ok  postgres ready on 5432
ok  valkey ready on 6379
ok  api-dev migrated and serving /openapi.json
ok  ui-dev generated client and started Vite

Or manually:

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 + SUPERUSER_PASSWORD in compose/.env, an admin user is also created. About 3 minutes on a fast laptop.

Open http://localhost:3001.

If you set SUPERUSER_EMAIL + SUPERUSER_PASSWORD in compose/.env before booting, sign in with those credentials. Otherwise hit “Sign up” on the form and register a new account; that user is the first user in the system. You land on the dashboard, which is minimal on purpose. Start building from here.

postgres (port 5432)

App database; schemas auth, billing, audit, app, notifications.

valkey (port 6379)
Cache and BullMQ queues.
api-migrate (one-shot)

db:push and optional superuser seed, then exits.

api-dev (port 3000)

Bun + Elysia API with hot reload via bind mount.

ui-dev (port 3001)

Vite dev server; proxies /api/* to api-dev.

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

  • Regenerate cross-app contracts: bun run regen from repo root (api must be on :3000 for OpenAPI).
  • Observability: WITH_OBSERVABILITY=1 ./scripts/compose-up.sh from infra/compose/compose. Details.
  • Self-hosted error tracking: WITH_GLITCHTIP=1 ./scripts/compose-up.sh. Details.
  • Local email testing: WITH_MAILPIT=1 ./scripts/compose-up.sh. Details.
  • Production deploy: Deployment when you are ready for GHCR images, TLS, firewall, and backups.
Stop, keep data

From infra/compose/compose: ./dev.sh down. Volumes stay on disk.

Stop and wipe data

./scripts/compose-down-clean.sh from infra/compose. Prompts before delete; CONFIRM=yes to skip the prompt.