Architecture
Learn about the technical architecture of JSON Resume, including system design, technology stack, and deployment infrastructure.
System Overview
JSON Resume is built as a modern monorepo with multiple applications and shared packages.
┌─────────────────────────────────────────────────────────────┐
│ JSON Resume Platform │
└─────────────────────────────────────────────────────────────┘
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Registry │ │ Homepage │ │ Docs │
│ (Main App)│ │ (Marketing) │ │ (Nextra) │
└─────────────┘ └──────────────┘ └─────────────┘
│ │ │
└────────────────────┴────────────────────┘
│
┌────────────────────┴────────────────────┐
│ Shared Packages │
├─────────────────────────────────────────┤
│ @repo/ui - UI components │
│ @repo/eslint-config - Linting │
│ @repo/typescript-config - TS config │
│ jsonresume-theme-* - Resume themes │
└─────────────────────────────────────────┘Technology Stack
Frontend
- Framework: Next.js 14 (App Router)
- UI Library: React 18
- Styling: Tailwind CSS
- Components: shadcn/ui (@repo/ui)
- State Management: React Context + Hooks
- Forms: React Hook Form + Zod
- Icons: Lucide React
Backend
- Runtime: Node.js 20
- API: Next.js API Routes
- Authentication: NextAuth.js (GitHub OAuth)
- Database: Supabase (PostgreSQL)
- Vector Store: Pinecone
- AI/ML: OpenAI API (GPT-5-mini, ada-002)
Infrastructure
- Hosting: Vercel
- Database: Supabase (PostgreSQL)
- Vector Search: Pinecone
- CI/CD: GitHub Actions
- Monitoring: Vercel Analytics
- Logging: Pino (structured JSON logs)
Build Tools
- Monorepo: Turborepo
- Package Manager: pnpm
- Linting: ESLint
- Formatting: Prettier
- Type Checking: TypeScript 5
- Testing: Vitest + Playwright
Application Structure
Registry App (apps/registry)
The main application handling resumes, themes, and job matching.
apps/registry/
├── app/ # Next.js App Router
│ ├── [username]/ # Public resume pages
│ │ ├── page.js # Resume viewer
│ │ ├── timeline/ # Timeline visualization
│ │ └── jobs/ # Job matches
│ ├── api/ # API routes
│ │ ├── auth/ # Authentication
│ │ ├── resume/ # Resume operations
│ │ └── jobs/ # Job search
│ ├── jobs/ # Job board
│ └── settings/ # User settings
├── lib/ # Shared utilities
│ ├── auth.js # Auth config
│ ├── supabase.js # DB client
│ ├── logger.js # Pino logger
│ └── retry.js # Retry logic
├── scripts/ # Background jobs
│ └── jobs/ # Job processing
│ ├── getLatestWhoIsHiring.js
│ ├── gpted.js
│ └── vectorize.js
└── public/ # Static assetsDocumentation (apps/docs)
Nextra-based documentation site (this site!).
apps/docs/
├── pages/ # MDX documentation
│ ├── index.mdx # Homepage
│ ├── getting-started.mdx
│ ├── jobs.mdx
│ ├── api.mdx
│ └── architecture.mdx
├── theme.config.tsx # Nextra theme config
└── next.config.js # Next.js configData Flow
Resume Rendering Pipeline
1. User Request
https://jsonresume.org/johndoe
│
2. GitHub Gist Fetch
├─> Fetch gist.github.com/johndoe/resume.json
└─> Cache in server memory
│
3. Theme Selection
├─> User preference or query param
└─> Load theme package (jsonresume-theme-*)
│
4. Server-Side Rendering
├─> Pass resume JSON to theme
├─> Generate HTML
└─> Return to browser
│
5. Client Hydration
└─> React hydrates interactive featuresJob Matching Pipeline
1. Resume Upload
User uploads resume.json
│
2. Skill Extraction
├─> Parse resume structure
├─> Extract skills, experience, preferences
└─> Generate embedding vector (OpenAI ada-002)
│
3. Vector Search
├─> Query Pinecone with resume vector
├─> Get top K similar job vectors
└─> Return job UUIDs with scores
│
4. Job Enrichment
├─> Fetch full job details from Supabase
├─> Apply additional filters (location, remote, etc.)
└─> Sort by relevance score
│
5. Results Display
└─> Render matched jobs with compatibility %Database Schema
Jobs Table (Supabase PostgreSQL)
CREATE TABLE jobs (
uuid UUID PRIMARY KEY DEFAULT gen_random_uuid(),
hn_id TEXT UNIQUE NOT NULL,
content TEXT NOT NULL,
gpt_content JSONB,
posted_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX idx_jobs_posted_at ON jobs(posted_at DESC);
CREATE INDEX idx_jobs_gpt_content ON jobs USING GIN(gpt_content);Vector Index (Pinecone)
Dimension: 1536 (OpenAI ada-002)
Metric: Cosine similarity
Metadata: { uuid, company, title, skills[] }Deployment
Vercel Configuration
{
"buildCommand": "pnpm turbo build --filter=registry",
"devCommand": "pnpm dev",
"framework": "nextjs",
"installCommand": "pnpm install"
}Environment Variables
Required secrets in production:
# Authentication
AUTH_SECRET=xxx
AUTH_GITHUB_ID=xxx
AUTH_GITHUB_SECRET=xxx
# Database
SUPABASE_KEY=xxx
DATABASE_URL=xxx
# AI/ML
OPENAI_API_KEY=xxx
PINECONE_API_KEY=xxx
PINECONE_ENVIRONMENT=xxx
# Monitoring
DISCORD_WEBHOOK_URL=xxx # For failure notificationsPerformance Optimizations
Caching Strategy
- Resume Gist: Server-side memory cache (5 min TTL)
- Theme Rendering: CDN edge caching (Vercel)
- Job Search: Pinecone vector cache
- Static Pages: ISR (Incremental Static Regeneration)
Code Splitting
- Lazy load job board components
- Dynamic imports for themes
- Route-based code splitting (Next.js automatic)
Image Optimization
- next/image for automatic WebP conversion
- Responsive image sizing
- Lazy loading below the fold
Security
Authentication Flow
1. User clicks "Sign in with GitHub"
│
2. NextAuth.js redirects to GitHub OAuth
│
3. GitHub authorization
│
4. Callback to /api/auth/callback/github
│
5. Create/update session
│
6. Store JWT in HTTP-only cookie
│
7. Redirect to dashboardAPI Security
- Rate limiting (60/hour anonymous, 5000/hour authenticated)
- CORS configuration
- Input validation (Zod schemas)
- SQL injection prevention (parameterized queries)
- XSS protection (React escaping + CSP headers)
Monitoring & Observability
Structured Logging
import { logger } from '@/lib/logger';
logger.info({ userId, action: 'resume_generated' }, 'Resume generated');
logger.error({ error: err.message, stack: err.stack }, 'Job processing failed');Metrics
- Vercel Analytics (page views, performance)
- GitHub Actions (workflow success/failure rates)
- OpenAI usage tracking (token consumption)
- Pinecone query metrics (latency, throughput)
Alerting
- Discord webhook for critical failures
- GitHub Issues auto-created for repeated failures
- Email notifications for security events
Scalability Considerations
Current Scale
- ~500-1000 jobs processed/month
- ~10-50 resumes generated/day
- ~100-500 API requests/day
Future Scaling
- Database: Supabase can scale to millions of rows
- Vector Search: Pinecone supports billions of vectors
- API: Horizontal scaling via Vercel serverless functions
- Background Jobs: Move to queue-based system (Bull, BullMQ)
Contributing
Want to contribute to the architecture? See the Contributing Guide.
Next Steps
- Getting Started - Use the platform
- Job Board - Understand job matching
- API Reference - Build on top of JSON Resume