Docs: ship pixel-art Phases A–D, prune stale TODOs, update README

PIXEL_ART_FEATURE.md: rewrite Implementation status to reflect that
Phases A–D all shipped (embedded layer, standalone design, raster
export + editor extras, animation, image → pixelize), with the
backlog (WebP/APNG, Blossom offload, animated pixel layers driving
Stack actions) called out as deferred.

TODO.md: drop stale items now that they're resolved —

- Pixel Art (moved to a "Shipped (recent)" section pointing at the
  spec doc).
- Pixel editor layout expansion (subsumed by the collapsible
  sidebar — both the pixel editor and vector canvas can now use
  the full viewport width).
- Print / Save event ID wrapping (the `<dd>` already uses
  `overflow-wrap: anywhere; word-break: break-word`).
- TMDB auto-fill cleanup (the doc was already deleted).

The Color picker fixes item is kept but narrowed to the vector
tools — the pixel editor's in-app HSV picker shipped in Phase A.

README.md: add Pixel Art everywhere it's relevant —

- One-liner mention in the intro paragraph.
- New "Pixel art" Designer-tab layout entry alongside Slide / Disc
  design.
- `pixelart` layer type added to the Layers list.
- New dedicated "Pixel art" section before Editor canvas, covering
  tools / transforms / animation / export / import / undo /
  animated previews.
- Editor canvas section mentions the new sidebar collapse toggle.
- Schema section lists `pixelart` template mode and layer type,
  documents the `pixelArt` data-model shape, and notes that the
  inline GIF89a encoder lives in `index.html` (not a vendored dep).

Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Opus 4.7 committed 2026-05-26 10:54:10 -04:00
1 parent e7e3039748
commit 6a1352904e
3 files changed
+98 -45

No files matched your search

+24 -6
View File
@@ -1,6 +1,6 @@
# Artstr Studio
Artstr Studio is a static, browser-only design tool for printable physical media packaging — and increasingly, a general-purpose Nostr-native graphics editor. It started as a DVD/Blu-ray case wrap maker and now also covers Avery 8960/8944 disc labels, Avery 8693/8943 CD jewel-case inserts, single-disc designs, free-form custom art canvases, and 16:9 slides assembled into presentable slide decks. Designs publish to and load from Nostr, are forkable and editable in place, and can be tipped via Lightning.
Artstr Studio is a static, browser-only design tool for printable physical media packaging — and increasingly, a general-purpose Nostr-native graphics editor. It started as a DVD/Blu-ray case wrap maker and now also covers Avery 8960/8944 disc labels, Avery 8693/8943 CD jewel-case inserts, single-disc designs, free-form custom art canvases, 16:9 slides assembled into presentable slide decks, and palette-indexed animated pixel art. Designs publish to and load from Nostr, are forkable and editable in place, and can be tipped via Lightning.
## Tabs and layouts
@@ -15,6 +15,7 @@ The editor has two tabs at the top level, each with its own Layout panel:
- **Custom art** (the Designer tab's default) — a free-form canvas with size presets (1920×1080, square sizes, etc.) or custom dimensions. Treats the project as generic art rather than packaging.
- **Slide** — a 16:9 design surface (a Custom Art canvas locked to 16:9) with a speaker-notes field. A standalone, publishable design that can be imported into a slide deck.
- **Disc design** — a reusable single-disc design you can publish on Nostr and import later into either disc position of a disc-label sheet.
- **Pixel art** — a dedicated palette-indexed grid editor (single static sprite up to 128×128, or a multi-frame animation). Publishes as `casewrap-pixelart`; exports to PNG, sprite sheet, and animated GIF.
Each layout keeps its own metadata (title / identifiers / category / language) so switching layouts — or loading a project — doesn't overwrite a design already in progress.
@@ -42,6 +43,7 @@ Layers compose on top of the per-mode artwork:
- **Shape** — vector primitives (rectangle / rounded rectangle / circle / ellipse / triangle / polygon / star / line) with solid, linear-gradient, or radial-gradient fills and optional solid strokes (color / width / solid / dashed / dotted).
- **Custom path / SVG upload** — upload an `.svg` file. Single-path SVGs land as editable shapes; multi-element SVGs preserve their internal fills and stacking, with a per-element editor that lets you change each `<rect>` / `<path>` / `<circle>` etc. fill and stroke individually.
- **QR code** — encode any URL or text as a scannable QR layer. Adjustable error-correction level (L/M/Q/H), quiet zone, module / background colors, and an optional transparent background for placing over artwork.
- **Pixel art** — a palette-indexed editable grid up to 128×128 cells, with full pencil / eraser / fill / eyedropper / line / rect / ellipse tools, mirror X/Y, flip/rotate/resize transforms, multi-frame animation with playback and onion-skin, an in-app HSV picker, an inline screen-eyedropper, and PNG / sprite-sheet / animated-GIF export. Importable from a published design (Browse community), a local JSON file, or any image file (image → pixelize with median-cut palette quantization).
Every layer supports drag / resize / rotate / opacity / z-order, an aspect-ratio lock toggle on the W/H inputs (default on), a lock toggle that prevents accidental drags, and a visibility (eye) toggle in the layer list.
@@ -68,13 +70,29 @@ Artstr Studio doubles as a Nostr-native presentation tool.
- **Deck theme** — a deck-level font and background that restyle every slide at render time without altering the slides themselves; any slide can opt out.
- **Presenter Mode** — a full-screen runtime that plays a deck: the themed current slide, speaker notes, a next-slide thumbnail, and a slide counter. Navigate with on-screen controls, click-to-advance, or the keyboard (arrows / space / Page keys / Home / End / Esc). A **Presenter ⇄ Audience** view toggle switches between the notes-and-thumbnail layout and a clean slide-only full-screen view. Launch it from the ▶ button in the Deck Builder tool palette, or from **Start Presentation** on a deck's preview page in the community browser.
## Pixel art
A dedicated palette-indexed editor for sprites and animations.
- **Two faces** — drop a `pixelart` layer into any other design (a cover, a slide, a custom-art canvas, etc.) or run **Pixel Art** as a standalone Designer-tab layout where the editor view *is* the whole canvas.
- **Tools** — pencil / eraser / fill bucket / colour eyedropper / line / rect / ellipse (with a Fill toggle), mirror X/Y, grid toggle, zoom; an in-app HSV picker (drag the saturation/value square + hue strip, then **+ Add** to push the colour into the palette).
- **Transforms** — flip H/V and rotate 90° CW/CCW apply across every frame; grid resize 4–128 per side, top-left anchored, transparent fill.
- **Animation** — a vertical timeline strip on the left holds the frames: add / duplicate / delete / drag-reorder / click to switch. Left / Right arrow keys cycle frames; **Space** plays / stops. Per-design FPS (1–60) and Loop, plus an Aseprite-style red-prev / blue-next **onion-skin** toggle.
- **Export** — crisp PNG at 1× / 2× / 4× / 8× / 16× / 32× (transparency, optional grid lines), sprite-sheet PNG (Grid or Row layout) with all frames tiled, and animated GIF via an inline GIF89a encoder (no vendored dependency — pixel-indexed input is what GIF expects natively).
- **Import** — *Browse community* opens the Nostr browser filtered to pixel-art designs and drops the chosen one in as a new layer; *Import from file* takes a local JSON design; *From image…* lets you pick any image file, then a live side-by-side preview tunes target W/H, colour count, and fit mode (Cover / Fit / Stretch) before applying.
- **Undo / redo** — fully integrated with the top-level toolbar; while the editor is open, **Ctrl+Z** / **Ctrl+Shift+Z** drive the pixel editor's local stack, restoring all frames plus the current-frame index together. Standalone-mode edits also push debounced entries to the global design history.
- **Animated previews** — multi-frame designs animate in the publish-confirm modal, the community browser, feed-card thumbnails, and profile pages. The RAF loop self-stops when the preview leaves the DOM, so closing a modal or scrolling a card out of view doesn't leak loops.
## Editor canvas
The canvas is a unified, Illustrator-style workspace: the tool palette, the
scrolling canvas, the contextual options panel, and the zoom bar are docked
flush around the artboard. Sidebar panels are collapsible (click the heading);
they start collapsed except the Layout panel, and selecting a layer opens the
Layers panel automatically.
Layers panel automatically. The whole side panel can also be **collapsed**
via a chunky vertical handle on the seam — handy when the canvas needs the
full width for a complex pixel sprite or a wide custom-art design. State
persists across reloads.
- **Undo / redo** — Ctrl+Z / Ctrl+Shift+Z (and Ctrl+Y), or the topbar buttons. A 50-deep in-memory history covering layer edits, mode switches, artwork loads, metadata, and more. Defers to the browser's native text-input undo while an input is focused.
- **Fit-to-view by default** — the canvas auto-scales so the whole artboard fits the preview area; it re-fits on window resize. The bottom zoom bar has zoom in/out, a 20–200% slider, Fit, and 1:1.
@@ -128,16 +146,16 @@ Two flavors of Lightning are wired in:
## Files
- `src/index.html` — the complete single-file app. Open it directly in a browser, or serve it from any static host. Vercel rewrites in `vercel.json` map `/share/:id` and `/u/:npub` to the SPA entry.
- `src/vendor/qrcode.min.js` — vendored QR encoder (used for Lightning tip invoices).
- `docs/` — feature specs. `PEN_TOOL_FEATURE.md` covers the shipped pen / pencil / vector tooling; `SLIDE_DECK_FEATURE.md` covers the shipped slide / deck / presenter system (Phases A–D; dual-window presenter is future). Badges, collections, NWC zaps, and zap-gated templates are still unbuilt.
- `src/vendor/qrcode.min.js` — vendored QR encoder (used for Lightning tip invoices). The GIF89a encoder for pixel-art animation export is implemented inline in `index.html`.
- `docs/` — feature specs. `PEN_TOOL_FEATURE.md` covers the shipped pen / pencil / vector tooling; `SLIDE_DECK_FEATURE.md` covers the shipped slide / deck / presenter system (Phases A–D; dual-window presenter is future); `PIXEL_ART_FEATURE.md` covers the shipped palette-indexed pixel-art system (Phases A–D). Badges, collections, NWC zaps, zap-gated templates, private publishing, and Stacks are still unbuilt.
- `TODO.md` — running list of deferred work and cleanup items.
## Schema
- Current project schema version: **5**.
- Minimum supported version: **4**. Older payloads load but won't round-trip cleanly.
- Template-mode discriminator in payloads: `cover`, `disc`, `jewel`, `customart`, `disc-design`, `slide`, `deck`. A `slide` payload carries a `slide` object (canvas dims + speaker `notes`); a `deck` payload carries a `deck` object (`theme` + an inline ordered `slides` array).
- Layer types: `image`, `text`, `color`, `shape`, `qr`. Shape kinds: `rect`, `rounded-rect`, `circle`, `ellipse`, `triangle`, `polygon`, `star`, `line`, `path`, `svg`. Any layer may carry a `clip` field for masking.
- Template-mode discriminator in payloads: `cover`, `disc`, `jewel`, `customart`, `disc-design`, `slide`, `deck`, `pixelart`. A `slide` payload carries a `slide` object (canvas dims + speaker `notes`); a `deck` payload carries a `deck` object (`theme` + an inline ordered `slides` array); a `pixelart` payload carries a `pixelArt` object (`width` / `height` / `palette[]` of `#rrggbbaa` strings + `frames[]` of `{ id, pixels: <RLE> }` + optional `fps` and `loop`).
- Layer types: `image`, `text`, `color`, `shape`, `qr`, `pixelart`. Shape kinds: `rect`, `rounded-rect`, `circle`, `ellipse`, `triangle`, `polygon`, `star`, `line`, `path`, `svg`. Any layer may carry a `clip` field for masking. Pixel-art layers carry their own `pixelArt` object inline (same shape as the standalone payload).
## Defaults and stack
+24 -20
View File
@@ -7,12 +7,10 @@ Running list of deferred work. Detailed specs for the larger items live in
- **Slide deck PDF export.** Add multi-slide PDF export for slide
presentations, producing one page per slide.
- **Pixel editor layout expansion.** Enlarge the pixel editor so it uses the
empty outer gaps around the current editing area.
- **Color picker fixes.** Fix the color picker, which currently does not work
on pixel or vector tools.
- **Print / Save event ID wrapping.** In the Print / Save panel, make sure the
event id wraps instead of forcing the side panel into horizontal scrolling.
- **Color picker fixes (vector tools).** The in-app HSV picker now works in
the pixel editor; verify the OS-native `<input type="color">` flow in the
vector tool panels (Pen / Shape / Text fill + stroke). If the same Brave
R=NaN bug bites there, port the in-app HSV picker over.
- **Copy / paste transform consistency.** Audit Copy, Paste, Copy All, and
cross-target paste so copied objects keep consistent position and scale
relative to the other copied objects, without unexpected misalignment or
@@ -36,17 +34,10 @@ surface + canvas export, JSON round-trip).
Small editor-usability improvements — no spec doc; scoped here.
All current items shipped (commit `1a517c9`): on-canvas drag-resize
handles for every layer type, text-box resize that never rescales the
point size, and the expanded Text tool panel (font / size / color /
alignment / bold / italic). Add new editor-UX improvements below as
they come up.
## Cleanup
- **Delete `docs/TMDB_AUTOFILL_FEATURE.md`.** TMDB auto-fill was declined —
the metadata fields work fine filled by hand, and the IMDb-style import
has been removed.
Shipped: on-canvas drag-resize handles for every layer type, text-box
resize that never rescales the point size, the expanded Text tool panel
(font / size / color / alignment / bold / italic), a collapsible sidebar
toggle that fits the early-web aesthetic. Add new editor-UX items below.
## Profile pages — deferred polish
@@ -81,9 +72,6 @@ Each has a full spec in `docs/`.
- **Artstr Stacks** — `docs/STACKS_FEATURE.md`. Interactive fullscreen
page/card stacks (HyperCard for Nostr) — the Slide Deck extended with
layer actions and an interactive viewer. Queued after private publishing.
- **Pixel Art** — `docs/PIXEL_ART_FEATURE.md`. An editable `pixelart`
layer type (palette-indexed grid in JSON), a dedicated Pixel Editor
view, PNG/GIF export, and a standalone `casewrap-pixelart` design.
- **Badges (NIP-58)** — `docs/BADGES_FEATURE.md`. Award / display Nostr
badges on profile pages.
- **Collections (NIP-51 sets)** — `docs/COLLECTIONS_FEATURE.md`. Let users
@@ -93,3 +81,19 @@ Each has a full spec in `docs/`.
- **Zaps via Nostr Wallet Connect** — `docs/ZAPS_NWC_FEATURE.md`. In-app
zapping without the wallet handoff. (Tracked LNURL-pay tips already ship;
this would be the NWC path.)
## Shipped (recent)
- **Pixel Art** — `docs/PIXEL_ART_FEATURE.md`. Phases A–D all shipped:
embedded `pixelart` layer + standalone `casewrap-pixelart` design,
PNG / sprite-sheet / GIF export, drawing tools (line / rect / ellipse,
flip / rotate, grid resize), animation (multi-frame timeline, playback,
onion-skin), image → pixelize, and animated previews in every preview
surface. Undo / redo integrated with the top-level toolbar.
- **Pixel editor layout expansion** — addressed by the collapsible
sidebar (gives both the pixel and vector editors a lot more breathing
room when needed).
- **Print / Save event ID wrapping** — the event-id `<dd>` already uses
`overflow-wrap: anywhere; word-break: break-word`, so no horizontal
scroll.
- **TMDB auto-fill cleanup** — `docs/TMDB_AUTOFILL_FEATURE.md` removed.
+50 -19
View File
@@ -86,25 +86,56 @@ template, it is *any design*.
## Implementation status
- **Phase A1 — embedded pixel layer: built (pending in-browser testing).**
The `pixelart` layer type + `pixelArt` data model (palette + RLE
frames), `renderPixelGridToCanvas` and crisp rendering across the
editor / preview-DOM renderers / export canvas. A `#pixelEditorView`
with pencil / eraser / fill / eyedropper, a palette panel (pick / add),
grid toggle, mirror X/Y, zoom, and a per-stroke in-editor undo.
Reachable via the **▦** tool-palette button ("Add Layer → Pixel Art")
and an "Edit pixels" button / double-click on a selected pixel layer.
Single static frame only.
- **Phase A2 — standalone Pixel Art design: built (pending in-browser
testing).** `templateMode: 'pixelart'` — a "Pixel Art" layout on the
Designer tab where the `#pixelEditorView` is the whole canvas area,
bound to `state.pixelArt`. Save / load / publish / fork as
`casewrap-pixelart`; appears in the community feed with a crisp
preview; the `pixel-art` category was added. Single static 32×32 grid
(grid resize is Phase B).
- **Phases B / C / D:** not started. (Note: a `drawPixelArtToCanvas`
export path is already wired, so pixel layers appear in PDF/JPEG
export — Phase B's dedicated PNG export is still pending.)
All four phases shipped.
- **Phase A1 — embedded pixel layer: shipped.** The `pixelart` layer
type + `pixelArt` data model (palette + RLE frames),
`renderPixelGridToCanvas` and crisp rendering across the editor /
preview-DOM renderers / export canvas. A `#pixelEditorView` with
pencil / eraser / fill / eyedropper, a palette panel (pick / add),
grid toggle, mirror X/Y, zoom, and per-stroke in-editor undo.
Reachable via the **▦** tool-palette button and an "Edit pixels"
button / double-click on a selected pixel layer.
- **Phase A2 — standalone Pixel Art design: shipped.**
`templateMode: 'pixelart'` — a "Pixel Art" layout on the Designer
tab where the editor view is the whole canvas area, bound to
`state.pixelArt`. Save / load / publish / fork as
`casewrap-pixelart`; shows in the community feed under the new
`pixel-art` category.
- **Phase B — raster export + editor extras: shipped.** Crisp PNG
export at 1× / 2× / 4× / 8× / 16× / 32× with transparency and
optional grid lines, sprite-sheet PNG (Grid or Row layout) for
multi-frame designs, line / rectangle / ellipse tools with a Fill
toggle, flip H/V + rotate 90° CW/CCW, grid resize (4–128 per side
with top-left anchor and transparent fill), and a Browse-community
/ Import-from-file pipeline that drops a published or local
pixel-art design into the current design as a new layer.
- **Phase C — animation: shipped.** Multi-frame `frames[]` data model
with a vertical timeline strip (add / duplicate / delete /
drag-reorder / click-to-select frames; arrow keys cycle), playback
with FPS (1–60) and Loop controls (Space to toggle, clicking the
canvas stops), Aseprite-style red-prev / blue-next onion-skin
toggle, sprite-sheet PNG export, and an inline GIF89a encoder for
animated GIF export — palette-indexed, no vendored dependency.
Multi-frame previews animate everywhere they're rendered (publish
modal, community browser, feed cards, profile pages).
- **Phase D — conversion: shipped.** "From image…" button in the
pixel editor toolbar: pick any image file → live side-by-side
preview as you tune W / H / Colors / fit mode (Cover / Fit /
Stretch) → median-cut palette quantization → nearest-neighbour
downscale → applies into the editor as a drop-in replacement
(one undo restores the prior state).
- **Undo / redo integration.** The pixel editor's local undo /
redo is driven by the top-level Undo / Redo buttons while the
editor is open, and falls back to the global design history
when the editor is closed. Snapshots capture all frames plus
the current-frame index, so an undo across a flip / rotate /
resize restores everything coherently. Standalone-mode edits
push debounced entries to the global stack too.
Not built (deferred to the backlog): WebP / APNG / animated-WebP
export, Blossom offload + external manifest form for very large art,
and animated pixel layers that drive Stack actions on click.
---