Skip to content
internal/cv
On this page

The CV as data: one declared TOML document rendered both as the page a reader sees and as the Person a crawler reads, so the two can never disagree.

#internal/cv

#internal/cv

Package cv holds the CV as data: one declared document, rendered as a page and as a Person.

A curriculum vitae is a record, not prose that happens to look like one -- every part of it is a field somebody could ask for by name. It is therefore declared in a TOML document and rendered from there, so the page a reader sees and the Person a crawler reads are two renderings of one source rather than two texts that have to be kept in agreement by hand.

The document is validated strictly: an unknown key anywhere, a missing required field, or an empty section is a hard error naming the offending declaration. Every section is required and non-empty, for the reason the curated project listing gives for the same rule -- an absent section would render as a heading over nothing, and there is no sensible default for a fact about a person.

Two renderings, both from [CV]:

- [RenderCVMarkdown] -- the page body, as Markdown, which the build converts like any other page content. - [CVPersonJSONLD] -- a Person carrying what the CV knows on top of the site's declared author: the job title, the summary, the languages, the schools, and every external profile.

#CVSource

Go go
const CVSource = "docs/cv.toml"

CVSource is where the home project declares its CV, relative to the project root.

#CVFormatVersion

Go go
const CVFormatVersion int64 = 1

CVFormatVersion is the document format this package reads. A document carrying anything else is a hard error, never a guess about which shape was meant.

#CVPageType

Go go
const CVPageType = "cv"

CVPageType is the page type a CV page declares in its frontmatter, which the schema-type mapping turns into ProfilePage.

#CVPersonAttr

Go go
const CVPersonAttr = "data-cv-person"

CVPersonAttr is the attribute the rendered page carries its Person in, for the SEO tag builder to lift into the head.

A directive resolves BEFORE the Markdown converter runs, so anything it emits is text the converter will rewrite: a JSON-LD script in body position comes back with the summary's link turned into an anchor tag inside a JSON string, and an HTML-escaped attribute fares no better, because the inline transforms run across attribute values too. The payload therefore crosses the conversion base64-encoded -- an alphabet with no Markdown meaning -- and is decoded into real structured data in the head, where the page's other JSON-LD is emitted.

#TopLevelKeys

Go go
var TopLevelKeys = []string{

TopLevelKeys is every key the document itself may carry.

#IdentityKeys

Go go
var IdentityKeys = []string{

IdentityKeys is every key the [identity] table may carry.

#ProfileKeys

Go go
var ProfileKeys = []string{"label", "url"}

ProfileKeys is every key an [[identity.profile]] block may carry.

#SkillKeys

Go go
var SkillKeys = []string{"category", "items"}

SkillKeys is every key a [[skills]] block may carry.

#ProjectKeys

Go go
var ProjectKeys = []string{"name", "notes", "technologies"}

ProjectKeys is every key a [[projects]] block may carry.

#InterestKeys

Go go
var InterestKeys = []string{"title", "body"}

InterestKeys is every key an [[interests]] block may carry.

#EducationKeys

Go go
var EducationKeys = []string{

EducationKeys is every key an [[education]] block may carry.

#ExperienceKeys

Go go
var ExperienceKeys = []string{

ExperienceKeys is every key an [[experience]] block may carry.

#LanguageKeys

Go go
var LanguageKeys = []string{"name", "url", "level"}

LanguageKeys is every key a [[languages]] block may carry.

#ContactKeys

Go go
var ContactKeys = []string{"body"}

ContactKeys is every key the [contact] table may carry.

#Profile

Go go
type Profile struct

Profile is one external address the CV's owner is reachable at.

#Identity

Go go
type Identity struct

Identity is who the CV is about.

#SkillGroup

Go go
type SkillGroup struct

SkillGroup is one category of skills with its items.

#Project

Go go
type Project struct

Project is one project the CV lists.

#Interest

Go go
type Interest struct

Interest is one hobby or interest with its description.

#Education

Go go
type Education struct

Education is one qualification.

#Experience

Go go
type Experience struct

Experience is one post held.

#Language

Go go
type Language struct

Language is one language spoken, with the level and an optional link.

#CV

Go go
type CV struct

CV is the whole declared document, in declared order.

#ParseCV

Go go
func ParseCV(text string, source string) (*CV, error)

ParseCV returns the CV the document text declares, naming source in every diagnostic.

It refuses, naming the offending declaration, a syntax error, an unknown key, a missing or empty required field, an empty section, a repeated entry, or a format version this package does not read.

#LoadCV

Go go
func LoadCV(path string) (*CV, error)

LoadCV returns the CV declared in the TOML document at path.

#RenderCVMarkdown

Go go
func RenderCVMarkdown(cv *CV) string

RenderCVMarkdown returns the CV as the Markdown body of a page.

Section headings are fixed, because they are the document's structure rather than one of its facts. The header block and the closing date are HTML, for the reason [renderCVHeader] gives; everything else is Markdown, so the headings enter the table of contents and the prose keeps its links and emphasis.

#CVPersonJSONLD

Go go
func CVPersonJSONLD(cv *CV, author map[string]any) (identity.Entity, error)

CVPersonJSONLD returns the Person a CV page states, as a JSON-LD document.

The identity itself -- name, url, sameAs -- comes from the site's declared author, so a CV page and the front page name the same person. What the CV adds is what a CV knows: the job title, the summary, the languages, the schools, and the external profiles it lists (folded into sameAs after the declared ones, without repeating any).

It returns [identity.ErrNoDeclaredAuthor] when the build declares no author.

#RenderCVPage

Go go
func RenderCVPage(cv *CV, author map[string]any) (string, error)

RenderCVPage returns the page body: the CV, carrying the Person it states.

#ExtractCVPerson

Go go
func ExtractCVPerson(bodyHTML string) (string, bool, error)

ExtractCVPerson returns the Person JSON a rendered CV page carries. The bool reports whether the page carried one at all.

It refuses when the attribute is there but does not decode to a JSON object -- a page that carried a broken entity would publish it as if it were a fact.

More tools from this site

  • claudestream Drive Claude Code from Python: run it as a subprocess and read its output as typed events, with async and sync sessions, sandbox policies, and tools you define in Python
  • claudewheel A TUI Claude Code Launcher that lets you have more than one profile, manage sessions lifecycle, pick the exact CC version, model to use (even older unlisted ones), pick which GitHub account to use, etc.
  • dirstat Fast, single-binary directory statistics CLI: every file under a tree grouped by format, with counts, sizes, and lines of code, as a colored terminal table or as JSON
  • fastware A batteries-included ASGI framework: msgspec JSON, a managed Granian server, dependency injection, SSE, WebSockets, auth, and a test client
  • go-toml-edit Zero-dep TOML editing library for Go with comment preservation
  • howmuchleft The fastest Claude Code statusline: context window, 5-hour, and weekly limit usage as three customizable gradient bars, rendering in about 6 ms
  • orxtra
  • pgdesign
  • predraw Declarative rendering pipeline: describe a scene in JSON and get SVG, PNG and WebP out, with light and dark style tokens, reusable components and text converted to path outlines
  • reposummary Turn a git repository's history into a Markdown journal: pick a time window or revision range and get a readable digest of what changed, optionally narrated by an LLM
  • rlsbl Release orchestration and project scaffolding CLI that bumps versions, validates a structured JSONL changelog, tags only the commit CI verified, and publishes to npm, PyPI, Go and more
  • safegit git wrapper CLI that gives each commit its own temporary index and retries ref updates on conflict, so concurrent agents share one repository
  • saferm Command-line replacement for rm that archives every deletion with a mandatory reason and the context it ran in, so deleted files can be listed, inspected and restored
  • strictcli
  • stricttest An always-on test-isolation floor: a pytest plugin and a Go env-hygiene module that make a test suite structurally unable to reach real credentials, the real HOME, the network, or the development repository.
  • wesktop A Python framework that turns an ASGI web app into a desktop application, serving it from a local Granian server and displaying it in a native OS window via pywebview
Search