Something went wrong. Try again.
draw things doodl.waow.tech
draw atproto
Something went wrong. Try again.
TypeScript 69%
JavaScript 23%
CSS 7%
HTML 1%
README.md
doodl #
draw something, save it as an image blob on your PDS, share it, and use drawings as the app's own iconography. the drawing app is client-side; Cloudflare Workers handle live rooms, share pages, and optional private-preview synchronization. an explore page reads everyone's drawings straight from their PDSes via your relay + slingshot, so it's a little stale by design.
Lives at https://doodl.waow.tech (static site on your PDS via wisp, custom domain on Cloudflare).
Collections:
tech.waow.doodl.drawing— every doodle is an image blob recordtech.waow.doodl.iconset— singletonself, mapping UI slots to drawing strongRefstech.waow.doodl.preferences— singletonself; public defaults (explore, bot feature)tech.waow.doodl.space— a private doodle: a permissioned space you own. add people by handle and draw on it together, live; it saves itself (as ordinary drawing records inside the space) whenever things go quiet. needs a PDS that supports atproto spaces; elsewhere the feature stays dormant.tech.waow.doodl.permissions— the permission set doodl asks for at sign-in (include:), which a spaces PDS expands into the canvas grants
how it works #
- draw — minimal freehand canvas (pen, color, stroke size, undo, clear), exports PNG. stroke controls live in a bottom sheet so the mobile toolbar stays one row tall.
- save —
com.atproto.repo.uploadBlob→ atech.waow.doodl.drawingrecord referencing the blob - icons — settings writes a
tech.waow.doodl.iconset/selfrecord whose assignments point at drawing records; the app renders those slots with the chosen drawings. any slot in the registry can be drawn over, including nav, toolbar, settings, theme, and stroke controls. - icon sets — settings can preview someone else's whole iconset across the app. trying one on is local-only until you save it as your own.
- auth — in-browser AT Protocol OAuth with drawing, icon, preference, live-room and Spaces permissions. OAuth continues to use DPoP; space reads use the current HTTP-signature contract. Private-room credentials renew without interrupting the drawing session.
- explore — UFOs
/records?collection=tech.waow.doodl.drawing(CORS-enabled, firehose-indexed) for the records, then slingshotresolveMiniDocper repo to build each blob'sgetBlobURL. (a raw relay'slistReposByCollectionhas no CORS, so it can't be called from the browser.) - share —
/l/<did>/<rkey>preview pages are served by the Cloudflare Worker inworker/so crawlers get per-drawing Open Graph image tags - bot — optional, opt-in, and deliberately small:
bot/runs the @doodl.waow.tech feature bot for consenting users.
dev #
bun install
bun run dev # localhost uses the atproto loopback OAuth client
bun run check # typecheck, lint, client and Workers tests
bun run build
deploy #
The Wisp site and custom-domain claim belong to waow.tech, which also
publishes the lexicons. The app stays at https://doodl.waow.tech.
one-time: custom domain #
wispctl login waow.tech
wispctl domain claim waow.tech --domain doodl.waow.tech # prints DNS records
# set those records on the waow.tech Cloudflare zone, then:
wispctl domain add-site waow.tech --domain doodl.waow.tech --site doodl
each release #
bun run deploy:live # live-room Worker
bun run deploy:sync # optional private-preview Worker
bun run deploy # metadata, build, wispctl deploy --spa
bunx wrangler deploy --config worker/wrangler.jsonc # share/preview worker
# optional: bunx wrangler deploy --config bot/wrangler.jsonc
See docs for the Spaces access model, integration checks, and cutover procedure.