Self-hosted coffee app for tracking espresso shots, with AI assistance
2
stars
314
commits
TypeScript
primary language
Sep 4, 2026
updated

The AI-native coffee journal you actually own.
Photograph the bag. Log the brew. Keep every gram of data on your own
infrastructure.
Live demo · Quick start · Documentation · Design system
[!TIP] Try it in ten seconds. The read-only demo runs entirely from bundled sample data — no account, no database, nothing to install.
Roastbook is a self-hosted home for your brews, beans, recipes, café visits, roasters, brewing methods, and gear — and it fills itself in for you.
Every accepted value keeps its source, and factory facts stay separate from your current setup.
Logging coffee should take seconds, not minutes. Log a brew with dose, yield, and time and you are done; the depth is there when you want it, not in your face when you don't. Roastbook runs equally well on the phone in your hand at the machine and on the desktop where you dig through the numbers afterwards.
[!NOTE] Set
OPENAI_API_KEYand these turn on. Everything else works without it.
Every AI call is optional, server-side only, rate-limited, schema-validated, and recorded in PostgreSQL for local debugging. Image logs retain metadata such as MIME type and byte count, not the image payload itself.
[!IMPORTANT] On the roadmap: an MCP server, so your own agents can read and write your coffee log directly — ask what your last ten Gesha brews had in common, or have an assistant log this morning's espresso for you.
A modern, boring-where-it-counts TypeScript stack with full-stack type safety from the database row to the rendered field:
| Layer | Choice |
|---|---|
| Runtime and package manager | Bun 1.3.14 |
| Full-stack framework | TanStack Start with server functions |
| Routing | TanStack Router, file-based and fully typed |
| UI | React 19, shadcn/ui, Radix and Base UI, Tailwind CSS v4 |
| Icons and maps | Lucide, MapLibre GL |
| Database | PostgreSQL when self-hosted; ephemeral PGlite for the demo |
| Media storage | Local filesystem or any S3-compatible bucket |
| AI | TanStack AI with any OpenAI-compatible endpoint |
| Validation | Zod at every boundary, including environment variables |
| Tooling | Vite, Biome, Knip, bun test |
| Deployment | Docker Compose or Helm, fronted by the Hodor auth proxy |
Server-only concerns — database access, storage providers, AI calls, and secrets — never cross into browser code, and configuration is validated lazily on first use, reporting the affected variable names.
Docker Compose starts PostgreSQL, applies committed migrations, starts Roastbook, and exposes it through Hodor.
cp .env.example .env
# Replace HODOR_PASSWORD and HODOR_SECRET in .env.
# Generate a signing secret with: openssl rand -hex 32
docker compose up --build
Open http://localhost:3000 after the database migration completes.
Roastbook uses Bun 1.3.14. With PostgreSQL available at the DATABASE_URL from
.env:
bun install --frozen-lockfile
cp .env.example .env
bun run dev
The unauthenticated development server listens on http://localhost:3000. It applies pending migrations before accepting requests, repeats the check on Vite configuration reloads, and watches for newly generated migrations while running.
| Command | Purpose |
|---|---|
bun run dev | Apply migrations and start the watched development server |
bun run check | Check source formatting, lint, and Markdown |
bun run typecheck | Run TypeScript without emitting files |
bun run test | Run tests; report unavailable integrations as skipped |
bun run test:integration | Require PostgreSQL and S3 integration tests |
bun run lint:deadcode | Find unused code and dependencies with Knip |
bun run build | Build production assets |
bun run build:demo | Build the database-free Vercel demo |
bun run verify | Run the complete local quality gate |
bun run db:generate | Generate a Drizzle migration after a schema change |
bun run db:migrate | Apply committed migrations |
bun run db:studio | Open Drizzle Studio |
bun run db:seed | Seed the same fictional dataset as the public demo |
bun run storage:orphans | Report media drift without changing data |
| Guide | What is inside |
|---|---|
| Development and testing | Workflow, tests, tooling |
| Configuration reference | Every environment variable |
| Read-only demo mode | How the PGlite demo is built |
| Deployment | Docker, Helm, security boundary |
| Design system | Layout contract and UI conventions |
| Helm chart reference | Chart values and defaults |
src/routes/ TanStack Router file routes and server endpoints
src/components/ Shared application and domain UI
src/components/ui/ shadcn/ui primitives
src/lib/server/ Server-side domain operations
src/lib/storage/ Local and S3-compatible storage providers
src/db/ Drizzle schema and database connection
drizzle/ Committed migrations and metadata
charts/ Helm chart
[!WARNING]
src/routeTree.gen.tsis generated. Runbun run generate-routesinstead of editing it manually.
Open-source software for people who care about coffee. ☕
Try the demo ·
Star it on GitHub
TypeScript
97.8%
PLpgSQL
1.4%
Self-hosted coffee app for tracking espresso shots, with AI assistance
2
stars
314
commits
TypeScript
primary language
Sep 4, 2026
updated

The AI-native coffee journal you actually own.
Photograph the bag. Log the brew. Keep every gram of data on your own
infrastructure.
Live demo · Quick start · Documentation · Design system
[!TIP] Try it in ten seconds. The read-only demo runs entirely from bundled sample data — no account, no database, nothing to install.
Roastbook is a self-hosted home for your brews, beans, recipes, café visits, roasters, brewing methods, and gear — and it fills itself in for you.
Every accepted value keeps its source, and factory facts stay separate from your current setup.
Logging coffee should take seconds, not minutes. Log a brew with dose, yield, and time and you are done; the depth is there when you want it, not in your face when you don't. Roastbook runs equally well on the phone in your hand at the machine and on the desktop where you dig through the numbers afterwards.
[!NOTE] Set
OPENAI_API_KEYand these turn on. Everything else works without it.
Every AI call is optional, server-side only, rate-limited, schema-validated, and recorded in PostgreSQL for local debugging. Image logs retain metadata such as MIME type and byte count, not the image payload itself.
[!IMPORTANT] On the roadmap: an MCP server, so your own agents can read and write your coffee log directly — ask what your last ten Gesha brews had in common, or have an assistant log this morning's espresso for you.
A modern, boring-where-it-counts TypeScript stack with full-stack type safety from the database row to the rendered field:
| Layer | Choice |
|---|---|
| Runtime and package manager | Bun 1.3.14 |
| Full-stack framework | TanStack Start with server functions |
| Routing | TanStack Router, file-based and fully typed |
| UI | React 19, shadcn/ui, Radix and Base UI, Tailwind CSS v4 |
| Icons and maps | Lucide, MapLibre GL |
| Database | PostgreSQL when self-hosted; ephemeral PGlite for the demo |
| Media storage | Local filesystem or any S3-compatible bucket |
| AI | TanStack AI with any OpenAI-compatible endpoint |
| Validation | Zod at every boundary, including environment variables |
| Tooling | Vite, Biome, Knip, bun test |
| Deployment | Docker Compose or Helm, fronted by the Hodor auth proxy |
Server-only concerns — database access, storage providers, AI calls, and secrets — never cross into browser code, and configuration is validated lazily on first use, reporting the affected variable names.
Docker Compose starts PostgreSQL, applies committed migrations, starts Roastbook, and exposes it through Hodor.
cp .env.example .env
# Replace HODOR_PASSWORD and HODOR_SECRET in .env.
# Generate a signing secret with: openssl rand -hex 32
docker compose up --build
Open http://localhost:3000 after the database migration completes.
Roastbook uses Bun 1.3.14. With PostgreSQL available at the DATABASE_URL from
.env:
bun install --frozen-lockfile
cp .env.example .env
bun run dev
The unauthenticated development server listens on http://localhost:3000. It applies pending migrations before accepting requests, repeats the check on Vite configuration reloads, and watches for newly generated migrations while running.
| Command | Purpose |
|---|---|
bun run dev | Apply migrations and start the watched development server |
bun run check | Check source formatting, lint, and Markdown |
bun run typecheck | Run TypeScript without emitting files |
bun run test | Run tests; report unavailable integrations as skipped |
bun run test:integration | Require PostgreSQL and S3 integration tests |
bun run lint:deadcode | Find unused code and dependencies with Knip |
bun run build | Build production assets |
bun run build:demo | Build the database-free Vercel demo |
bun run verify | Run the complete local quality gate |
bun run db:generate | Generate a Drizzle migration after a schema change |
bun run db:migrate | Apply committed migrations |
bun run db:studio | Open Drizzle Studio |
bun run db:seed | Seed the same fictional dataset as the public demo |
bun run storage:orphans | Report media drift without changing data |
| Guide | What is inside |
|---|---|
| Development and testing | Workflow, tests, tooling |
| Configuration reference | Every environment variable |
| Read-only demo mode | How the PGlite demo is built |
| Deployment | Docker, Helm, security boundary |
| Design system | Layout contract and UI conventions |
| Helm chart reference | Chart values and defaults |
src/routes/ TanStack Router file routes and server endpoints
src/components/ Shared application and domain UI
src/components/ui/ shadcn/ui primitives
src/lib/server/ Server-side domain operations
src/lib/storage/ Local and S3-compatible storage providers
src/db/ Drizzle schema and database connection
drizzle/ Committed migrations and metadata
charts/ Helm chart
[!WARNING]
src/routeTree.gen.tsis generated. Runbun run generate-routesinstead of editing it manually.
Open-source software for people who care about coffee. ☕
Try the demo ·
Star it on GitHub
TypeScript
97.8%
PLpgSQL
1.4%