I got tired of fighting Word docs and Canva templates every time I updated my resume.
Your resume is structured data. A name, jobs, dates, skills. Once I realized that, I stopped treating it like a document and started treating it like a data model with renderers. That's resumelang.
How it works
Write one resume.yml:
# yaml-language-server: $schema=https://resumelang.dev/schema/v1.json
resumelang: v1
meta:
theme: sap # 13 built-in themes
language: en
page_size: a4
sections:
- summary
- experience
- skills
- education
- projects
person:
name: Jane Doe
title: Senior Software Engineer
email: jane@example.com
github: janedoe
linkedin: janedoe
summary: |
Experienced engineer with 8 years building distributed systems.
experience:
- company: Acme Corp
role: Lead Engineer
start: "2021"
end: ""
highlights:
- Scaled API to 10M requests/day
- Reduced CI deploy time by 60%
tags: [Go, Kubernetes, Postgres]
skills:
- category: Languages
skills: [Go, TypeScript, Python, Rust]
Run one command:
resumelang build resume.yml
Get:
dist/
├── resume.html # themed, print-ready
├── resume.json # JSON Resume schema
├── resume.md # GitHub-flavored markdown
└── resume.txt # ATS-safe plain text
The theme system
13 built-in themes: SAP, Vercel, Linear, Aurora, Material, Brutalist, Terminal, Editorial, Dossier, Academic, Finance, Timeline, Minimal.
Switch with one line:
meta:
theme: vercel
Your content doesn't move. Only the rendering changes.
Each theme is a folder with a validated theme.yml spec:
spec: v1
name: aurora
version: 1.0.0
author: ovsec
supports:
layouts: [timeline, grid]
blocks: [bullets, tags, text]
tokens:
colors:
accent: "#6366f1"
spacing:
section_gap: 24
typography:
heading_weight: 600
body_size: 14
The compiler validates every theme at load time against the spec. Missing template → build error. Unknown component → warning. This means community themes that pass resumelang theme validate are guaranteed to render correctly.
Why Go
- Single binary, zero runtime dependencies
- Same binary serves the web editor, runs the CLI, and powers the GitHub Action
- Cross-compiles to Linux/macOS/Windows without Docker
-
go install github.com/ovsec/resumelang@latestand you're done
The web editor
The editor is Go Fiber + HTMX + CodeMirror 5. No React, no build step.
- Edit YAML on the left, live preview on the right
- Theme gallery rendered server-side via HTMX lazy loading
- Share modal with gzip-encoded URLs and AES-GCM password encryption
- Decryption happens entirely in the browser — server never sees resume content
- Sign in with GitHub or LinkedIn to save resumes to a dashboard
GitHub Actions path
Drop this into .github/workflows/resume.yml:
on:
push:
paths: ["resume.yml"]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with: { go-version: "1.22" }
- run: go install github.com/ovsec/resumelang@latest
- run: resumelang build resume.yml --out dist
- uses: actions/upload-pages-artifact@v3
with: { path: dist }
- uses: actions/deploy-pages@v4
Push resume.yml, get a live GitHub Pages site. Every change is a commit. git diff shows exactly what changed.
What's on the roadmap
- Native PDF export (Puppeteer server-side)
-
resumelang lint— ATS keyword score, date-gap detection - LinkedIn import (
resumelang import linkedin export.zip) - AI tailoring — paste a JD, rewrite highlights to match (Pro)
- Link analytics — see when recruiters open your resume (Pro)
Contribute
The theme ecosystem is community-driven. If you have design opinions, the spec is documented at docs.resumelang.dev/themes. Submit a theme, open an issue, or just star the repo.
🔗 resumelang.dev
📖 docs.resumelang.dev
⭐ github.com/ovsec/resumelang
What would you want from a YAML-first resume tool? Drop it in the comments.
Top comments (1)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.