Files
Resume-Matcher/docs/frontend-workflow.md
srbhr a9152c34ab feat: Implement dynamic resume sections with custom section support
- Added SectionMeta and CustomSection interfaces to manage dynamic sections in resumes.
- Created DynamicResumeSection component to render custom sections based on metadata.
- Updated ResumeData interface to include sectionMeta and customSections.
- Refactored ResumeSingleColumn and ResumeTwoColumn components to utilize dynamic sections.
- Introduced utility functions in section-helpers.ts for managing section metadata and visibility.
- Enhanced frontend documentation to reflect changes in resume data structure and section management.
2025-12-29 23:56:21 +05:30

17 KiB
Raw Blame History

Frontend Workflow Documentation

This document outlines the user flow and architecture for the Resume Matcher frontend. The application follows a "Master Resume" centric workflow, allowing users to maintain a base resume and tailor it for specific job descriptions.

Core Workflow

1. Dashboard & Initialization (/dashboard)

The entry point of the application.

  • State: Reads localStorage for master_resume_id, then reconciles with GET /api/v1/resumes/list?include_master=true to recover if local storage is stale.
  • No Master Resume: Displays an "Initialize Master Resume" card.
    • Triggers ResumeUploadDialog.
    • On success: Saves resume_id to localStorage and updates UI.
  • Master Resume Exists: Displays a "Master Resume" card.
    • Action: Clicking the card navigates to the Resume Viewer (/resumes/[id]).
  • Create Tailored Resume: A "+" card opens /tailor (enabled only when the master resume is ready) with label text "Create Resume".
  • Tailored Resume Tiles: Fetched from GET /api/v1/resumes/list and rendered as grey cards that open /resumes/[id].
  • Filtering: Excludes master resume by both is_master flag AND master_resume_id (handles sync issues).
  • Auto-Refresh: Dashboard refreshes resume list and master status when window gains focus (handles deletions from viewer).
  • Layout: Dashboard grid targets 5 columns at large breakpoints, with filler tiles using neutral greys to balance the canvas.
  • Navigation: Settings access lives in the footer as a Swiss-style orange button.

2. Resume Viewer (/resumes/[id])

A read-only hub for a specific resume (either the Master or a Tailored version).

  • Data Fetching: Fetches resume details from the backend using the id from the URL.
  • Processing Status: Shows loading, processing, or failed states with appropriate messaging.
  • Display: Uses the Resume component to render the document at 250mm width with Swiss-style shadow (shadow-[8px_8px_0px_0px_#000000]).
  • Navigation: Back to Dashboard button in header.
  • Actions:
    • Edit Resume: Navigates to /builder?id=[id].
    • Download Resume: Requests GET /api/v1/resumes/{id}/pdf for a headless-Chromium PDF.
    • Delete Resume: Full delete workflow with confirmation dialogs (see Delete Flow below).

3. Tailoring Process (/tailor)

The core AI feature where a Master Resume is optimized for a specific job.

  • Input: Large text area for the Job Description (JD).
  • Validation: Enforces a minimum character count (e.g., 50 chars) to ensure valid input.
  • Process:
    1. Upload JD: Sends JD to /api/v1/jobs/upload.
    2. Improve: Calls /api/v1/resumes/improve with master_resume_id and job_id.
  • Output:
    • Redirects to the Resume Viewer (/resumes/[new_id]) for the newly created resume.
    • The new resume is saved in the backend and can be edited further.

4. Resume Builder (/builder)

The editor interface for modifying resume content with WYSIWYG paginated preview.

  • Navigation: Back to Dashboard button in header with Swiss styling.
  • Modes:
    • Create/Preview Mode: If accessed via the tailored flow (data passed via ResumePreviewContext).
    • Edit Mode: If accessed via URL query param (?id=xyz). Fetches data from the backend.
  • Template & Formatting Controls (collapsible panel in Editor Panel):
    • Template Selection: Visual thumbnail buttons for switching templates.
      • swiss-single: Traditional single-column layout (default)
      • swiss-two-column: Two-column layout with experience sidebar
    • Page Size: Toggle between A4 (210×297mm) and US Letter (8.5×11in).
    • Margins: Sliders for top/bottom/left/right (5-25mm range).
    • Spacing: Button groups for section spacing, item spacing, line height (1-5 levels).
    • Font Size: Button groups for base font size and header scale (1-5 levels).
    • All settings apply in real-time to the live preview via CSS custom properties.
    • Settings persist to localStorage under resume_builder_settings.
  • Components:
    • Left Panel: ResumeForm for editing fields (Personal Info, Experience, etc.). Scrollable with fixed height.
      • Header: Blue square indicator (bg-blue-700) + "EDITOR PANEL" label
      • Contains: FormattingControls panel (template, page size, formatting) + ResumeForm sections
    • Right Panel: WYSIWYG Paginated Preview (PaginatedPreview component).
      • Header: Green square indicator (bg-green-700) + "LIVE PREVIEW" label
      • See Paginated Preview System section below for details.
  • Data Recovery:
    • Auto-saves drafts to localStorage under key resume_builder_draft.
    • Auto-saves template settings to localStorage under key resume_builder_settings.
    • Warns user before leaving page with unsaved changes.
    • Priority loading: API (if ID) → Context (tailor flow) → localStorage → defaults.
  • Actions:
    • Save: PATCHes the resume to the backend when an id is present.
    • Reset: Reverts to the last saved state.
    • Download: Requests GET /api/v1/resumes/{id}/pdf with all template settings (including page size) as query params.
  • Footer: Shows current template type and page size.

Paginated Preview System

The right panel uses a true WYSIWYG preview that shows exactly what the PDF will look like.

Preview Controls (toolbar at top of preview):

  • Zoom: +/- buttons (40% to 150%), shows current zoom percentage
  • Margins Toggle: Eye icon to show/hide dashed margin guides (hidden by default)
  • Page Count: Shows total number of pages (e.g., "2 pages")

Page Display:

  • Each page rendered at exact dimensions (A4: 210×297mm, US Letter: 215.9×279.4mm)
  • Pages scaled to fit preview area with auto-zoom
  • Swiss-style shadow on each page (shadow-[6px_6px_0px_0px_#000000])
  • Page number indicator: "Page X of Y" (bottom-right of each page)
  • Visual "Page Break" separator between pages

Pagination Rules:

  • Sections (Experience, Projects, etc.) CAN span multiple pages - this is normal
  • Individual items (single job entry, single project) stay together on one page
  • Pages must be at least 50% full before moving an item to the next page
  • Section titles won't be orphaned at the bottom of a page

Architecture:

components/preview/
├── page-container.tsx      # Single page with margin guides
├── paginated-preview.tsx   # Main component with controls
├── use-pagination.ts       # Page break calculation hook
└── index.ts

lib/constants/
└── page-dimensions.ts      # A4/Letter dimensions, mm↔px utilities

5. Settings (/settings)

System configuration and status monitoring page.

System Status Panel

Displays cached health and statistics (see Status Caching below):

  • LLM Status: Shows HEALTHY (green) or OFFLINE (red) based on provider connectivity.
  • Database Status: Shows CONNECTED when backend is reachable.
  • Resumes Count: Total number of resumes stored in the database.
  • Jobs Count: Total number of job descriptions stored.
  • Improvements Count: Total number of tailored resumes generated.
  • Master Resume: Shows CONFIGURED or NOT SET status.
  • Last Fetched: Shows when status was last refreshed (e.g., "Just now", "5m ago").
  • Refresh Button: Manually refresh system status from backend.

Status Caching

The Settings page uses cached status data to avoid expensive LLM health check API calls:

  • No API call on page load: Uses useStatusCache() hook for cached data.
  • Initial load: Status fetched once when app starts (via StatusCacheProvider).
  • Auto-refresh: Background refresh every 30 minutes.
  • Manual refresh: User can click "Refresh" to fetch fresh data.
  • Last fetched indicator: Shows relative time since last refresh.

LLM Configuration

Configure the AI provider for resume tailoring:

  • Provider Selection: Choose from 6 providers:
    • OpenAI (default: gpt-4o-mini)
    • Anthropic (default: claude-3-5-sonnet-20241022)
    • OpenRouter (default: anthropic/claude-3.5-sonnet)
    • Google Gemini (default: gemini-1.5-flash)
    • DeepSeek (default: deepseek-chat)
    • Ollama (default: llama3.2, local models)
  • Model Input: Customize the model name for the selected provider.
  • API Key: Enter API key (not required for Ollama).
  • Ollama Server URL: Configure local Ollama endpoint (shown only for Ollama provider).

Actions

  • Save Configuration: Validates config with backend before saving, then refreshes cached status.
  • Test Connection: Makes a test LLM call and displays success/failure result.

Displays overall system readiness with Swiss-style visual indicators:

  • Ready State: Green square indicator (bg-green-700) + green text "STATUS: READY"
  • Setup Required: Amber square indicator (bg-amber-500) + amber text "STATUS: SETUP REQUIRED"
  • Checking State: Spinner + "CHECKING..." during refresh
  • Offline State: "STATUS: OFFLINE" if no cached status available
  • Visual Pattern: w-3 h-3 square + matching colored text with font-bold emphasis

6. Delete Flow

The complete workflow for deleting a resume (Master or Tailored).

From Resume Viewer

  1. Trigger: User clicks "Delete Resume" button (red, bottom-right of viewer).
  2. Confirmation Dialog: Swiss-style danger variant dialog appears.
    • Title: "Delete Master Resume" or "Delete Resume" based on type.
    • Description: Warns that action cannot be undone.
    • Actions: "Keep Resume" (cancel) or "Delete Resume" (confirm with trash icon).
  3. API Call: DELETE /api/v1/resumes/{resume_id} via deleteResume() function.
  4. localStorage Cleanup: If deleting master resume, removes master_resume_id from localStorage.
  5. Success Dialog: Swiss-style success variant dialog confirms deletion.
    • Title: "Resume Deleted"
    • Single action: "Return to Dashboard"
  6. Navigation: Redirects to /dashboard.
  7. Dashboard Refresh: List auto-refreshes on window focus.

From Dashboard (Master Only)

  1. Trigger: Delete action from dashboard confirmation dialog.
  2. API Call: Same as above.
  3. State Update: Clears master state and refreshes tailored resume list.

Error Handling

  • If deletion fails, shows error dialog with "OK" button.
  • Error message displayed in Swiss-style danger variant.

ConfirmDialog Variants

The ConfirmDialog component (components/ui/confirm-dialog.tsx) supports:

  • danger: Red styling, trash icon (for delete confirmations)
  • warning: Orange styling, alert icon
  • success: Green styling, checkmark icon (for success confirmations)
  • default: Blue styling, alert icon
  • showCancelButton: Optional prop to hide cancel button (for info/success dialogs)

Key Components

  • ResumePreviewProvider: React Context for passing transient state (like AI generation results) between routes.
  • ResumeUploadDialog: Handles file upload to the backend with progress states.
  • Resume: Shared component for rendering the resume layout. Used in Viewer, Builder (Preview), and Dashboard (thumbnail).
    • Width: Fills parent container (parent sets max-w-[250mm])
    • Padding: p-10 md:p-16 for comfortable spacing
    • Typography: Serif headers, mono metadata, sans body text
    • No internal shadow (parent provides Swiss-style shadow)
  • ResumeForm: Dynamic form editor that renders sections based on sectionMeta order.
    • Supports section renaming, reordering (up/down), hiding, and deletion
    • Custom sections can be added via AddSectionDialog
    • Uses specialized forms for default sections, generic forms for custom sections
  • PaginatedPreview: WYSIWYG preview component that shows exact page layout with pagination.
    • Renders pages at actual dimensions (A4 or US Letter)
    • Auto-calculates page breaks based on content
    • Zoom controls (40%-150%) and margin guide toggle
    • Shows page count and page break indicators
  • PageContainer: Single page wrapper with margin guides and page number.
    • Renders at exact page dimensions, scaled for preview
    • Optional dashed margin guides (toggleable)
    • Clips content to prevent overlap between pages
  • usePagination: Custom hook for calculating page breaks.
    • Measures content height using hidden container
    • Respects .resume-item boundaries (won't split individual entries)
    • Uses ResizeObserver + MutationObserver for real-time updates
    • 150ms debounce for performance

Section Management

The Builder supports full customization of resume sections:

Section Operations

Action Description
Rename Click pencil icon to edit display name
Reorder Up/down arrow buttons to change section order
Hide/Show Eye icon to toggle visibility (all sections except Personal Info)
Delete Trash icon - hides default sections, deletes custom sections
Add Custom "Add Section" button opens dialog to create new sections

Hidden Section Behavior

  • Hidden sections remain editable in the form (form uses getAllSections)
  • Hidden sections appear with:
    • Dashed border and 60% opacity
    • "Hidden from PDF" badge (amber colored)
  • Only the PDF/preview hides them (templates use getSortedSections)

Section Types for Custom Sections

Type Form Component Use Case
Text GenericTextForm Single text block (objective, statement)
Item List GenericItemForm Structured entries (publications, research)
String List GenericListForm Simple list (hobbies, interests)

Key Components

Component Purpose
section-header.tsx Section controls (visibility, rename, reorder, delete)
add-section-dialog.tsx Modal to create custom sections
resume-form.tsx Dynamic form rendering with all sections
forms/generic-*.tsx Generic forms for custom section types

Data Flow

  1. getAllSections(resumeData) returns ALL sections (including hidden) for form editing
  2. ResumeForm renders each section wrapped in SectionHeader
  3. Changes update sectionMeta and customSections in resume data
  4. Templates use getSortedSections() which filters to visible-only for PDF/preview

State Management

  • Local Storage: Persists the master_resume_id to maintain the user's setup across sessions.
  • URL Params: Used to identify specific resumes for viewing (/resumes/[id]) or editing (/builder?id=...).
  • Context API: Used for passing immediate results from the AI tailoring process to the Builder/Viewer.
  • Status Cache: Global cache for system status with optimistic counter updates (see below).

Status Cache Context (lib/context/status-cache.tsx)

The StatusCacheProvider wraps the app and provides cached system status:

const {
  status,              // SystemStatus | null
  isLoading,           // boolean
  lastFetched,         // Date | null
  refreshStatus,       // Manual refresh
  incrementResumes,    // Optimistic counter update
  decrementResumes,
  incrementJobs,
  incrementImprovements,
  setHasMasterResume,
} = useStatusCache();

Optimistic Updates: When user actions modify data, counters update instantly:

Action Updates
Upload master resume incrementResumes(), setHasMasterResume(true)
Delete master resume decrementResumes(), setHasMasterResume(false)
Upload job description incrementJobs()
Generate tailored resume incrementJobs(), incrementImprovements(), incrementResumes()
Delete any resume decrementResumes()

API Client (lib/api/)

Centralized Client (lib/api/client.ts)

Single source of truth for API configuration:

  • API_URL - Base URL from environment or default
  • API_BASE - Full API path (${API_URL}/api/v1)
  • apiFetch(endpoint, options?) - Base fetch wrapper
  • apiPost(endpoint, body) - POST with JSON
  • apiPatch(endpoint, body) - PATCH with JSON
  • apiPut(endpoint, body) - PUT with JSON
  • apiDelete(endpoint) - DELETE request
  • getUploadUrl() - Returns upload endpoint URL

Barrel Export (lib/api/index.ts)

All API functions re-exported for clean imports:

import { fetchResume, API_BASE } from '@/lib/api';

Resume Operations (lib/api/resume.ts)

  • uploadJobDescriptions(descriptions, resumeId) - Upload job descriptions
  • improveResume(resumeId, jobId) - Generate tailored resume
  • fetchResume(resumeId) - Fetch resume by ID
  • fetchResumeList(includeMaster) - List all resumes (optionally include master)
  • updateResume(resumeId, resumeData) - Update resume with structured JSON
  • downloadResumePdf(resumeId, template) - Download resume as PDF
  • deleteResume(resumeId) - Delete a resume permanently

Configuration Operations (lib/api/config.ts)

  • fetchLlmConfig() - Get current LLM configuration
  • updateLlmConfig(config) - Update LLM provider/model/key
  • fetchSystemStatus() - Get system health and database stats
  • testLlmConnection() - Test LLM provider connectivity
  • PROVIDER_INFO - Provider metadata (names, defaults, requirements)