# P5js For Zcl

> P5.js visual composition pipeline with a mandatory 8-10 question visual-brief interview and a post-interview mode choice. Use this skill whenever the user asks for p5.js sketches, creative coding, generative art, interactive canvas animations, shaders, 3D p5 scenes, browser visual prototypes, data visualization, or any p5.js project. After the interview, ask whether the user wants Source Preview Mode (decompose elements, research reusable source/templates, show selectable live previews, then compose a final adjustable sketch) or Direct Generation Mode (skip source/gallery work and generate the final adjustable p5 sketch directly). In both modes, the final HTML must include a parameter panel exposing the useful tunable controls the AI identifies from the algorithm.

- Skill: `seyseyseyz/p5js-for-zcl` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add seyseyseyz/p5js-for-zcl`
- Raw SKILL.md: https://api.skillmd.com/api/skills/seyseyseyz/p5js-for-zcl/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: seyseyseyz (https://skillmd.com/u/seyseyseyz)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/seyseyseyz/p5js-for-zcl

---


# p5js-for-zcl

## When to use

Use when users request: p5.js sketches, creative coding, generative art, interactive visualizations, canvas animations, browser-based visual art, data viz, shader effects, or any p5.js project.

## What's inside

Production pipeline for interactive and generative visual art using p5.js. Creates browser-based sketches, generative art, data visualizations, interactive experiences, 3D scenes, audio-reactive visuals, and motion graphics — exported as HTML, PNG, GIF, MP4, or SVG. Covers: 2D/3D rendering, noise and particle systems, flow fields, shaders (GLSL), pixel manipulation, kinetic typography, WebGL scenes, audio analysis, mouse/keyboard interaction, and headless high-res export.

This skill starts from the original `p5js` production pipeline, copies its references/scripts/templates, bundles the original `grilling` skill at `bundled-skills/grilling/SKILL.md`, adds gallery/environment scripts from `p5-visual-composer`, and adds a strict front-loaded interview plus a post-interview mode choice:

```
BASE ENV → GRILL → MODE CONFIRMATION
  ├─ SOURCE PREVIEW MODE: WORKSPACE → PREVIEW ENV → ELEMENTS → SOURCE SEARCH → PREVIEW GALLERY → USER CHOICE → FINAL PARAMETRIC P5 WITH PARAMETER PANEL
  └─ DIRECT GENERATION MODE: CREATIVE CONCEPT → TECHNICAL DESIGN → FINAL PARAMETRIC P5 WITH PARAMETER PANEL → VERIFY
```

The interview exists because visual prompts are often underspecified. A quick one-shot sketch can look plausible while missing the user's actual taste. Every p5 request goes through the 8-10 question brief gate. The source-backed preview/gallery workflow is powerful but expensive, so it only runs after the user confirms Source Preview Mode. If the user chooses Direct Generation Mode, skip element decomposition, source search, and preview gallery, then generate the final sketch from the agreed brief. In both modes, the final artifact must be user-adjustable through an on-page parameter panel.

## Mandatory Front Gate

Before writing final p5 code, run this gate in order.

### 0. Base Environment Check

Before interviewing or building anything, bootstrap the base command-line environment. This script handles Node/npm/npx first, because both Source Preview Mode and verification can depend on Node:

```bash
bash /Users/temptrip/.agents/skills/p5js-for-zcl/scripts/bootstrap_env.sh --json
```

The bootstrap script:

- selects an existing Node that satisfies Vite's practical floor: Node 20.19+ or newer
- prefers Homebrew Node when the default shell Node is too old
- installs Node via Homebrew when Node/npm/npx are missing
- can install Homebrew itself only when explicitly run with `--install-homebrew`
- can install ffmpeg for video work when run with `--include-ffmpeg`

If base bootstrap changes PATH, use the reported PATH for the following commands, or rerun them with `PATH=/opt/homebrew/bin:$PATH` when Homebrew Node was selected.

Then run detailed environment detection:

```bash
node /Users/temptrip/.agents/skills/p5js-for-zcl/scripts/init_env.mjs --json
```

Do not create the gallery workspace yet. Create it only after the user confirms Source Preview Mode. Direct Generation Mode should not pay the workspace/source/gallery setup cost.

For detailed patterns, read these only when needed:

- `references/environment.md` for environment fallbacks
- `references/interview.md` for approachable question patterns
- `references/p5_engineering_brief.md` for the brief shape
- `references/layer_composition.md` for composing selected layers

### 1. Grilling Interview

Start by reading and following the bundled original `grilling` implementation at `bundled-skills/grilling/SKILL.md`. Its core behavior is:

- Interview the user about the visual plan until there is a shared understanding.
- Ask one question at a time and wait for the answer before continuing.
- For each question, provide your recommended answer so the user can approve quickly.
- If a question can be answered from local files, reference images, existing sketches, or codebase context, inspect those instead of asking.

This is a real multi-turn gate, not a polite preface. "Ask one question at a time" means one question per assistant turn, then stop and wait for the user's reply. It does not mean ask one question total.

Ask 8-10 questions for every p5 request before Mode Confirmation. This applies to simple, broad, quick, and highly specific prompts. If the user explicitly asks to skip questions, ask one confirmation explaining that the skill normally requires the full visual brief; only synthesize defaults if the user confirms the skip.

Every grilling question must include:

- the decision being resolved
- a plain-language recommended answer
- why this decision affects the final sketch

Do not treat your recommended answer as user approval. It is only a proposed default that the user may accept, reject, or modify.

Resolve these decision axes before moving on:

1. mood / atmosphere
2. primary subject character
3. secondary subjects and environmental details
4. composition and camera/view
5. background / midground / foreground layering
6. palette and light source
7. motion grammar and rhythm
8. material / rendering style
9. interaction and controls
10. export target / loop length

Before Mode Confirmation, output a short `Grilling Decisions` checklist. Mark each axis as `user answered`, `user approved default`, `inferred from source/context`, or `explicitly skipped`. If fewer than 6 axes are answered, approved, or inferred, continue interviewing instead of choosing a build mode. Do not create files, search sources, build a gallery, or write final p5 code while waiting for the next interview answer.

### 2. Mode Confirmation

After `Grilling Decisions`, ask the user exactly one mode-confirmation question and wait for the answer. Match the user's language. Do not proceed on silence.

Use this structure:

```markdown
接下来请选择生成模式：

A. Source Preview Mode：我会拆分视觉元素，搜索/整理可用开源实现或模板，做本地预览 gallery，你选择方案后我再合成最终 p5 作品。
B. Direct Generation Mode：我跳过开源候选和预览 gallery，直接根据刚才确认的方向生成最终 p5 sketch。

推荐：如果你想比较风格或重用现成实现，选 A；如果你想尽快看到成品，选 B。
```

If the user says they need options, selectable styles, previews, source reuse, OpenProcessing/GitHub candidates, or equivalent, select Source Preview Mode. If the user says no, not needed, direct, skip gallery, or equivalent, select Direct Generation Mode. If the answer is ambiguous, ask one short follow-up before moving on.

### 3A. Direct Generation Mode

Use Direct Generation Mode only after the user chooses it. In this mode:

- skip Element Analysis, Source And Template Search, Preview Gallery, gallery validation, and source manifest generation
- articulate a creative concept from the `Grilling Decisions`
- choose technical design: mode, canvas size, renderer, frame rate, interaction model, export target, and whether to use `templates/viewer.html`
- generate the final p5 sketch directly, preserving the original p5.js production standards below
- include a visible parameter panel with project-specific controls that expose the algorithm's character
- verify with a browser or static check when practical

Direct Generation Mode is not a lower-quality mode. It is the no-gallery path.

### 3B. Source Preview Mode: Workspace And Element Analysis

Use Source Preview Mode only after the user chooses it. First create a temporary gallery workspace:

```bash
node /Users/temptrip/.agents/skills/p5js-for-zcl/scripts/create_workspace.mjs \
  --name <safe-project-name> \
  --out <workspace-dir>
```

Immediately after creating the workspace, automatically install missing preview dependencies in that workspace:

```bash
node /Users/temptrip/.agents/skills/p5js-for-zcl/scripts/ensure_env.mjs \
  --workspace <workspace-dir> \
  --json
```

This script installs `package.json` dependencies with npm and installs Playwright Chromium when Playwright is declared. For video/MP4 tasks, pass `--include-ffmpeg` so it also tries `brew install ffmpeg` when ffmpeg is missing. Do not ask the user to install Node/npm or normal preview dependencies manually unless both bootstrap and automatic install fail.

If automatic setup fails, retry once with the most relevant repair:

- if default Node is too old and Homebrew Node exists, retry with `PATH=/opt/homebrew/bin:$PATH`
- if Node/npm/npx are missing, run `scripts/bootstrap_env.sh` first; on macOS it may install Node through Homebrew
- if package install failed because of a transient network error, rerun `ensure_env.mjs` once
- if local server listening is blocked, continue with Vite build plus standalone HTML
- if npm, npx, Homebrew, or network access is unavailable, document the blocker and use the best fallback available

The workspace template lives at `templates/workspace` and is used for selectable element previews. Write normalized gallery data to `<workspace-dir>/src/gallery-data.js`. The expected contracts are in `references/gallery_schema.json` and `references/selection_schema.json`.

After the requirement is clear, write a concise element brief before research. Include 4-8 key elements, grouped when needed so the preview page stays understandable.

For each element, record:

- `id`
- plain-language visual role
- implementation strategy
- search terms
- dependencies
- acceptance criteria for preview
- likely final parameters

Example elements: `wind_field`, `tree_sway`, `branch_physics`, `falling_stars`, `meteor_trails`, `night_sky`, `leaf_particles`, `shader_glow`, `camera_parallax`.

Do not create a gallery element solely for preview method, UI chrome, or final control style. The gallery should compare visual/source choices only. Unless the user explicitly asks for a different control model, the final HTML should use the default viewer-style control bar from the viewer template.

### 4. Source And Template Search

Dispatch subagents when available. Each subagent gets one element or a small related cluster. Ask for 3-5 reusable candidates per element.

Candidate schema:

```json
{
  "element": "tree_sway",
  "candidate_id": "tree-sway-noise-01",
  "source_title": "Short title",
  "source_family": "p5-official | nature-of-code | coding-train | openprocessing | independent-github | local-template | agent-created",
  "source_identity": "stable source id, e.g. github:hey24sheep/LSystem_Fractal_Trees_P5 or local-template:previewRegistry/night-sky",
  "source_url": "https://...",
  "raw_source_url": "https://...",
  "retrieved_at": "YYYY-MM-DD",
  "source_visible": true,
  "source_visible_evidence": "raw file fetched | editor/files/download visible | local template file exists | ...",
  "quality_score": 1,
  "source_reuse_mode": "literal_source | parameter_tuned_source | minimal_patch | inspiration_only | agent_created",
  "source_preservation": "which original functions/classes/rules/data structures stay as the rendering core",
  "native_parameter_map": "which original constants/settings/sliders/rules are tuned to match the brief",
  "source_patch_scope": "none, wrapper-only, or the smallest code changes made beyond native parameters",
  "reuse_value": "direct source, parameter-tuned source, minimal patch, inspiration-only, or agent-created; what concrete code or pattern should be reused",
  "why_it_fits": "what visual behavior this contributes",
  "tradeoff": "what this option sacrifices",
  "code_pattern": "noise-driven recursive branch angle",
  "dependencies": ["p5"],
  "adaptation_notes": "how to fit the user's brief",
  "preview_plan": "how the gallery preview will show the final effect"
}
```

Research priorities:

- Prefer source-visible examples and templates: official p5 examples, The Nature of Code, Coding Train, GitHub repos, and OpenProcessing sketches with readable code.
- Use source code whenever it can materially improve the element. When source is visible, use it directly or as a tight adaptation; do not evaluate authorization clarity as part of candidate selection.
- Treat source-native reuse as the default. For each source-backed candidate, preserve the original sketch's main loop, data model, classes, recursive grammar, shader, or particle update/render functions as the implementation core whenever practical.
- Tune through the source's own controllable parameters first: constants, settings objects, sliders, rule strings, angles, magnification rates, spawn counts, forces, palettes, and timing variables already present in the source. Map the user's brief to these native controls before editing algorithm code.
- Wrapper changes are allowed for p5 instance mode, canvas sizing, seeded setup, import/export, gallery lifecycle, and layer composition. Keep these separate from the source core so the source lineage remains obvious in code.
- If native parameters cannot satisfy the brief, make the smallest localized patch that does. Do not rewrite a source-backed option into a new sketch while keeping only a symbolic fragment such as an axiom, branch angle, or class name.
- Mark each option with `source_reuse_mode`: `literal_source` when the source runs essentially as-is, `parameter_tuned_source` when the source core is preserved and only native controls are tuned, `minimal_patch` when small code changes beyond native parameters are needed, `inspiration_only` when only an idea/pattern remains, or `agent_created` when no source was used.
- For every source-backed option, fill `source_preservation`, `native_parameter_map`, and `source_patch_scope`. A strong source-first option should make it clear which original code is still doing the work, which original knobs were adjusted, and where the adaptation boundary is.
- Source diversity is mandatory inside each element. For every element, build a 3-5 option candidate set with distinct `source_identity` values. Do not fill tree, particle, wind, shader, or typography candidates with different presets from the same source just because that source is easy to adapt.
- Use `source_identity` to identify the actual repo/sketch/page/template, not just the broad family. Do not create two options from the same `source_identity` to show different parameter presets; put those presets inside one candidate's `native_parameter_map` or `adaptation_notes`, and search for a genuinely different source for the extra option.
- Prefer different `source_family` values too, but do not fake family diversity. If two strong candidates are both independent GitHub repos, keep them as separate `source_identity` values and record the real family.
- Quality ranking is mandatory before selecting candidates. Score candidates 1-5 on visual fit, source quality, isolation ease, runtime fit, and adaptation value. Keep the highest-quality set after enforcing source-identity diversity, not the first easy sources.
- Search across the relevant source pools instead of privileging any one pool. OpenProcessing/source-visible datasets, independent GitHub repos, p5 official examples, The Nature of Code, Coding Train, and local templates can all be high-quality sources depending on the element.
- If a single `source_family` supplies more than one option for the same element, document which alternate families were checked in the option/adaptation notes. Repetition is acceptable only when `source_identity` remains unique and the repeated-family candidates score better on the objective metrics than the alternatives.
- If a single source must appear more than once because no alternative exists, do not pass it as a normal gallery option. Collapse the variants into one option and document the source debt; the validator treats duplicate `source_identity` values within one element as a failure.
- Default selections across the composed gallery should prefer at least three distinct `source_family` values for a normal 4-8 element project when competitive. No source family should provide more than two defaults unless a short source-debt note explains why the selected source identities scored higher.
- Track provenance, including `source_url`, `raw_source_url`, `source_title`, `retrieved_at`, and adaptation notes. Provenance is for traceability, not for filtering source out of the final composition.
- If source is not visible, do not claim direct source reuse. Keep searching for a readable source, use a source-visible alternative, or create an `agent_created` candidate when no usable code can be found.
- If no suitable source exists, create an `agent_created` candidate and say so honestly.
- Search the web when current source availability or OpenProcessing pages matter.
- Read `references/source_curation.md` before doing research-heavy source/template discovery.
- Before building the gallery, run `scripts/validate_gallery_sources.mjs --gallery <workspace-dir>/src/gallery-data.js --json` when a gallery data file exists. Fix source metadata, per-element diversity, and default diversity failures before asking the user to choose.
- After source metadata validates, snapshot the declared raw sources:
  `node /Users/temptrip/.agents/skills/p5js-for-zcl/scripts/fetch_gallery_sources.mjs --gallery <workspace-dir>/src/gallery-data.js --out <workspace-dir>/sources --json`
  Use the generated `sources/source-manifest.json` as the evidence ledger. Correct stale `raw_source_url`, `source_visible_evidence`, `retrieved_at`, and source-backed claims when the manifest shows failed fetches, HTML pages instead of raw source, missing local files, or local-only placeholders. Only use `--allow-failures` when the failures are explicitly shown to the user as source debt.

### 5. Preview Gallery

Before final composition, build a local HTML preview page that shows the element options. The user should choose by visual effect, not implementation jargon.

Gallery requirements:

- 3-5 options per element.
- Every option renders the intended final visual behavior, whether it came from reusable source, an adapted template, or agent-created code. Use a live p5 preview when possible, a short animated mock when needed, or a faithful static fallback only when live preview is impossible.
- For source-backed options, the preview should be implemented from the source core itself, tuned through native parameters where possible. Do not create a separate hand-written approximation just because it is easier to style.
- The page labels each option with provenance, `source_family`, `source_identity`, retrieved date, raw/source links, source-visible evidence, quality score, `source_reuse_mode`, native parameter map, source preservation, patch scope, reuse value, why it fits, and tradeoff. Do not expose `preview_factory`, factory counts, or "preview mode" implementation details to the user.
- The page includes a current composed preview if practical, using the default option for each element.
- The current composed preview must reflect the live selected options. On selection changes, rebuild or update the composed p5 instance and the selection JSON.
- Preview factories should support `context.mode === "preview"` and `context.mode === "composition"` when they can be layered. In preview mode, an option may draw a complete mini-scene so it is understandable alone. In composition mode, it should draw only its own layer; only background-layer options should repaint the whole backdrop.
- The page displays a selection JSON with `{ element, candidate_id }` pairs and provides a copy-to-clipboard action. Tell the user to paste the copied selection back into the chat. Do not default to downloading the selection as a file.
- Build and export a standalone gallery page when possible:
  `node scripts/build_standalone.mjs --dist <workspace-dir>/dist --out <workspace-dir>/standalone.html`
- After the standalone page is built, verify it with:
  `node /Users/temptrip/.agents/skills/p5js-for-zcl/scripts/verify_gallery_render.mjs --file <workspace-dir>/standalone.html --expected-sections <N> --expected-cards <N> --expected-canvases <N> --screenshot <workspace-dir>/gallery-render-check.png --json`
  Add `--expect-selected <element>:<candidate_id>` for each default or user-approved selection when freshness matters. Fix console errors, blank canvases, stale standalone output, missing selected cards, and count mismatches before asking the user to choose.

Do not move to final composition until the user chooses or explicitly approves defaults after seeing the gallery. If the user responds in prose, convert it into the selection JSON yourself.

### 6. Final Parametric Composition

In Source Preview Mode, after user confirmation, compose the final sketch using the selected candidates and the original p5.js production standards below.

In Direct Generation Mode, compose the final sketch directly from the `Grilling Decisions` and the technical design. Do not claim source-backed reuse unless source/template search actually happened.

Source-backed selected candidates should remain source-native in the final composition too. Keep the original source core in an adapter/module, expose the original source parameters as the primary controls, and add only the smallest glue needed for layer ordering, shared timing, canvas sizing, or brief-specific polish. If a final layer has drifted so far that the source code is no longer recognizable as the working core, reclassify it as `inspiration_only` or replace it with a better source-backed candidate before shipping.

When a gallery JSON and selection JSON are available, prefer the bundled helper to create the selected layer set:

```bash
node /Users/temptrip/.agents/skills/p5js-for-zcl/scripts/compose_layers.mjs \
  --gallery <gallery.json-or-src/gallery-data.js> \
  --selection <selection.json> \
  --out <workspace-dir>/src/gallery-data.js
```

Then build or export the final page from that workspace, using `scripts/build_standalone.mjs` when a single-file fallback is useful.

The final output must include a visible parameter panel or viewer-style control bar in both Source Preview Mode and Direct Generation Mode. Before coding the final sketch, audit the selected or generated algorithm and choose the useful parameters to expose. Prefer `templates/viewer.html` when it fits; otherwise build an equivalent panel into the final HTML.

Expose controls that change how this specific algorithm behaves:

- density/count controls where the system has quantities
- speed/rhythm controls where the system moves
- scale/frequency controls where noise or texture matters
- force/threshold/ratio controls where behavior changes
- seed and export controls for generative work

In Source Preview Mode, expose source-native parameters from the selected candidates first, then add composition-level controls for layer balance, timing, and export. In Direct Generation Mode, derive controls from the generated algorithm's real state and parameters. Controls must have clear labels, sensible ranges/defaults, and live update or deterministic re-render behavior. Include seed, reset/randomize, and PNG/export controls for generative sketches unless the requested format makes them irrelevant.

Avoid generic cosmetic-only controls unless they support the concept. Do not ship a final p5 HTML with only keyboard shortcuts when an on-page parameter panel is practical.

### Handoff Outputs

Keep the user loop short and concrete:

- after grilling: brief summary of agreed visual direction
- after mode confirmation: selected mode and what will happen next
- in Source Preview Mode, after element analysis: element list and research plan
- in Source Preview Mode, after source search: link/path to gallery page and ask for choices
- after final build: final HTML path, verification summary, and notable parameters

### Execution Checklist

Before saying the final work is complete, check that the run produced or explicitly covered:

- one-question-per-turn grilling that resolves the required decision axes, or a documented explicit user shortcut to synthesize defaults
- a `Grilling Decisions` checklist before Mode Confirmation
- explicit user choice of Source Preview Mode or Direct Generation Mode
- in Source Preview Mode, an element analysis with 4-8 implementation elements
- in Source Preview Mode, 3-5 candidates per element, with provenance, source-family/source-identity metadata, quality scores, source-native reuse metadata, no duplicate `source_identity` values inside an element, and `agent_created` status only when source search genuinely fails
- in Source Preview Mode, `scripts/validate_gallery_sources.mjs --gallery <gallery-data.js> --json` passed or source-debt failures were explicitly shown to the user before choice
- in Source Preview Mode, `scripts/fetch_gallery_sources.mjs --gallery <gallery-data.js> --out <workspace>/sources --json` produced a source manifest, and every source-backed failure was fixed or reported as source debt
- in Source Preview Mode, a preview gallery page that shows each element's visual effect
- in Source Preview Mode, `scripts/verify_gallery_render.mjs --file <standalone.html> ... --json` passed with no console/page errors, no blank canvases, and expected section/card/canvas/selection counts
- in Source Preview Mode, user selection or explicit approval of defaults after the gallery
- in Direct Generation Mode, no element/source/gallery work was performed unless the user later switched modes
- in Direct Generation Mode, creative concept and technical design were stated before coding
- a final p5 HTML with a visible parameter panel or viewer-style control bar
- the parameter panel exposes useful algorithm parameters with clear labels, ranges/defaults, and live update or deterministic re-render behavior
- standalone gallery/final HTML fallback where possible
- browser or static verification notes

## Creative Standard

This is visual art rendered in the browser. The canvas is the medium; the algorithm is the brush.

For this source-backed skill, the source-native contract above takes precedence over open-ended invention. Be creative through source selection, source-diverse composition, parameter tuning, layer orchestration, color/light treatment, and small glue code. Do not satisfy the creative standard by replacing a selected source's working core with a freshly invented implementation.

**Before writing a single line of code**, articulate the creative concept. What does this piece communicate? What makes the viewer stop scrolling? What separates this from a code tutorial example? The user's prompt is a starting point — interpret it with creative ambition.

**First-render excellence is non-negotiable.** The output must be visually striking on first load. If it looks like a p5.js tutorial exercise, a default configuration, or "AI-generated creative coding," it is wrong. Rethink before shipping.

**Go beyond the reference vocabulary.** The noise functions, particle systems, color palettes, and shader effects in the references are a starting vocabulary. For every project, combine, layer, and invent. The catalog is a palette of paints — you write the painting.

**Be proactively creative.** If the user asks for "a particle system," deliver a particle system with emergent flocking behavior, trailing ghost echoes, palette-shifted depth fog, and a background noise field that breathes. Include at least one visual detail the user didn't ask for but will appreciate.

**Dense, layered, considered.** Every frame should reward viewing. Never flat white backgrounds. Always compositional hierarchy. Always intentional color. Always micro-detail that only appears on close inspection.

**Cohesive aesthetic over feature count.** All elements must serve a unified visual language — shared color temperature, consistent stroke weight vocabulary, harmonious motion speeds. A sketch with ten unrelated effects is worse than one with three that belong together.

## Modes

| Mode | Input | Output | Reference |
|------|-------|--------|-----------|
| **Generative art** | Seed / parameters | Procedural visual composition (still or animated) | `references/visual-effects.md` |
| **Data visualization** | Dataset / API | Interactive charts, graphs, custom data displays | `references/interaction.md` |
| **Interactive experience** | None (user drives) | Mouse/keyboard/touch-driven sketch | `references/interaction.md` |
| **Animation / motion graphics** | Timeline / storyboard | Timed sequences, kinetic typography, transitions | `references/animation.md` |
| **3D scene** | Concept description | WebGL geometry, lighting, camera, materials | `references/webgl-and-3d.md` |
| **Image processing** | Image file(s) | Pixel manipulation, filters, mosaic, pointillism | `references/visual-effects.md` § Pixel Manipulation |
| **Audio-reactive** | Audio file / mic | Sound-driven generative visuals | `references/interaction.md` § Audio Input |

## Stack

Single self-contained HTML file per project. No build step required.

| Layer | Tool | Purpose |
|-------|------|---------|
| Core | p5.js 1.11.3 (CDN) | Canvas rendering, math, transforms, event handling |
| 3D | p5.js WebGL mode | 3D geometry, camera, lighting, GLSL shaders |
| Audio | p5.sound.js (CDN) | FFT analysis, amplitude, mic input, oscillators |
| Export | Built-in `saveCanvas()` / `saveGif()` / `saveFrames()` | PNG, GIF, frame sequence output |
| Capture | CCapture.js (optional) | Deterministic framerate video capture (WebM, GIF) |
| Headless | Puppeteer + Node.js (optional) | Automated high-res rendering, MP4 via ffmpeg |
| SVG | p5.js-svg 1.6.0 (optional) | Vector output for print — requires p5.js 1.x |
| Natural media | p5.brush (optional) | Watercolor, charcoal, pen — requires p5.js 2.x + WEBGL |
| Texture | p5.grain (optional) | Film grain, texture overlays |
| Fonts | Google Fonts / `loadFont()` | Custom typography via OTF/TTF/WOFF2 |

### Version Note

**p5.js 1.x** (1.11.3) is the default — stable, well-documented, broadest library compatibility. Use this unless a project requires 2.x features.

**p5.js 2.x** (2.2+) adds: `async setup()` replacing `preload()`, OKLCH/OKLAB color modes, `splineVertex()`, shader `.modify()` API, variable fonts, `textToContours()`, pointer events. Required for p5.brush. See `references/core-api.md` § p5.js 2.0.

## Original p5.js Pipeline

After the mandatory front gate, every final project follows the same 6-stage path:

```
CONCEPT → DESIGN → CODE → PREVIEW → EXPORT → VERIFY
```

1. **CONCEPT** — Articulate the creative vision: mood, color world, motion vocabulary, what makes this unique
2. **DESIGN** — Choose mode, canvas size, interaction model, color system, export format. Map concept to technical decisions
3. **CODE** — Write single HTML file with inline p5.js. Structure: globals → `preload()` → `setup()` → `draw()` → helpers → classes → event handlers
4. **PREVIEW** — Open in browser, verify visual quality. Test at target resolution. Check performance
5. **EXPORT** — Capture output: `saveCanvas()` for PNG, `saveGif()` for GIF, `saveFrames()` + ffmpeg for MP4, Puppeteer for headless batch
6. **VERIFY** — Does the output match the concept? Is it visually striking at the intended display size? Would you frame it?

## Creative Direction

### Aesthetic Dimensions

| Dimension | Options | Reference |
|-----------|---------|-----------|
| **Color system** | HSB/HSL, RGB, named palettes, procedural harmony, gradient interpolation | `references/color-systems.md` |
| **Noise vocabulary** | Perlin noise, simplex, fractal (octaved), domain warping, curl noise | `references/visual-effects.md` § Noise |
| **Particle systems** | Physics-based, flocking, trail-drawing, attractor-driven, flow-field following | `references/visual-effects.md` § Particles |
| **Shape language** | Geometric primitives, custom vertices, bezier curves, SVG paths | `references/shapes-and-geometry.md` |
| **Motion style** | Eased, spring-based, noise-driven, physics sim, lerped, stepped | `references/animation.md` |
| **Typography** | System fonts, loaded OTF, `textToPoints()` particle text, kinetic | `references/typography.md` |
| **Shader effects** | GLSL fragment/vertex, filter shaders, post-processing, feedback loops | `references/webgl-and-3d.md` § Shaders |
| **Composition** | Grid, radial, golden ratio, rule of thirds, organic scatter, tiled | `references/core-api.md` § Composition |
| **Interaction model** | Mouse follow, click spawn, drag, keyboard state, scroll-driven, mic input | `references/interaction.md` |
| **Blend modes** | `BLEND`, `ADD`, `MULTIPLY`, `SCREEN`, `DIFFERENCE`, `EXCLUSION`, `OVERLAY` | `references/color-systems.md` § Blend Modes |
| **Layering** | `createGraphics()` offscreen buffers, alpha compositing, masking | `references/core-api.md` § Offscreen Buffers |
| **Texture** | Perlin surface, stippling, hatching, halftone, pixel sorting | `references/visual-effects.md` § Texture Generation |

### Per-Project Variation Rules

Never use default configurations. For every project:
- **Custom color palette** — never raw `fill(255, 0, 0)`. Always a designed palette with 3-7 colors
- **Custom stroke weight vocabulary** — thin accents (0.5), medium structure (1-2), bold emphasis (3-5)
- **Background treatment** — never plain `background(0)` or `background(255)`. Always textured, gradient, or layered
- **Motion variety** — different speeds for different elements. Primary at 1x, secondary at 0.3x, ambient at 0.1x
- **At least one invented element** — a custom particle behavior, a novel noise application, a unique interaction response

### Project-Specific Invention

For every project, invent at least one of:
- A custom color palette matching the mood (not a preset)
- A novel noise field combination (e.g., curl noise + domain warp + feedback)
- A unique particle behavior (custom forces, custom trails, custom spawning)
- An interaction mechanic the user didn't request but that elevates the piece
- A compositional technique that creates visual hierarchy

### Parameter Design Philosophy

Parameters should emerge from the algorithm, not from a generic menu. Ask: "What properties of *this* system should be tunable?"

**Good parameters** expose the algorithm's character:
- **Quantities** — how many particles, branches, cells (controls density)
- **Scales** — noise frequency, element size, spacing (controls texture)
- **Rates** — speed, growth rate, decay (controls energy)
- **Thresholds** — when does behavior change? (controls drama)
- **Ratios** — proportions, balance between forces (controls harmony)

**Bad parameters** are generic controls unrelated to the algorithm:
- "color1", "color2", "size" — meaningless without context
- Toggle switches for unrelated effects
- Parameters that only change cosmetics, not behavior

Every parameter should change how the algorithm *thinks*, not just how it *looks*. A "turbulence" parameter that changes noise octaves is good. A "particle size" slider that only changes `ellipse()` radius is shallow.

## Workflow

### Step 1: Creative Vision

Before any code, articulate:

- **Mood / atmosphere**: What should the viewer feel? Contemplative? Energized? Unsettled? Playful?
- **Visual story**: What happens over time (or on interaction)? Build? Decay? Transform? Oscillate?
- **Color world**: Warm/cool? Monochrome? Complementary? What's the dominant hue? The accent?
- **Shape language**: Organic curves? Sharp geometry? Dots? Lines? Mixed?
- **Motion vocabulary**: Slow drift? Explosive burst? Breathing pulse? Mechanical precision?
- **What makes THIS different**: What is the one thing that makes this sketch unique?

Map the user's prompt to aesthetic choices. "Relaxing generative background" demands different everything from "glitch data visualization."

### Step 2: Technical Design

- **Mode** — which of the 7 modes from the table above
- **Canvas size** — landscape 1920x1080, portrait 1080x1920, square 1080x1080, or responsive `windowWidth/windowHeight`
- **Renderer** — `P2D` (default) or `WEBGL` (for 3D, shaders, advanced blend modes)
- **Frame rate** — 60fps (interactive), 30fps (ambient animation), or `noLoop()` (static generative)
- **Export target** — browser display, PNG still, GIF loop, MP4 video, SVG vector
- **Interaction model** — passive (no input), mouse-driven, keyboard-driven, audio-reactive, scroll-driven
- **Viewer UI** — every final sketch needs an on-page parameter panel. For interactive generative art, start from `templates/viewer.html` which provides seed navigation, parameter sliders, and download. For simple sketches or video export, use bare HTML only if you build an equivalent control panel into it.

### Step 3: Code the Sketch

For **interactive generative art** (seed exploration, parameter tuning): start from `templates/viewer.html`. Read the template first, keep the fixed sections (seed nav, actions), replace the algorithm and parameter controls. This gives the user seed prev/next/random/jump, parameter sliders with live update, and PNG download — all wired up.

For **animations, video export, or simple sketches**: use bare HTML with an embedded parameter panel:

Single HTML file. Structure:

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Project Name</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.3/p5.min.js"></script>
  <script>p5.disableFriendlyErrors = true;</script>
  <!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.3/addons/p5.sound.min.js"></script> -->
  <!-- <script src="https://unpkg.com/p5.js-svg@1.6.0"></script> -->  <!-- SVG export -->
  <!-- <script src="https://cdn.jsdelivr.net/npm/ccapture.js-npmfixed/build/CCapture.all.min.js"></script> -->  <!-- video capture -->
  <style>
    html, body { margin: 0; padding: 0; overflow: hidden; }
    canvas { display: block; }
  </style>
</head>
<body>
<script>
// === Configuration ===
const CONFIG = {
  seed: 42,
  // ... project-specific params
};

// === Color Palette ===
const PALETTE = {
  bg: '#0a0a0f',
  primary: '#e8d5b7',
  // ...
};

// === Global State ===
let particles = [];

// === Preload (fonts, images, data) ===
function preload() {
  // font = loadFont('...');
}

// === Setup ===
function setup() {
  createCanvas(1920, 1080);
  randomSeed(CONFIG.seed);
  noiseSeed(CONFIG.seed);
  colorMode(HSB, 360, 100, 100, 100);
  // Initialize state...
}

// === Draw Loop ===
function draw() {
  // Render frame...
}

// === Helper Functions ===
// ...

// === Classes ===
class Particle {
  // ...
}

// === Event Handlers ===
function mousePressed() { /* ... */ }
function keyPressed() { /* ... */ }
function windowResized() { resizeCanvas(windowWidth, windowHeight); }
</script>
</body>
</html>
```

Key implementation patterns:
- **Seeded randomness**: Always `randomSeed()` + `noiseSeed()` for reproducibility
- **Color mode**: Use `colorMode(HSB, 360, 100, 100, 100)` for intuitive color control
- **State separation**: CONFIG for parameters, PALETTE for colors, globals for mutable state
- **Class-based entities**: Particles, agents, shapes as classes with `update()` + `display()` methods
- **Offscreen buffers**: `createGraphics()` for layered composition, trails, masks

### Step 4: Preview & Iterate

- Open HTML file directly in browser — no server needed for basic sketches
- For `loadImage()`/`loadFont()` from local files: use `scripts/serve.sh` or `python3 -m http.server`
- Chrome DevTools Performance tab to verify 60fps
- Test at target export resolution, not just the window size
- Adjust parameters until the visual matches the concept from Step 1

### Step 5: Export

| Format | Method | Command |
|--------|--------|---------|
| **PNG** | `saveCanvas('output', 'png')` in `keyPressed()` | Press 's' to save |
| **High-res PNG** | Puppeteer headless capture | `node scripts/export-frames.js sketch.html --width 3840 --height 2160 --frames 1` |
| **GIF** | `saveGif('output', 5)` — captures N seconds | Press 'g' to save |
| **Frame sequence** | `saveFrames('frame', 'png', 10, 30)` — 10s at 30fps | Then `ffmpeg -i frame-%04d.png -c:v libx264 output.mp4` |
| **MP4** | Puppeteer frame capture 

…(truncated)
