190 lines
8.8 KiB
Markdown
190 lines
8.8 KiB
Markdown
# Math Tasks Generator
|
||
|
||
Printable math worksheet generator (A4 PDF) for children aged 7–9. Claude Code-driven workflow: user describes a task idea → Claude generates JSON config → creates HTML pages with Tailwind CSS → converts to PDF via Puppeteer.
|
||
|
||
**No template engine.** Claude Code generates fresh HTML pages directly from JSON task configs each time.
|
||
|
||
## Commands
|
||
|
||
```bash
|
||
npm run build:css # Build Tailwind CSS (minified)
|
||
npm run build:css:watch # Watch mode for CSS
|
||
npm run preview # Serve HTML at localhost:3000
|
||
npm run dev # CSS watch + preview server (concurrent)
|
||
npm run pdf -- <file> # Convert HTML file to PDF
|
||
npm run remove-bg -- <file|dir> # Remove white background from PNG icons
|
||
```
|
||
|
||
Generate images via Banatie API:
|
||
```bash
|
||
node src/scripts/banatie.mjs --type background --prompt "forest theme" --output assets/backgrounds/forest.png
|
||
node src/scripts/banatie.mjs --type icon --prompt "golden star" --output assets/icons/stars/star1.png
|
||
```
|
||
|
||
## Directory Structure
|
||
|
||
```
|
||
src/
|
||
styles/main.css — Tailwind source with A4/print styles
|
||
templates/space-base.html — Base template (layout/styling reference)
|
||
examples/space-worksheet2.html — Finished 3-page example (output reference)
|
||
scripts/
|
||
generate-pdf.mjs — HTML → PDF via Puppeteer
|
||
banatie.mjs — Banatie API client for image generation
|
||
remove-bg.mjs — Remove white background from PNGs (flood fill)
|
||
tasks/ — JSON task definition files
|
||
assets/
|
||
hero-images/ — spaceship1-6.jpeg (header hero images)
|
||
footers/ — planet1-6.jpeg (footer panorama images)
|
||
icons/pack1/ — minerals1-6 + plants1-6, 16 variants each ({name}-{row}-{col}.png)
|
||
backgrounds/ — large background images per theme (~1200x1700px)
|
||
output/
|
||
html/ — generated HTML (gitignored)
|
||
pdf/ — generated PDFs (gitignored)
|
||
css/ — built Tailwind CSS (gitignored)
|
||
```
|
||
|
||
## JSON Task Format
|
||
|
||
Each task is a JSON file in `tasks/` defining a multi-page document. See `tasks/space-exploration-1.json` for a real example.
|
||
|
||
```json
|
||
{
|
||
"id": "space-exploration-1",
|
||
"title": "Исследуй Планету",
|
||
"description": "3-page space worksheet: addition ±, multiply by 5 ±, multiplication table ±",
|
||
"labels": {
|
||
"title": "Исследуй Планету",
|
||
"subtitle": "Собери ресурсы, решая примеры!",
|
||
"footerBubble": "Итого собрано на планете:"
|
||
},
|
||
"theme": {
|
||
"style": "space",
|
||
"template": "space-base",
|
||
"icons": "assets/icons/pack1/"
|
||
},
|
||
"layout": {
|
||
"columns": 2,
|
||
"problemsPerPage": 20
|
||
},
|
||
"pages": [
|
||
{
|
||
"task": "A + B ± C, где A от 8 до 16, B от 4 до 8, C от 1 до 3. Знак ± выбирается случайно",
|
||
"problemCount": 20,
|
||
"heroImage": "assets/hero-images/spaceship2.jpeg",
|
||
"footerImage": "assets/footers/planet3.jpeg",
|
||
"heroDirection": "row-reverse"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
### Fields
|
||
|
||
- **pages[]** — array of pages, each with its own task and images
|
||
- **pages[].task** — free-text description of problems to generate (Claude reads this and creates concrete expressions)
|
||
- **pages[].problemCount** — how many problems on this page
|
||
- **pages[].heroImage** — path to hero image for this page
|
||
- **pages[].footerImage** — path to footer panorama for this page
|
||
- **pages[].heroDirection** — `row` (hero left) or `row-reverse` (hero right)
|
||
- **layout.columns** — 1 or 2 column layout
|
||
- **layout.problemsPerPage** — max problems per A4 page
|
||
- **labels** — all visible text (no hardcoded language)
|
||
- **theme.style** — visual theme name (e.g. "space")
|
||
- **theme.template** — which base template to use (e.g. "space-base")
|
||
- **theme.icons** — path to icon directory for problem cards
|
||
|
||
## Space Base Template
|
||
|
||
Base template: `src/templates/space-base.html`
|
||
Finished example: `src/examples/space-worksheet2.html` (3-page output matching `tasks/space-worksheet2.json`)
|
||
|
||
The base template defines the visual design for all space-themed worksheets. The example shows a complete generated document. When generating a new worksheet, **read both files first**, then produce a new HTML with these variations:
|
||
|
||
### What to vary per worksheet
|
||
|
||
1. **Hero image** — pick one from `assets/hero-images/spaceship{1-6}.jpeg`
|
||
2. **Footer image** — pick one from `assets/footers/planet{1-6}.jpeg`
|
||
3. **Hero position** — use `flex-row-reverse` class (hero right) or default flex direction (hero left) on the header div
|
||
4. **Problem icons** — pick from `assets/icons/pack1/` (minerals and plants, any variant `{name}-{row}-{col}.png`). **Every icon must be unique across the entire document** (no repeats across pages). Shuffle minerals and plants together randomly — do not sort by type
|
||
5. **Problem alignment** — for each problem card, randomly assign `justify-start`, `justify-center`, or `justify-end` within its grid column. No repeating patterns — should look chaotic/scattered
|
||
6. **Title, subtitle, footer text** — set from the task description
|
||
7. **Problems** — generate directly from the `task` text in JSON config. Claude reads the free-text description and creates concrete math expressions
|
||
|
||
### Layout structure (do not change)
|
||
|
||
- Page: `w-[210mm] h-[297mm]` white container
|
||
- Footer: absolute bottom, `h-[80mm]`, with white-to-transparent fade on top. **No `overflow-hidden`** on footer container (causes 1px hairline artifact in PDF)
|
||
- Footer bubble: absolute `bottom-[12mm]`, pill-shaped with semi-transparent white bg
|
||
- Content area: `px-[12mm] pt-[4mm] pb-[65mm]` flex column
|
||
- Header: hero image `w-[48%]` + title block centered, use `flex-row-reverse` for hero-right
|
||
- Footer gradient: `linear-gradient(to bottom, white 0%, rgba(255,255,255,0.6) 25%, transparent 50%)` with `h-full`
|
||
- Problems: `grid grid-cols-2 gap-x-3 gap-y-[3px]` — 20 problems total
|
||
- Each problem: 58px icon outside pill + `text-[1.2rem]` expression + `w-16` answer underline inside pill
|
||
- Font: Nunito via Google Fonts
|
||
- Uses Tailwind CDN (`<script src="https://cdn.tailwindcss.com">`)
|
||
|
||
### Color palette (do not change)
|
||
|
||
| Element | Hex |
|
||
|---------|-----|
|
||
| Title text | `text-indigo-950` (#1e1b4b) |
|
||
| Subtitle | `text-indigo-400` (#6366f1) |
|
||
| Card border | `border-indigo-100` (#e0e7ff) |
|
||
| Answer underline | `border-indigo-300` (#a5b4fc) |
|
||
| Card bg gradient | `from-white to-indigo-50/40` |
|
||
| Footer bubble border | `border-indigo-200` |
|
||
|
||
## HTML Generation Guidelines
|
||
|
||
When generating HTML worksheets:
|
||
|
||
- **Always read** `src/templates/space-base.html` (structure) and `src/examples/space-worksheet.html` (finished output) before generating
|
||
- **Page size:** A4 = 210mm × 297mm
|
||
- **CSS:** Uses Tailwind CDN in the HTML `<script>` tag (not the compiled CSS file)
|
||
- **Page breaks:** Use `break-after: page` between pages
|
||
- **Icons:** 58×58px inline images from `assets/icons/` next to each problem (outside the pill card)
|
||
- **Fonts:** Nunito from Google Fonts via `<link>`
|
||
- **Images in PDF:** Use local file paths (not URLs). Puppeteer resolves `file://` protocol
|
||
- **Embed images** as base64 data URIs when possible for reliable PDF rendering
|
||
|
||
## Banatie API
|
||
|
||
REST API for generating images.
|
||
|
||
- **Backgrounds:** ~1200×1700px, themed illustrations (forest, space, ocean, etc.)
|
||
- **Icons:** 128×128px, transparent PNG, simple collectible items (stars, gems, animals)
|
||
|
||
Configuration is in `src/scripts/banatie.mjs`. Set the `BANATIE_API_KEY` environment variable for authentication.
|
||
|
||
## Background Removal
|
||
|
||
Script `src/scripts/remove-bg.mjs` removes white backgrounds from PNG icons using flood-fill from edges (like magic wand in Photoshop). Uses sharp. White areas inside objects are preserved.
|
||
|
||
```bash
|
||
node src/scripts/remove-bg.mjs <file|dir> [--threshold N] [--fuzz N]
|
||
```
|
||
|
||
- `--threshold` — whiteness threshold for R,G,B (default: 230, lower = more aggressive)
|
||
- `--fuzz` — anti-alias radius in pixels at the boundary (default: 0)
|
||
- Default input: `assets/icons/pack2/`
|
||
|
||
This is optional — not all icons need it. After generating/splitting new icons, ask the user if they want background removal on specific files.
|
||
|
||
## PDF Generation
|
||
|
||
Puppeteer settings for A4 worksheets:
|
||
- Format: A4
|
||
- `printBackground: true` (required for background images)
|
||
- Margins: zero (CSS handles margins)
|
||
- `preferCSSPageSize: true`
|
||
|
||
## Workflow
|
||
|
||
1. User describes the math task idea (or runs `/new-doc`)
|
||
2. Claude creates/updates a JSON config in `tasks/` with `pages[].task` descriptions
|
||
3. Claude reads `src/templates/space-base.html` + `src/examples/space-worksheet.html` as references
|
||
4. Claude generates HTML file in `output/html/` — creates concrete problems from `task` text, assigns unique shuffled icons, builds all pages
|
||
5. Run `npm run pdf -- output/html/<file>.html` to create PDF
|
||
6. Preview with `npm run preview` at localhost:3000
|