14 KiB
Math Tasks Generator
Printable math worksheet generator (A4 PDF) for children aged 7–9. Claude Code is the central orchestrator: user describes a task idea → Claude creates/edits HTML templates → optional visual editor fine-tuning → PDF via Puppeteer.
Commands
pnpm build:css # Build Tailwind CSS (minified)
pnpm build:css:watch # Watch mode for CSS
pnpm preview # Serve at localhost:3300 with live-reload
pnpm dev # CSS watch + preview server (concurrent)
pnpm pdf -- <file> # Convert HTML file to PDF
pnpm remove-bg -- <file|dir> # Remove white background from PNG icons
Generate images via /gen-image skill (uses Banatie API, reads BANATIE_KEY from .env).
Directory Structure
tasks/
index.html — document index (Claude updates manually)
{task-type}/ — one folder per task type
CLAUDE.md — type-specific rules and conventions
editor.html — visual editor for this task type
scripts/ — type-specific scripts (validation, generation)
docs/ — document instances
{docId}.md — task description, problem patterns, notes (Claude reads/writes)
{docId}.template.html — near-final HTML maintained by Claude
{docId}.data.json — editor data layer (positions, values — may not exist)
{docId}.output.html — generated from template+data (gitignored)
temp/ — diffs and transient data (gitignored)
src/
editor/editor-core.js — shared editor framework
scripts/
generate-pdf.mjs — HTML → PDF via Puppeteer (all types)
remove-bg.mjs — Remove white background from PNGs
split-sprites.mjs — Split sprite sheets into icons
generate-problems.mjs — Problem generation utility
styles/main.css — Tailwind source with A4/print styles
templates/space-base.html — Shared base template reference
assets/ — images (hero, footer, icons, items, backgrounds)
output/pdf/ — generated PDFs (gitignored)
Task Types
Each task type lives in tasks/{type-name}/ with its own CLAUDE.md, scripts, editor, and document instances. Current types:
- space-exploration — math problem worksheets with hero images and icon-decorated cards
- collecting-asteroids — match asteroids to cargo ships by weight sum
- space-route — navigate hex graph routes with difficulty constraints
Type-specific rules (layout details, asset conventions, generation algorithms) live in each type's own CLAUDE.md — NOT in this file. Read tasks/{type}/CLAUDE.md before working on any task of that type.
Document File Set
Each document instance consists of up to 4 files in tasks/{type}/docs/:
| File | Purpose | Owner |
|---|---|---|
{docId}.md |
Task description, problem patterns, page notes | Claude writes, user reviews |
{docId}.template.html |
Near-final static HTML, maintained by Claude | Claude |
{docId}.data.json |
Editor data layer (positions, values) | Editor UI via save endpoint |
{docId}.output.html |
Final HTML = template + data applied | generate.mjs (gitignored) |
Key: .data.json may not exist — and that's fine. When it doesn't exist, .template.html IS the final output.
The .md file does NOT directly drive HTML generation. It's context for Claude — problem patterns, non-obvious details (e.g., hero orientation per page), things Claude needs to know when editing the template. It does NOT contain titles, footers, or asset paths that are already in the HTML.
Creating New Task Types
- Create folder
tasks/{type-name}/ - Create
CLAUDE.mdwith type-specific rules - Create
scripts/generate.mjs— template + data → output pipeline - Create
editor.htmlimportingsrc/editor/editor-core.js+ type-specific logic - Create
scripts/for any validation/generation utilities - Add section to
tasks/index.html
Creating New Documents
When the user asks to create a new document of an existing type:
- Copy the previous document's files with incremented number:
{type}-N.template.html→{type}-(N+1).template.html{type}-N.md→{type}-(N+1).md
- Update the
.mdfile with new problem patterns / page descriptions - Edit
.template.htmlas needed (new problems, different assets, etc.) - Add card to
tasks/index.html
No script for this — Claude does it manually. .data.json starts empty (created only when the editor is used).
Adding Pages to Existing Documents
- Read the
.mdfile to understand existing patterns - Edit
.template.htmldirectly — add new page markup - Update
.mdif new patterns were added
Generation Pipeline
.template.html + .data.json (if exists) → scripts/generate.mjs → .output.html + screenshots
- Same pipeline for both Claude-initiated regeneration and editor-save flow
- If no
.data.jsonexists → template.html copied as-is to output.html generate.mjsis a per-task-type script; it callspostGenerate()fromsrc/scripts/post-generate.mjsat the endpostGenerate()runssrc/scripts/take-screenshots.mjswhich produces per-page PNG screenshots intasks/{type}/temp/{docId}-page-{N}.png- Screenshots are automatically regenerated on every generate — old ones are deleted before new ones are written
- All new task types must include
postGenerate()call in theirgenerate.mjs— this is part of the standard pipeline
Editor System
Each task type has its own editor.html in its folder. All editors share src/editor/editor-core.js for common functionality (drag, selection, keyboard, toolbar, save, toast).
Opening in editor:
http://localhost:3300/tasks/{type}/editor.html?file={docId}
Save flow:
- User clicks Save in editor
- Editor POST
/api/save-editswith{ taskType, docId, data } - Server writes
docs/{docId}.data.json - Server computes diff → writes
temp/{docId}.diff.json - Server runs
generate.mjs→ regenerates output.html + screenshots
Claude reviewing editor changes:
cat tasks/{type}/temp/{docId}.diff.json # see what changed
# Read screenshot PNGs from tasks/{type}/temp/{docId}-page-{N}.png to verify visually
Preview Pages Structure
Three-level navigation hierarchy, maintained manually by Claude:
tasks/index.html — main index (all categories)
→ tasks/{type}/index.html — category page (all documents of this type)
→ tasks/{type}/docs/{docId}.* — individual document files
Main index (tasks/index.html) — lists all task types as cards. Each card links to the category page (/tasks/{type}/).
Category page (tasks/{type}/index.html) — lists all documents within this type. Contains View/PDF/Editor links per document. Back link to main index. Has "editor mode" toggle for dev-only features.
When creating a new task type: create both the main index card AND the category index.html.
When creating a new document: add a doc-card to the category index.html.
Preview: http://localhost:3300/tasks/index.html
The frontend-design skill is installed but applies only to tasks/index.html, category pages, and other UI/navigation pages. Worksheet documents (*.template.html) are print/PDF layouts, not web pages — web design principles do not apply to them.
Script Principles (Orchestrator Pattern)
Claude Code is the central orchestrator. Scripts are tools for Claude, not autonomous actors.
Rules:
- Scripts read input → compute → output to stdout (JSON) or write a single specific output file
- Scripts NEVER chain together
- Scripts NEVER auto-modify documents or make decisions
- Claude runs a script, reads its output, decides what to do next
Allowed write exceptions:
generate.mjs— writes.output.html+ screenshots viapostGenerate()(template+data→output, deterministic)generate-pdf.mjs— writes PDF (final artifact)take-screenshots.mjs— writes page PNGs totemp/(called bypostGenerate, part of generate pipeline)/api/save-edits— writes.data.json+.diff.json+ runsgenerate.mjs(user-initiated from editor UI)
Example of correct flow:
Claude: node tasks/collecting-asteroids/scripts/verify.mjs --ships 10,10,14 --asteroids 3,2,1,4,5
Script → stdout: { "valid": false, "errors": ["ship 2 overflow by 3"] }
Claude: *reads output, decides how to fix, edits template*
Proactive Rule Saving
During sessions, when the user gives feedback or instructions specific to a task type, proactively suggest saving it as a rule:
"Сохранить это как правило для {type}?"
If confirmed → write to tasks/{type}/CLAUDE.md.
General rules that apply to all types → root CLAUDE.md (this file).
Visual Verification
MANDATORY for: refactoring, new features, new task types, new documents, any significant changes to templates or generation logic.
Automatic screenshots (passive)
Every generate.mjs run produces per-page screenshots in tasks/{type}/temp/{docId}-page-{N}.png. These are always up-to-date — read them with the Read tool to verify results without asking the user.
Chrome DevTools MCP (interactive)
Use chrome-devtools-mcp tools (navigate_page, take_screenshot) to check pages in the live browser when the dev server is running. This is useful for:
- Checking editor functionality (drag, keyboard, save)
- Verifying hover/click states
- Inspecting specific elements
- Verifying all links and navigation after creating new task types or documents
When to verify
- After generating a new document — read at least page 1 screenshot to confirm images load and layout is correct
- After refactoring — check all affected task types
- After editing template.html — regenerate and check screenshots
- After modifying asset paths or server config — check all types
- Do not ask the user to verify what you can check yourself via screenshots
Post-creation link verification (MANDATORY)
After creating a new task type or new document, use chrome-devtools MCP to verify the full navigation chain:
- Navigate to the main index (
/tasks/index.html) — verify the new card renders and its link works - Click through to the category page (
/tasks/{type}/) — verify it loads and lists all documents - Click through to each document link — verify View/Editor links work
- If any link is broken or page fails to load — fix the issue immediately and re-verify in Chrome that the fix works
Do not consider the task complete until all links are verified in the live browser.
Editor end-to-end verification (MANDATORY)
After creating or modifying any editor, verify the FULL save cycle in Chrome DevTools before telling the user it works:
- Open the editor in the browser (
editor.html?file=...) - Make a real change (click element, press keyboard shortcut)
- Click Save (or call save programmatically)
- Wait for save to complete (check server response)
- Read the saved
data.jsonfile — verify it contains the changed values (NOT defaults) - Run
generate.mjsand verify transforms appear inoutput.html - Reload the editor page — verify saved state is restored from
data.json
If ANY step fails, the editor is broken — fix it before presenting to the user. Never tell the user "editor works" based on visual-only checks without verifying the saved data file.
Common editor pitfalls:
- Live-reload can reset editor state after save (fix: load data.json on init to restore)
- ES module imports may not work with
window-exported globals (fix: use<script src>notimport) - Serializer must read actual modified state, not initial defaults
HTML Generation Guidelines
- OUTPUT MUST BE STATIC HTML. Template files must contain only static markup — no embedded
<script>that computes, generates, or modifies content at runtime. Tailwind CDN<script>tag is the only exception. - Page size: A4 = 210mm × 297mm
- Page breaks:
break-after: pagebetween pages - Fonts: Nunito from Google Fonts via
<link> - Images in PDF: Use local file paths. Puppeteer resolves
file://protocol. Embed as base64 data URIs when possible for reliable rendering.
Image Generation
Use the /gen-image skill to generate images via the Banatie API. Auth via BANATIE_KEY in .env. Rate limit: 100 requests/hour.
Reference Policy
When generating new assets for assets/items/, use existing images from the same subfolder as --ref to maintain visual consistency. The gen-image skill's default policy is to ask before using refs — this project overrides that: use refs automatically for items in the same asset group.
Style reference chain:
assets/items/asteroids/— use any existing asteroid as refassets/items/crystals/— use any existing crystal as refassets/icons/— generate independently (icon packs have their own pipeline)assets/hero-images/,assets/footers/,assets/backgrounds/— generate independently
Background Removal
src/scripts/remove-bg.mjs — flood-fill white background removal from PNGs (like magic wand). Uses sharp.
node src/scripts/remove-bg.mjs <file|dir> [--threshold N] [--fuzz N]
Optional — not all icons need it. Ask user after generating/splitting new icons.
PDF Generation
node src/scripts/generate-pdf.mjs tasks/{type}/docs/{docId}.output.html
Puppeteer: A4, printBackground: true, zero margins, preferCSSPageSize: true.
Workflow Summary
- User describes the task idea (or runs
/new-doc) - Claude creates/updates
.mdfile with patterns and notes - Claude creates/edits
.template.html(reading type CLAUDE.md and base references) - Run
generate.mjsto create.output.html - (Optional) User opens editor → fine-tunes positions → Save → data.json + output.html updated
- Claude reviews diff if asked:
cat tasks/{type}/temp/{docId}.diff.json - Add card to
tasks/index.html - Generate PDF:
node src/scripts/generate-pdf.mjs tasks/{type}/docs/{docId}.output.html - Preview at
http://localhost:3300/tasks/index.html