Back to Sketch Loop
SOURCE / PINNED RELEASE

Made of little things.

Sketch Loop

Release
14966bba4a2a
Author-recorded commit
e68361295d81…
License
LICENSE
Author’s source reference
nostr://npub1n8ga89w8h6tvwamxusfyzexw8gjy84yxu9rxgnmk955cxtml4ujswzxydd/wss%3A%2F%2Fgit.napplet.soy%2F/n-929bc2a88cb

Archive hash verified: 5e0385e3c08f944f. The source-to-build association is the author’s claim; it has not been independently rebuilt.

README.md
# Sketch Loop

A compact napplet for pasting 2D p5-style creative code, watching it animate, and exporting a timed GIF. BusyMozaic by Kurt Moerman (@KurtMoerman4) is preloaded, alongside two original examples.

## Use

1. Paste code in **Code**, then press **Run**. Pause or restart the preview with the toolbar.
2. Open **GIF** (always visible alongside the preview in a wide frame).
3. Choose **Duration** (1–30 seconds), **Start at** (0–30 seconds), **Frame rate** (10–30 fps), original/half size, and whether the GIF repeats.
4. Press **Render GIF**. Rendering is cancellable and shows progress. Start at zero for the beginning, or a later time for artwork that accumulates over many frames.
5. Press **Save GIF**, accept the host's file picker, then use its download link. soyLI stores the generated file in session files before offering the download.

**Save draft** persists the editor and export settings through the host. A restored draft waits for Run before executing. Host **Settings** provides defaults and crisp/smooth preview scaling; changes to local export controls take precedence for that session.

## Sketch compatibility

This is a documented **2D p5-style subset**, not the complete p5.js library. The help panel lists the supported API. Both `draw = _ => { ... }` golfed sketches and `function setup()` / `function draw()` work. The supplied social-post string is accepted, including escaped Markdown operators, hashtag links and collapsed line breaks.

Supported features include arithmetic and bitwise expressions, simple functions, variables, loops, conditions, arrays by index, plain objects, 2D shapes, transforms, colors, text, seeded random numbers and deterministic value noise. Canvas dimensions are limited to 1,024 × 1,024. Array methods, destructuring, classes, imports, async functions, external assets, WebGL, DOM and browser APIs are not implemented. Unsupported constructs produce an inline error.

Source is parsed with [Acorn](https://github.com/acornjs/acorn) and executed by a bounded interpreter with explicit drawing/math capabilities. No dynamic evaluation or browser/shell objects are given to sketches. Loops, recursion, source size, strings, arrays, canvases and output size have limits. This is a small interpreter, not a claim of full JavaScript compatibility.

GIFs use [gifenc](https://github.com/mattdesl/gifenc). Each export starts a fresh sketch with a fixed random seed, simulates at its own frame rate (60 fps by default), and samples at the requested export FPS. GIF centisecond delays sum to the requested duration. Transparent pixels are flattened on black. Repeat enables GIF replay; it cannot make arbitrary code seamlessly loop. GIF rendering is limited to 160 million sampled pixels and 24 MB output; host storage limits may be smaller. Lower resolution, frame rate, or duration if needed.

## Host boundaries

Read [docs/napplet-space.md](docs/napplet-space.md) for the installed soyLI toolchain and publishing workflow.

All NAP domains are optional:

| Domain | Purpose | Missing-domain behavior |
| --- | --- | --- |
| `theme` | Whole-surface runtime colors | Charcoal/mint fallback |
| `storage` | Explicit draft save and restoration | Save draft disabled |
| `config` | Host settings and defaults | Local controls keep defaults |
| `fs` | Picker and chunked GIF file writes | GIF preview works; saving explains unavailable support |

No Nostr operations, relay escape hatches, network requests, or inter-napplet operations are used. GIF bytes stay local and pass to the shell only when Save GIF is pressed. All calls use `@napplet/sdk`. The built artifact is one inlined `dist/index.html`.

## Development and verification

The project is already scaffolded; do not run a creator again. Skills are installed locally. On another checkout, install upstream guidance with `npx skills add napplet/napplet` and follow `napplet-make`.

```sh
soyli dev --no-open          # actual sandbox preview, normally http://127.0.0.1:4173/
pnpm type-check
pnpm build
pnpm test:guidance
pnpm test:sketch             # interpreter boundaries and GIF timing
pnpm test:conformance        # real Chromium reference shell
pnpm test:browser            # soyLI must already be running on port 4173
soyli check                  # actual host artifact check
```

`pnpm dev` is the raw source server, not a napplet runtime. Preserve the upstream Vite plugin and conformance scripts. The SDK was updated to 0.28.0 for its shipped FS wrappers; the remaining substrate was kept.

Browser checks cover all examples, pause/resume, parse errors, runaway loops, cancellation, generation, the actual host save/download flow, draft restoration, and 200×160 / 320×560 / 900×600 / 2400×1200 frames in both themes. Private screenshots and test exports are written to ignored `.napplet-space/qa/`.

Reference-shell conformance reports manifest, wire and lifecycle evidence as skipped when it is not supplied. The separate browser test exercises real SDK calls against soyLI. See [docs/verification.md](docs/verification.md) for the latest results.