From david-skills
Generates professional cover letters using Typst markup, compiles to PDF, and outputs version-controlled .typ source files.
npx claudepluginhub thedavidweng/skillsThis skill uses the workspace's default tool permissions.
> Tool: [Typst](https://typst.app/) ([GitHub](https://github.com/typst/typst)) — A markup-based typesetting system. Modern, lightweight alternative to LaTeX.
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Processes PDFs: extracts text/tables/images, merges/splits/rotates pages, adds watermarks, creates/fills forms, encrypts/decrypts, OCRs scans. Activates on PDF mentions or output requests.
Share bugs, ideas, or general feedback.
Tool: Typst (GitHub) — A markup-based typesetting system. Modern, lightweight alternative to LaTeX.
.typ source file. Never persist the PDF — generate it on demand with typst compile..typ file is the single source of truth. It should be human-readable and editable.Check that typst is available:
command -v typst >/dev/null 2>&1 || { echo "ERROR: typst not installed"; exit 1; }
typst --version
| Method | Command | Size |
|---|---|---|
| Homebrew (recommended on macOS) | brew install typst | ~40 MB |
| Cargo (Rust) | cargo install --locked typst-cli | Builds from source |
| Binary download | Download from GitHub Releases | ~40 MB |
Note: Typst is a single binary (~40 MB). No texlive, no multi-GB downloads. This is the whole point of choosing Typst over LaTeX for cover letters.
The template uses Times New Roman, which is pre-installed on macOS. On Linux, install it via ttf-mscorefonts-installer or substitute with a compatible serif font.
Before creating a cover letter, ask the user which paper size to use:
| Option | Typst value | When to use |
|---|---|---|
| US Letter | "us-letter" | North American employers (US, Canada) |
| A4 | "a4" | International / European employers |
Do NOT assume. If the user doesn't specify, ask. This is the only parameter that varies per letter.
Every cover letter MUST use this exact preamble. Only paper: changes based on user choice — everything else is fixed:
#set page(paper: "us-letter", margin: (top: 1in, bottom: 0.75in, left: 1in, right: 1in)) // or "a4"
#set text(font: "Times New Roman", size: 11pt, hyphenate: false)
#set par(justify: true, leading: 0.75em, spacing: 1.18em)
| Parameter | Value | Rationale |
|---|---|---|
| Paper | "us-letter" or "a4" — ask user | Depends on target country |
| Top margin | 1 inch | Standard business letter |
| Bottom margin | 0.75 inch | Slightly tighter for single-page fit |
| Left/Right margins | 1 inch | Standard |
| Font | Times New Roman, 11pt | Professional serif |
| Hyphenation | OFF | Prevents ugly word breaks |
| Line leading | 0.75em | Matches ~15.4pt actual spacing |
| Paragraph spacing | 1.18em | ~20.5pt between paragraphs |
// ── Sender address (right-aligned) ──
#align(right)[
{{SENDER_NAME}} \
{{SENDER_EMAIL}} \
{{SENDER_CITY}}, {{SENDER_REGION}}, {{SENDER_COUNTRY}}
#v(0.6em)
{{DATE}}
]
#v(1.6em)
// ── Recipient ──
{{RECIPIENT_NAME_OR_TITLE}} \
{{RECIPIENT_ORG}} \
{{RECIPIENT_DEPT}} \
{{RECIPIENT_FACULTY_OR_DIVISION}}
#v(1.5em)
// ── Salutation ──
Dear {{SALUTATION}},
// ── Body paragraphs ──
{{PARAGRAPH_1}}
{{PARAGRAPH_2}}
{{PARAGRAPH_3}}
{{PARAGRAPH_4}}
// ── Closing ──
#v(0.8em)
#align(right)[
Sincerely,
#v(0.55em)
{{SENDER_NAME}}
]
These exact #v() values produce correct visual spacing. DO NOT MODIFY:
| Location | Value | Purpose |
|---|---|---|
| After address, before date | #v(0.6em) | Small gap between address lines and date |
| After date, before recipient | #v(1.6em) | Section separator |
| After recipient, before salutation | #v(1.5em) | Section separator |
| After last body paragraph, before closing | #v(0.8em) | Slightly larger than paragraph gap |
| Between "Sincerely," and name | #v(0.55em) | Tight — electronic letter, no signature space |
\ (backslash + space after)@ symbol must be escaped: \@// text#parbreak() between body paragraphs — just leave a blank line#v() between body paragraphs — par(spacing: 1.18em) handles itpaper: per user choice)cover-letter-{slug}.typ (slug = lowercase, hyphenated short name for the role)typst compile cover-letter-{slug}.typopen cover-letter-{slug}.pdf (macOS).typ filetypst compile <filename>.typtypst compile cover-letter-{slug}.typ
That's it. One command. No need to save the PDF permanently.
cover-letter-{target-slug}.typ
Examples:
cover-letter-ubc-cel.typcover-letter-amazon-sde.typcover-letter-stripe-pm.typDo NOT enable hyphenation — it creates ugly word breaks like "coordi-nating"
Do NOT add extra #v() between body paragraphs — paragraph spacing is already set
Do NOT leave a large gap between Sincerely and the name — this is electronic, not hand-signed
Do NOT save the PDF to version control — only the .typ file matters