- Two apps must both run for WhatsApp/AI features: frontend (
/, Vite+React) and bridge server (whatsapp-bridge/, Express). - Frontend entrypoint:
src/main.jsx→src/App.jsx(wrapped byErrorBoundary,BrowserRouter,AuthProvider). - Bridge entrypoint:
whatsapp-bridge/bridge-server.js. - Frontend is ESM (
"type": "module"); bridge is CommonJS ("type": "commonjs"). Don't mix import styles across the boundary.
- Frontend:
npm run dev,npm run build,npm run preview. - Tests:
npm run test(watch mode),npx vitest run <path-to-test-file>(single run),npm run test:coverage,npm run test:ui. - Typecheck:
npx tsc --noEmit(notypecheckscript). - Bridge: in
whatsapp-bridge/, usenpm start(production) ornpm run dev(watch mode with--watch). - Deploy frontend:
npm run build && firebase deploy --only hosting. - Deploy bridge: Render auto-deploys on
git push(connected Git repo). Userender.yamlat repo root for Blueprint infra-as-code. No CLI needed. - There is no ESLint, Prettier, or CI/CD pipeline in this repo.
- Frontend uses
VITE_BRIDGE_URL(notVITE_WHATSAPP_BRIDGE_URL).SETUP.mdstill references the old name — trust the code, not the docs. - In dev,
whatsappClient.jsintentionally setsBRIDGE_URLto''(empty string) so requests go through the Vite dev proxy. Only in production (whenimport.meta.env.DEVis false andVITE_BRIDGE_URLis unset) does it fall back tohttp://localhost:3001. - Vite dev proxy forwards
/register,/users,/health, and/ws(WebSocket) tohttp://localhost:3001(seevite.config.js). New bridge endpoints need adding there too. VITE_USE_BRIDGE_PROXY=truewith a missing/empty/undefinedVITE_BRIDGE_URLwill throw insrc/api/groqClient.js:240.- Never set
VITE_GROQ_API_KEYin production —VITE_*vars are baked into the client bundle and visible to anyone. Use the bridge proxy (VITE_USE_BRIDGE_PROXY=true) instead. - Auth behavior is environment-driven (
src/lib/envConfig.js): production always requires auth; in dev,VITE_REQUIRE_AUTHcontrols it. - Render auto-sets
PORT; do not setBRIDGE_PORTin production. Locally, bridge defaults to3001.
- Only
/healthand/registerare public endpoints (defined beforeapp.use(bridgeAuthMiddleware)atbridge-server.js:217). - All
/users/:userId/*routes requireX-User-ID+X-API-Keyvia middleware (middleware/bridgeAuth.js), plusvalidateUserParamto prevent cross-user access. - Dev auth bypass requires both:
BRIDGE_REQUIRE_AUTH=falseANDNODE_ENV=development. The middleware explicitly warns ifBRIDGE_REQUIRE_AUTH=falseis set in production (ignores it). - API keys are stored in
whatsapp-bridge/config/api-keys.json(file-based, not in Supabase). This file is gitignored. Keys are generated on first/registercall per user. - Bridge CORS auto-allows
*.ngrok-free.dev,*.ngrok.io,*.railway.app,*.up.railway.app, and*.onrender.comorigins — convenient for testing.
- Global: 120 req/min per user/IP (
whatsapp-bridge/bridge-server.js:113). /register: 10 req per 15 min per IP — can block test suites that register repeatedly./users/:userId/chat(AI): 30 req/min per user.
- Vitest runs in
jsdomwith globals andsrc/setupTests.js. setupTests.jsglobally mockslocalStorage,matchMedia,DOMMatrix,Path2D(needed bypdfjs-dist),scrollIntoView, and silencesconsole.error/console.warn.- Default test timeout is 5000 ms.
- Test files:
src/__tests__/(unit/integration) andsrc/components/Modal/__tests__/(component). Bridge tests inwhatsapp-bridge/__tests__/. - Run a single file:
npx vitest run src/__tests__/dateUtils.test.js.
- Supabase schema in
supabase/schema.sql(no migration tool configured). - RLS is expected on user-scoped tables; app/store code assumes
user_idfiltering when querying Supabase.
- Frontend: built by Vite (
dist/), hosted on Firebase Hosting with SPA rewrite (firebase.json). Immutable cache headers on assets. - Bridge: Docker on Render (
whatsapp-bridge/Dockerfile— node:20-alpine + Chromium for whatsapp-web.js).
- Use
@/*path alias (configured in Vite, Vitest, and TS config). - React files are mostly
.jsx; TS (.ts/.tsx) used selectively with strict options enabled (noUnusedLocals,noUnusedParameters,noImplicitReturns,noUncheckedIndexedAccess). - State management: Zustand stores in
src/store/(useEventStore, useDarkStore, useSettingsStore, useChatStore, useToastStore, useNotificationStore, useWhatsAppSettings). - Bridge
package.jsonsays"main": "index.js"but actual entrypoint isbridge-server.js— thestartscript targets the correct file. - Bridge uses Express v4 (
whatsapp-bridge/package.json), not v5.