ljg-cards: ljg-skills: The Claude Code Repo That Treats Design Like a Scoring Problem

Inside `ljg-card`, raw text is parsed for meaning first, assigned visual weight next, and rendered into polished PNG cards with headless-browser typography.

12 min read • View on GitHub • More from lijigang

A wide desk scene where messy notes are fed into a print press and emerge as a neat stack of finished cards. The image explains that the repo's core move is to judge what matters before it decides how to render it.
The hard part is not drawing the card. It is deciding what deserves space on it.
Key Takeaways

The judgment happens before the layout

Most text-to-image tools start with the canvas. `ljg-card` starts with judgment. It asks what matters, weighs each block, and then decides how much room it deserves before the browser ever renders a pixel.

That is the reason this repo feels different from a normal card generator. It does not simply pour Markdown into a template. It turns structure into a semantic problem, then lets rendering follow that decision.

Inside `SKILL.md`: the visual-weight engine

The heart of the skill lives in instructions, not in a giant codebase. `SKILL.md` tells the model how to classify content, assign weight to each element, and split long input into cards without breaking the logic of the page.

// Simplified visual-weight model
const weight = {
  h1: chars => chars * 6.0,
  h2: chars => chars * 4.0,
  quote: chars => chars * 2.4,
  p: chars => chars * 1.4,
};

// Keep adding blocks until the total crosses the card limit,
// then split at a sensible boundary and continue.

The key move is separating interpretation from rendering. The model decides structure, then the browser turns that decision into a finished image.

The interesting trade-off is that this makes the model do a little math and a lot of editorial judgment. In return, the layout becomes adaptive. A short quote can carry more visual weight than a long paragraph, and an orphaned header can be avoided because the split logic understands structure, not just character counts.

Why Playwright is part of the design system

A browser window is shown like a typesetting machine, with glyphs, line boxes, and a screenshot frame being aligned by careful mechanical tools. The image explains why the repo uses a headless browser instead of a simpler canvas pipeline.
The browser is doing more than capture. It is acting like a typesetter with full CSS and font rendering.

This is where the stack gets practical. Playwright and Chromium give the skill access to the full browser rendering model, which means flexbox, font faces, and sub-pixel anti-aliasing all work the way a designer expects them to work.

That matters most for CJK typography. A canvas library can place text, but a browser can typeset it. For a card meant to look polished on a phone, that difference is the whole game.

await page.goto(fileUrl);
await page.setViewportSize({ width, height });
await page.screenshot({ path: output, fullPage: true });

The repo is a skill stack, not a single trick

Hedcut-style portrait of Li Jigang based on his public GitHub avatar. It places the repo's creator in the context of a broader skill stack, not just one card generator.

`ljg-card` sits inside a wider ecosystem. The repo also includes skills like `ljg-learn`, `ljg-plain`, `ljg-writes`, and `ljg-paper`, plus workflow chains such as `ljg-paper-flow` and `ljg-word-flow` that hand work from one skill to another.

值钱的不是 7 个 skill 本身,而是它把“理解内容 → 重写表达 → 视觉转译”做成了一套可拼装的工作流。

Simon的白日梦, Technology Blogger · Sina interview

That is the real product strategy. The repo is not just shipping prompts. It is turning content work into a modular workflow where understanding, rewriting, and visual output can be chained together instead of handled in isolated tools.

What it replaces, and where it wins

ApproachLayout logicTypographyAdaptabilityOutput
`ljg-card`LLM scores content first, then splits by visual weightBrowser-rendered CSS with strong CJK supportHigh, because structure can change with content densityPolished PNG cards
Fixed-template generatorsRules and slots decide everything up frontOften fine, but rigidLow, because the template is the productStatic social cards
Canvas or PIL renderersManual placement or simple text flowFunctional, but less nuancedMedium, but hard to make editorialRaster images
AI note toolsSummarize or reorganize text, not render itNo real typesetting pipelineHigh for notes, low for visual outputsText inside an app
A split composition shows a rigid template on one side and a judgment-driven layout on the other. The image explains the difference between forcing text into boxes and giving content room based on importance.
The advantage is not that one side is prettier. It is that one side understands structure before it draws.

The win is not that `ljg-card` makes images. The win is that it decides structure first and presentation second. That is why it feels closer to editorial production than to a simple export button.

Why this feels like agentic design

The broader idea here is bigger than one repo. `ljg-skills` shows a pattern where the model does the reading, the editing, and part of the layout strategy, while the browser becomes the typesetter that makes the result concrete.

That is a useful split. It keeps the judgment where language models are strong and the rendering where browsers are strong. The result is not just automation. It is a design system with an editor in the loop.