vole
Clone
Read only, no credentials:
https://rodent.software/vole.git
Write over SSH with a registered key:
git clone ssh://git@rodent.software:2222/vole.git
A free and open-source forge that lives in your Git repo.
Draw the celebration on the main thread, not in a blocked worker
6b7d6a1897dca7a8f42669a02c3f6981192ccd22 · Keenan Nemetz · 13d ago · parent 0f8054ad
Draw the celebration on the main thread, not in a blocked worker The burst never painted. canvas-confetti's default export is built with useWorker: true, and it builds that worker from a blob: URL, which this page's CSP (default-src 'self', no worker-src) blocks. The library does not fall back: it transfers its canvas to the worker with transferControlToOffscreen and then posts to it, so the canvas is created, is full-size, is permanently empty, and reports no error. reload, shared link and bookmark behaviour, and the address-bar strip, all worked — which is why the flag looked handled and the burst looked absent. Creating our own instance with useWorker: false draws on the main thread, where 120 particles for ~2s cost nothing, and needs no CSP change. Widening the policy with worker-src blob: to keep the offscreen path would trade a real security boundary for a party trick. Verified by clicking Merge in a real Firefox against a scratch instance: the canvas has 4148 non-transparent pixels and no transferred context. The same probe against the old build reports getContext failing with InvalidStateError.
docs/ui-plan.md +7
| @@ -303,6 +303,13 @@ or a shared link is an ordinary visit; the library honours | |||
| 303 | 303 | nothing for it, which is why the 25 KB bundle is acceptable where a | |
| 304 | 304 | loaded-always library would not be. | |
| 305 | 305 | ||
| 306 | The burst always comes from an instance created with `useWorker: false`. The | ||
| 307 | library's default export opts into a Web Worker built from a `blob:` URL, which | ||
| 308 | `default-src 'self'` blocks — and it transfers its canvas to that worker before | ||
| 309 | drawing, so the canvas appears and stays empty with no error. Drawing on the main | ||
| 310 | thread avoids the CSP question entirely instead of widening the policy with | ||
| 311 | `worker-src blob:` for a celebration. | ||
| 312 | |||
| 306 | 313 | The route table is `server/routes.go`, one function per surface (assets, global, | |
| 307 | 314 | auth, admin, repository, git). Routes are grouped by prefix rather than by | |
| 308 | 315 | registration order because `ServeMux` ranks by pattern specificity, and the | |