# Mode: latex — LaTeX/Overleaf CV Export Export a tailored, ATS-optimized CV as a `.tex` file and compile it to PDF via `tectonic` or `pdflatex`. ## Pipeline 1. Read `cv.md` as source of truth 2. Read `config/profile.yml` for candidate identity and contact info 3. Ask the user for the JD if not already in context (text or URL) 4. Extract 15-20 keywords from the JD 5. Detect JD language → CV language (EN default) 6. Detect role archetype → adapt framing 7. Rewrite Professional Summary injecting JD keywords (same rules as `pdf` mode — NEVER invent skills) 8. Select top 3-4 most relevant projects for the offer 9. Reorder experience bullets by JD relevance 10. Inject keywords naturally into existing achievements 11. Build a JSON payload (see schema below) and write to `/tmp/cv-{candidate}-{company}.json` 12. Run: `node build-cv-latex.mjs /tmp/cv-{candidate}-{company}.json output/cv-{candidate}-{company}-{YYYY-MM-DD}.tex` 13. Run: `node generate-latex.mjs output/cv-{candidate}-{company}-{YYYY-MM-DD}.tex output/cv-{candidate}-{company}-{YYYY-MM-DD}.pdf` *(Replace `{candidate}`, `{company}`, `{YYYY-MM-DD}` with actual values.)* 14. Report: .tex path, .pdf path, file sizes, section count, keyword coverage % **Requires:** `tectonic` (preferred — `brew install tectonic`, auto-downloads packages) or `pdflatex` (MiKTeX / TeX Live) on PATH. ## Language support - **Localized section titles are fine.** The validator counts `\section{}` blocks instead of matching English titles, so a Spanish/French/German CV (e.g. `\section{Educación}`) validates normally. - **CJK (Japanese / Chinese / Korean) is NOT supported on this path yet.** The template is a pdfLaTeX / Computer-Modern setup with no CJK font, so kana/kanji/hangul cannot render. `generate-latex.mjs` detects CJK characters and stops with guidance. For a Japanese CV, use `pdf` mode (HTML → PDF), which renders CJK via a `lang="ja"` font fallback. ## JSON Input Schema Write a JSON file with this structure. `build-cv-latex.mjs` handles template merge and LaTeX escaping — no need to escape special characters yourself. ```json { "name": "Jane Smith", "contact_line": "San Francisco, CA | +1 415 555 0100", "email": { "url": "jane@example.com", "display": "jane@example.com" }, "linkedin": { "url": "https://linkedin.com/in/janesmith", "display": "linkedin.com/in/janesmith" }, "github": { "url": "https://github.com/janesmith", "display": "github.com/janesmith" }, "education": [ { "institution": "University Name", "location": "City, State", "degree": "Bachelor of Science in Computer Science", "dates": "2018 - 2022", "coursework": ["Data Structures", "Algorithms", "Machine Learning"] } ], "experience": [ { "company": "Company Name", "role": "Job Title", "location": "Remote", "dates": "June 2022 - Present", "bullets": [ "Achievement bullet with JD keywords injected", "Another bullet with quantified impact" ] } ], "projects": [ { "name": "Project Name", "context": "Tech stack summary for the project line", "dates": "", "bullets": [ "What you built and what it does" ] } ], "skills": [ { "category": "Languages", "items": "Python, JavaScript, C++" }, { "category": "Frameworks", "items": "FastAPI, React, PyTorch" } ] } ``` ### Field reference | Field | Type | Source | |-------|------|--------| | `name` | string | `profile.yml → candidate.full_name` | | `contact_line` | string | Phone / City, State / Visa — built from profile.yml | | `email.url` | string | Email for `\href{mailto:...}` (sanitized via sanitizeUrl, not LaTeX-escaped) | | `email.display` | string | Display text for the email link | | `linkedin.url` | string | Full URL with scheme for `\href{}` (sanitized via sanitizeUrl, not LaTeX-escaped) | | `linkedin.display` | string | Display text only (no scheme) | | `github.url` | string | Full URL with scheme for `\href{}` (sanitized via sanitizeUrl, not LaTeX-escaped) | | `github.display` | string | Display text only (no scheme) | | `education[].institution` | string | From cv.md Education | | `education[].location` | string | Institution location | | `education[].degree` | string | Degree name | | `education[].dates` | string | Date range | | `education[].coursework` | string[] | Optional — generates a coursework line if present | | `experience[].company` | string | From cv.md Experience | | `experience[].role` | string | Job title | | `experience[].location` | string | Work location | | `experience[].dates` | string | Date range | | `experience[].bullets` | string[] | Reordered and keyword-injected achievement bullets | | `projects[].name` | string | From cv.md Projects | | `projects[].context` | string | Tech stack — appears next to project name | | `projects[].dates` | string | Date range (or empty) | | `projects[].bullets` | string[] | Selected project achievements | | `skills[].category` | string | Skill category name (e.g. "Languages", "Frameworks") | | `skills[].items` | string | Comma-separated skills in that category | ## LaTeX Escaping (handled by the script) `build-cv-latex.mjs` automatically escapes all user-supplied text before insertion: | Character | Escape | |-----------|--------| | `&` | `\&` | | `%` | `\%` | | `$` | `\$` | | `#` | `\#` | | `_` | `\_` | | `{` | `\{` | | `}` | `\}` | | `~` | `\textasciitilde{}` | | `^` | `\textasciicircum{}` | | `\` | `\textbackslash{}` | | `±` | `$\pm$` | | `→` | `$\rightarrow$` | **Exception:** URLs inside `\href{}` are NOT escaped by the LaTeX escaper, but `sanitizeUrl()` still validates the scheme (mailto/http/https) and removes dangerous characters to prevent injection. ## ATS Rules (same as pdf mode) - Single-column layout (enforced by template) - Standard section headers: Education, Work Experience, Personal Projects, Technical Skills - UTF-8, machine-readable via `\pdfgentounicode=1` - Keywords distributed: first bullet of each role, skills section - No images, no graphics, no color in body text ## Keyword Injection Strategy Same ethical rules as `modes/pdf.md`: - NEVER add skills the candidate doesn't have - Only reformulate existing experience using JD vocabulary - Examples: - JD says "RAG pipelines" → reword "LLM workflows with retrieval" to "RAG pipeline design" - JD says "MLOps" → reword "observability, evals" to "MLOps and observability" ## Overleaf Compatibility The generated `.tex` file uses only standard CTAN packages (no custom or bundled dependencies): - `latexsym`, `fullpage`, `titlesec`, `marvosym`, `color`, `verbatim`, `enumitem` - `hyperref`, `fancyhdr`, `babel`, `tabularx`, `fontawesome5`, `multicol`, `glyphtounicode` Upload the `.tex` file directly to Overleaf — compiles with no extra configuration.