Monorepo with a Fastify API server and a React Native (Expo) mobile app.
- Node.js (v20+)
- pnpm (v10+) —
npm i -g pnpm - Docker Desktop
pnpm installServer — copy the example and generate a secret:
cp apps/server/.env.example apps/server/.envOpen apps/server/.env and replace BETTER_AUTH_SECRET with a random string (min 32 chars):
# generates and prints a secret you can paste
openssl rand -base64 32The rest of the defaults work out of the box with the Docker setup below.
Native app — copy the example and set your LAN IP:
cp apps/native/.env.example apps/native/.envOpen apps/native/.env and replace 192.168.x.x with your machine's local IP:
# macOS
ipconfig getifaddr en0
# Linux
hostname -I | awk '{print $1}'pnpm db:startThis runs Postgres 17 and Redis 7 via Docker Compose.
pnpm db:pushpnpm dev:serverThe API starts at http://localhost:3000.
In a separate terminal:
pnpm dev:nativeScan the QR code with Expo Go on your phone (make sure your phone is on the same Wi-Fi network).
| Command | Description |
|---|---|
pnpm dev |
Start everything (server + native) |
pnpm dev:server |
Start the API server |
pnpm dev:worker |
Start the background worker |
pnpm dev:native |
Start the Expo dev server |
pnpm db:start |
Start Postgres & Redis containers |
pnpm db:stop |
Stop containers (keeps data) |
pnpm db:down |
Stop containers and remove volumes |
pnpm db:push |
Push schema changes to the database |
pnpm db:studio |
Open Drizzle Studio (DB GUI) |
pnpm db:seed |
Seed the database |
pnpm build |
Build all packages |
pnpm check-types |
Type-check all packages |
apps/
server/ Fastify API (Bun runtime)
native/ React Native app (Expo)
packages/
auth/ Authentication (Better Auth)
db/ Database schema & migrations (Drizzle + Postgres)
env/ Environment variable validation (t3-env)
shared/ Shared types and contracts
config/ Shared TypeScript config