resume renderer

Turn one resume JSON into HTML or a print-ready PDF. POST the resume to /api/render (or /api/render/pdf), or GET with ?source=<url> pointing at a hosted JSON.

A resume is { meta?, main, sections[] }: main is your identity (name + contacts); sections is an ordered list rendered top to bottom, each tagged by its type; meta (SEO / OpenGraph) is optional. Almost every text field is a Text — read that first.

Machine-readable schema: /schemas/resume.json

Minimum valid resume — a name and one section:

{
  "main": { "fullName": "Jane Doe" },
  "sections": [ { "type": "text", "text": "Hello" } ]
}

Making requests

Two ways in, same for every endpoint — POST the resume JSON as the request body, or GET with ?source=<url> pointing at a hosted JSON:

# POST the JSON → PDF, saved as "<fullName> - resume.pdf"
curl -X POST 'https://resume.hire-me.now/api/render/pdf' \
  -H 'content-type: application/json' --data @resume.json -OJ

# or GET a hosted resume as HTML
curl 'https://resume.hire-me.now/api/render?source=https://example.com/resume.json'

Endpoints under /api/render:

pathreturns
/api/render or /api/render/htmlHTML
/api/render/pdfPDF
/api/render/validate{ ok, errors, warnings } — validates without rendering; run it before publishing

Query parameters

paramvalueseffect
sourceURLGET only — fetch the resume JSON from this URL (required on GET)
papera4 | letterpage size (default letter)
printablefalsedefault = paper copy (URLs expanded for print); false = electronic (clickable links)
downloadtrueforce a download (attachment) instead of opening inline
fileNametemplatePDF filename; {a.b} placeholders filled from the resume data, e.g. {main.fullName} - resume - Acme.pdf
templatenamepresentation template (default default)

Text — the core building block

Most content fields take a Text value. A Text is either a plain string, or an object when a field needs more than words:

fieldtypedescription
text string The text content (optional — a name-only or link-only object is valid). May contain inline HTML (<strong>, <nobr>, <a>).
class string Extra CSS class(es) added to the rendered element — your hook for custom styling.
url string Makes the text a link to this href.
printUrl string URL printed as text in the paper copy (expanded by @media print).
name string Bold label prefix, rendered as "<strong>name:</strong> ".
leadingLink object

What it buys you:

So these are all valid Text values:

"A plain string"

{ "text": "Portfolio", "url": "https://example.com" }

{ "name": "Email", "text": "you@example.com" }

Envelope

meta (optional — head / SEO)

Head/SEO data (OpenGraph etc.). Entirely optional — omit it if you just want a PDF.

fieldtypedescription
summaryShort string One-line summary → <meta name="description"> and og:description.
links object Head-only links (favicon, canonical URL, social image).

links — item fields

Head-only links (favicon, canonical URL, social image).

fieldtypedescription
favicon string Favicon URL for the HTML page.
resume string Canonical URL of the published resume → og:url.
avatar object Social-preview image (OpenGraph).

Head-only — produces <meta> / OpenGraph tags in <head>, so there is no visible block to preview.

main (identity)

Identity block: name + contacts, rendered as the top header.

fieldtypedescription
fullName string Required. Your name → page <h1>, document title, og:title. The only truly required field.
contacts object[] Header contact links (email, phone, profiles, location).

contacts — item fields

A single contact line in the header.

fieldtypedescription
class string Contact kind — drives the icon and print ordering: 'linkedin' | 'phone' | 'email' | 'github' | 'portfolio' | 'location'.
text string Required. Display text, e.g. the email address or handle.
url string Live href (mailto:, tel:, profile URL).
printUrl string URL printed as text on the paper copy.
example — data
{
  "fullName": "Jane Doe",
  "contacts": [
    {
      "class": "email",
      "text": "jane@example.com",
      "url": "mailto:jane@example.com"
    },
    {
      "class": "phone",
      "text": "+1 (555) 010-0000"
    },
    {
      "class": "location",
      "text": "City, Country"
    },
    {
      "class": "linkedin",
      "text": "in/janedoe",
      "url": "https://www.linkedin.com/in/janedoe"
    }
  ]
}

Sections

Each item in sections[] is one of these, picked by its type. All also carry class and hidden.

type: "title"

Role headline shown under your name (e.g. "Solution Architect").

fieldtypedescription
type "title" Required.
class string Extra CSS class(es) added to the rendered element — your hook for custom styling.
hidden boolean | "print" Hide this block. true → hidden everywhere; 'print' → shown on screen but hidden on the PDF/paper copy.
title Text Required.
example — data
{
  "type": "title",
  "title": "Senior Software Engineer"
}

type: "summary"

Opening summary paragraph (the elevator pitch under the title).

fieldtypedescription
type "summary" Required.
class string Extra CSS class(es) added to the rendered element — your hook for custom styling.
hidden boolean | "print" Hide this block. true → hidden everywhere; 'print' → shown on screen but hidden on the PDF/paper copy.
summary Text Required.
example — data
{
  "type": "summary",
  "summary": "A concise opening statement summarizing experience, focus, and strengths."
}

type: "text"

Generic content block: optional heading + paragraph + bullet list. Each piece renders only when present.

fieldtypedescription
type "text" Required.
class string Extra CSS class(es) added to the rendered element — your hook for custom styling.
hidden boolean | "print" Hide this block. true → hidden everywhere; 'print' → shown on screen but hidden on the PDF/paper copy.
title Text
text Text
items Text[] List items → <ul><li>, or a comma list when inline.
inline boolean Render text + items + notes on one line instead of a list.
notes string Trailing text after the list.
nobrItems boolean Wrap each multi-word item in <nobr> so it never breaks across lines.
example 1 — data
{
  "type": "text",
  "title": "About",
  "text": "A short paragraph of body copy.",
  "items": [
    "First highlight",
    "Second highlight"
  ]
}
example 2 — data
{
  "type": "text",
  "title": "Languages",
  "items": [
    "English",
    "German",
    "Ukrainian"
  ],
  "inline": true
}

type: "skills"

Key skills / competencies, one per bullet.

fieldtypedescription
type "skills" Required.
class string Extra CSS class(es) added to the rendered element — your hook for custom styling.
hidden boolean | "print" Hide this block. true → hidden everywhere; 'print' → shown on screen but hidden on the PDF/paper copy.
title Text
skills Text[] Required. Skill bullets; each a Text (often "<strong>Area:</strong> detail").
example — data
{
  "type": "skills",
  "title": "Key Skills",
  "skills": [
    {
      "name": "Focus Area",
      "text": "short description of the skill"
    },
    "Another skill"
  ]
}

type: "technologies"

Flat technologies/tools block.

fieldtypedescription
type "technologies" Required.
class string Extra CSS class(es) added to the rendered element — your hook for custom styling.
hidden boolean | "print" Hide this block. true → hidden everywhere; 'print' → shown on screen but hidden on the PDF/paper copy.
title Text
technologies string | object[] Required. Technologies and tools.

technologies — item fields

fieldtypedescription
list string[] Required. Grouped technologies rendered together.
example — data
{
  "type": "technologies",
  "title": "Technologies",
  "technologies": [
    "Language A",
    "Framework B",
    {
      "list": [
        "Tool C",
        "Tool D"
      ]
    }
  ]
}

type: "experience"

Professional experience. Consecutive entries at the same company are merged into one block with multiple positions.

fieldtypedescription
type "experience" Required.
class string Extra CSS class(es) added to the rendered element — your hook for custom styling.
hidden boolean | "print" Hide this block. true → hidden everywhere; 'print' → shown on screen but hidden on the PDF/paper copy.
title Text
experience object | string[] Required. Work history, newest first. A plain string between items is a relocation marker, rendered as a captioned <hr>.

experience — item fields

One job: company, role, dates, description, achievements, tech.

fieldtypedescription
company string | null Required. Employer name. null = freelance/independent.
project string | null Product/client shown after the role as "› project".
position string Required. Job title.
location string City, country.
startDate string Required. ISO date as year-month, e.g. "2021-06".
endDate string | null Required. ISO date as year-month, e.g. "2021-06".
description Text
achievements Text[] Bullet list of accomplishments.
technologies string[] Tech/tools used, joined into a "Technologies:" line.
hidden boolean | "print" Hide this block. true → hidden everywhere; 'print' → shown on screen but hidden on the PDF/paper copy.
isFreelance boolean Tags the entry as freelance (shows a "(freelance)" marker).
class string Extra CSS class(es) added to the rendered element — your hook for custom styling.
example — data
{
  "type": "experience",
  "title": "Experience",
  "experience": [
    {
      "company": "Example Company",
      "position": "Job Title",
      "location": "City, Country",
      "startDate": "2021-01",
      "endDate": null,
      "description": "A short summary of the role and scope.",
      "achievements": [
        "A notable result or accomplishment",
        "Another measurable outcome"
      ],
      "technologies": [
        "Tech A",
        "Tech B"
      ]
    }
  ]
}

type: "projects"

Selected projects / portfolio highlights.

fieldtypedescription
type "projects" Required.
class string Extra CSS class(es) added to the rendered element — your hook for custom styling.
hidden boolean | "print" Hide this block. true → hidden everywhere; 'print' → shown on screen but hidden on the PDF/paper copy.
title Text
projects Text[] Required. Selected projects; each a Text (string, or object with a link/label).
example — data
{
  "type": "projects",
  "title": "Selected Projects",
  "projects": [
    {
      "name": "Project Name",
      "text": "a short description of the project",
      "url": "https://example.com"
    },
    {
      "leadingLink": {
        "text": "Link to project",
        "url": "https://resume.hire-me.now/render",
        "printUrl": "resume.hire-me.now/render"
      },
      "text": "service that renders a resume from a JSON schema supporting multiple formats and themes",
      "class": "print-condensed-01"
    },
    "Another project"
  ]
}

type: "volunteering"

Volunteer / community work.

fieldtypedescription
type "volunteering" Required.
class string Extra CSS class(es) added to the rendered element — your hook for custom styling.
hidden boolean | "print" Hide this block. true → hidden everywhere; 'print' → shown on screen but hidden on the PDF/paper copy.
title Text
volunteering object[] Required. Volunteering entries, newest first.

volunteering — item fields

One volunteering entry.

fieldtypedescription
project string Initiative/project name, shown before the role.
position string Required. Your role.
startDate string ISO date as year-month, e.g. "2021-06".
endDate string | null ISO date as year-month, e.g. "2021-06".
description Text
hidden boolean | "print" Hide this block. true → hidden everywhere; 'print' → shown on screen but hidden on the PDF/paper copy.
class string Extra CSS class(es) added to the rendered element — your hook for custom styling.
example — data
{
  "type": "volunteering",
  "title": "Volunteering",
  "volunteering": [
    {
      "position": "Role",
      "project": "Organization",
      "startDate": "2022-01",
      "endDate": null,
      "description": "A short summary of the contribution."
    }
  ]
}

type: "education"

Education, courses, and certifications.

fieldtypedescription
type "education" Required.
class string Extra CSS class(es) added to the rendered element — your hook for custom styling.
hidden boolean | "print" Hide this block. true → hidden everywhere; 'print' → shown on screen but hidden on the PDF/paper copy.
title Text
education object[] Required. Education entries, newest first.

education — item fields

One degree / course / certification.

fieldtypedescription
position string Required. Degree, course, or certification name.
company string Institution / school.
project string Department or specialization.
location string City, country.
startDate string ISO date as year-month, e.g. "2021-06".
endDate string ISO date as year-month, e.g. "2021-06".
description Text
hidden boolean | "print" Hide this block. true → hidden everywhere; 'print' → shown on screen but hidden on the PDF/paper copy.
class string Extra CSS class(es) added to the rendered element — your hook for custom styling.
example — data
{
  "type": "education",
  "title": "Education",
  "education": [
    {
      "position": "Degree or Certification",
      "company": "Institution",
      "location": "City",
      "startDate": "2010",
      "endDate": "2014"
    }
  ]
}

Styling system

There are three render contexts, each a class prefix: screen-* (on-screen), mobile-* (≤ 600px), print-* (PDF / paper). Utility class names follow {context?}-{function}-{impact?} — the impact is the value with a leading zero for the integer part (005 = 0.05, 11 = 1.1).

The class field — on any section, item, or Text — is your styling hook.

Typography

screenmobileprinteffect
text-08font-size 0.8rem (children too)
text-09font-size 0.9rem
text-11font-size 1.1rem
text-12font-size 1.2rem
unaccentedfont-weight: normal
screen-expanded-01mobile-expanded-01print-expanded-01letter-spacing +0.1pt
screen-condensed-004print-condensed-004letter-spacing −0.04pt
screen-condensed-005mobile-condensed-005print-condensed-005letter-spacing −0.05pt
screen-condensed-01mobile-condensed-01print-condensed-01letter-spacing −0.1pt
screen-condensed-015mobile-condensed-015letter-spacing −0.15pt
screen-condensed-02mobile-condensed-02print-condensed-02letter-spacing −0.2pt
mobile-condensed-03letter-spacing −0.3pt

Visibility & spacing

screenmobileprinteffect
hiddenremove entirely
margins-05-0margin 0.5rem top & bottom
print-hiddenhide on paper only (same as hidden: "print")
print-no-break-blockkeep the block together on one page