Skip to content

Repository files navigation

Willow

Lasso painting in the browser. You draw closed loops, each one becomes a filled shape, and they stack in the order you paint them. No brushes, no strokes: the lasso is the tool.

Everything is rendered with three.js on a WebGL canvas, so the artwork is real geometry rather than pixels. That is why a reload restores your drawing exactly rather than a flattened image of it, and why the eyedropper can read colour straight out of the frame buffer.

Local first

This build has no backend and no accounts. Drawings are kept in the browser's localStorage on the device that made them, which has two consequences worth knowing before you rely on it:

  • Nothing syncs. A sketch made on a tablet stays on that tablet.
  • Storage is not permanent. iOS Safari evicts localStorage for any site you have not visited in seven days, and the quota is around 5MB.

Use Back up in the portfolio toolbar to download everything as a single JSON file, and Restore to load it back or move it to another device. Restore merges, so it will not wipe work already on the device.

Controls

Lasso L
Eyedropper I, or hold Alt / right mouse button
Pan H, or hold Space / middle mouse button
Zoom Z plus click, or Cmd / Ctrl with + and -
Zoom to 100% Cmd / Ctrl + 0
Undo last shape Cmd / Ctrl + Z
Show or hide the palette Shift + P
Export as an image Cmd / Ctrl + E
Cancel the current lasso Esc

On a tablet, drag to lasso, one finger to pan, two to zoom, and long press to sample a colour.

Running it

yarn
yarn dev

To reach it from another device on the same network, yarn dev --host and open the printed network address.

Building

yarn build

PUBLIC_BASE_PATH sets the asset prefix, which a project site served from a subdirectory needs. The deploy workflow sets it from the repository name automatically.

Gate

yarn lint && yarn typecheck must pass. yarn test runs vitest in watch mode, so use yarn vitest run anywhere that needs to exit.

Where the backend went

Willow previously stored canvases in Supabase, behind magic link and Discord sign in. That project no longer exists, and nothing that defined it was ever in version control: not the table, not the four Postgres functions the client called, not the storage bucket. Rather than reconstruct it, the eleven calls it served are implemented against localStorage in src/DataSource/LocalBackend.ts.

Every repository function in src/Feature/*/Api dispatches on one flag, so restoring a real backend means writing a second module with the same eleven functions. No component, and none of the rendering code, needs to change.

About

Lasso painting in the browser. Local first, no accounts, no backend.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages