Skip to content

Repository files navigation

Resume Workbench

A local-first, professional resume & CV builder that runs entirely in your browser.

Resume Workbench lets you create, edit, design, analyze, and export resumes without uploading anything to a server. All documents are stored in IndexedDB on your own device, and every feature — from WYSIWYG editing to ATS checking to PDF export — happens locally.

Built with React 18, TypeScript, Vite, Tailwind CSS, and Zustand.


Table of Contents


Features

Editing

  • True WYSIWYG canvas — click any text on the rendered resume to edit it in place
  • Live pagination — the document reflows and re-paginates as you type, in single-page or continuous-page view
  • Zoom controls — zoom in/out from 40% to 200%, with one-click reset
  • Rich text — bold, italic, and other markup with sanitization (DOMPurify)
  • Undo / redo — up to 120 history snapshots with debounced history commits
  • In-page search — find and jump to any text in the document

Sections & Content

  • 20+ built-in section types: Summary, Experience, Education, Skills, Projects, Certifications, Awards, Publications, Research, Volunteer, Leadership, Languages, Interests, Coursework, Conferences, Memberships, References, Achievements, Hobbies, and Custom
  • Add, reorder, hide/show, and delete sections from the Sections panel
  • Reorder entries within a section and move sections up/down
  • Per-entry fields tailored to the entry type (role/company, degree/institution, etc.), with dates, bullets, technologies, URLs, and more

Design & Layout

  • 18 built-in templates in four categories:
    • ATS (5): Harvard Professional, Classic ATS, Minimal ATS, Executive ATS, Technical ATS
    • Modern (6): Modern Professional, Clean Modern, Elegant, Corporate, Minimalist
    • Technical (5): Software Engineer, Full Stack Developer, DevOps Engineer, Data Engineer, Cloud Engineer
    • Academic (3): Academic CV, Research CV, Graduate CV
  • Typography — 6 bundled fonts (Inter, Roboto, Open Sans, Source Sans 3, Lato, EB Garamond) with control over base size, name size, section headings, line height, letter spacing, weights, small caps, and uppercase headings
  • Theme controls — primary/accent/text/heading/link colors, heading rules and dividers
  • Per-section styling — heading rule, color, weight, transform, letter spacing, spacing, divider, and column layout
  • Save your own designs as reusable templates and re-apply them later

Page Setup & Headers/Footers

  • Paper sizes — Letter, A4, Legal, and custom dimensions; portrait or landscape
  • Margins — per-side control in millimeters
  • Page numbers — off, {page}, {page} / {pages}, name, or name + page
  • Headers & footers — enable/disable, custom text with placeholders ({name}, {title}, {email}, {phone}, {location}, {page}, {pages}), alignment, font size, gap, and "show on first page"

Style Presets

  • 4 built-in style presets — Classic Black, Modern Navy, Elegant Serif, Clean Minimal — each bundling a coordinated theme, typography, page setup, and per-section styling
  • Apply with one click from the presets dialog, toolbar, or command palette; changes are undoable (they run through the same history system as every other edit)
  • Save any current design as a reusable custom preset; edit or delete your own presets (built-ins are read-only)

Freeform Canvas

  • Structured ↔ Freeform mode — toggle the whole canvas from content-driven layout to a free-positioned design surface
  • Free-positioned elements — text, headings, lines, rectangles, dividers, lists, icons, and images placed by x/y coordinates in millimeters
  • Per-element styling — font, weight, align, color, letter spacing, line height, opacity, rotation, lock, and visibility
  • Canvas helpers — optional grid, snap-to-grid, alignment guides, and a ruler
  • Duplicate, delete, and multi-select elements; every action is history-aware (undo/redo)

Cover Letters

  • Dedicated cover-letter view — create, edit, rename, duplicate, and delete letters from the Cover Letters page (toolbar "Letters" button or command palette)
  • Start blank or "New from resume" — a letter can be seeded from any existing resume, inheriting your personal info, signature, colors, and typography
  • WYSIWYG body editor — recipient details (name, title, company, address), date, salutation, a live-rendered letter canvas, and editable body paragraphs with add/remove controls
  • Layout mirrors your resume — the letter uses the same theme, fonts, and page setup as your documents, so a letter and resume match visually
  • Export & print — save a plain-text version or open a styled print window for PDF
  • Autosave — every keystroke in the letter editor is saved with a short debounce

Career Hub (Job Hunt)

  • Track your job hunt — companies, contacts, job postings, applications, and interviews, all cross-linked in one place
  • Application snapshots — capture the exact resume, cover letter, and job posting used for any application
  • Career asset library — reusable snippets in 18 categories (experience, projects, skills, certifications, and more) with per-category field schemas and version history
  • Skill matrix — group skill assets by category with 5-segment proficiency ratings
  • Tasks & follow-ups — task-driven to-do items linked to applications, postings, companies, contacts, and interviews, with due dates, reminders, and priority
  • Asset-driven writing — insert saved assets straight into resumes and cover letters from the asset picker
  • Backup & restore — export and import your entire local database (all stores) as a single JSON file

Appearance

  • Dark mode — light, dark, and system (follows OS) themes, applied app-wide to the shell
  • Quick toggle — switch themes from the toolbar (sun/moon button), Settings, or the command palette (Toggle Dark Mode)
  • The resume canvas itself always stays white — it represents a printable page

Analysis Tools

  • ATS Compatibility Check — score your resume against common applicant-tracking-system parsing rules
  • Resume Quality Check — automated feedback on structure, content density, and readability
  • Keyword Checker — paste a job description and see which keywords your resume matches
  • Compare Versions — diff any two snapshots of the same resume
  • Preflight export check — warns about empty sections, missing name/contact, etc. before export

Snapshots (Versions)

  • Named snapshots — save a point-in-time copy of any resume and restore it later
  • Compare — pick any two snapshots and diff them line by line
  • Delete — remove individual snapshots; snapshots are stored separately from the live document, so restoring never overwrites your current draft history

Import / Export

  • Export:
    • PDF / Print via a styled print window (browser "Save as PDF")
    • JSON (.resume.json) — lossless, round-trippable
    • Markdown (.md)
    • Plain text (.txt)
  • Cover letter export — plain text (.txt) and PDF / print with matching styles
  • Import:
    • Resume Workbench JSON (wrapped or bare document)
    • Saved-template JSON
  • Snapshots (versions) — save named snapshots of any resume and restore or diff them later

Persistence & Safety

  • Autosave — debounced autosave (default 1.5 s) with save-on-tab-hide and save-on-unload
  • Local-first — all data lives in IndexedDB on your device; nothing is uploaded
  • Settings persisted to localStorage for synchronous reads

Tech Stack

Layer Technology
UI React 18 + TypeScript
Build Vite 5
Styling Tailwind CSS 3 (CSS variables + dark mode)
State Zustand
Storage IndexedDB via idb + localStorage
Validation Zod
Components Radix UI primitives + custom shadcn-style UI
Icons Lucide React
Sanitizer DOMPurify
Testing Vitest + Testing Library (jsdom)

Getting Started

Prerequisites

  • Node.js 18+ and npm

Installation

npm install

Run the dev server

npm run dev

Open the printed URL (default http://localhost:5173).

Production build

npm run build

The output is written to dist/. Serve it with any static host or preview it locally:

npm run preview

Project Structure

resume-workbench/
├── index.html
├── package.json
├── tailwind.config.ts
├── tsconfig.json
├── vite.config.ts
└── src/
    ├── main.tsx                 # App entry
    ├── App.tsx                  # Shell: toolbar, view switch, command bus, shortcuts
    ├── types/
    │   └── resume.ts            # Core domain types (document, entries, templates, settings)
    ├── validators/
    │   └── resumeSchema.ts      # Zod schemas for documents & templates
    ├── services/
    │   ├── db.ts                # IndexedDB store + settings persistence
    │   ├── export.ts            # JSON/Markdown/text export + PDF/print pipeline
    │   ├── import.ts            # JSON & template import + normalization
    │   └── backup.ts            # Full-database backup & restore
    ├── store/
    │   ├── useDocuments.ts      # Resume/template/snapshot collections, views
    │   ├── useEditor.ts         # Open document, selection, history, panels, zoom
    │   ├── useUi.ts             # Dialogs, command palette, confirm modal
    │   ├── useSettings.ts       # App settings (theme, autosave, shortcuts)
    │   ├── useCoverLetters.ts   # Cover letter collection + active draft
    │   ├── useStylePresets.ts   # Built-in + user style presets
    │   ├── useCareer.ts         # Companies, contacts, jobs, applications, interviews, snapshots
    │   ├── useAssets.ts         # Career asset library + version history
    │   ├── useTasks.ts          # Tasks & follow-ups
    │   └── useCareerNav.ts      # Career-hub tab state
    ├── hooks/
    │   ├── useAutosave.ts       # Debounced autosave + beforeunload/visibility flush
    │   ├── useTheme.ts          # Applies light/dark/system theme to the shell
    │   └── useKeyboardShortcuts.ts
    ├── lib/
    │   ├── commands.ts          # Command palette command registry + event bus
    │   ├── resumeFactory.ts     # Blank docs, duplicates, template application
    │   ├── sections.ts          # Section type metadata & creation
    │   ├── sanitize.ts          # DOMPurify wrapper / markup stripping
    │   ├── fonts.ts             # Font stack resolution
    │   ├── freeform.ts          # Freeform layout normalization helpers
    │   ├── assetToResume.ts     # Career asset → resume/letter section mapping
    │   ├── taskSuggestions.ts   # Follow-up suggestions from stale applications
    │   └── id.ts                # ID & timestamp helpers
    ├── templates/
    │   ├── catalog.ts           # 18 built-in template definitions
    │   └── stylePresets.ts      # Built-in + custom style preset helpers
    ├── features/
    │   ├── ats/analyze.ts       # ATS compatibility scoring
    │   ├── quality/analyze.ts   # Resume quality feedback
    │   ├── keywords/match.ts    # Job-description keyword matching
    │   └── compare/diff.ts      # Snapshot diffing
    ├── components/
    │   ├── dashboard/Dashboard.tsx
    │   ├── editor/              # EditorShell, EditorPane, SidePanel, InspectorPanel, FreeformPanel, ...
    │   ├── resume/              # ResumeCanvas, ResumeFlow, blocks, RichText
    │   ├── cover/               # CoverLettersView, CoverLetterEditor, CoverLetterBody
    │   ├── career/              # Career hub: Companies, Contacts, JobBoard, Applications, Interviews, SkillMatrix, AssetsLibrary, TasksView
    │   ├── dialogs/             # ATS, Quality, Keywords, Compare, Export, Import, Style Presets, ...
    │   ├── toolbar/             # Toolbar + StatusBar
    │   ├── settings/SettingsDialog.tsx
    │   ├── common/              # CommandPalette, ConfirmDialog
    │   └── ui/                  # Reusable shadcn-style primitives
    └── test/
        └── setup.ts            # Vitest setup (jest-dom, matchMedia, confirm)

The Document Model

A resume is a single ResumeDocument object:

Field Description
id Unique ID
name Display name
personal Full name, job title, contact fields, links
sections Ordered, typed sections, each with visible flag, style, and entries
theme Colors, heading rules, divider style
typography Fonts, sizes, weights, spacing, transforms
pageSetup Paper size, orientation, margins, page numbers
header / footer Header/footer config + placeholder tokens
metadata Template reference, ATS mode, language, tags, timestamps

Section entries are discriminated by entry.type (experience, education, skills, projects, etc.), so the editor, renderer, and exporters all branch on the typed structure.

Documents are validated against Zod schemas in src/validators/resumeSchema.ts on import, so malformed files are rejected with a readable error instead of crashing the renderer.

Cover letters

A cover letter is a separate CoverLetterDocument model sharing the same theme, typography, and page setup as resumes:

Field Description
id, name Unique ID and display name
personal Full name, title, email, phone, location
recipient Name, title, company, address
date Letter date
salutation / closing / signature Greeting, sign-off, signature
body Array of paragraphs
theme / typography / pageSetup / header / footer Shared styling

Cover letters are created blank or seeded from a resume with buildCoverLetterFromResume (src/lib/resumeFactory.ts), which copies your personal info and matches the resume's visual design so the pair looks consistent.


Local Storage

Data never leaves your device.

IndexedDB database resume-workbench (schema v5):

Store (IndexedDB resume-workbench) Key path Contents
resumes id ResumeDocument objects
versions id Named snapshots, indexed by resumeId
templates id User-saved templates
coverLetters id CoverLetterDocument objects
stylePresets id User-created style presets
companies id Job-hunt companies
contacts id Contacts at companies
jobPostings id Job postings
applications id Job applications
interviews id Interview events
applicationSnapshots id Resume/letter/posting snapshots per application
assets id Career asset library snippets
assetVersions id Asset version history
tasks id Tasks & follow-ups
meta key App metadata (incl. settings mirror)

Settings are also mirrored to localStorage (rw.settings.v1) so they can be read synchronously on startup. Deleting the resume list deletes its snapshots too. Backups capture all 15 stores in a single JSON file.


Using the App

Dashboard

  • Lists all resumes saved on the device, with section counts and last-updated dates
  • Create a new resume (blank or from a template), import a file, or open the template gallery
  • Per-resume actions: Rename, Duplicate, Delete (with confirmation)

Editor

The editor is a three-region workspace:

  • Left — Sections panel: reorder, show/hide, add, and delete sections; jump to a section
  • Center — Canvas: the live, zoomable resume; click any text to edit in place
  • Right — Header & Footer inspector: configure header/footer text, alignment, and page numbers

Both side panels can be toggled from the toolbar. On screens narrower than 1024 px they open as overlay drawers with a backdrop; picking a section closes the panel so you can see the result. Panels default to closed on small screens and open on desktop.

Freeform Canvas

  • Switch the canvas from structured to freeform layout from the Sections panel or inspector; the mode is stored per document and can be toggled back any time
  • In freeform mode, use the Freeform panel to add text, headings, lines, rectangles, dividers, lists, icons, and images, then drag them anywhere on the page
  • Select elements directly on the canvas (or via the panel), and use duplicate, delete, and multi-select to arrange them
  • Enable the grid, snap-to-grid, and guides for precise alignment; adjust element opacity, rotation, locking, and visibility per element
  • All freeform edits are captured by the same undo/redo history as structured edits

Templates

  • Open the Template Gallery to preview the 18 built-ins and apply one to the current resume
  • Apply from the gallery, from the command palette (Apply: <template>), or via the toolbar
  • Save current design (Ctrl+Alt+S equivalent via command) to create a reusable template
  • Recent templates are tracked in settings for quick re-application

Style Presets

  • Click the Styles toolbar button (or use the command palette) to open the Style Presets dialog
  • Choose one of the four built-in presets to instantly restyle the current resume — theme, typography, page setup, and per-section defaults all update together
  • Use Save current to store your own palette/typography as a preset; rename or delete custom presets from the same dialog
  • Applied presets are undoable, so you can freely experiment

Cover Letters

  • Open the Cover Letters page from the toolbar Letters button, the dashboard, or the command palette (Open Cover Letters)
  • New Letter creates a blank letter; New from resume lets you pick any resume to seed the letter with your contact info, signature, and matching visual style
  • Click any saved letter to open the editor: edit recipient details, date, salutation, and body paragraphs on the left while watching the letter render live on the right
  • The editor autosaves as you type; use the toolbar buttons to export as plain text or to open the styled print window (PDF)
  • Use the Back button, the toolbar, or the command palette to return to the letter list

Career Hub

  • Open the Job Hunt page from the dashboard or the command palette (Open Job Hunt)
  • Companies, Contacts, Jobs, Applications, and Interviews tabs with full CRUD and cross-linking (jobs link to companies, applications link to jobs, etc.)
  • Skills tab — skill matrix grouping skill assets by category with proficiency bars
  • Assets tab — the career asset library with 18 categories, version history, favorites, archiving, and duplicate
  • Tasks tab — tasks & follow-ups with due dates, reminders, priority, and status
  • Application snapshots — when you apply, capture the exact resume, cover letter, and posting used so you can revisit what you sent

Backup & Restore

  • Export Backup (Dashboard header, command palette, or Export Backup) downloads all 15 stores as a single .json backup file
  • Import Backup restores a previous backup, replacing all stored data with a per-store record count report
  • Backups are validated on import; malformed or wrong-app files are rejected

Tools

The Tools menu and command palette expose:

  • ATS Check — compatibility scoring for ATS parsing
  • Quality Check — structural and content feedback
  • Keyword Checker — match your resume against a job description
  • Compare Versions — diff two snapshots
  • Snapshots — save named versions and restore them later
  • Page Setup — paper size, orientation, margins, page numbers

Snapshots

  • Open the Snapshots dialog from the toolbar (camera icon) or the Tools menu
  • Save snapshot captures the current resume with a label of your choice
  • Restore replaces the working copy with a snapshot; Compare diffs any two snapshots side by side; Delete removes a snapshot permanently

Import / Export

  • Export PDF / Print: opens a styled print window with matching fonts and CSS @page rules (headers, footers, page numbers), then lets you save as PDF or print
  • Export JSON: lossless .resume.json round-trip
  • Export Markdown / Plain text: for ATS-friendly pasting or further editing
  • Cover letters: export as plain text or open the same styled print window for PDF
  • Import: accepts wrapped or bare Resume Workbench JSON and template JSON

Settings

  • Theme: light / dark / system (applied app-wide; quick toggle in the toolbar)
  • Default template for new resumes
  • Autosave toggle and interval
  • Keyboard shortcuts on/off
  • Reduced motion

Keyboard Shortcuts

Shortcut Action
Ctrl/Cmd + K Open command palette
Ctrl/Cmd + S Save resume
Ctrl/Cmd + Z Undo
Ctrl/Cmd + Shift + Z, Ctrl/Cmd + Y Redo
Ctrl/Cmd + F Search in resume
Ctrl/Cmd + P Print / export PDF
Esc Close dialog / clear selection

Command Palette

Ctrl/Cmd + K opens a fuzzy-search palette with commands across File, Edit, View, Template, Section, Export, Tools, and Settings categories, including hidden commands such as adding any section type, applying a specific template, opening the style presets, and cover-letter actions (Open Cover Letters, New Cover Letter, New Cover Letter from Resume), Toggle Dark Mode, career navigation (Open Job Hunt, Open Tasks & Follow-ups), and backup (Export Backup, Import Backup).


Responsive Design

  • Desktop (≥1024 px): full three-region workspace with both side panels docked
  • Tablet / phone (<1024 px):
    • Side panels become slide-over drawers with a dimmed backdrop; tap the backdrop to close
    • Opening a document starts with panels closed so the canvas is immediately usable
    • Selecting a section auto-closes the sections panel
    • The toolbar scrolls horizontally (scrollbar hidden) so every control stays reachable
    • Less-critical toolbar buttons (Templates below md, Page Setup below lg) collapse into the Tools menu / command palette
    • Dashboard cards reflow from 3 → 2 → 1 columns
  • Editor canvas wraps its header controls and re-paginates to the available width

Scripts

Script Description
npm run dev Start the Vite dev server
npm run build Type-check (tsc -b) then production build
npm run preview Preview the production build
npm run typecheck TypeScript check without emitting
npm run test Run Vitest once
npm run test:watch Run Vitest in watch mode
npm run lint ESLint the src directory (requires eslint)

Note: npm run lint is declared in package.json but eslint is not currently installed and there is no ESLint config file. Run npm install -D eslint and add an eslint.config if you want to use it.


Testing

Unit tests run on Vitest with jsdom and Testing Library.

npm test          # run once
npm run test:watch # watch mode

The suite covers the core stores, export/import, backup, and helpers:

Test file Covers
src/store/useEditor.test.ts Document open, patch/history, undo/redo, delete, freeform
src/store/useDocuments.test.ts Load/seed, create, open, rename, duplicate, navigation
src/store/useCoverLetters.test.ts Create blank / from resume, patch/save, duplicate/rename/remove, open
src/store/useStylePresets.test.ts Load merge, save current, remove, apply with history
src/store/useCareer.test.ts Companies, contacts, jobs, applications, interviews, snapshots
src/store/useAssets.test.ts Asset CRUD, version history, favorites, archive, duplicate
src/store/useTasks.test.ts Task CRUD, status/due-date transitions, suggestion inputs
src/services/export.test.ts JSON wrap, plain text (resume + letter), preflight checks
src/services/backup.test.ts Backup export, import validation, restore counts
src/lib/assetToResume.test.ts Asset-category → resume/letter section mapping
src/lib/taskSuggestions.test.ts Follow-up suggestions from stale applications

Test setup lives in src/test/setup.ts (jest-dom matchers, matchMedia, and confirm stubs). Stores are tested through their public actions with IndexedDB mocked via vi.mock.


Data Schemas & Validation

  • src/types/resume.ts — hand-written TypeScript interfaces for the full domain model
  • src/validators/resumeSchema.ts — Zod schemas that mirror the types; used on import to validate and normalize documents and templates
  • src/services/import.ts — normalization fills any missing nested fields so rendering and export never crash on partial data

Templates are applied through applyTemplateConfig / withDefaultStyles (src/lib/resumeFactory.ts), which merge theme, typography, page setup, header/footer, and per-section defaults into the target document.

About

Local-first resume & CV builder that runs entirely in your browser. WYSIWYG editing, live pagination, 18 templates, ATS checks, cover letters, a full job-hunt tracker, and PDF/JSON/Markdown export. All data stored on your device.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages