The original ZAP_GATED_TEMPLATES_FEATURE.md said "no platform fee, no
backend" — that's exactly the opposite of what we actually want to
ship. ZAPS_NWC_FEATURE.md was scoped as a general tip upgrade,
listing splits as a "future enhancement." For our purposes the two
are a single arc, with NWC being the only thing that gives the
mandatory creator/platform split a tolerable UX.
ZAP_GATED_PREMIUM_FEATURE.md is the new canonical plan:
- 5 phases (0 crypto bundle, 1 NWC, 2 platform-fee plumbing,
3 zap-gated UI, 4 E2E + edge cases). ~16-23h total.
- 30% platform fee, single-constant for easy adjustment later.
- PLATFORM_NPUB hard-coded; lud16 resolved dynamically from the
npub's kind-0 each session (so the lightning address can change
later without a code update).
- CoinOS recommended via a guided "Set up with CoinOS" path in
the wallet-connection modal; generic "paste any NIP-47 URI"
fallback for Alby Hub, Mutiny, Phoenix, Cashu.me, etc.
- Idempotent retry of partial unlocks via localStorage receipt
tracking — creator-leg pays first so a half-failed unlock at
least pays the creator.
- Explicit threat model + non-goals (no creator-only fallback,
no refunds, no bolt11-QR fallback path).
The two old specs are marked superseded with a banner at the top so
historical context is preserved without future contributors getting
crossed wires. TODO.md drops them from the drafted-but-unbuilt list
and points to the merged doc; it also fixes the stale Private
Publishing entry — Phases 1 & 2 already shipped in 3e6e89e, only
Phases 3 & 4 remain.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
9.8 KiB
Artstr Studio — TODO
Running list of deferred work. Detailed specs for the larger items live in
docs/. Each entry notes scope and where the spec is (if any).
Adam's working list
(Empty — see "Shipped (recent)" below for the items that just landed. Drop new items in here as they come up.)
QR code layer — remaining phases
Phases A and B shipped (the qr layer type: data, error-correction level,
quiet zone, module / background colors, transparent background, renders
on every surface + canvas export, JSON round-trip; plus "Insert npub" and
"Insert share link" buttons under the QR data field).
- Phase C — visual polish. Optional center logo overlay and rounded modules. Riskier: a logo eats into the error-correction budget, so it should nudge the ECC level up. Skippable.
Editor / tool UX
Small editor-usability improvements — no spec doc; scoped here.
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
(Core profile pages at /u/<npub> already shipped.)
- Make author chips clickable in the community thread view (comments and
reposts) — currently only feed-card and preview-meta author chips route to
openProfilePage. - About-text clamp — long bios overflow the profile header; clamp to ~4 lines with a "Show more" toggle.
- Profile-grid pagination — an author with 100+ designs renders them all at once; cap the initial render and add a "Show more" pager.
Edit-published-designs — deferred polish
(Core edit-in-place via NIP-33 replaceable semantics already shipped.)
- Replace the remaining
confirm()calls in the edit / publish flow with the styled in-app modal pattern, for consistency with the close-project and publish-confirm modals. - "Editing a previously-deleted design" warning — if the user opens Edit on a design they had tombstoned with a kind-5, warn that publishing will republish it.
Pixel art — future polish
pixelsB64size-fallback encoder. The spec calls for each frame to store whichever is smaller:pixels(RLE pairs) orpixelsB64(base64 of the rawUint8Arrayof indices). Only RLE is implemented today. For noisy / photo-pixelized content with many palette colours, base64 is ~5× smaller — a 24-frame 64×64 sprite tested at 785 KB RLE would drop to ~150 KB. Worth shipping alongside a live event-size readout in the editor (soft warn at 50% of relay budget, hard block at 90%) so users see the budget before publish.
Drafted-but-unbuilt features
Each has a full spec in docs/.
- Zap-gated premium templates (with NWC + platform split) —
docs/ZAP_GATED_PREMIUM_FEATURE.md. In-progress / current focus. Creators mark a template premium with a minimum sat amount; consumers pay via NWC; the payment is split between the creator (70%) and the Artstr platform (30%) in one user gesture. Recommended wallet is CoinOS; any NIP-47 wallet works. Supersedes the olderZAP_GATED_TEMPLATES_FEATURE.md+ZAPS_NWC_FEATURE.mddrafts. - 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 zap-gated lands. - Badges (NIP-58) —
docs/BADGES_FEATURE.md. Award / display Nostr badges on profile pages. - Collections (NIP-51 sets) —
docs/COLLECTIONS_FEATURE.md. Let users organize favorite community templates into named sets.
Phase-3+ work on shipped features
- Private (encrypted) publishing — Phases 3 & 4.
docs/PRIVATE_PUBLISHING_FEATURE.md. Phases 1 (private-to-me) and 2 (toggle public ⇄ private) shipped in commit3e6e89e. Still unbuilt: Phase 3 (share with selected pubkeys) and Phase 4 (NIP-59 gift-wrap metadata privacy + Blossom/NIP-96 offload for oversized encrypted blobs).
Shipped (recent)
-
Pixel-art dropdowns — no more sidebar clipping. The pixel-editor resize-grid and PNG-export menus were
position: absolute; right: 0inside their toolbar wrap. When the toolbar wrapped and the trigger button landed at the left of its row, the menu slid leftward under the main sidebar. Switched both menus toposition: fixedwith a JS-placed coord that anchors to the button's right edge by default, flips to its left edge if anchoring right would clip past the sidebar (sidebar's actual right edge, not just the viewport), and clamps inside the viewport on both sides. Also auto-closes any open menu on window resize to avoid stranded fixed-position remnants. -
Top-right action strip — permanent, never wraps. Pulled the canvas-size readouts and the undo / redo pair out of the topbar's flex flow and pinned them in a fixed strip directly under the Nostr widget, right-anchored, with
flex-wrap: nowrap. Order: canvas-size pills on the left, undo / redo on the right (so undo / redo hug the viewport edge). The topbar's right padding now tracks the wider of the Nostr widget or the strip via the existing--nostr-widget-spacevar, so the project title never slides under it. -
Click canvas background → deselect. The existing #sheet click handler missed clicks in the gutter between sheet edge and previewShell edge; added a #previewShell handler.
-
Crop marks for Custom Art / Slide canvases. New
.canvasCropscorner marks inside .sheet, scoped to those template modes. The existing showCrops / printCrops toggles drive screen + print visibility (relaxed from cover-only to a new.crops-toggleclass). -
Strip selection chrome from PDF Print / JPEG-fallback output. Dead
body.exportingCSS rules were renamed to actually match the class JS sets. Wired both the regular printBtn flow and the JPEG-PDF flow to set the class. Two-class split (body.exportingfor chrome-stripping in either flow,body.export-printfor the heavier container-isolation only the JPEG-PDF flow does) avoids the blank-print regression that a single class caused. -
Custom Art: match canvas to image's natural dimensions. New "Match canvas to image size" button on the image-layer panel (Custom Art mode only; Slide is 16:9 locked). Loads the image via loadImageWithCors, clamps to CUSTOM_ART_MAX, pushes one undo entry.
-
JPEG export — rich text rendering (P2). Canvas-based engine that walks the layer's HTML into styled runs (bold/italic/underline, bullets, numbered lists, line breaks), lays them out with ctx.measureText + word wrap, and draws each item with its own font
- underline. Dispatches to plain
fillTextwhen no inline marks are present. SVG-foreignObject was tried first; it taints the canvas in Chromium so we built the run-layout engine instead.
- underline. Dispatches to plain
-
Independent-axis corner-node resize. Corner handles default to independent axes (each axis follows its own drag delta); Shift+drag locks aspect (Figma / Photoshop / Keynote convention). The sidebar 🔒 toggle still governs typed W/H input cascades.
-
JPEG export — DPI / quality selector (P4 polish). 96/150/300 dpi presets in a dropdown next to the Export JPEG button.
-
JPEG export — one-click direct rasterizer (P1). Replaces the print-to-PDF-then-re-pick flow for Cover, Disc sheet, Jewel, Disc design, Custom Art, and Slide canvases. The infrastructure was already 90% built (drawLayerToCanvas + four canvas-type rasterizers existed but were never wired to any entry point); P1 added the missing Custom-Art rasterizer + the orchestrator that picks the right rasterizer per templateMode, pre-flights CORS via the existing _exportFailedImages set, and falls back to the print modal when any image can't be embedded directly.
-
Slide deck PDF export — multi-page PDF, one page per slide. The existing Print / Save PDF button is context-aware: in the Deck Builder it builds a hidden print-only container with one page per slide (themed via
composeSlideForDeck, each page sized to the preview's native dimensions so the slide fills the page exactly) and emits one PDF viawindow.print(). Inside a single-slide editor, the button still prints just that slide. -
Copy / paste transform consistency — paste now computes a single group bounding box across all clipboard items, applies one shared scale (only shrinks, never enlarges) and one shared translation, so cross- target paste keeps every layer's relative position and size to the others intact.
-
Pixel-editor colour picker — ported the OS native
<input type="color">over from the vector tools (same swatch styling; opens the OS picker with its built-in eyedropper on click). Removed the Screen-Capture-API screen- eyedropper workaround (~170 lines of dead code). Palette swatches and the in-canvas eyedropper tool now sync the picker too, so grabbing a palette colour as the starting point for a tweaked variant just works. -
Pixel Art —
docs/PIXEL_ART_FEATURE.md. Phases A–D all shipped: embeddedpixelartlayer + standalonecasewrap-pixelartdesign, 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 usesoverflow-wrap: anywhere; word-break: break-word, so no horizontal scroll. -
TMDB auto-fill cleanup —
docs/TMDB_AUTOFILL_FEATURE.mdremoved.