Public
Sprite sheet animator web app
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.

🎞️ sprite-animator

Sprite Forge β€” a browser sprite-sheet animator. Loads a built-in sample sheet, lets you set the grid (columns Γ— rows), pick a row to play, scrub frames, and tune speed/zoom. Upload, drag-drop, or paste any other sheet to animate it instead; uploaded sheets persist and show up in the gallery.

Live: https://dcm31--a0f721e05e3711f1b6c61607ee4eb77e.web.val.run

Use it

  • Columns / Rows β€” match the sheet's grid. Frame size is derived automatically.
  • Single row / All frames β€” play just one row, or every frame left-to-right, top-to-bottom.
  • Loop / Ping-pong β€” ping-pong bounces back through the frames (nice for short cycles).
  • Speed / Zoom β€” fps and nearest-neighbour scale, so pixels stay crisp.
  • Upload / drag-drop / paste an image to add a sheet. Click any frame in the strip to play that row.
  • Save grid to sheet stores the columns/rows/fps you dialled in for an uploaded sheet.

The bundled sample is a 4Γ—4 sheet β€” rows are down / up / side / side.

How it works

The server is static + a small JSON API. The sample sheet is embedded as base64 and served like any other sheet; uploads live in blob storage. All animation happens client-side on a <canvas>.

Rendering mermaid diagram...

API

RouteDoes
GET /api/sheetsList sheets (sample first, then newest uploads)
GET /api/sheets/:id/imageRaw sheet pixels (sample from embed, rest from blob)
POST /api/sheetsUpload a sheet (multipart: file, name, cols, rows, fps)
PATCH /api/sheets/:idUpdate name/cols/rows/fps
DELETE /api/sheets/:idRemove an uploaded sheet

Files

FileRole
main.tsHono server β€” JSON API, static files, /source redirect
index.htmlMarkup + controls
style.cssRetro-arcade styling
app.jsAll animation logic (geometry, rAF loop, strip, gallery, upload/paste)
default-sprite.jsThe built-in sample sheet as an embedded base64 PNG

Storage

Uploaded sheets are kept in std/blob under three keys: sprite:index (an id list), sprite:meta:<id> (the metadata), and sprite:img:<id> (base64 pixels). The sample id is special-cased and never touches blob.

Swap the built-in sample

Replace SAMPLE_B64 (and tweak SAMPLE_META) in default-sprite.js with another base64-encoded image. It's served straight from /api/sheets/sample/image, so no upload is needed for the default.