Build write-up

Ask my CV

How I turned my CV into one YAML source of truth, five renderers, and a digital twin you can talk to - and had an AI agent build most of it.

Don't read my CV. Ask it.

There is a chat box on my CV site. It answers questions about my work in my own grounding, not a generic model's guesses.

Try it with something a recruiter would actually ask: "What has Jin-Ho done with RNA-Seq data?" or "Does he have production ML experience, or only research?" or "Summarize his last three years in two sentences."

The rest of this post is how that box - and the CV behind it - is built, and why I built it that way.

One source of truth, many renderers

The CV is not a document. It is data: a set of YAML files plus a BibTeX bibliography, with a JSON Schema that every field is validated against.

Nothing that presents the CV reads from a rendered artifact. The PDF, the website, a JSON Resume export, a schema.org JSON-LD graph, and a plain-text version are all independent scripts that consume the same content. Swap any one of them and the others do not notice.

That inversion - content knows nothing about presentation - is the whole design. A new output format is a new consumer, never a new copy of the data. The digital twin is just the sixth consumer.

The twin: full context, not retrieval

The obvious way to build a CV chatbot in 2026 is retrieval-augmented generation: chunk the CV, embed it, fetch the top matches per question. I did not do that.

A whole CV is small - well under the context window of any current model. So a build step compiles the entire CV into one Markdown blob and the model gets all of it on every question. No retrieval step means no retrieval mistakes: the model never fails to fetch the one bullet that mattered.

There is a deliberate asymmetry here. The public site is a sharp, curated selection. The twin reads from a larger, gitignored "master" overlay - a superset life-database that never ships to the public HTML. The twin can therefore answer questions the crawled page cannot, which is exactly the reason to talk to it instead of scraping the site.

Running an LLM for free, reliably

The twin runs on a Cloudflare Worker with no paid inference bill. It uses free model tiers, and free tiers have daily request caps.

So the Worker does not depend on one model. It cascades: a best-first chain of Gemini and Gemma models, and when every one of those is exhausted or erroring, it falls through to a different vendor entirely (Cloudflare Workers AI). Each rung has its own separate quota, so chaining them multiplies the daily headroom instead of dying when the top model's quota runs out.

Getting this right meant learning each family's quirks the hard way - which models need a "thinking" budget set to zero, which reject that setting outright, which stream their reasoning as tokens you have to filter out before the answer reaches the browser. The cascade is boring on purpose: the twin stays reachable.

Guardrails, and keeping PII out

A CV site has real private data behind it - a phone number, an address - that must never leak into a public repo or a model's mouth.

So the same PII guard runs on three surfaces: a pre-commit hook, an editor-tool hook, and a CI check. All three call one detection core, so there is a single place to be right. Private files live outside git entirely; the guard is the backstop for the day someone runs git add -f.

The twin has its own guardrails: a bot-check on the browser, per-visitor rate caps, and persona rules that keep it answering as a grounded CV assistant rather than a general chatbot. Consented contact details a visitor chooses to leave are the one thing kept deliberately, because that is the point of leaving them.

Built by directing an agent

I did not hand-write most of this. I directed an AI coding agent through it, in fifteen phases, each one a loop: brainstorm the scope, write a spec, turn the spec into a step-by-step plan, then execute the plan task by task with a fresh agent per task and a review gate between them.

Tests came first where it mattered - the schema, the renderers, the guards all have failing tests written before the code. The interesting skill in 2026 is not typing the code. It is decomposing the work so an agent can do it correctly, and knowing what to reject when it comes back wrong.

The whole history is public, spec files and all. If you want to see what agent-directed engineering actually looks like as a git log, it is right there.

What it cost, and where to look

Nothing, in running costs. Static hosting, a free Worker tier, free model tiers, free CI. The bounded pieces are bounded on purpose.

The code, every spec, and the full build history: https://github.com/Jin-HoMLee/jin-ho-lee-cv.

And the twin is still waiting for a question: ask it something.

Can I use this for my own CV?

Yes, with some assembly. The code and reusable templates are MIT-licensed where marked in the file-level license map. My personal CV data, portrait, and article prose are not part of that license, so replace them with your own.

This is still my working repository, not a one-command template. The PDF and static site are the easiest starting points. The digital twin is optional and needs your own Cloudflare and model configuration.

The reuse guide lists the current path and the parts that still need manual replacement.