My resume lives in a .tex file. Most people compile that to PDF and upload it somewhere. I wanted the source of truth to be the website — edit the LaTeX, refresh, done.
The approach
latex.js is a full LaTeX parser and HTML generator that runs in the browser. Feed it a document, get back a DOM fragment:
const { parse, HtmlGenerator } = await import("latex.js");
const generator = new HtmlGenerator({ hyphenate: false });
const doc = parse(source, { generator });
container.append(doc.domFragment());
No server round-trip, no headless TeX Live install, no 400MB Docker image. The whole thing happens client-side after hydration.
Sharp edges
- It's a subset. latex.js implements core LaTeX — sections, lists, tabular-ish layouts, text formatting. Your 400-package
moderncvresume will not compile. Write vanillaarticleclass and it works. - Styling fights you. The generated HTML ships with its own CSS meant to mimic paper. I render it on a white "sheet" against the dark UI instead of fighting it — it reads as a document preview, which is what a resume is.
- SSR is off the table. The generator touches
documentat parse time, so it must run in auseEffectafter mount. Show the raw source as a fallback while it loads — on a fast connection you never see it.
Was it worth it?
Yes. One file drives the printed resume and the web version. And there is something deeply satisfying about a portfolio that compiles LaTeX on the fly while pretending to be a terminal.