Your career story, authentically presented.
Resumate helps you curate and present your human-written professional experiences for different audiences. You write your career history once; AI helps you select and organize what's most relevant for each opportunity.
You create the content. AI selects what's relevant.
This framework follows Anthropic's AI guidance principles:
✅ All experiences: Human-written by you ✅ All selection: Heuristic-based, or AI-assisted curation ✅ All content: Authentic and real ❌ Never fabricates career history or achievements
Resumate is not an AI resume generator. It's a curation system that helps you present your authentic professional story effectively. You write your bullets once, with all the detail and context. When you need a resume for a specific role, AI helps you select which experiences are most relevant - never generating or fabricating content.
Compliant with Anthropic's candidate AI guidance.
- Experience Data Explorer - Beautiful, filterable view of all your career history
- Smart Search - Filter experiences by text across all fields
- Tag-Based Filtering - Multi-select tags with OR logic (shows items with any selected tag)
- Company Timeline - Hierarchical structure: Company → Position → Achievements
- Priority System - Manually rank importance of each bullet (1-10)
- Metrics Highlighting - Emphasize quantifiable achievements
- Protected Contact Info - Email and phone never exposed to client-side code
- Cloudflare Turnstile - CAPTCHA protection for vCard downloads
- Server-Side vCard Generation - Contact details only used in API routes
- Bot Detection - Middleware blocks scrapers while allowing legitimate search engines
- Rate Limiting - IP-based throttling (30 req/min, 100 req/min for Googlebot)
- Security Headers - CSP, X-Frame-Options, X-Content-Type-Options
- Auto-Download - vCard download triggers automatically after verification (works in Chrome & Arc)
- Fallback Button - Manual download option if auto-download fails
- Mobile-First - Responsive design with Tailwind CSS
- Accessible - ARIA labels, keyboard navigation, semantic HTML
Prerequisites: just (brew install just), bun, Rust
git clone https://github.com/yourusername/resumate.git
cd resumate
just install # bun, cargo, wasm-pack, wasm32 target
vercel link # pulls .env.local from Vercel
just data-pull # fetch resume data from gist
just wasm # build WASM (first time ~2min)
just dev # http://localhost:3000git clone https://github.com/yourusername/resumate.git
cd resumate
just install
# Create resume data from template
cp data/resume-data-template.json data/resume-data.json
# Configure environment (see "Environment Variables" below)
# Then:
just wasm
just devAvailable Commands: Run just to see 40+ automation targets.
Routes:
/- Landing page with contact links/resume- Resume overview/resume/view- Full data explorer (search, filter, explore all experiences)
Create .env.local with:
# Contact info (server-side only, never exposed to client)
CONTACT_EMAIL_PERSONAL=your-email@personal.com
CONTACT_EMAIL_PROFESSIONAL=your-email@work.com
CONTACT_PHONE=+1234567890
# Cloudflare Turnstile (see setup below)
NEXT_PUBLIC_TURNSTILE_SITE_KEY=0x4...
TURNSTILE_SECRET_KEY=0x4...
# Resume data source (GitHub Gist raw URL)
RESUME_DATA_GIST_URL=https://gist.githubusercontent.com/[user]/[hash]/raw/resume-data.json
# Optional: PostHog analytics
NEXT_PUBLIC_POSTHOG_KEY=phc_...
POSTHOG_API_KEY=phc_...Tip: If deploying to Vercel, run vercel link to pull all env vars automatically.
Free, privacy-friendly CAPTCHA that protects your contact information from bots.
-
Create Account
- Go to https://dash.cloudflare.com/turnstile
- Sign in or create free account
-
Add Widget
- Click "Add Site"
- Domain:
localhost(development) or your production domain - Widget Mode: Managed
- Widget Type: Invisible (best UX)
-
Copy Keys
- Site Key: Starts with
0x4AAAA...(public, safe to expose) - Secret Key: Private, add to
.env.localonly
- Site Key: Starts with
-
Add to Environment
NEXT_PUBLIC_TURNSTILE_SITE_KEY=your-site-key TURNSTILE_SECRET_KEY=your-secret-key
Cloudflare provides test keys that always pass:
NEXT_PUBLIC_TURNSTILE_SITE_KEY=1x00000000000000000000AA
TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AAResumate uses a hierarchical JSON structure:
{
"personal": {
"name": "Your Name",
"fullName": "Your Full Name",
"location": "City, Country",
"linkedin": "username",
"github": "username",
"website": "yourdomain.com"
},
"companies": [
{
"name": "Company Name",
"positions": [
{
"role": "Your Role",
"description": "What you did (human-written)",
"bullets": [
{
"text": "Achievement or responsibility (human-written)",
"tags": ["developer-relations", "team-leadership"],
"priority": 9,
"metrics": "20% increase",
"link": "https://..."
}
]
}
]
}
]
}See data/TEMPLATE_GUIDE.md for complete documentation.
This project uses CodeRabbit for AI-powered code reviews.
Installation:
bun install -g @coderabbit/cli
coderabbit authUsage:
# Review uncommitted changes with context from CLAUDE.md
coderabbit review --plain --type uncommitted --config CLAUDE.md
# Review all files
coderabbit review --plain --type all
# Review specific commit
coderabbit review --plain --type committedWhen to run:
- ✅ Before committing (catch issues early)
- ✅ After major refactors (verify quality)
- ✅ When stuck (get AI suggestions)
- ✅ Regular check-ins (maintain code health)
Claude Code and Warp editors should run this extensively when making changes.
-
Install Vercel CLI
npm i -g vercel vercel login
-
Link Project
vercel link
-
Set Environment Variables
Use
printfto avoid newline issues. Set scopes based on where each var is needed:# Contact info (ALL ENVIRONMENTS - needed for vCard downloads) printf "%s" "your@email.com" | vercel env add CONTACT_EMAIL_PROFESSIONAL production preview development printf "%s" "personal@email.com" | vercel env add CONTACT_EMAIL_PERSONAL production preview development printf "%s" "+1234567890" | vercel env add CONTACT_PHONE production preview development # Turnstile - TEST KEYS for preview/dev (always pass, work on any domain) printf "%s" "1x00000000000000000000AA" | vercel env add NEXT_PUBLIC_TURNSTILE_SITE_KEY preview development printf "%s" "1x0000000000000000000000000000000AA" | vercel env add TURNSTILE_SECRET_KEY preview development # Turnstile - PRODUCTION KEYS (domain-restricted, from Cloudflare dashboard) printf "%s" "0x4AAA..." | vercel env add NEXT_PUBLIC_TURNSTILE_SITE_KEY production printf "%s" "0x4AAA..." | vercel env add TURNSTILE_SECRET_KEY production # Gist URL (ALL ENVIRONMENTS - for build-time data fetch) printf "%s" "https://gist.githubusercontent.com/..." | vercel env add RESUME_DATA_GIST_URL production preview development # Analytics (ALL ENVIRONMENTS - optional) printf "%s" "phc_..." | vercel env add NEXT_PUBLIC_POSTHOG_KEY production preview development printf "%s" "https://eu.i.posthog.com" | vercel env add NEXT_PUBLIC_POSTHOG_HOST production preview development printf "%s" "phc_..." | vercel env add POSTHOG_API_KEY production preview development
Note: See
.env.examplefor complete list with Vercel scope recommendations -
Deploy
vercel --prod
Set up automatic deploys when your gist is updated:
-
Create Vercel Deploy Hook
- Vercel Dashboard → Project Settings → Git → Deploy Hooks
- Create hook for
mainbranch
-
Create Vercel API Token
- https://vercel.com/account/tokens
- Scope: your project
-
Get Project ID
vercel project inspect resumate | grep "ID"
-
Set GitHub Secrets
# Project ID printf "%s" "prj_..." | gh secret set VERCEL_PROJECT_ID -R your-username/resumate # API Token printf "%s" "your_token" | gh secret set VERCEL_TOKEN -R your-username/resumate # Deploy Hook URL printf "%s" "https://api.vercel.com/v1/integrations/..." | gh secret set VERCEL_DEPLOY_HOOK_URL -R your-username/resumate
The GitHub Action (.github/workflows/gist-deploy-trigger.yml) will:
- Run hourly via cron
- Check if gist was updated since last Vercel deployment
- Validate JSON format
- Trigger deploy if changes detected
- ✅ Environment variables set in Vercel (no newlines!)
- ✅
.env.localis gitignored - ✅ No secrets in repository
- ✅ Build succeeds:
just build - ✅ Turnstile working on production
- ✅ GitHub Action secrets configured
Your resume data (data/resume-data.json) is gitignored for privacy. To edit from anywhere (phone, tablet, any browser), use a private GitHub Gist as your remote data source.
-
Create Secret Gist
- Go to https://gist.github.com
- Filename:
resume-data-[yourname].json - Paste your
data/resume-data.json - Select "Create secret gist"
-
Get Raw URL
- Click "Raw" button
- Copy URL:
https://gist.githubusercontent.com/[user]/[hash]/raw/resume-data-[yourname].json
-
Add to .env.local
RESUME_DATA_GIST_URL=https://gist.githubusercontent.com/[user]/[hash]/raw/resume-data-[yourname].json
just data-pull # Pull latest from gist to local
just data-push # Push local changes to gist
just data-view # View gist content in terminalEdit from anywhere: Visit https://gist.github.com/[your-username], find your gist, click "Edit". Changes sync automatically.
Build-time fetch: Vercel automatically pulls from gist during builds (via prebuild hook).
Auto-deploy: GitHub Action checks gist hourly and triggers Vercel deploy when changes detected.
resumate/
├── app/ # Next.js 16 app (pages, API routes)
├── components/ # React components (data + ui)
├── crates/ # Rust workspace (types, core, typst, wasm)
│ ├── shared-types/ # Type definitions (source of truth)
│ ├── resume-core/ # Scoring + bullet selection
│ ├── resume-typst/ # PDF generation via Typst
│ └── resume-wasm/ # WASM bindings for browser
├── typst/ # Fonts + templates for PDF generation
├── lib/ # TypeScript utilities
├── scripts/ # Gist sync + type generation
├── data/ # Resume data (gitignored)
├── docs/ # Architecture docs
├── .github/workflows/ # CI/CD (hourly gist auto-deploy)
└── justfile # Build automation (40+ commands)
See .claude/CLAUDE.md for detailed structure.
This project uses a hierarchical documentation system designed to prevent drift and maintain single sources of truth.
- .claude/CLAUDE.md - Project router and entry point for AI agents
- docs/CURRENT_PHASE.md - Current development phase and status
- docs/METRICS.md - Auto-generated test counts and coverage
- docs/TESTING_STRATEGY.md - TDD philosophy and patterns
- docs/ARCHITECTURE.md - System design and WASM pipeline
- docs/DEPLOYMENT_GUIDE.md - Deployment instructions
- docs/META_DOCUMENTATION.md - How the documentation system works
- Linear project - Active tasks, issues, and milestones
- Single Source of Truth - Every fact has exactly one canonical location
- Temporal Separation - Files organized by update frequency (never, quarterly, per phase, daily, per commit)
- Auto-Generated Facts - Test counts and coverage generated from actual test runs
- Manual Observations - Strategic decisions and philosophy documented manually
- Automated Verification - Pre-commit hooks ensure documentation consistency
just docs-health # Generate metrics + verify documentation
just docs-verify # Check documentation consistency
just metrics-generate # Update METRICS.md from test logsFor details: See docs/META_DOCUMENTATION.md
- Framework: Next.js 16 (Turbopack, bleeding edge)
- Language: TypeScript 5
- Styling: Tailwind CSS v4
- Security: Cloudflare Turnstile
- Icons: Lucide React
- Deployment: Vercel
- ✍️ Write every bullet point yourself
- 📝 Add context, metrics, links
- 🏷️ Tag each experience with categories
- ⭐ Prioritize manually (1-10)
- 🔍 Helps you find relevant experiences for a role
- 📊 Suggests which bullets are most applicable
- 🎯 Organizes content by relevance
- ✨ Refines presentation (never content)
- ❌ Generate bullet points
- ❌ Fabricate achievements
- ❌ Create experiences you haven't had
- ❌ Replace your authentic voice
This distinction is crucial for compliance with Anthropic's guidance and maintaining authenticity in professional representation.
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Run CodeRabbit review before committing
- Submit a pull request
See CLAUDE.md for development guidelines.
MIT License - see LICENSE file for details.
Built with Claude Code following best practices for AI-assisted development.
Philosophy: Human creativity, AI enhancement. Never the other way around.
For questions or issues:
- 📖 Check
data/TEMPLATE_GUIDE.mdfor data structure help - 🔒 See
SECURITY.mdfor security details - 💻 See
CLAUDE.mdfor development notes - 🐛 Open an issue on GitHub
Remember: This is YOUR resume, YOUR career story, YOUR authentic experiences. Resumate just helps you present them effectively.