Skip to content

Repository files navigation

Resume Forge

A single professional knowledge base in Markdown that generates resumes as projections. A local, open-source (MIT) command-line tool.

You treat your resume as a single knowledge base: you write your experiences, projects and education once, in Markdown. Each resume is a projection of that base for a given job - you select what goes in, and the tool generates a consolidated Markdown file and a PDF (ATS template, readable by screening systems).

The pain it tackles: keeping several resume documents (Word, Google Docs, LinkedIn) and adapting them to each job leads to duplicated content, versions that drift apart, high maintenance cost and no decent versioning. Here there is one single source of truth, versionable in git; nothing is duplicated to serve a specific job.

The content lives in Markdown files organized by section, with conditional snippets marked by tags. A resume config (YAML) chooses the language, filters by tags and adjusts what goes in. Validation is all-or-nothing - the worst possible failure would be a silently incomplete resume, so the whole base is checked before anything is generated.

Running (Docker)

The repository ships with a complete example base in data/ - a fictional frontend engineer's resume, bilingual (pt/en), with experiences, projects, education, skills, logos and ready-made resume configs. With Docker installed, from a clone you generate a resume in one command:

docker compose run --rm forge generate resume-configs/fullstack.yaml

Important

The first run is slow. The image is built on the spot (Node + Pandoc + LaTeX), and downloading TeX Live alone usually takes 5 to 10 minutes on a clean machine - it is normal for the first run to look stuck at that step. This happens only once: with the image cached, later runs are almost instant.

Each config lists its languages in output.locales, so this writes one document set per language (fullstack-en and fullstack-pt) into data/output/.

There are configs for different targets - try them out and compare:

docker compose run --rm forge generate resume-configs/frontend.yaml   # frontend focus
docker compose run --rm forge generate resume-configs/short.yaml      # short version
docker compose run --rm forge validate                                # checks the whole base
docker compose run --rm forge list                                    # lists blocks and tags

Tip

Compare fullstack with frontend: the conditional tags turn the backend content of the same resume on and off.

Your own base

Write your base in a directory of your own (keep it outside the repository if it is personal), with the same structure as data/:

<your-base>/
├── content/
│   ├── sections/
│   │   └── experiences/
│   │       └── acme.md          # one content unit
│   ├── titles.yaml              # section titles
│   └── personal_info.yaml       # personal information (optional)
└── resume-configs/
    └── my-job.yaml              # one config per job

Point forge at it with the RESUME_DATA variable (without it, the example in data/ is used):

RESUME_DATA="$HOME/Desktop/my-resume-data" docker compose run --rm forge generate resume-configs/my-job.yaml

Writing content (example)

A content file (content/sections/experiences/acme.md) - each file opens with a front matter (id + tags) and uses a minimal markup:

---
id: acme
tags: [backend, java]
---
::locale{en-US}

## Acme Corp

REST API development::span{tags=[cloud]}{ on AWS}.

::div{id=leadership tags=[leadership]}
- Led a team of 6 people.
::end
  • ::locale{en-US} declares the region's language (translations share the same id).
  • ::span{tags=[cloud]}{…} conditions a snippet in the middle of a line (it enters only if the job asks for cloud).
  • ::div{…}::end conditions a block of lines by tags.
  • Text outside any block enters whenever the section and the language match.

And content/titles.yaml gives each section's title:

experiences:
  en-US: Experience

Configuring a resume (example)

A resume config (resume-configs/backend.yaml):

title: Backend Developer
tags: [backend, java]     # a block enters with ≥1 tag in common
sections:                 # section order
  - experiences
output:
  locales: [en-US, pt-BR] # one document set per language
  formats: [pdf, md]

Generates one resume per language (backend-en, backend-pt) with the blocks that match backend or java.

Documentation

  • Usage guide - everything about writing the base, the full grammar, experience/education entries, personal information, all the resume config fields, the selection semantics, commands and outputs.
  • Technical characteristics - stack, determinism, the Markdown → PDF contract, exit codes and the Docker environment.
  • Automation - the prebuilt runtime image and the CI flow that generate resumes and publish them as dated releases.
  • docs/product.md - the product specification (the source of truth for behavior).

License

MIT.

About

Generate tailored, ATS-friendly resumes from a single Markdown knowledge base. Select content by tags and language instead of duplicating it.

Resources

Stars

5 stars

Watchers

0 watching

Forks

Packages

Contributors

Languages