# 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 ```bash 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 -- # Convert HTML file to PDF pnpm remove-bg -- # 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 1. Create folder `tasks/{type-name}/` 2. Create `CLAUDE.md` with type-specific rules 3. Create `scripts/generate.mjs` — template + data → output pipeline 4. Create `editor.html` importing `src/editor/editor-core.js` + type-specific logic 5. Create `scripts/` for any validation/generation utilities 6. Add section to `tasks/index.html` ## Creating New Documents When the user asks to create a new document of an existing type: 1. 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` 2. Update the `.md` file with new problem patterns / page descriptions 3. Edit `.template.html` as needed (new problems, different assets, etc.) 4. 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 1. Read the `.md` file to understand existing patterns 2. Edit `.template.html` directly — add new page markup 3. Update `.md` if 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.json` exists → template.html copied as-is to output.html - `generate.mjs` is a per-task-type script; it calls `postGenerate()` from `src/scripts/post-generate.mjs` at the end - `postGenerate()` runs `src/scripts/take-screenshots.mjs` which produces per-page PNG screenshots in `tasks/{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 their `generate.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:** 1. User clicks Save in editor 2. Editor POST `/api/save-edits` with `{ taskType, docId, data }` 3. Server writes `docs/{docId}.data.json` 4. Server computes diff → writes `temp/{docId}.diff.json` 5. Server runs `generate.mjs` → regenerates output.html + screenshots **Claude reviewing editor changes:** ```bash 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 via `postGenerate()` (template+data→output, deterministic) - `generate-pdf.mjs` — writes PDF (final artifact) - `take-screenshots.mjs` — writes page PNGs to `temp/` (called by `postGenerate`, part of generate pipeline) - `/api/save-edits` — writes `.data.json` + `.diff.json` + runs `generate.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: 1. Navigate to the main index (`/tasks/index.html`) — verify the new card renders and its link works 2. Click through to the category page (`/tasks/{type}/`) — verify it loads and lists all documents 3. Click through to each document link — verify View/Editor links work 4. 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: 1. Open the editor in the browser (`editor.html?file=...`) 2. Make a real change (click element, press keyboard shortcut) 3. Click Save (or call save programmatically) 4. **Wait for save to complete** (check server response) 5. **Read the saved `data.json` file** — verify it contains the changed values (NOT defaults) 6. **Run `generate.mjs`** and verify transforms appear in `output.html` 7. **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 `