Add pastel presets, piece selection and colors, mask brushes, subdivision and conservative decimation with bounded worker operations and mixed undo history. Amp-Thread-ID: https://ampcode.com/threads/T-01a0b4b4-202c-73f1-984d-9a55c88f9c83 Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
Yawn
Yawn Core is two things: a generic structure-of-arrays arena in a SharedArrayBuffer, and a Rust render graph that turns externally supplied WGSL into an up-front WebGPU loadout.
JSO or FXNode → AST → S-expression → worker messages → Rust/WebGPU
↑
any thread → direct shared row writes ─────────────┘
The arena starts with only one eight-float signals row for frame timing and render invalidation. Messages create or delete other { name, rows, stride, format } arrays, allocate named slots, compile graphs, switch loadouts, and control render pacing. Existing render data is changed by writing f32, u32, or i32 rows directly, then setting the shared-data dirty signal. Allocations are 64-byte aligned, row strides are multiples of 16 bytes, and compatible non-overlapping transient textures share physical allocations.
WGSL, pipelines, glTF import, and conventional mesh/camera/material handles live in addons/; core contains no shader or scene model.
Run the Go website, in-memory package server, SQLite-backed playground, and tutorial:
npm run server
The server rebuilds @yawn/core and @yawn/handles at startup and serves the public CDN modules at
https://yawn.heaust.org/pkg/core.js and https://yawn.heaust.org/pkg/handles.js. Handles keeps Core
as a separate module dependency instead of bundling it. Map and import both URLs as shown in
server/examples/basic.html; their workers and WASM stay on the CDN automatically. The complete editor is at /playground; saved revisions use
/playground/{id}/{revision} URLs. Set PORT or YAWN_DATABASE to override the default port and
server/data/yawn.db database path.
VPS deployment
Clone the repository to ~/yawn on a VPS with Docker and the Compose plugin, then run:
cd ~/yawn
./server/deploy-docker.sh
The deploy script requires a clean main, fast-forwards it to origin/main, builds the production
image, starts it with Docker Compose, and waits for the health check. Core, Handles, workers, and
WASM are compiled while building the image; the runtime container only holds the Go server,
prebuilt package assets, Monaco, and the persistent SQLite volume. Configure the port and database
path in compose.yaml. The default port binding is private to the VPS at 127.0.0.1:5002; put
Caddy or nginx in front of it for HTTPS. Follow logs with docker compose logs -f yawn.
To check for new pushes every minute, add this entry with crontab -e:
* * * * * $HOME/yawn/server/poll-deploy.sh >> $HOME/yawn-deploy.log 2>&1
The poller compares origin/main with the last healthy deployed revision and does nothing when they
match. A shared lock prevents overlapping manual and scheduled deployments. Failed deployments do
not update the revision marker, so the next poll retries them.
Run the previous VitePress documentation site with npm start.
Run npm run coredocs for the raw worker-message, shared-memory, and render-graph reference intended for custom handles, editors, and direct SAB clients.