Resumx
Resumx renders resumes from Markdown to PDF, HTML, PNG, and DOCX. It auto-fits content to a target page count, supports tags and views for tailored output from a single source file, and uses style options for styling.
Resources
This skill includes reference documents for specific workflows. Read them when applicable:
| Resource | When to use |
|---|
| json-resume-to-markdown.md | Converting between Resumx Markdown and JSON Resume format (either direction) |
| writing-resume.md | Interactive resume creation, guiding users step-by-step to collect info and generate a resume |
| tagging-resume.md | Systematically tagging a resume for tailored output, including hierarchical tag taxonomy |
Markdown Syntax
Standard Markdown with extensions for inline columns, bracketed spans, and fenced divs.
Structure
| Element | Syntax |
|---|
| Name | |
| Contact | email@example.com | github.com/user | linkedin…
|
| Section | |
| Entry | |
| Subtitle | _Role or Degree_ || Location
|
| Bullets | tech` tags` |
| Skills | Definition list ( + ) |
Inline Columns
splits a line into columns, pushing them to opposite sides. Simplest way to right-align a date or location:
markdown
### Google || Jan 2020 - Present
_Senior Software Engineer_ || San Francisco, CA
More than two columns:
. Escape with
.
Inline Formatting
| Syntax | Result |
|---|
| Bold |
| Italic |
| Tech tag/badge |
| Highlighted text |
| Subscript |
| Superscript |
| / | En-dash / Em-dash |
| Smart quotes |
Definition Lists
markdown
Languages
: JavaScript, TypeScript, Python
Frameworks
: React, Node.js, Express
Also used as inline metadata below entries:
markdown
### Google || June 2022 - Present
Senior Software Engineer
: Infrastructure Platform Team
: San Francisco, CA
Tables
markdown
| :-------- | ---------------------: |
| Languages | Python, TypeScript, Go |
Horizontal Rule
renders as a standard thematic break or section divider.
Comments
HTML comments (
) are stripped from output.
Classes, IDs & Fenced Divs
Bracketed Spans
wraps text in a
with classes/IDs/attributes:
markdown
### Google [2022 - Present]{.right}
_Senior Software Engineer_ [San Francisco, CA]{.right}
Element Attributes
at end of a block element applies to the whole element:
markdown
- Built interactive dashboards {.@frontend}
Fenced Divs
applies attributes to block content. Single child: attributes go directly on it (no wrapper div). Multiple children: auto-wraps in a
.
markdown
::: {.grid .grid-cols-3}
- JavaScript
- TypeScript
- Python
:::
Prefix a tag name for a specific HTML element:
::: footer {.text-center}
.
Frontmatter
YAML (
) or TOML (
). CLI flags always override frontmatter.
Render Fields
| Field | Type | Default | Description |
|---|
| | None | Path(s) to custom CSS file(s) |
| | Input filename stem | Output path (name, directory with , or template with /) |
| | No clamping | Target page count |
| { hide?: string[], pin?: string[] }
| All in source order | Section visibility and ordering |
| | | Bullet ordering strategy |
| | No overrides | Style option overrides |
| Record<string, string[] | TagConfig>
| No composed tags | Tag composition and tag view configuration |
| | No variables | Template variables for placeholders |
| | No custom icons | Custom icon definitions (SVG, URL, or base64) |
| | No custom data | Arbitrary user-defined data |
Validate Fields
| Field | Type | Default |
|---|
| | |
| Record<string, Severity | 'off'>
| Per-preset defaults |
Available rules:
,
,
,
,
,
,
,
,
.
Unknown Fields
Unknown top-level keys error. Use
for custom data.
Full Example
yaml
---
pages: 1
output: ./out/Jane_Smith-{view}
bullet-order: tag
style:
accent-color: '#0ea5e9'
tags:
fullstack: [frontend, backend]
leadership: false
vars:
tagline: 'Full-stack engineer with 8 years of experience'
validate:
extends: recommended
rules:
long-bullet: warning
single-bullet-section: off
extra:
name: Jane Smith
target-role: Senior SWE
---
CLI
bash
resumx <file> # Render (defaults to resume.md, PDF)
resumx init [filename] # Create template resume
Sandbox Requirement
Resumx uses Playwright with Chromium for PDF rendering. Chromium cannot launch inside Cursor's default sandbox because the sandbox blocks syscalls Chromium needs to initialize.
Always run resumx commands with required_permissions: ["all"]
to disable the sandbox. Without this, rendering will fail with "Chromium not found" even though Chromium is installed.
Render Options
| Flag | Description |
|---|
| Path to custom CSS file, repeatable, comma-separated |
| Output path (name, directory, or template) |
| , , , , repeatable, comma-separated |
| Override style property, repeatable |
| Tag view name, custom view name, glob pattern, or for the default view |
| Override a template variable, repeatable |
| Hide sections (comma-separated values) |
| Pin sections to top in order (comma-separated values) |
| Bullet ordering: (default) or |
| Language filter (BCP 47), repeatable, comma-separated |
| Target page count |
| Auto-rebuild on changes |
| Validate only, no render |
| Skip validation |
| Fail on any validation error |
| Filter validation output |
Stdin
bash
cat resume.md | resumx
git show HEAD~3:resume.md | resumx -o old
Output Naming
| Scenario | Output |
|---|
| No view, no langs | |
| With tag/view | |
| With langs | |
| Tag/view + langs | |
Style Options
Override via frontmatter
or CLI
.
Typography: ,
,
,
(default
),
(default
).
Headings: ,
(
,
,
),
,
,
,
,
,
,
,
,
,
,
.
Spacing: (unitless scale factor for all vertical gaps),
,
,
,
,
,
,
.
Custom CSS
Your CSS cascades on top of the default stylesheet, so you only write overrides:
css
:root {
--font-family: 'Inter', sans-serif;
--accent-color: #2563eb;
}
h2 {
letter-spacing: 0.05em;
}
For building a stylesheet from scratch,
bundled modules:
(reset, typography, layout),
(icon sizing),
(
,
,
).
Fit to Page
Set
to auto-fit. Shrinks in order of visual impact (least noticeable first):
- Gaps (row-gap, entry-gap, section-gap)
- Line height
- Font size
- Margins (page-margin-x, page-margin-y, last resort)
For
, gaps also expand to fill remaining space.
Minimums: font-size 9pt, line-height 1.15, section-gap 4px, entry-gap 1px, page-margin-y 0.3in, page-margin-x 0.35in.
When
is set,
values are starting points that may be reduced. Without
, they apply as-is.
Icons
Syntax
for built-in icons,
for Iconify (200k+ icons), standard emoji shortcodes as fallback.
Auto-Icons
Links to recognized domains get icons automatically:
(Email),
(Phone),
,
,
,
,
,
/
,
/
,
,
,
,
,
,
marketplace.visualstudio.com
.
Custom Icons (Frontmatter)
yaml
icons:
mycompany: '<svg>...</svg>'
partner: 'https://example.com/logo.svg'
Resolver order: Frontmatter > Built-in > Iconify > Emoji.
Tailwind CSS
Resumx compiles Tailwind CSS v4 on-the-fly. Apply via
syntax:
markdown
[React]{.bg-blue-100 .text-blue-800 .px-2 .rounded}
Works with bracketed spans, element attributes, and fenced divs. Supports arbitrary values:
.
Built-in utilities:
,
,
–
(hide children beyond the Nth).
Tags
Tags filter content. Add
to any element to mark it for a specific audience. Untagged content always passes through. Tagged content only appears when rendering for a matching tag.
markdown
- Shared bullet
- Frontend-only bullet {.@frontend}
- Backend-only bullet {.@backend}
Hierarchical Tags
Use
to nest tags when a domain spans multiple ecosystems:
markdown
- Designed REST APIs with OpenAPI documentation {.@backend}
- Built microservices with `Express` {.@backend/node}
- Migrated `Spring Boot` monolith {.@backend/jvm}
Inheritance: a view includes its entire lineage (ancestors + self + descendants) and untagged content. Siblings are excluded.
- → (ancestor) + (self) + untagged. Excludes .
- → (self) + + (descendants) + untagged.
Depth is unlimited:
nests three levels.
Tag Composition
Define composed tags in frontmatter as unions of constituents:
yaml
tags:
fullstack: [frontend, backend]
node-fullstack: [frontend, backend/node]
tech-lead: [backend, leadership]
startup-cto: [fullstack, leadership, architecture]
Hierarchical tags work as constituents. Lineage expands per constituent:
includes
(+ descendants),
(ancestor of
),
, and untagged. Sibling
is excluded.
Compositions expand recursively (
includes
and
via
). Every constituent must exist as a content tag or another composed tag; typos produce an error with a suggestion.
Views
Tags filter content (what to show). Views configure rendering (how to show it). Every render uses a view.
Four Kinds of View
| Kind | Where | Nature |
|---|
| Default view | Frontmatter render fields | Base config for all renders |
| Tag view | Frontmatter expanded form | Per-tag overrides, implicit for every tag |
| Custom view | files | Per-application config |
| Ephemeral view | CLI flags | One-off, not persisted |
Tag Views
Every tag implicitly generates a tag view. Configure with the expanded form:
yaml
tags:
frontend:
sections:
hide: [publications]
pin: [skills, projects]
pages: 1
fullstack:
extends: [frontend, backend]
sections:
pin: [work, skills]
pages: 2
The shorthand
fullstack: [frontend, backend]
is sugar for
fullstack: { extends: [frontend, backend] }
.
Custom Views
Custom views live in
files, auto-discovered recursively relative to the resume:
yaml
# stripe.view.yaml
stripe-swe:
selects: [backend, distributed-systems, leadership]
sections:
hide: [publications]
pin: [skills, work]
vars:
tagline: 'Stream Processing, Event-Driven Architecture, Go, Kafka'
Render with
. Batch with
or
. Use
to target the default view (no tag filtering); combine with named views, e.g.
, to render both. Do not name a view
(reserved).
Custom view fields:
(content tags to include),
,
,
,
,
,
,
.
A view without
applies no content filter (all content renders). An explicit
means only untagged content.
Ephemeral Views
CLI flags create an ephemeral view inline without persisting:
bash
resumx resume.md --for backend -v tagline="Stream Processing, Go" --pin skills,work -o stripe.pdf
Cascade Order
Built-in defaults
→ Default view (frontmatter render fields)
→ Tag view OR Custom view (whichever --for resolves)
→ Ephemeral view (CLI flags)
Template Variables
Inject per-application text via
placeholders:
markdown
# Jane Doe
jane@example.com | github.com/jane
{{ tagline }}
Define in frontmatter
, in a custom view, or via CLI
:
yaml
vars:
tagline: 'Full-stack engineer with 8 years of experience'
When undefined or empty, the placeholder produces nothing (line removed). Variable values can contain markdown formatting. Defining a variable with no matching placeholder is an error.
Sections
Control which sections appear and their order:
yaml
sections:
hide: [publications, volunteer]
pin: [skills, work]
removes sections.
moves them to the top in the specified order. Non-pinned sections follow in source order. Values are
types:
,
,
,
,
,
,
,
,
,
,
,
.
CLI:
--hide publications --pin skills,work
.
Multi-Language Output
Tag content with
(BCP 47). Untagged content appears in all languages.
markdown
## [Experience]{lang=en} [Expérience]{lang=fr}
### Google
- [Reduced API latency by 60%]{lang=en}
[Réduction de la latence API de 60%]{lang=fr}
Combines with tags:
. Filter with
or
.
Dimensions multiply: 2 langs × 2 tags = 4 PDFs.
Semantic Selectors
Resumx auto-generates semantic HTML attributes for CSS targeting:
Sections: section[data-section='work']
,
section[data-section='education']
,
section[data-section='skills']
,
section[data-section='projects']
,
section[data-section='awards']
,
section[data-section='certificates']
,
section[data-section='publications']
,
section[data-section='volunteer']
,
section[data-section='languages']
,
section[data-section='interests']
,
section[data-section='references']
,
section[data-section='basics']
.
Headings are classified by fuzzy keyword matching.
Entries: (container),
(individual
).
Dates: with ISO 8601
.
wraps start/end
tags.
Git Integration
If the user hasn't set up the
alias yet, run this first:
bash
git config alias.resumx '!f() { spec="$1"; shift; case "$spec" in *:*) ;; *) spec="$spec:resume.md";; esac; git show "$spec" | resumx "$@"; }; f'
Then render from git history:
bash
git resumx sent/stripe-2026-02:resume.md # render from tag
git resumx HEAD~3:resume.md --css my-styles.css -o stripe # past commit
git show :resume.md | resumx -o staged # staged changes
Pre-commit hook:
for validation.
Post-commit hook: auto-render on every commit.
Using AI
Install agent skills:
npx skills add resumx/resumx
.
Tailoring to Job Postings
- Give the agent and the job posting URL
- Agent reads the JD, maps each requirement to existing bullets (covered, weak, missing)
- Agent decides what's durable vs ephemeral: will this change make the next 10 applications better, or just this one?
- Durable improvements (better phrasing, new bullets, new tags) → edit
- Ephemeral adjustments (keywords, section order, tagline) → create a view or use CLI vars
- Render:
resumx resume.md --for stripe-swe -o out/stripe.pdf
With
, layout auto-adjusts after every edit.
Zero-File-Modification Rendering
For maximum speed and zero git diff, render entirely from CLI flags:
bash
resumx resume.md --for backend -v tagline="Stream Processing, Go, Kafka" --pin skills,work -o stripe.pdf
Resume Template
markdown
---
pages: 1
---
# Full Name
email@example.com | [linkedin.com/in/user](https://linkedin.com/in/user) | [github.com/user](https://github.com/user)
{{ tagline }}
## Education
### University Name || Sept 2019 - June 2024
_Degree Name_
- GPA: 3.85
## Work Experience
### Company Name || Start - End
_Job Title_
- Achievement with quantified impact using `Technology`
## Projects
### Project Name _(Individual/Group)_
- Description of what was built
## Technical Skills
Languages
: Java, Python, TypeScript
Frameworks
: React, Node.js, FastAPI
Writing Best Practices
- Start bullets with strong action verbs (Led, Developed, Engineered, Increased)
- Quantify results (20% improvement, 500+ users)
- Wrap technologies in backticks
- Use consistent date formats ()
- Use for literal brackets in dates: