What a MyCV document can contain
The reference for everything a document holds: sections and fields, bold and links inside text, layout, designs and exports. The in-app agent and connected AI apps follow the same rules, so a CV built in a chat matches one built by hand.
A MyCV document is one JSON object. The editor, the in-app agent, connected AI apps (MCP), the PDF, Word and LaTeX exports and the published page all read the same object, so anything described here works everywhere. This page is the reference for people and for agents; the MCP server hands out the same text through its get_cv_guide tool.
Header and contacts
| Field | What it is |
|---|---|
full_name | The name at the top of the page. |
tagline | The headline under the name, e.g. "Senior Backend Engineer". |
email, phone, location | Printed in the contact line. Email opens a mail client, phone dials, on every export. |
linkedin, website, github, twitter, behance, dribbble | Addresses without https:// are fine (linkedin.com/in/ada). Each one is a working link in the PDF, Word, LaTeX and published page. |
custom_contacts | Up to six extra {label, value} links: portfolio, Google Scholar, ORCID, a booking page. |
| Photo | Uploaded by the person with the camera button on the CV. Designs with a photo header or sidebar show it. Agents never set it. |
Sections
Every section is optional. What is printed, and in what order, is decided by section_order; the order of keys in the JSON means nothing.
| Section | Shape | Limits |
|---|---|---|
summary | One paragraph of text, 2 to 5 sentences. Takes inline formatting and links. | 3,000 characters |
experience | Entries of role, company, location, date, bullets. Most recent first. | 40 entries |
education | Entries of degree, subtitle (optional: concentration, NYSC role, class of degree), institution, location, date, bullets. | 20 entries |
projects | Entries of title, institution (the organisation or client), location, date, bullets. | 30 entries |
skills | An object of category to comma-separated list: {"Languages": "Python, Go", "Cloud": "AWS, Terraform"}. | 12 categories |
skill_levels | Optional 1 to 5 proficiency per category, drawn as dots on designs that have them. | |
awards | Items of year, title, issuer, and an optional description (why it was awarded, same formatting as a bullet). | 20 items |
custom_sections | Anything else, see below. | 10 sections |
target_job | The posting this CV is aimed at, as plain text. The ATS score uses it for its job-fit group whenever a score is not given a posting of its own, so it only has to be pasted once (the editor's ATS modal, the free check page and connected apps all save it here). | 20,000 characters |
Dates are free text printed exactly as written: Jan 2021 - Present, 2019, Summer 2023. Prefer month and year (Mar 2021 - Jun 2024): many applicant tracking systems count months of experience, and a bare year is read as January.
Every entry can carry bullets: up to 40 short achievement lines, each up to 1,500 characters. A good bullet starts with a verb and carries a number where one is true.
Every entry can carry a description: a short paragraph under the heading and before the bullets, for what the company or team does, the scope of the role, or the goal of the project. It takes the same formatting and links as a bullet. Every entry can also carry tags: a short row of the tools, languages or skills used on it (["Python", "Docker", "AWS"]), printed small under the entry. In the editor, hover an entry: the three buttons on its right add a link, a description and a skills row.
Every entry, and every award, can also carry a url. The title then opens that address: the company's site on a job, the repository or live demo on a project, the certificate page on a certification, the paper on a publication. In the editor, hover an entry and press its link button; the title shows in the design's accent colour, and it is a working link in the PDF, Word, LaTeX and published page. Agents set "url" on the entry.
Custom sections
A custom section covers what the built-ins do not: certifications, languages, publications, volunteering, references, interests. Each has an id starting with cs_ (for example cs_certifications), a title, and one of four section_type bodies.
section_type | Body | Good for |
|---|---|---|
entries | entries of title, subtitle, location, date, bullets, plus for certifications expiry, credential_id and a url to the verification page. In the editor, a certifications section offers "Fill from Credly / Coursera link", which reads the badge page into these fields. | Certifications, publications, volunteering, courses |
bullets | A plain bullets list | Achievements, memberships, references on request |
keyval | keyval pairs of label and value | Languages (English: Native), personal details |
tags | A tags list of short words | Interests, tools, keywords |
Order, titles and hidden sections
| Key | What it does |
|---|---|
section_order | Ids in page order: summary, experience, education, projects, skills, awards, plus each custom section id. Omit it to use the design's default order. |
section_titles | Rename a built-in heading: {"experience": "Work History"}. |
hidden_sections | Ids kept in the document but not printed. |
page_breaks | What starts on a new page: section ids ("projects") and single entries as section.index ("experience.2", "cs_certifications.1"). In the editor, hover a section heading and press its page-break button, or open an entry's ⋯ menu and choose "Start on a new page". The PDF, Word and LaTeX all break in the same place. The Layout tab's "Fit to 1 page / 2 pages" tightens spacing, font scale and margins until the CV fits, and says what sits on the last page when it cannot. |
Text formatting and links
The summary and every bullet may carry a small amount of inline markup. Everything else (names, titles, dates, skills, contacts) is plain text.
| You want | Write | Stored as |
|---|---|---|
| Bold, italic, underline | In the editor: select text and use the B / I / U bar, or Ctrl+B, Ctrl+I, Ctrl+U. Agents: <b>, <i>, <u>. | <b>text</b> |
| A clickable label | In the editor: select the words, press the link button on the bar or Ctrl+K, paste the address. Agents: [Verify credential](https://www.credly.com/badges/...). | <a href="https://...">Verify credential</a> |
| An address as itself | Just type it: github.com/ada/engine or ada@example.com. | Plain text, linked automatically on export. |
| A line break | In the editor: Shift+Enter (Enter alone finishes the field). Agents: <br>. Useful for a two-paragraph summary. | first part<br>second part |
Labelled links are the right way to point at a certificate, a portfolio piece, a publication, a live demo or a repository: the page shows the label instead of a long address, and the label opens the address in the PDF, the Word file, the LaTeX build and the published page. The label prints in the design's accent colour so it reads as a link; in the PDF and on the published page a small arrow follows it as well.
Links accept http, https, mailto and tel addresses. A bare domain (credly.com/badges/...) is given https://; anything else is kept as plain text.
In the editor, click into a link to see its address, change it or remove it. An address typed as text is not linked on screen while you edit, so the words stay easy to click into, but it is linked on every export.
Layout
The layout object tunes the page without changing the design.
| Key | Values |
|---|---|
pageSize | a4, letter |
margin | narrow, normal, wide |
density | compact, normal, relaxed |
fontScale | 0.8 to 1.25 |
fontFamily | auto, serif, sans, modern |
headingCase | auto, upper, normal |
divider | auto, line, thick, none |
durations | off, on. On, each experience entry prints how long it lasted next to its dates, read from the dates as typed: Jan 2021 - Present · 5 yrs 9 mos, 2019 - 2021 · 2 yrs. Dates that cannot be read (Summer 2023) print as typed. Layout tab, "Dates". |
skillsFormat | grid (default), lines. Grid prints skills as a category / items grid, which the Word export writes as a two-column table. Lines prints each category on its own line with no table, the shape older applicant tracking systems read reliably. The ATS score checks the actual Word file and offers this switch when it finds the table. Layout tab, "Skills". |
rail | Two-column designs only: the section ids printed in the side column, in order, e.g. ["skills", "education", "awards"] (custom sections by id). Everything else prints in the main column. Leave it out for the design's default: skills, or skills and education on the designs with a full-width header. The summary stays where the design puts it. In the editor, the column button on a section's toolbar moves it between the columns. |
Designs
There are 30 designs, numbered 1 to 30. Designs 21 to 25 are Pro-exclusive; the rest come with any paid download. Designs 6, 16, 18, 20, 25, 26, 27, 29 and 30 are two-column, with a sidebar; some applicant tracking systems parse two-column pages less reliably, so single-column designs are the safer choice for online applications. The gallery on the landing page shows every design; connected AI apps can show the same gallery with show_template_gallery.
Exports and publishing
| Output | Notes |
|---|---|
| Rendered from the editor's own page, so it is exactly what you see. | |
| Word (.docx) | Pro. Rebuilt in the same design with the same fonts embedded; links stay links. |
| LaTeX | Pro. A zip with main.tex and the fonts, compiled with XeLaTeX (Overleaf works). |
| JSON backup | Pro. The document itself, for import elsewhere or safekeeping. |
| Published page | Pro. A public page at /cv/<your-link>, or on a domain you own. |
The published page
A published CV is a web page of its own, read by people rather than by applicant tracking systems, so it can be designed separately from the PDF. The page is a *page design*: a style, a theme and an ordered list of blocks. Blocks that read from the CV (experience, education, projects, skills, awards, a custom section) stay in sync with it; the others (an intro, facts, free text, an image gallery, links, the PDF itself, contact) are the page's own content. The page builder in the dashboard edits it visually; connected apps use get_page_design, set_page_design, preview_page_design (a screenshot at desktop or phone width) and list_page_styles.
| Part | What it holds |
|---|---|
style | paper, column, dark, editorial, minimal, studio, sunset, ocean or mono. Each is a designed look; switching one brings its own palette and fonts. |
base | styled (the default) or bare: structure and theme tokens only, none of the style's decoration, for a layout of your own. |
theme | accent, background, surface, ink, muted (hex colours); font_display and font_body from the font list; radius 0-40; width 480-1280; spacing compact, normal or airy; mode light, dark or auto (follows each visitor's system); toggle to offer a light/dark switch; palettes {light, dark} of background, surface, ink, muted, line, field, accent (leave one out and it is derived); preset (x, ink, slate) fills both palettes. |
blocks | {id, type, props} in page order. Types: hero, facts, section, text, gallery, links, document, contact, form, divider, and the version 2 blocks header, profile, tabs, html (below). A form block is a contact form: messages are emailed to the owner and kept under Published pages → Messages, with a hidden field and rate limits against bots. |
css | Optional custom CSS for the page, written against the hooks below. Imports, anything that runs, and images from outside MyCV are refused, with the line and column of the problem; escapes such as content:'\2600' are fine. |
nav | true for the automatic section dock, false for none, or a configured nav (below). |
seo | title (70 characters), description (160) and favicon (a MyCV upload, square PNG) for the browser tab, search results and link previews. Blank falls back to the name, headline and summary. |
Hero fields left blank fall back to the CV (name, tagline, summary, photo), so a page never needs the person's details typed twice. Hero buttons open the PDF (pdf), a contact card download (vcard), the person's email, phone, LinkedIn or website, or any link; each takes an icon (auto picks one for the action; none, download, mail, phone, linkedin, globe, arrow, github, calendar, file or card). Views, downloads and contact clicks are counted per page (the owner's own are not) and shown on the dashboard and in get_page_design. Images in a gallery or the hero must be MyCV uploads. Setting a design saves a draft; the page goes live only when the person publishes, or when a connected app is asked to publish explicitly, and a preview link is returned either way. Every reply carries a version of the design and readability warnings when the theme's text would be hard to read; a write can pass if_version so a page edited in the builder meanwhile is not overwritten.
Advanced blocks
A design that uses any of the following is on schema version 2. The page then loads MyCV's own small behaviours script; a design never carries JavaScript of its own.
| Block | What it is |
|---|---|
header | A sticky, frosted top bar: title (blank is the name), badge, subtitle, leading and trailing actions. Always the first block. |
profile | A social-style profile: cover and avatar images, name, badge (verified, verified-gold, verified-grey), handle, bio (blank is the CV summary), a meta row of icon + text (+ link), stats, actions, and a layout of social, centered or split. |
tabs | Shows other blocks inside tabs: tabs is [{name, label, blocks: [block ids]}], with style underline, pills or segmented. Keyboard, screen readers and #tab-<name> links work; without JavaScript every panel is simply on the page. |
html | Your own markup. With template: true it is a Liquid template over the live CV. |
An *action* is {label, action, url, target, icon, variant, keep_on_mobile}. action is link, email, phone, linkedin, website, pdf, vcard, theme-toggle, share, copy-link or scroll-to (with target: "#blockId"); variant is primary, outline, accent, ghost or icon. nav may be an object: {type: dock|bar|sidebar|bottom, items: [{label, icon, target | href | action}], mobile, show_labels}. Every block also takes class, extra class names for its root element.
Markup. Text and HTML blocks accept ordinary structure (div, span, section, article, headings, lists, tables, figure, img, picture, video, button, details), id, class, aria-*, data-*, and inline SVG. Scripts, style attributes, event handlers, iframes and forms are removed, and every removal is reported back, never silent. Images come from MyCV uploads. Ids you write become u-<blockId>-<id> on the page (references inside the same block follow), so style with classes. Links that leave the site open in a new tab; #fragment, relative, mailto: and tel: links stay in the page.
Icons. Any name from the icon set (about a hundred interface, status and brand glyphs) works wherever a design takes an icon, as <svg data-icon="map-pin" class="icon"></svg> in markup and as {% icon "map-pin" %} in templates. Note x is the X/Twitter logo; the close glyph is close.
Behaviours. Interactivity is declared, not written: data-theme-toggle, data-theme-set, data-tabs / data-tab / data-tab-panel, data-tab-link, data-scroll-to, data-copy, data-share, data-disclosure, data-dismiss, data-sticky, data-reveal, data-local-time.
Templates. {{ cv.full_name }}, {% for p in cv.projects %}…{% endfor %}, cv.experience, cv.education, cv.skills (category, items), cv.awards, cv.sections and cv.section["cs_id"], page, assets["name"]. Values are escaped; rich CV fields (summary, description, bullets) go through | html. Filters include hashtag, date, relative_date, where, sort_by, slugify, markdown, truncate. {% render "badge" %}, "avatar", "entry-card", "post-card" and "skill-chips" are built in. Email and phone are empty unless the page shows them, and placeholders like [your.email@example.com] are always empty. Because the template reads the CV when the page is served, editing the CV updates the page with no design change.
Tokens. --pg-background, --pg-surface, --pg-ink, --pg-muted, --pg-line, --pg-field, --pg-accent, plus computed --pg-on-accent, --pg-accent-text, --pg-accent-soft, --pg-hover, --pg-bar, --pg-primary-bg, --pg-primary-ink, and --pg-radius, --pg-width, --pg-display, --pg-body, --pg-space-1 to --pg-space-6. They switch with the palette, so CSS written against them works in light and dark.
The full DOM of every block is in [page-dom.md](page-dom.md). Every saved design is kept as a version (the last 50, and all that went live) and can be restored.
CSS hooks
Custom CSS should only use these selectors; anything else may change without notice.
| Selector | What it is |
|---|---|
.pg-main | The page column (its max-width comes from theme.width). |
.pg-block | Every block; also .pg-hero, .pg-facts, .pg-section, .pg-text, .pg-gallery, .pg-links, .pg-contact, .pg-divider. |
.pg-hero-inner, .pg-hero-media, .pg-hero-copy | The intro grid, its photo and its text column. |
.pg-eyebrow, .pg-title, .pg-subtitle, .pg-lead | The intro text, top to bottom. |
.pg-buttons, .pg-btn, .pg-btn.is-primary | Button rows and buttons; the first hero button is primary. |
.pg-contacts | The contact line under the intro. |
.pg-h2, .pg-intro, .pg-section-head | A block heading, its intro line and the row holding them. |
.pg-facts-list, .pg-fact | The facts grid and one label/value pair. |
.pg-entries, .pg-entry, .pg-entry-date, .pg-entry-title, .pg-entry-org, .pg-entry-desc, .pg-bullets, .pg-tags | A CV section and the parts of one entry. |
.pg-skills, .pg-skill-group | The skills block and one category. |
.pg-prose | A text block body. |
.pg-gallery-grid, .pg-tile | The gallery grid and one tile. |
.pg-link-list, .pg-link-label, .pg-link-note | The links block. |
.pg-nav | The floating section dock. |
.pg-header, .pg-header-inner, .pg-header-title, .pg-header-sub | The sticky top bar and its text. |
.pg-profile, .pg-cover, .pg-avatar, .pg-actions, .pg-name, .pg-handle, .pg-bio, .pg-meta, .pg-stats | The profile block, top to bottom. |
.pg-act, .pg-act.is-primary (is-outline, is-accent, is-ghost, is-icon) | Buttons in the profile, header and nav. |
.pg-tabs, .pg-tablist, .pg-tab, .pg-tab[aria-selected="true"], .pg-tabpanel | The tabs block. |
.pg-html | A free HTML block; your own classes live inside it. |
.pg-nav.is-dock (is-bar, is-sidebar, is-bottom), .pg-nav-item | A configured nav and one item. |
.icon, .pg-badge | An icon from the set, and the verified badge. |
[data-block-id], [data-block-type], [data-block-index], [data-entry-id], [data-entry-index], [data-skill-group] | Stable attributes on every block, entry and skill group, so rules never need :first-child. |
:root[data-theme="dark"], [data-base="bare"] | The theme a visitor toggled to, and the bare base. |
[data-style="paper"] | The html element carries the style id, for rules scoped to one style. |
--pg-accent, --pg-background, --pg-surface, --pg-ink, --pg-muted, --pg-radius, --pg-display, --pg-body | The theme as CSS variables on :root. |
For agents
The in-app agent and connected apps (ChatGPT, Claude, Cursor and any MCP client) write the same object.
- Follow the
cv_dataschema published by the MCP server'screate_cvandupdate_cvtools.update_cvmerges: send only the keys that change. - Section order comes from
section_orderonly. skillsis an object of category to comma-separated list, not an array.- Never invent employers, dates, degrees or numbers. Leave an unknown detail out and say so.
- Write links as
[label](https://url)in the summary or a bullet. They are stored as anchors and are clickable in every export. - Set
"url"on an entry or award to make its title a link. Use<br>for a line break inside a summary or bullet. List section ids orsection.indexentries inpage_breaksto start them on a new page;preview_cvandfit_layoutreport which page each section lands on. - Give an entry a
"description"(one short paragraph) and"tags"(the tools and skills used) when the person's story has them; setlayout.durationsto"on"when they want the length of each role shown; setlayout.skillsFormatto"lines"when the CV is going through an applicant tracking system. On a two-column design, setlayout.railwhen the person wants a section in, or out of, the side column. - Save the posting the person is applying to as
target_job;score_cvthen scores job fit without being handed the text each time. - Tell the person whenever the design or the section order changes;
update_cvsays so in its reply. - To shape the published page, read it with
get_page_design, edit the object and send it back withset_page_design(pass itsversionasif_version), then look at the result withpreview_page_designbefore showing the person the preview link, and publish only withpublish: trueonce they agree. A site they admire can be echoed through the style, theme and custom CSS, never by writing HTML. import_github_projectsadds a public GitHub profile's repositories to the projects section (name, link, description, language, topics, active years); nothing is invented, and the person should be told what was added.upload_page_imagestores a public image address or base64 bytes on MyCV's CDN for the page design, and can set it as the intro photo or the tab icon directly.list_page_messagesreads what visitors sent through aformblock.- Every write takes a version snapshot first, so the person can undo it from Progress in the editor.
- The photo is the person's own; do not set or clear
profile_photo_url.