Tech stack
Status: Scaffolded 2026-09-24
Runtimes and frameworks
| Layer | Choice | Version policy | Why |
|---|---|---|---|
| Node | 24 LTS | .nvmrc in every repo | Current LTS on the dev box; The Trick Book's Node 20 line hit a jsonwebtoken crash on 24, which we avoid by not using that library |
| API | Express 5, TypeScript, ESM | Exact pins in package.json, Dependabot weekly | The Trick Book pattern, typed |
| ORM | Mongoose 9 | Schemas with declared indexes, the single biggest debt fix over The Trick Book's schema-less collections | |
| Validation | zod | Route-boundary validation with typed inference | |
| Logging | pino, pino-http | JSON logs with redaction | |
| Realtime | Socket.IO 4 | Namespaces and rooms, same shape as The Trick Book | |
| Web | Next 15 (App Router), React 19, Tailwind 4, shadcn/ui, next-themes | Exact next pin; Amplify supports 12 to 15 | SSR for public pages, SEO for places and events |
| Maps (web) | maplibre-gl | No Google SDK, no key | |
| Mobile | Expo SDK 57, expo-router, React Native, TypeScript | Upgrade one SDK at a time | Current Expo, same navigation model as The Trick Book v2 |
| Maps (mobile) | @maplibre/maplibre-react-native | Needs a dev client; Expo Go will not load it | |
| State (mobile) | zustand (auth only), TanStack Query (server data) | The Trick Book mounted Query and never used it; here it is the only fetch path | |
| Docs | PokeDocs preset on Docusaurus 3.10 | Build-time mermaid, one-config branding, llms.txt and .md twins for agents | |
| Lint and format | Biome 2.5 | Exact pin, schema pinned | One tool, fast, same config in four repos |
| Tests | vitest, supertest, mongodb-memory-server (API); Playwright (web) | ||
| Secrets hygiene | secretlint (pre-commit), gitleaks (CI), GitHub push protection | See ADR-0009 |
Services
| Need | Service | Notes |
|---|---|---|
| Database | MongoDB Atlas M0 | Free tier, 512 MB, allowlisted to the API host's IP (ADR-0008) |
| API hosting | EC2 t4g.micro, Ubuntu 24.04 arm64, PM2, nginx, certbot | ADR-0002 |
| Web hosting | AWS Amplify Hosting (WEB_COMPUTE) | Auto-deploys main |
| Images | S3 (private bucket) + CloudFront | Presigned PUT, public read through the CDN |
| Video | Bunny Stream | TUS upload, HLS playback, signed URLs for non-public posts (ADR-0013) |
| SES SMTP | Magic links and account mail | |
| Push | Expo push service | |
| Map tiles | OpenFreeMap public instance | No key, no cookies, no personal data (ADR-0006) |
| Companion | Anthropic API | Streaming, model from config (ADR-0012) |
| SSO | Sign in with Apple, Google Identity | Email from the verified token only |
| DNS and certs | Route 53, ACM (Amplify), certbot (API) | |
| Mobile builds | EAS Build free tier | 30 builds a month |
| Docs hosting | AWS Amplify Hosting (static) | Same account and region as the web app |
Design tokens
The same values live in the web CSS, the mobile tokens.ts, and this site's custom.css.
| Token | Value | Use |
|---|---|---|
--vg-bg | #0B0F0C | Dark background, near-black with a green cast |
--vg-surface | #121A15 | Cards and panels |
--vg-text | #E6F2EA | Body text on dark |
--vg-muted | #8FA89A | Secondary text |
--vg-primary-dark | #3DFF8A | Neon green, primary in dark mode |
--vg-primary-light | #0E7C3A | Deep green, primary in light mode |
--vg-accent | #FF2BD6 | Magenta, sparingly |
--vg-accent-2 | #22E5FF | Cyan, links and focus rings |
--vg-danger | #FF4D4D | Errors |
Fonts are the system UI stack for body and the system monospace stack for labels, badges, and headings that carry the cyberpunk feel. No third-party font or icon CDN anywhere: fonts are a tracking vector and an availability dependency, and the system stacks look right on every platform.
Deliberately absent
Google Maps SDK, PostHog, Google Analytics, Sentry with PII, Stripe, any LLM router that spreads prompts across providers, Docker Desktop on the dev box, and a monorepo tool. Each absence is a decision, most of them recorded in the ADRs.