From ea4994692712586a926cdf18cb7b2b904ddccb0a Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Mon, 4 May 2026 19:58:43 +0200 Subject: [PATCH] spec: md-to-pdf skill design (v1) --- .../2026-05-04-md-to-pdf-skill-design.md | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-04-md-to-pdf-skill-design.md diff --git a/docs/superpowers/specs/2026-05-04-md-to-pdf-skill-design.md b/docs/superpowers/specs/2026-05-04-md-to-pdf-skill-design.md new file mode 100644 index 0000000..12d06a1 --- /dev/null +++ b/docs/superpowers/specs/2026-05-04-md-to-pdf-skill-design.md @@ -0,0 +1,126 @@ +# md-to-pdf Skill — Design Spec + +**Date:** 2026-05-04 +**Author:** Jean-Luc Makiola +**Status:** Approved (pending implementation) + +## Goal + +Provide a globally available Claude Code skill that converts the user's working Markdown file to a PDF on demand, triggered by natural language ("exportier mal", "mach das als PDF", "regenerate the PDF") rather than a slash command. The skill is distributed as a Claude Code plugin via a self-hosted Gitea marketplace, so installing it once on each device makes it permanently available with auto-updates. + +## Non-Goals + +- Other output formats (DOCX, HTML, EPUB) — out of scope, kept open for later. +- Watch mode or batch (`--all`) conversions — not part of the current workflow. +- Multiple named style presets — a single sensible default plus per-project override is enough. +- Slash command UX — explicitly excluded; the trigger is the skill description. + +## Distribution + +The repository is published to Gitea (`gitea./jlmak/claude-md-to-pdf`) using Claude Code's plugin marketplace format. On each device, the user runs once: + +``` +/plugin marketplace add https://gitea./jlmak/claude-md-to-pdf +/plugin install md-to-pdf@claude-md-to-pdf +``` + +After that, Claude Code's plugin update mechanism handles new versions. + +## Repository Layout + +``` +claude-md-to-pdf/ +├── .claude-plugin/ +│ └── marketplace.json # marketplace manifest, lists the md-to-pdf plugin +├── plugins/ +│ └── md-to-pdf/ +│ ├── .claude-plugin/ +│ │ └── plugin.json # plugin manifest (name, version, description) +│ └── skills/ +│ └── md-to-pdf/ +│ ├── SKILL.md # trigger description + instructions +│ └── default.config.js # bundled md-to-pdf style config +├── docs/ +│ └── superpowers/specs/ +│ └── 2026-05-04-md-to-pdf-skill-design.md (this file) +├── README.md +└── LICENSE +``` + +The `default.config.js` is a verbatim copy of the user's proven A4 / small-table CSS currently used in the Databases project. + +## Skill Trigger + +The SKILL.md description is written so Claude's skill-matcher activates on natural-language requests in either German or English. Examples that must trigger: + +- "exportier mal das PDF" +- "mach mir daraus ein PDF" +- "regenerate the PDF" +- "PDF neu generieren" +- "convert this markdown to pdf" + +The description is explicit enough to *not* trigger on unrelated PDF requests (e.g. "open this PDF", "show me the lecture PDF"). + +## Skill Behavior + +When invoked, the skill follows this flow: + +### 1. Identify the source `.md` + +Order of resolution: + +1. A `.md` path explicitly mentioned in the user's most recent message. +2. The `.md` file most recently read or written in the current session, if unambiguous. +3. The single most-recently-modified `.md` file in the current working directory. +4. If none of the above resolves to a single file, the skill asks the user which file to convert. + +### 2. Resolve the config + +1. Walk upward from the source `.md` looking for `.md-to-pdf.config.js`. Use the first one found. +2. Otherwise, fall back to the bundled `default.config.js` shipped with the skill (`${CLAUDE_PLUGIN_ROOT}/skills/md-to-pdf/default.config.js`). + +### 3. Run the converter + +``` +npx --yes md-to-pdf --config-file +``` + +The output PDF is written next to the source (`Loesung.md` → `Loesung.pdf`), overwriting an existing file. + +### 4. Confirm + +Report back: PDF path, byte size, and which config was used (project vs. bundled default), so the user can tell at a glance which style applied. + +## Default Config + +The bundled `default.config.js` mirrors the user's current setup — A4, 15mm/12mm margins, 5pt fixed-layout tables with no wrap, system sans-serif at 11pt. Optimized for German university homework with wide tables. + +Project-local `.md-to-pdf.config.js` files always win, so the default is just a sensible fallback. + +## Error Handling + +Boundaries where validation is needed: + +- **`npx` / Node not available** → surface a clear error pointing the user to install Node. +- **`md-to-pdf` package fetch fails** → relay the npx error directly; don't retry silently. +- **Source `.md` ambiguous** → ask the user to disambiguate (do not guess). +- **Config file syntactically broken** → relay the error from md-to-pdf; don't try to "fix" the user's config. + +Internal calls between skill steps trust each other; no defensive validation between them. + +## Testing Strategy + +Manual smoke tests on first commit: + +1. Run skill in the existing Databases project — must regenerate `Uebungen/03/Loesung.pdf` and visually match the current output (same layout, fonts, table rendering). +2. Run skill in a fresh directory with no `.md-to-pdf.config.js` — must produce a PDF using the bundled default. +3. Run skill where the source `.md` is ambiguous — must ask, not guess. + +No automated test suite for v1; the toolchain is a thin wrapper over `npx md-to-pdf`. + +## Open Questions + +None blocking. Future considerations (not part of v1): + +- Should the bundled default eventually grow into multiple presets (homework / article / slides)? +- Should the skill help bootstrap a project-local `.md-to-pdf.config.js` on request?