Protocol Guide is a Node.js/TypeScript monorepo-style app centered on a jurisdiction-aware EMS protocol search product. The core constraint is that protocol search must be scoped to the user's county or agency, not treated as national guidance.
- Read
CLAUDE.mdfirst for project-specific rules and domain constraints. - The most important architectural reference is
docs/EMS_ARCHITECTURE.md. - Prefer existing patterns already used in
app/,server/,hooks/,lib/, anddrizzle/. - Keep files under 500 lines when practical; split by responsibility.
pnpm install
pnpm dev # server :3001 + web :8081
pnpm dev:server # backend only
pnpm dev:metro # Expo web frontend onlypnpm check # TypeScript
pnpm lint # Expo/ESLint
pnpm test # Vitest suite
pnpm test:integration
pnpm test:e2epnpm test tests/integration/user-journey.test.ts
pnpm test:watch
vitest run tests/path/to/file.test.tspnpm build # server bundle
pnpm build:web # Expo web export + PWA/SEO steps
pnpm db:push # drizzle generate + migrateapp/is the Expo Router app.app/(tabs)/index.tsxis the main search experience.components/search/contains the reusable jurisdiction/search UI.hooks/contains app behavior such as auth, search, voice, disclaimer, offline caching, and county restrictions.lib/trpc.tscreates the typed client and keepssuperjsoninsidehttpBatchLink.
server/_core/index.tsis the Express entrypoint.- tRPC setup lives in
server/_core/trpc.ts; use existing procedure types likepublicProcedure,protectedProcedure,csrfProtectedProcedure,rateLimitedProcedure, anduserAwareRateLimitedProcedure. - Router composition is split under
server/routers/; search routes are organized underserver/routers/search/rather than a singlesearch.tsfile. _core/contains shared backend infrastructure: tracing, middleware, auth/session handling, embeddings, RAG orchestration, resilience, and Claude integration.
drizzle/schema.tsis the schema source of truth.- There are two important data domains:
- Drizzle-managed application tables such as
users,agencies,bookmarks,search_history, subscriptions, invitations, and analytics. - Production Supabase protocol corpus tables such as
manus_protocol_chunks,manus_agencies, andcounty_agency_mapping.
- Drizzle-managed application tables such as
county_agency_mappingis the critical bridge from user county selection to the agency-specific protocol corpus.
The central workflow is:
- Normalize EMS query terms and abbreviations.
- Resolve county to agency through
county_agency_mapping. - Generate embeddings and run agency-scoped vector search against
manus_protocol_chunks. - Re-rank results with protocol-aware scoring.
- Generate a retrieval-only Claude response with mandatory protocol citations.
Safety-critical queries like medication dosing, contraindications, emergent conditions, and pediatric medication questions trigger enhanced retrieval behavior.
- Use explicit TypeScript types; avoid
any. - Use Zod for runtime validation in routers.
- Use
TRPCErrorwith clear error codes. - Match existing naming: kebab-case files, PascalCase components/types, camelCase functions, UPPER_SNAKE_CASE constants.
- Do not bypass jurisdiction scoping in search-related work.
- For auth and sensitive mutations, preserve existing CSRF and rate-limit middleware patterns.
- After code changes, run at least the relevant validators from
pnpm check,pnpm lint, and the affected Vitest tests. - Run broader suites before finishing when the change touches shared infrastructure.
- Integration tests rely on database setup described in
tests/integration/README.md.
- This repo contains many docs, but
CLAUDE.md,README.md,docs/EMS_ARCHITECTURE.md,docs/BACKEND.md, anddocs/FRONTEND.mdprovide the fastest accurate orientation. - Some older template-style docs exist; prefer the current project-specific router structure and schema over generic examples.
- If you need search routes, inspect
server/routers/search/index.tsand its sibling modules.