A beer inventory and trading platform — beercellar.io
- Framework — TanStack Start (React 19, Vite)
- Database — PostgreSQL 16 via Drizzle ORM
- UI — Radix UI + Tailwind CSS v4
- Auth — Untappd OAuth
- Testing — Vitest + Playwright
# 1. Install dependencies pnpm install # 2. Set up environment variables cp .env.example .env # Edit .env with your Untappd OAuth credentials (optional for basic dev) # 3. Start PostgreSQL pnpm docker:up # 4. Run migrations and seed the database pnpm db:migrate && pnpm db:seed # 5. Start the dev server pnpm devThe app is available at http://localhost:3000.
| Script | Description |
|---|---|
pnpm dev | Start Vite dev server with HMR |
pnpm build | Production build |
pnpm start | Serve the production build |
pnpm test | Run unit tests (Vitest) |
pnpm test:watch | Run tests in watch mode |
pnpm test:e2e | Run E2E tests (Playwright) |
pnpm docker:up | Start PostgreSQL container |
pnpm docker:down | Stop PostgreSQL container |
pnpm docker:dev | Run Postgres + app in Docker |
pnpm docker:prod | Build and run production Docker stack |
pnpm db:generate | Generate Drizzle migration files |
pnpm db:migrate | Apply pending migrations |
pnpm db:seed | Seed the database |
pnpm db:reset | Drop, recreate, migrate, and seed the DB |
pnpm db:shell | Open a psql shell to the dev database |
src/ routes/ # File-based routing (TanStack Router) __root.tsx # Root layout index.tsx # Landing page dashboard.tsx # User dashboard auth/ # OAuth callback routes beers/ # Beer detail/list pages breweries/ # Brewery pages search/ # Search pages users/ # User profile pages settings.tsx # User settings server/ auth/ # Untappd OAuth + session handling db/ # Drizzle schema, migrations, seed functions/ # Server functions (RPC-style) components/ ui/ # Radix-based primitives (button, card, dialog, etc.) nav/ # Navigation components inventory/ # Inventory management components notifications/ # Toast/notification components lib/ # Shared utilities styles/ # Global Tailwind styles See .env.example for all variables. Key ones:
| Variable | Purpose |
|---|---|
DATABASE_URL | PostgreSQL connection string |
SESSION_SECRET | Server-side session encryption key |
UNTAPPD_CLIENT_ID | Untappd OAuth app client ID |
UNTAPPD_CLIENT_SECRET | Untappd OAuth app client secret |
UNTAPPD_CALLBACK_URL | OAuth redirect URL |
VITE_UNTAPPD_CLIENT_ID | Client-side Untappd client ID |
VITE_UNTAPPD_CALLBACK_URL | Client-side OAuth redirect URL |
Development — By default, Docker only runs PostgreSQL. The app runs natively via pnpm dev:
pnpm docker:up # Postgres only pnpm dev # App on hostTo run everything in Docker: pnpm docker:dev
Production — Uses a multi-stage Dockerfile with a separate compose file:
cp .env.production.example .env.production # Edit with real credentials pnpm docker:prodpnpm test # Unit tests with Vitest pnpm test:e2e # E2E tests with Playwright (requires running app + DB)Tests are co-located with source files as *.test.ts(x).
Authentication uses Untappd OAuth. To enable login locally:
- Create an app at untappd.com/api/register
- Set the callback URL to
http://localhost:3000/auth/oauth/untappd - Add the client ID and secret to your
.envfile