Generate ATS-friendly, single-page resumes from a JSON spec and a pre-formatted Microsoft Word slot template. The toolchain validates, fills, exports to PDF, and asserts the result is exactly one page — so you spend time on content, not on margins.
- Validates a JSON spec against a strict schema (three roles with 7 / 6 / 5 bullet caps, education, 2–5 skill lines).
- Fills
templates/slot_template.docxby replacing{{PLACEHOLDER}}tokens — original run formatting (bold, italic, tab stops) is preserved exactly. - Converts to PDF via Microsoft Word (PowerShell COM automation), then asserts the PDF is one page.
- Warns about layout traps before you eyeball the PDF — skill lines that wrap to a half-empty second line, and bullets that end with one or two orphan words on their own line.
- The toolchain itself does not write your resume. Either you write the JSON, or an LLM agent writes it for you (see "Agent-driven workflow" below). Either way, the toolchain formats and builds.
- It does not run end-to-end on macOS or Linux. The PDF step uses Word COM, which is Windows-only. The
.docxfill step (fill_template.py) works everywhere — convert to PDF separately if you're not on Windows.
- Windows 10/11 with Microsoft Word installed (for the PDF step).
- Python 3.10+.
- The three packages in
requirements.txt:python-docx,lxml,pypdf.
git clone https://github.com/fedoup/resume-builder.git
cd resume-builder
pip install -r requirements.txt
python build_resume.py examples/jane_doe_swe.jsonThe output lands in output/ — open output/jane_doe_swe.pdf.
{
"name": "Jane Doe",
"contact": "jane@example.com | (555) 123-4567 | San Francisco, CA",
"role1": {
"company": "Acme",
"dates": "Jan 2024 – Present",
"title": "Senior Software Engineer",
"location": "San Francisco, CA",
"bullets": [
"Built a distributed tracing service in Python cutting median incident debug time by 60%.",
"Shipped a new payments API to production, handling $4M/mo in transaction volume."
]
},
"role2": { "company": "...", "dates": "...", "title": "...", "location": "...", "bullets": ["..."] },
"role3": { "company": "...", "dates": "...", "title": "...", "location": "...", "bullets": ["..."] },
"education": {
"primary": {
"school": "Boston University",
"dates": "Sep 2017 – May 2021",
"degree": "BS, Computer Science",
"location": "Boston, MA"
}
},
"skills": [
{ "label": "Languages", "items": "Python; TypeScript; Go; SQL" },
{ "label": "Infrastructure", "items": "AWS; Kubernetes; Terraform; PostgreSQL" }
],
"output_filename": "Jane Doe - Resume.docx"
}Full field reference: docs/SCHEMA.md.
Two contrasting personas ship with the repo — both fit one page, both demonstrate the schema:
| Persona | Spec | DOCX | |
|---|---|---|---|
| Jane Doe — Senior Software Engineer, ~5 years, tech-heavy skills, no interests | examples/jane_doe_swe.json |
examples/jane_doe_swe.docx |
examples/jane_doe_swe.pdf |
| Alex Kim — Senior Growth PM, non-tech skill mix, includes interests | examples/alex_kim_growth_pm.json |
examples/alex_kim_growth_pm.docx |
examples/alex_kim_growth_pm.pdf |
The repo also ships a Claude Code skill (SKILL.md) and an experience/ template folder so an LLM agent can drive the whole loop end-to-end: read your career inventory, parse a posting you paste in, pick bullets that match, emit the JSON, run the build, and surface a skills-gap analysis.
One-time setup: fill experience/ once with your own roles, skills, proof points, and education. The worked example at examples/jane-doe-experience/ shows what a complete inventory looks like — compare its files to examples/jane_doe_swe.json to see how the agent cherry-picks bullets from a larger source set.
Then, in any session: paste a posting. The agent reads SKILL.md, walks the 9-step workflow, and ships you a tailored PDF.
Install as a Claude Code skill (Windows; one-time):
mklink /J "%USERPROFILE%\.claude\skills\resume-builder" "<absolute-path-to-this-repo>"Then restart Claude Code so the skill registers. Any other LLM agent can just read SKILL.md directly — the file is portable.
See docs/TAILORING.md for the role-profile pattern (caching positioning for role types you target often).
docs/WORKFLOW.md— the iteration loop: picking starting bullet counts, what to cut when the page check fails, what to add when there's whitespace, the quality checklist.docs/RULES.md— content principles: XYZ bullet formula, action-verb bank, ATS-safe patterns, the no-em-dashes / no-orphan-line rules the toolchain enforces.docs/SCHEMA.md— JSON field-by-field reference.docs/TAILORING.md— role-profile pattern (when and how to codify positioning for a role type).
If you edit templates/base_template_v2.docx (margins, font, section borders), regenerate the slot template:
python create_slot_template.pyThis rewrites templates/slot_template.docx from the base template and is idempotent — safe to re-run.
python build_resume.py <content.json> [--output PATH] [--template PATH] [--validate-only]
python fill_template.py <content.json> [--output PATH] [--template PATH]
python create_slot_template.py
python check_pages.py <pdf_path>