heading-resume

@preview

Editorial resume with a crisp two-column layout.

v0.1.0
MIT-0
Template
heading-resume preview

Heading Resume

Heading Resume creates a polished editorial resume with a compact two-column layout. It keeps content in small semantic data structures, uses fonts bundled with Typst, and needs no images or external assets.

Quick start

Create a ready-to-edit project:

typst init @preview/heading-resume:0.1.0

Or import the package into an existing document:

#import "@preview/heading-resume:0.1.0": contact, entry, entry-section, resume, skill, skill-section

#show: resume.with(
  name: [Avery Example],
  contacts: (
    contact([avery\@example.com], url: "mailto:[email protected]"),
    contact([example.com], url: "https://example.com"),
  ),
  profile: [Short professional profile.],
  main-sections: (
    entry-section(
      [Projects],
      (
        entry(
          [Useful project],
          organisation: [Independent work],
          dates: [2025–Present],
          body: (
            [Explain the problem and your contribution.],
            [Show a concrete outcome.],
          ),
        ),
      ),
    ),
    skill-section(
      [Skills],
      (skill([Programming], [Python · Rust · SQL]),),
    ),
  ),
)

Public definitions

resume

Use resume with a show rule. Its first argument is the document body supplied by that rule. Named arguments:

  • name: required display name.
  • contacts: array of values returned by contact.
  • profile: optional introductory content.
  • main-sections: sections in the wider left column.
  • aside-sections: sections in the narrower right column.
  • full-sections: sections below both columns.
  • language: document language. Default: English.
  • document-title: title stored in document metadata. Default: "Resume".
  • footer: optional footer content.
  • style: visual overrides grouped by page region. Default: (:).

default-style

default-style contains every visual default used by resume. Normal use does not need it: pass only the values you want to change in style. Each supplied group is merged with its defaults.

#show: resume.with(
  name: [Avery Example],
  style: (
    typography: (
      base-size: 10.5pt,
      display-font: ("New Computer Modern", "Libertinus Serif"),
    ),
    header: (
      name-size: 3.3em,
      contact-size: 7pt,
    ),
    columns: (widths: (1.7fr, 1fr),),
  ),
)

Relative em lengths scale with typography.base-size; absolute lengths such as 7pt remain fixed. Unknown groups and keys produce an error with the full path.

Available style groups:

  • page: paper, fill, margin, footer-size, footer-fill, and footer-alignment.
  • colors: accent, ink, muted, hairline, link, emphasis, and marker. auto makes the last three use their semantic default.
  • typography: base-size, display-font, body-font, label-font, section-font, emphasis-font, emphasis-style, paragraph-justify, and paragraph-leading. Optional font roles fall back to their related base role.
  • header: name-size, name-weight, name-tracking, name-after-gap, contact-size, contact-separator, contact-separator-gap, rule-length, rule-stroke, profile-size, and profile-weight.
  • columns: widths, gutter, divider-stroke, aside-inset, and full-section-gap.
  • sections: before, title-columns, title-rule-gap, title-size, title-weight, title-tracking, title-transform, rule-length, rule-stroke, rule-start, and after.
  • entries: heading-columns, column-gutter, title-size, compact-title-size, title-weight, inline-organisation-size, dates-size, organisation-size, compact-organisation-size, organisation-style, subtitle-size, metadata-gap, metadata-separator, body-size, compact-body-size, body-before, body-leading, compact-body-leading, after, compact-after, divider-before, divider-after, divider-length, and divider-stroke.
  • skills: size, label-weight, columns, and row-gutter.
  • list: indent, body-indent, spacing, and marker.

Stroke values accept none, any value supported by Typst's line or grid stroke parameters, or a function that receives the relevant semantic color. Use none to remove a rule or divider.

contact

contact(value, url: none) creates one item in the contact row. With url, the displayed value becomes a link.

entry

entry(title, organisation: none, dates: none, subtitle: none, body: none) creates a project, education, or work item. An array passed as body renders as a bullet list; other content renders directly.

entry-section

entry-section(title, entries, compact: false, inline-organisation: false) groups entries. compact tightens their spacing. inline-organisation places the organization beside each entry title.

skill

skill(label, value) creates one labeled skills row.

skill-section

skill-section(title, rows) groups one or more skills rows.

Layout tips

  • Keep the initialized example to one page by shortening content before reducing text-size.
  • Put the most important evidence in main-sections, compact facts in aside-sections, and work history in full-sections.
  • Pass a font fallback array when using optional local fonts. Do not assume other readers have those fonts installed.

License

Heading Resume is licensed under the MIT No Attribution license.

Version History

0.1.0
19a4acb29e34...