MAV Resume is a role-based resume platform built for students and reviewers.
It combines a structured resume builder, AI bullet refinement, live PDF output, and an end-to-end review workflow with inline PDF annotations.
MAV Resume supports two connected workflows:
- Student workflow: create resumes from templates, edit sections, refine bullets with AI, preview/export PDF, and submit for review.
- Reviewer workflow: claim pending submissions, annotate PDFs inline, leave summary feedback, and complete reviews.
- Guided section editing with dynamic section management (add, remove, reorder)
- Personal Info locked as the top section
- Major-specific templates and custom template creation
- Section alias normalization for stable ordering (for example, tools -> technical-skills)
- Live PDF preview tied directly to builder state
- PDF settings support through centralized store
- Single bullet refinement endpoint
- Batch bullet refinement endpoint (up to 20 bullets per request)
- Context-aware refinement (title, technologies, optional target role context)
- Sanitization and prompt-injection checks
- Cache-backed refinement responses (when Upstash Redis is configured)
- Rate limiting for uncached refinement requests
- Student review submission flow from dashboard
- Reviewer queue with pending and active review states
- Claim/complete lifecycle for reviewers
- Inline text/area annotations on resume PDFs
- Final reviewer summary feedback attached to completed review
- Role-based access controls on review pages
- Supabase authentication (email/password and Google OAuth)
- Middleware-based protected routing
- Role handling for student, reviewer, and admin
- /: marketing and product entry page
- /login: auth page (sign in/up and Google OAuth)
- /auth/callback: OAuth callback
- /faqs: searchable FAQ page
- /features: feature overview page
- /dashboard: student dashboard, resume list, and review submission entry
- /builder: resume editing workspace
- /templates: template library and custom template entry
- /review/[id]: review detail page (student/read-only or reviewer/edit mode depending on status/role)
- /reviewer/dashboard: reviewer queue and active reviews
Refines one bullet point.
Request body:
{
"bulletText": "Built a web app",
"context": {
"title": "Project Lead",
"technologies": ["Next.js", "TypeScript"]
}
}Success response:
{
"refinedText": "Led development of a Next.js TypeScript web app, improving usability and delivery speed through structured component architecture.",
"rateLimit": {
"limit": 20,
"remaining": 19,
"reset": 1743312000000
}
}Refines multiple bullets in one request (maximum 20 bullets).
Request body:
{
"bullets": [
{
"text": "Built dashboard",
"context": {
"title": "Frontend Developer",
"technologies": ["React", "Tailwind"]
}
}
]
}Success response:
{
"results": [
{
"refinedText": "Developed a React/Tailwind dashboard that improved task visibility and reduced manual reporting overhead.",
"fromCache": false
}
],
"rateLimit": {
"limit": 20,
"remaining": 19,
"reset": 1743312000000
}
}Returns remaining refinement quota for the authenticated user.
Success response:
{
"limit": 20,
"remaining": 15,
"reset": 1743312000000
}- Framework: Next.js 15, React 18, TypeScript 5
- Styling/UI: Tailwind CSS 4, DaisyUI 5, Radix UI, shadcn/ui
- State: Zustand
- PDF: @react-pdf/renderer
- Auth: Supabase
- AI: OpenAI (gpt-4o-mini)
- Caching/Rate Limit: Upstash Redis + @upstash/ratelimit
- Motion/UI: framer-motion, lucide-react
app/
api/
rate-limit/
refine-bullet/
refine-bullets-batch/
auth/callback/
builder/
dashboard/
faqs/
features/
login/
review/[id]/
reviewer/dashboard/
templates/
components/
sections/ # Builder form sections
previews/ # Resume preview renderers
review/ # PDF viewer and annotation UI
elements/ # Reusable feature-specific UI
ui/ # Primitive UI components
lib/
actions/ # Server actions for reviews/annotations
auth/ # Auth and role helpers
resume/ # Resume section/PDF/runtime registries
supabase/ # Supabase clients and middleware helpers
bulletRefinement.ts # Client-side refinement calls
refine-cache.ts # Cache key + Redis cache helpers
ratelimit.ts # Refinement quota logic
store/
useResumeStore.tsx
useSessionStore.tsx
useGuideStore.ts
useRateLimitStore.ts
data/
resume-templates.tsx
university-data.tsx
faqs.ts
docs/
ai-refinement.md
pdf-generation.md
state-management.md
Create .env.local in the project root.
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_API_KEY=your_supabase_anon_key
OPENAI_API_KEY=your_openai_api_keyUPSTASH_REDIS_REST_URL=your_upstash_redis_url
UPSTASH_REDIS_REST_TOKEN=your_upstash_redis_token
REFINE_RATELIMIT_REQUESTS=20
REFINE_RATELIMIT_WINDOW="30 m"
REFINE_CACHE_TTL_SECONDS=604800Notes:
- Upstash Redis is required for refinement endpoints in the current implementation because rate limiting fails closed when Redis is unavailable.
- OPENAI_API_KEY is required for bullet refinement endpoints.
- Node.js 18.18+
- npm
- Supabase project
- OpenAI API key
npm install
npm run devApp runs at http://localhost:3000.
npm run lint
npm run typecheck
npm run build
npm start- npm run dev: start local dev server
- npm run build: production build
- npm run start: run production server
- npm run lint: run ESLint
- npm run typecheck: run TypeScript checks
Use these docs for deeper implementation details:
- docs/ai-refinement.md
- docs/state-management.md
- docs/pdf-generation.md
When contributing:
- Keep route behavior and role guards consistent with middleware protections.
- Validate builder + preview + PDF output after section or store changes.
- Validate reviewer flow (pending -> accepted -> completed) after review-related changes.
- Run lint and typecheck before opening a PR.
Maintained by ACM at The University of Texas at Arlington for student use.