248 lines
12 KiB
Markdown
248 lines
12 KiB
Markdown
# 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 -- <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
|
||
|
||
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
|
||
```
|
||
|
||
## Index Page
|
||
|
||
`tasks/index.html` — Claude updates manually when creating new documents. Each document has View and Edit links. Different task types can have different card styles.
|
||
|
||
**Preview:** `http://localhost:3300/tasks/index.html`
|
||
|
||
## 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
|
||
|
||
### 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
|
||
|
||
## 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: page` between 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 ref
|
||
- `assets/items/crystals/` — use any existing crystal as ref
|
||
- `assets/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.
|
||
|
||
```bash
|
||
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
|
||
|
||
```bash
|
||
node src/scripts/generate-pdf.mjs tasks/{type}/docs/{docId}.output.html
|
||
```
|
||
|
||
Puppeteer: A4, `printBackground: true`, zero margins, `preferCSSPageSize: true`.
|
||
|
||
## Workflow Summary
|
||
|
||
1. User describes the task idea (or runs `/new-doc`)
|
||
2. Claude creates/updates `.md` file with patterns and notes
|
||
3. Claude creates/edits `.template.html` (reading type CLAUDE.md and base references)
|
||
4. Run `generate.mjs` to create `.output.html`
|
||
5. **(Optional)** User opens editor → fine-tunes positions → Save → data.json + output.html updated
|
||
6. Claude reviews diff if asked: `cat tasks/{type}/temp/{docId}.diff.json`
|
||
7. Add card to `tasks/index.html`
|
||
8. Generate PDF: `node src/scripts/generate-pdf.mjs tasks/{type}/docs/{docId}.output.html`
|
||
9. Preview at `http://localhost:3300/tasks/index.html`
|