The application is used to make tailored resumes for users. Users provide their current resume (PDF/DOCX/LaTeX), job description, job title, output resume template, and optional personalization prompt. The system processes all inputs and outputs a tailored resume for the specific job.
Note: Keep updating README.md and Project.md(tick and update) files before every step while making code changes.
- Frontend: React + Next.js + Tailwind CSS
- Backend: Next.js API Route Handlers
- Auth: Supabase Auth (Google OAuth2)
- Database: Supabase Postgres
- File Processing: mammoth (DOCX), pdfjs-dist (PDF)
- LLM: OpenAI API
- Storage: AWS S3
- Hosting: Vercel
A landing page with a brief description of the application and a "Get Started" button that navigates to Step 1. The page should be visually appealing and interactive.
- User uploads their current resume (PDF, DOCX, or LaTeX)
- User provides the Job Description (JD) of the target job
- File Processing:
- DOCX files: Use
mammothto extract all text data - PDF files: Use
pdfjs-distto extract all text data - LaTeX files: Read file content directly
- DOCX files: Use
- Store extracted content in application state
- User inputs the Job Role Name
- User selects a resume template:
- For PDF/DOCX files: 3 options (Modern, Classic, Old-school)
- For LaTeX files: 4 options (Modern, Classic, Old-school, Your Format)
- Templates displayed as selectable cards/tiles with:
- Preview image
- Template name
- Single selection only
- Optional text input for user suggestions
- Example: "Add a project I did with React, Next.js, and AWS"
- Authentication Required:
- Input is disabled by default
- Enabled only when user logs in via Google OAuth2
- Guest users can skip this step
- Requires Supabase setup for Google OAuth2
- Database needed to store user data
- LLM Processing:
- Combine all user inputs into a system prompt:
- Resume content (extracted text)
- Job description
- Job title
- Template selection
- Personalization prompt (if provided)
- Send to OpenAI API
- Receive LaTeX code for tailored resume
- Combine all user inputs into a system prompt:
- AWS S3 Storage:
- Store generated LaTeX file in S3 bucket (
latex-snips-001/snips/) - Generate Overleaf link
- Redirect user to Overleaf for further editing
- Store generated LaTeX file in S3 bucket (
- Verify Next.js 16.1.1 setup
- Install core dependencies:
mammoth(for DOCX extraction)pdfjs-dist(for PDF extraction)@supabase/supabase-js(for auth & database)openai(for LLM integration)
- Configure TypeScript paths and aliases
- Set up environment variables structure
- Define color palette and theme
- Create reusable UI components (Button, Input, Card, etc.)
- Set up Tailwind configuration
- Create layout components
- Create
ResumeFormContextwith React Context API - Define TypeScript interfaces for form data
-
Implement form state persistence (localStorage for guest users)- Not needed, state resets on refresh - Add form validation utilities (placeholders ready for implementation)
- Set up Next.js routing:
/- Landing page/resume-builder- Main multi-step form
- Implement route protection (if needed) - Deferred to Phase 5
- Design hero section with value proposition
- Create "Get Started" CTA button
- Add interactive elements (animations, hover effects)
- Make it responsive (mobile, tablet, desktop)
- Test navigation to resume builder
- Create drag-and-drop file upload area
- Add file type validation (PDF, DOCX, .tex)
- Add file size validation (10MB limit)
- Show file preview/confirmation
- Handle file removal
- Install and configure
mammoth(already installed) - Create utility function:
extractDocxText()inutils/text-extraction.ts - Implement DOCX text extraction (client-side)
- Handle extraction errors
- Integrate with file upload handler
- Store extracted text in form context
- Install and configure
pdfjs-dist(already installed) - Create utility function:
extractPdfText()inutils/text-extraction.ts - Implement PDF text extraction (client-side, handle multi-page)
- Handle extraction errors
- Integrate with file upload handler
- Store extracted text in form context
- Create utility function:
readLatexFile()inutils/text-extraction.ts - Read file content directly (client-side using FileReader)
- Integrate with file upload handler
- Store LaTeX content in form context
- Create textarea for job description
- Validate minimum length (required field)
- Store in form context
- Combine file upload + job description in Step 1 component
- Add validation (both required)
- Add "Next" button (disabled until valid)
- Test all file types
- Create
StepIndicatorcomponent with progress visualization - Implement step navigation logic (next/back)
- Add step validation before allowing progression
- Create smooth transitions between steps
- Create input field for job role/title
- Add autocomplete suggestions (optional enhancement)
- Store in form context
- Design template card components:
- Modern template card
- Classic template card
- Old-school template card
- "Your Format" card (only for LaTeX files)
- Add template preview images/placeholders
- Implement single-selection logic
- Add visual feedback (selected state)
- Show 3 templates for PDF/DOCX files
- Show 4 templates (including "Your Format") for LaTeX files
- Implement conditional rendering logic
- Combine job role + template selection
- Add validation (both required)
- Add "Back" and "Next" buttons
- Test template selection flow
- Create Supabase project
- Get Supabase URL and anon key
- Add Supabase credentials to
.env.local - Install Supabase client library
- Install
@supabase/ssrfor Next.js App Router support
- Create Google OAuth 2.0 credentials
- Configure OAuth in Supabase dashboard
- Set up redirect URLs
- Implement PKCE flow for secure OAuth
- Test OAuth flow
- 📖 See OAuth-signin.md for detailed implementation documentation
- Design database tables:
resumestable with all input/output fields (id, user_id, resume_file_type, resume_file_name, resume_extracted_text, job_description, job_role, template, personalization_prompt, s3_url, created_at, updated_at)- user_id: UUID with foreign key to auth.users(id), NULL for guest users
- Create migrations in Supabase using Supabase CLI
- Set up Row Level Security (RLS) policies (3 policies: SELECT, INSERT for users, INSERT for guests)
- Create indexes for performance (user_id, created_at)
- Create trigger function and trigger for auto-updating updated_at
- 📖 See supabase/README.md for migration setup instructions
- Create Supabase client utility (client-side and server-side)
- Set up client-side auth hooks
- Create auth context/provider
- Implement login/logout functions
- Integrate auth state management in navbar
- Create textarea for personalization prompt
- Add placeholder text with examples
- Add helpful description text explaining the field's purpose
- Check authentication status
- Disable input for guest users
- Enable input for authenticated users
- Show login prompt for guests (prominent banner + overlay)
- Implement sessionStorage persistence for form state during OAuth redirect
- Restore form state after authentication (preserves step and all inputs)
- Combine personalization input with auth logic
- Store prompt in form context (empty string for guests)
- Add "Back" and "Next" buttons
- Test both authenticated and guest flows (manual testing required)
- Design LLM system prompt structure:
- Include resume content
- Include job description
- Include job role
- Include template selection
- Include personalization prompt (if provided)
- Include LaTeX formatting instructions
- Create prompt template function (
lib/server/prompt-builder.ts) - Accept
ResumeFormDataas input parameter - Implement conditional logic for "your-format" template rules
- Dynamic job role insertion throughout prompt
- Include LaTeX template example for format reference
- Test prompt with sample data (manual testing required)
- Install OpenAI SDK
- Create API route:
/api/generate-resume - Implement OpenAI API call:
- Use GPT-4 or GPT-3.5-turbo
- Set appropriate temperature
- Handle streaming (optional) or wait for complete response
- Add error handling
- Validate LaTeX output format
- Verify existing S3 upload route works
- Update route to handle generated LaTeX from LLM
- Ensure proper file naming (
snips/resume-{uuid}.tex) - Test S3 upload with generated content
- Generate Overleaf form with S3 URL
- Create success page/component
- Display Overleaf link button
- Test Overleaf integration
- Create loading state during LLM processing
- Show progress indicator
- Handle errors gracefully
- Display success state with Overleaf link
- Add "Back" button (optional)
- Save resume generation to Supabase
- Link to user account (if authenticated)
- Store generation metadata
- Create history page (future enhancement)
- Add error boundaries
- Handle API errors gracefully
- Show user-friendly error messages
- Add retry mechanisms where appropriate
- Add loading spinners for all async operations
- Show progress for file uploads
- Show progress for LLM processing
- Disable buttons during processing
- Validate all inputs at each step
- Show validation errors clearly
- Prevent progression with invalid data
- Add client-side validation
- Test on mobile devices
- Test on tablets
- Test on desktop
- Fix any layout issues
- Add ARIA labels
- Ensure keyboard navigation
- Test with screen readers
- Ensure color contrast
- Optimize file uploads
- Add code splitting
- Optimize images
- Add loading states
- Update README with project description
- Add setup instructions
- Add environment variables documentation
- Add deployment instructions
- Add JSDoc comments to functions
- Document API routes
- Document component props
- Add inline comments for complex logic
- Configure Vercel project
- Set up environment variables in Vercel
- Configure build settings
- Deploy to production
- Test production deployment
- Test all flows in production
- Monitor error logs
- Set up analytics (optional)
- Create user documentation
# AWS
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
# Supabase
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY=
# OpenAI
OPENAI_API_KEY=
# S3 (already configured)
# Bucket: latex-snips-001
# Region: us-east-1- Phase 0 → Foundation & Setup
- Phase 1 → Multi-Step Form Infrastructure
- Phase 2 → Landing Page
- Phase 3 → Step 1 (Resume Upload & JD)
- Phase 4 → Step 2 (Job Role & Templates)
- Phase 5 → Auth Setup (can be done in parallel with Phase 6)
- Phase 6 → Step 3 (Personalization)
- Phase 7 → Step 4 (LLM + S3)
- Phase 8 → Polish & Testing
- Phase 9 → Documentation & Deployment
- Test each phase before moving to the next
- Update README after each major phase
- Keep environment variables secure (never commit
.env.local) - Consider adding unit tests for critical functions
- Consider adding E2E tests for the full flow
- Authentication Documentation: See OAuth-signin.md for comprehensive Google OAuth implementation details, setup instructions, and troubleshooting guide
Completed:
- Verified Next.js 16.1.1 setup
- Installed all core dependencies:
mammoth(v1.11.0) for DOCX extractionpdfjs-dist(v5.4.530) for PDF extraction@supabase/supabase-js(v2.89.0) for auth & database@supabase/ssrfor Next.js App Router cookie-based authopenai(v6.15.0) for LLM integrationuuid(v13.0.0) for unique identifiers
- TypeScript paths and aliases configured (
@/*mapping) - Environment variables structure documented
Completed:
- Implemented comprehensive dark/light theme system using
next-themes - Created CSS variable system with semantic color names (background, foreground, accent, error, success, navbar colors)
- Built reusable UI components:
Buttoncomponent with primary, secondary, and outline variantsAccordioncomponent for FAQ sectionsNavbarwith theme toggle integrationLogoStrip,ProcessSection,FAQSection,FooterCTAcomponents
- Refactored all styling to use CSS variables (no hardcoded colors)
- Created utility classes for status colors (text-error, bg-success, etc.)
- Standardized hover patterns and transitions
- Added comprehensive styling guidelines to
.cursorrules - All components are theme-aware and work seamlessly in dark/light modes
Completed:
- Created TypeScript interfaces in
types/resume-form.ts:ResumeFileType,ResumeTemplatetypesResumeFileData,ResumeFormData,ValidationResultinterfacesResumeFormContextValueinterface for context API
- Created validation utilities in
utils/validation.ts:validateStep1()- placeholder for resume file & job description validationvalidateStep2()- placeholder for job role & template validation (includes LaTeX template logic)validateStep3()- placeholder for optional personalization prompt validation
- Created
ResumeFormContextincontext/resume-form-context.tsx:- Full React Context implementation with state management
- Update functions for all form fields (resume file, job description, job role, template, personalization prompt)
nextStep()function with validation before advancingprevStep()function for backward navigationuseResumeForm()custom hook with error handling- Supports authentication state for Step 3 logic
- Integrated
ResumeFormProviderinapp/resume-builder/page.tsx - Note: No localStorage persistence (state resets on refresh as per requirements)
Completed:
- Next.js App Router routes set up:
/- Landing page (app/page.tsx) ✅/resume-builder- Main multi-step form (app/resume-builder/page.tsx) ✅/auth/callback- OAuth callback route ✅/auth/auth-code-error- OAuth error page ✅
- Navigation between routes working correctly
- Route protection deferred (authentication is now implemented in Phase 5)
Completed:
- Hero section with value proposition ("The truly Limitless resume builder")
- "Get Started" CTA button linking to
/resume-builder - Process section explaining the 3-step workflow
- FAQ section with accordion component
- Footer CTA section with contact information
- Logo strip component showing company logos
- Fully responsive design (mobile, tablet, desktop)
- All interactive elements styled with theme-aware colors
- Smooth hover effects and transitions
Completed:
- Installed
@supabase/supabase-js(v2.89.0) and@supabase/ssrfor Next.js App Router support - Created Supabase client utilities:
utils/supabase/client.ts- Client-side Supabase client usingcreateBrowserClientutils/supabase/server.ts- Server-side Supabase client usingcreateServerClientwith cookie management
- Environment variables structure documented:
NEXT_PUBLIC_SUPABASE_URL- Supabase project URLNEXT_PUBLIC_SUPABASE_ANON_KEY- Supabase anonymous key
- Note: Manual setup required: Create Supabase project and add credentials to
.env.local
Completed:
- Implemented Google OAuth with PKCE (Proof Key for Code Exchange) flow for enhanced security
- Created OAuth callback route (
app/auth/callback/route.ts):- Handles authorization code exchange for session
- Saves session to HTTP-only cookies
- Redirects user back to original page after authentication
- Created error page (
app/auth/auth-code-error/page.tsx) for OAuth failures - 📖 Detailed documentation: See OAuth-signin.md for:
- Complete implementation details
- Setup instructions for Google Cloud Console
- Code explanations and architecture
- Troubleshooting guide
- Reference links to Supabase and Next.js documentation
Completed:
- Designed and created
resumestable schema with:- Input fields: resume_file_type, resume_file_name, resume_extracted_text, job_description, job_role, template, personalization_prompt
- Output field: s3_url (populated after LLM processing)
- Metadata: id (UUID primary key), user_id (UUID foreign key to auth.users, nullable for guests), created_at, updated_at
- User association:
- Authenticated users:
user_id = auth.uid()(UUID from auth.users) - Guest users:
user_id = NULL - Foreign key constraint:
REFERENCES auth.users(id) ON DELETE CASCADE
- Authenticated users:
- Created migration file using Supabase CLI:
supabase/migrations/20260105202050_create_resumes_table.sql- Includes table creation, indexes, trigger function, trigger, and RLS policies
- Set up Row Level Security (RLS) with 3 policies:
- "Users can view own resumes": SELECT policy for authenticated users to view their resume history
- "Users can insert own resumes": INSERT policy for authenticated users
- "Allow guest inserts": INSERT policy for guest users (user_id = NULL)
- Created performance indexes:
idx_resumes_user_idonresumes(user_id)idx_resumes_created_atonresumes(created_at DESC)
- Created trigger function and trigger:
update_updated_at_column()functionupdate_resumes_updated_attrigger (BEFORE UPDATE) for auto-updating updated_at
- Created
supabase/README.mdwith:- Supabase CLI setup instructions
- Migration workflow documentation
- Database schema documentation
- Verification checklist
Key Implementation Details:
- Foreign Key Constraint: Ensures data integrity with auth.users table
- Cascade Delete: Automatically deletes user's resumes when user is deleted
- Type Safety: UUID type for user_id (more efficient than TEXT)
- Guest Support: NULL user_id for guest users, allowing them to use the app without authentication
- Read-Only Operations: Only INSERT and SELECT operations (no UPDATE or DELETE needed)
Manual Steps Required:
- Link Supabase project:
npx supabase link --project-ref <project-ref> - Apply migration:
npx supabase db push - Verify in Supabase Dashboard (table, policies, indexes, triggers)
- 📖 See supabase/README.md for detailed setup instructions
Completed:
- Created client-side Supabase client utility (
utils/supabase/client.ts) - Created server-side Supabase client utility (
utils/supabase/server.ts) - Created authentication context (
context/auth-context.tsx):- Manages user session state with React Context API
- Provides
signIn()function that triggers Google OAuth flow - Provides
signOut()function for user logout - Real-time auth state synchronization via
onAuthStateChangelistener - Exports
useAuth()hook for consuming components
- Created auth provider wrapper (
components/providers/auth-provider.tsx) - Integrated
AuthProviderin root layout (app/layout.tsx) - Updated navbar (
components/layout/navbar.tsx):- Shows "Sign In" button when user is not authenticated
- Shows user email/name and "Sign Out" button when authenticated
- Handles loading states gracefully
- Triggers OAuth flow directly from navbar button
Key Implementation Details:
- PKCE Flow: Uses secure code exchange flow recommended for Next.js App Router
- Cookie-Based Sessions: Sessions stored in HTTP-only cookies for security
- Server-Side Rendering Safe: Compatible with Next.js App Router SSR
- Type-Safe: Full TypeScript support with proper type definitions
- Real-Time Updates: Auth state automatically syncs across the application
Manual Configuration Required:
- Create Supabase project and get URL/anon key
- Configure Google OAuth in Supabase Dashboard (Authentication → Providers → Google)
- Set up Google Cloud Console OAuth credentials
- Add authorized redirect URIs in Google Console
- See OAuth-signin.md for detailed setup instructions
- Uses
next-themesfor SSR-safe theme management - All colors defined as CSS variables for maintainability
- Automatic theme switching with smooth 500ms transitions
- System preference detection supported
- Context-based state management for multi-step form
- Type-safe with full TypeScript coverage
- Validation utilities ready for implementation when building steps
- Simple navigation: only forward/backward one step at a time
- No hardcoded colors (all use CSS variables)
- Consistent naming conventions (kebab-case files, PascalCase components)
- Proper TypeScript types throughout
- Error handling for context hook usage
- DRY principles followed (shared utilities, reusable components)
- Real-time error clearing for better UX
- Component-level and step-level validation separation
Completed:
- Created
FileUploadcomponent (components/file-upload.tsx) with:- Drag-and-drop file upload zone with visual feedback
- Click-to-browse file input
- File type validation (PDF, DOCX, .tex) - case-insensitive
- File size validation (10MB limit)
- File preview showing name, size, and type icon
- Remove button to clear selected file
- Error display with red border styling
- Component-level validation (immediate feedback)
- Theme-aware styling using CSS variables
- Created shared file utilities (
utils/file-utils.ts):getFileExtension(),getFileTypeFromExtension(),getFileTypeFromFilename()formatFileSize(),getFileTypeIcon()- Constants:
ACCEPTED_EXTENSIONS,MAX_FILE_SIZE
- Error handling: Component-level errors take precedence over step-level errors
Completed:
- Created textarea for job description in Step 1
- Integrated with
ResumeFormContext - Real-time error clearing when text becomes valid
- Error border styling when validation fails
- Error message display below textarea
Completed:
- Combined file upload + job description in Step 1 component
- Implemented
validateStep1()inutils/validation.ts:- Validates resume file is provided
- Validates job description is non-empty (after trim)
- Returns appropriate error messages
- Step validation runs on "Next" button click
- Real-time error clearing when fields become valid
- Error UI with red borders and error messages
Completed:
- Created
StepIndicatorcomponent (components/step-indicator.tsx):- Visual progress indicator showing current, completed, and pending steps
- Theme-aware styling
- Reusable component
- Created
StepNavigationcomponent (components/step-navigation.tsx):- Back/Next buttons with proper disabled states
- Customizable labels (e.g., "Complete" for last step)
- Reusable across all steps
- Implemented step navigation logic in context:
nextStep()validates current step before advancingprevStep()allows backward navigation without validation- Step validation prevents progression with invalid data
- Smooth transitions between steps
- Error UI System:
- Added
border-errorutility class to CSS - Red borders on form elements when errors exist
- Error messages displayed below fields
- Added
- Real-time Validation:
- Errors clear immediately when fields become valid
- Component-level validation for immediate feedback
- Step-level validation on "Next" click
- Code Quality:
- Extracted duplicate error clearing logic to helper function
- Fixed error precedence (component-level errors take priority)
- Follows DRY principles
- Clean, maintainable code structure
Completed:
- Created
extractDocxText()function inutils/text-extraction.ts - Uses
mammothlibrary for DOCX text extraction - Client-side processing (no API routes needed)
- Error handling with user-friendly error messages
- Integrated with file upload handler in
app/resume-builder/page.tsx - Extracted text stored in
ResumeFileData.extractedTextfield
Completed:
- Created
extractPdfText()function inutils/text-extraction.ts - Uses
pdfjs-distlibrary with dynamic import (to avoid SSR issues) - PDF.js worker setup: Worker file copied to
public/pdf.worker.min.mjs - Multi-page PDF support (iterates through all pages)
- Client-side processing (no API routes needed)
- Error handling with user-friendly error messages
- Integrated with file upload handler
- Extracted text stored in
ResumeFileData.extractedTextfield
Completed:
- Created
readLatexFile()function inutils/text-extraction.ts - Uses browser's native
FileReader.readAsText()API - No external library needed (LaTeX files are plain text)
- Promise-based implementation for async/await compatibility
- UTF-8 encoding for proper text reading
- Error handling with user-friendly error messages
- Integrated with file upload handler
- LaTeX content stored in
ResumeFileData.extractedTextfield
1. Client-Side vs Server-Side Processing
- All text extraction (DOCX, PDF, LaTeX) is performed client-side using browser APIs
- No API routes needed - reduces server load and improves user experience
- Files are processed directly in the browser after upload
2. PDF.js Worker Setup for Next.js App Router
pdfjs-distrequires a worker file for PDF processing- Worker file must be accessible from the browser (placed in
public/folder) - Dynamic import (
await import('pdfjs-dist')) is essential to avoid SSR errors - Browser-only libraries like
pdfjs-distcannot be imported at module level in Next.js - Error: "DOMMatrix is not defined" occurs when browser-only code runs during SSR
3. Dynamic Imports for Browser-Only Libraries
- Libraries that use browser APIs (like
pdfjs-dist) must be dynamically imported - Top-level imports cause SSR errors because Node.js doesn't have browser APIs
- Solution: Use
await import('pdfjs-dist')inside the function that uses it - This ensures the library only loads on the client side when actually needed
4. FileReader API for Plain Text Files
- LaTeX files are plain text, so no library is needed
FileReader.readAsText()is a browser-native API- Wrapped in Promise for async/await compatibility
- UTF-8 encoding ensures proper character handling
5. Error Handling Patterns
- Consistent error handling across all extraction functions
- User-friendly error messages displayed via FileUpload component
- Errors don't prevent file metadata from being stored (user can see error and retry)
- Extraction errors are separate from file validation errors
6. Multi-Page PDF Handling
- PDFs can have multiple pages
- Extract text from each page using a loop
- Concatenate page texts with double newlines (
\n\n) for separation - All pages processed sequentially to maintain order
7. File Processing Flow
- File upload → File validation (type, size) → Text extraction → Store in context
- Extraction happens asynchronously after file selection
- User sees loading state during extraction
- Errors are displayed inline without blocking the UI