CTO is a context-aware career copilot that constructs a unified knowledge base from every artifact you share — resumes, LinkedIn, GitHub, market research, recruiter notes, and more. That shared profile lets the product extract the right wins for each job description, tailor outreach, and keep HR conversations cohesive. Under the hood, a Vite/React experience (/web) talks to an Express + TypeScript API (/api) that ingests sources, normalizes context, and orchestrates secure storage.
- Unified knowledge base – Aggregate every document into Supabase-backed context so the AI always “remembers” the candidate.
- Immediate personalization – Use that shared profile to tailor resumes, cover letters, and HR messages for each JD automatically.
- Actionable job workflow – Browse curated roles, apply the unified profile as a lens, and ship tailored assets without leaving the product.
- Extensible architecture – Storage adapters and modular pipelines keep business logic isolated from any single vendor.
| Path | Description |
|---|---|
/api |
Express service, resume parsing pipeline, fit scoring engine, Supabase integration, automated tests. Docs |
/web |
Vite + React front-end, Tailwind UI system, Zustand profile store, React Query networking. |
/resources |
Prompt templates and product collateral. |
/supabase |
Database schema plus SQL migrations grouped under supabase/migrations/. |
docker-compose.yml |
Spins up API + web with sensible defaults for local dev. |
Requirements: Node 20+, pnpm 8+
# Install all workspace dependencies
pnpm install
# Copy env templates
cp .env.example .env
cp api/.env.example api/.env
# Update secrets in both .env files:
# - Root .env: VITE_API_URL, VITE_SUPABASE_URL, VITE_SUPABASE_ANON_KEY
# - api/.env: OPENAI_API_KEY, SUPABASE_URL, SUPABASE_SECRET_KEY, WEB_ORIGIN
# Launch both services
pnpm -w dev # API on :8080, web on :5173pnpm -w dev # Run API + web in watch mode
pnpm -w test # Run Vitest suites for both workspaces
pnpm -w build # Type-checks + builds production bundles
pnpm -w lint # Type-level linting via tsc --noEmit- Root
.env: Build-time variables for the web frontend (VITE_*) api/.env: Runtime variables for the API backend (OpenAI, Supabase, CORS)- See
.env.examplefiles for complete reference
For detailed production deployment instructions, see DEPLOYMENT.md.
# 1. Build Docker images for AMD64 (most cloud servers)
docker build --platform linux/amd64 -t cto-api:latest -f api/Dockerfile .
docker build --platform linux/amd64 -t cto-web:latest -f web/Dockerfile .
# 2. Save and transfer to server
docker save cto-api:latest | gzip > cto-api.tar.gz
docker save cto-web:latest | gzip > cto-web.tar.gz
scp *.tar.gz user@your-server:~/
# 3. On server: load and start
docker load < cto-api.tar.gz
docker load < cto-web.tar.gz
docker compose up -d- Platform compatibility: Always use
--platform linux/amd64for production servers (especially when building on Apple Silicon) - Environment variables: Must be configured on the server (
.envfile) - NOT bundled in images - Reverse proxy: Connect containers to your Caddy/Nginx network
- Production logging: Console logs are automatically stripped from production builds
- Supabase config: Update Site URL and Redirect URLs in Supabase dashboard
See DEPLOYMENT.md for complete setup instructions, reverse proxy configuration, and troubleshooting.
Upload resumes, link profiles, or add HR research into the knowledge base. Files are parsed via pdf-parse, mammoth, and OpenAI-assisted analysis before landing in Supabase with automated summaries and semantic tags.
Extraction helpers convert the unified profile into structured traits and highlights so downstream generators can pull the best proof points for each JD. Shared utilities (scoring modules, profile normalizers, and prompt templates) keep the front end and API aligned on how context is interpreted.
- Self-assessment wizard captures core profile facts.
- Resume upload refreshes the knowledge base and enriches the profile graph.
- Dashboard surfaces top matches alongside calls to action for resume tailoring and HR outreach.
- Knowledge base + applications tracker keep a timeline of what’s been tried.
- Storage adapters (
StorageAdapter,InMemoryStore,FileStore) abstract persistence so DynamoDB/RDS swaps are straightforward. - Supabase SQL lives in
supabase/schema.sqland incremental files undersupabase/migrations/. - Front-end consumes typed API responses via
web/src/api/client.ts, keeping auth and headers in one place.
- Frontend can’t reach API – Confirm
VITE_API_URLinsideweb/.envand restartpnpm dev. - Context extraction disabled –
OPENAI_API_KEYor Supabase creds missing inapi/.env. Restart API after changes. - File upload rejected – Max 3 MB PDF/DOCX, enforced by Multer + MIME guards; errors bubble up to toasts.
- Rate limiting – Resume analysis capped at 10/hour per IP; wait or update the limiter config if running privately.
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
This project is licensed under the MIT License - see the LICENSE file for details.
Happy shipping with your personal Chief Talent Officer. 🚀