Privacy-first "missed connections" mobile app. Users post a Glimpse about someone they noticed at a real-world venue; the post becomes visible to others who were in the same coarse area, with a delay, and only proceeds to chat after mutual confirmation.
This repository is a pnpm TypeScript monorepo containing the mobile app, the API server, shared libraries, and the OpenAPI contract that ties them together.
| Layer | Tech |
|---|---|
| Mobile client | Expo SDK 54 / React Native 0.81 / Expo Router 6 |
| Auth | Clerk (@clerk/expo on client, @clerk/express on server) |
| API | Express 5, esbuild bundle, pino logging |
| Database | PostgreSQL via Drizzle ORM |
| API contract | OpenAPI 3.1 (lib/api-spec), Orval-generated React Query + Zod |
| Object storage | Replit App Storage (GCS-compatible) for profile photos |
| Location data | Google Places API (server-proxied) + OSM/Nominatim fallback |
| Package manager | pnpm workspaces |
artifacts/
api-server/ Express 5 API. Build: esbuild → dist/index.mjs
glimpse/ Expo / React Native client. Built via EAS for stores.
mockup-sandbox/ Internal-only Vite preview tool (NOT shipped, NOT deployed)
lib/
api-spec/ OpenAPI 3.1 spec + orval codegen entry point
api-client-react/ Generated React Query hooks (consumed broadly by glimpse client)
api-zod/ Generated Zod schemas (currently consumed only by health.ts; routes mostly use handwritten Zod — adopting these is a planned cleanup)
db/ Drizzle schema + drizzle-kit push entry point
location-validation/ Shared presence-gate constants & helpers
scripts/ Maintenance scripts (post-merge install, etc.)
.local/ Replit-only tooling and skills (gitignored)
Architecture: the mobile client never talks to the database directly. All access goes through the API, which validates Clerk identity, runs Zod-validated handlers, and uses Drizzle for persistence. The OpenAPI spec is the source of truth for the client hooks; server validators are generated alongside them in @workspace/api-zod but the routes today mostly use handwritten Zod (planned cleanup).
Prerequisites: Node 20+, pnpm 9+, PostgreSQL 14+, an Expo account for mobile builds.
# 1. install
pnpm install
# 2. copy env files (see .env.example in root + per-artifact)
cp .env.example .env
cp artifacts/api-server/.env.example artifacts/api-server/.env
cp artifacts/glimpse/.env.example artifacts/glimpse/.env
# fill in real values — see ENV section below
# 3. push schema to your local Postgres
pnpm --filter @workspace/db run push
# 4. start services (in separate terminals)
PORT=8080 pnpm --filter @workspace/api-server run dev # PORT is required — src/index.ts throws if unset
pnpm --filter @workspace/glimpse run devIn the Replit workspace, services start via the artifacts/api-server: API Server and artifacts/glimpse: expo workflows — you do not run pnpm dev at the root.
| Command | Purpose |
|---|---|
pnpm install |
Install all workspace deps |
pnpm run typecheck |
Full repo typecheck (libs + leaf packages) |
pnpm run typecheck:libs |
Build composite libs only |
pnpm run build |
typecheck + build every package |
pnpm --filter @workspace/api-spec run codegen |
Regenerate React Query hooks + Zod schemas |
pnpm --filter @workspace/db run push |
Push Drizzle schema to DATABASE_URL |
PORT=8080 pnpm --filter @workspace/api-server run dev |
Build + start API on $PORT (NOT a watch loop — re-run after changes) |
pnpm --filter @workspace/api-server run build |
esbuild → dist/index.mjs |
pnpm --filter @workspace/glimpse run dev |
Start Expo dev server |
pnpm --filter @workspace/scripts run seed |
Insert dev/staging seed data (NEVER prod) |
There is no test runner wired in yet — the QA loop today is typecheck + manual device testing. See AUDIT_CHECKLIST.md for the manual flows.
A consolidated .env.example at the repo root lists every variable across both services with comments. Per-artifact .env.example files exist under artifacts/api-server/ and artifacts/glimpse/.
Never put real secrets in any committed file. In the Replit workspace, secrets live in the project secrets store. In production deployments they live in Replit deployment secrets (server) and EAS secrets (mobile). See RUNBOOK.md § "Secrets" for the full mapping.
- API server: Replit deployment. Production build runs
drizzle-kit pushagainst the deployment'sDATABASE_URLbefore bundling, thennode dist/index.mjs. Health check at/api/healthz. Configured inartifacts/api-server/.replit-artifact/artifact.toml. - Mobile client: Expo / EAS Build → TestFlight (iOS) and Play Internal Testing (Android). Not deployed by Replit. See
RUNBOOK.md§ "Mobile release" for the full EAS flow.
HANDOFF.md— what's built, what's open, where the bodies are buriedARCHITECTURE.md— system diagram, auth model, data model, location/matching designAUDIT_CHECKLIST.md— section-by-section review checklistRUNBOOK.md— deploy, rotate secrets, debug productionreplit.md— historical design decisions and TestFlight readiness notesthreat_model.md— assets, trust boundaries, threat categories