Architecture overview
Before writing any code, read the how it works page. It explains how the three services fit together and how data flows through the system.Repository overview
Nous is open-source and the code is at github.com/NousC/nous. It’s a pnpm monorepo with three apps:| App | What it is |
|---|---|
apps/api | Express API — all REST routes, OAuth, enrichment |
apps/worker | Background worker — pollers (Gmail, Calendar, SMTP, Slack) + inbound webhook handlers |
apps/frontend | React + Vite SPA |
packages/core — shared DB helpers, contact resolution, and type definitions used by both api and worker.
The main scripts are:
API
Express.js with ESM throughout. Routes live inapps/api/src/routes/ split into:
/api/*— internal app routes (Supabase JWT auth)/v1/*— REST API routes (API key auth)/inbound/*— unauthenticated webhook receivers (routed via Caddy to the worker)
Worker
Node.js service that runs pollers on a schedule (Gmail every 30min, Calendar every 10min, SMTP every 15min, Slack hourly) and handles inbound webhooks from Instantly, Fireflies, Fathom, Calendly, and LinkedIn/Unipile.Frontend
React + Vite + TailwindCSS + shadcn/ui. No Next.js — pure SPA served by nginx in production.Database
Supabase (Postgres). Schema is insupabase/schema.sql. No ORM — raw Supabase client queries.
Development setup
Configure environment
SUPABASE_URL+SUPABASE_SERVICE_ROLE_KEY— from your Supabase project → Settings → APIVITE_SUPABASE_URL+VITE_SUPABASE_ANON_KEY— same project, anon keyANTHROPIC_API_KEY— for AI featuresENCRYPTION_KEY— random 32-byte hex string (openssl rand -hex 32)
Before submitting a PR
- Under 3 lines — submit directly.
- Over 3 lines — open an issue or discuss in Discord first. This avoids wasted effort if the approach doesn’t fit the direction.
PR process
- Fork the repo and create a feature branch from
main - Make your changes
- Run
pnpm typecheckandpnpm lint— fix any errors - Submit a PR with a clear description of what and why
- Link any related issues
Code conventions
- ESM throughout — no CommonJS
require() - Named exports only — no default exports
- No hardcoded secrets or API keys
- No AI-generated PRs
Commit style
feat · fix · docs · refactor · test · chore
Get help
Discord
Fastest way to get help — chat, screenshots, screen sharing.
GitHub Issues
For bug reports and feature requests.