Architecture Overview
folksbase is a monorepo — all apps and shared packages live in one repository, managed by pnpm workspaces and Turborepo. This page explains what each piece does and why the tech stack was chosen.Monorepo Structure
Apps
| App | What it does | Deployed to |
|---|---|---|
apps/web | Next.js 15 frontend with App Router and React Server Components. Handles the UI, auth redirects, and server-side rendering. | Vercel |
apps/api | Hono v4 REST API. Handles all business logic, database access, file uploads, and background job orchestration. | Render |
apps/docs | This documentation site, built with Mintlify. Auto-deploys on push to main. | Mintlify |
Packages
Packages are shared code that both apps can import. They live inpackages/ and are referenced by their package names.
| Package | What it does | Package name |
|---|---|---|
packages/db | Drizzle ORM schema definitions and database migrations. Both the API and background jobs use this to talk to Postgres. | @folksbase/db |
packages/emails | React Email templates for transactional emails (import complete, export ready, weekly digest). Sent via Resend. | @folksbase/emails |
packages/types | Shared TypeScript types used by both frontend and backend — contacts, imports, exports, API responses. Single source of truth for data shapes. | @folksbase/types |
Why a monorepo?
A few reasons:- Shared types stay in sync. When you change a type in
@folksbase/types, both the frontend and backend see the change immediately. No version mismatches, no publishing packages. - One PR, one review. A feature that touches the API, the UI, and the types can be reviewed as a single pull request.
- Turborepo caches builds. If you only change
apps/web, Turborepo skips rebuildingapps/apiand all packages. This keeps CI fast.
Why pnpm?
pnpm’s strict dependency resolution prevents phantom dependencies — you can’t accidentally import a package that isn’t in yourpackage.json. It also uses a content-addressable store, so shared dependencies across the monorepo are stored once on disk.
Tech Stack
Here’s what folksbase uses and, more importantly, why.Frontend
| Technology | Why |
|---|---|
| Next.js 15 (App Router) | React Server Components reduce client-side JavaScript. The App Router’s file-based routing and layouts keep the codebase organized. |
| Tailwind CSS | Utility-first CSS that’s fast to write and easy to maintain. No CSS-in-JS runtime overhead. |
| Radix Primitives + Radix Colors | Accessible, unstyled UI primitives (dialogs, dropdowns, selects) with a consistent color system built on oklch. |
| SWR | Lightweight data fetching for client components. Handles caching, revalidation, and optimistic updates with minimal boilerplate. |
| Zod | Runtime validation for API responses, form inputs, and environment variables. Types are derived from schemas via z.infer<>. |
Backend
| Technology | Why |
|---|---|
| Hono v4 | Lightweight, fast, and TypeScript-native. Runs anywhere (Node, Bun, Cloudflare Workers). Perfect for a REST API that doesn’t need the overhead of Express. |
| Drizzle ORM | Type-safe SQL queries without the magic of heavy ORMs. You write queries that look like SQL, and TypeScript catches mistakes at compile time. |
| Neon (Postgres, HTTP driver) | Serverless Postgres with instant branching. The HTTP driver was chosen over WebSocket because the API runs on Render, where persistent WebSocket connections to Neon were unreliable. |
| Upstash Redis | Serverless Redis for caching (stats, contact counts) and rate limiting. Pay-per-request pricing keeps costs near zero for small workloads. |
| Inngest | Background job orchestration with step-level retries. CSV imports and exports run as multi-step jobs — if one step fails, only that step retries. |
Infrastructure
| Technology | Why |
|---|---|
| Vercel Blob | File storage for uploaded CSVs and exported files. Integrates natively with the Vercel ecosystem. |
| Supabase Auth | Authentication with email/password, magic links, and OAuth. Handles JWTs, session management, and user metadata. |
| Resend | Transactional email delivery with React Email templates. Simple API, good deliverability. |
| Anthropic API (Claude Haiku) | AI-powered CSV column mapping. Haiku is fast and cheap — perfect for a feature that needs to respond in under 2 seconds. |
Developer Experience
| Technology | Why |
|---|---|
| Biome | Replaces ESLint + Prettier with a single, faster tool. Handles linting and formatting in one pass. |
| Vitest | Fast unit testing with native TypeScript support. Compatible with the Jest API but significantly faster. |
| Playwright | E2E testing against real browsers. Runs against Vercel preview URLs in CI. |
| Storybook 8 | Component documentation and visual testing. Deployed to Netlify for the team to browse. |
| Turborepo | Monorepo build orchestration with caching. Only rebuilds what changed. |