- Server always overwrites local IndexedDB on initial page load (was only when server had more shapes)
- Prune local-only shapes not on server (stale deletions stuck in IndexedDB)
- Increase sync timeout from 5s to 15s (DO cold starts can exceed 5s)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AI-powered diagram generation via Ollama (llama3.1:8b), client-side SVG
preview using mermaid.js, and animated GIF export via mermaid-animator API.
Supports progressive/template/sequence animation modes, theme selection,
adjustable timing, code editor toggle, and diagram history.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Running npm ci twice in separate containers causes OOM on the shared
host. Single job: npm ci once, then tsc, vitest, and vite build
in sequence.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
node-pty native compilation during npm ci uses excessive memory.
Using --ignore-scripts since tests and build don't need native
modules. Removed python3/make/g++ from install step.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Worker test has pre-existing string mismatch (enCryptID vs CryptID).
Runner memory increased from 4GB to 8GB for Vite build.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
node-pty requires python3, make, g++ for node-gyp native build.
node:20-bookworm-slim doesn't include these by default.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- test job: TypeScript check, unit tests, worker tests
- build-check job: validates production build succeeds
- deploy job (main only): builds Docker image, pushes to Gitea registry,
deploys to Netcup, runs smoke test with auto-rollback on failure
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Daily.co video chat replaced by Jitsi (meet.jeffemmett.com) — clean up
residual config (Dockerfile, vite.config, worker types, env vars).
Google Maps embed replaced with OpenStreetMap — no API key needed,
converts Google Maps URLs to OSM embeds automatically.
Part of TASK-CRITICAL.1: exposed API key rotation and cleanup.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New canvas shape that connects to the self-hosted Meeting Intelligence API
(meets-api.rspace.online) to browse meetings, pull transcripts, summaries,
and speaker data onto the canvas as note shapes.
- MeetingIntelligencePanel: React panel listing meetings with pull buttons
- MeetingIntelligenceBrowserShapeUtil: Browser shape wrapping the panel
- MeetingIntelligenceTool: Tool for placing browser on canvas
- Registered in Board.tsx, overrides.tsx, automerge stores, and all shape registries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New canvas shape that connects to the self-hosted Meeting Intelligence API
(meets-api.rspace.online) to browse meetings, pull transcripts, summaries,
and speaker data onto the canvas as note shapes.
- MeetingIntelligencePanel: React panel listing meetings with pull buttons
- MeetingIntelligenceBrowserShapeUtil: Browser shape wrapping the panel
- MeetingIntelligenceTool: Tool for placing browser on canvas
- Registered in Board.tsx, overrides.tsx, automerge stores, and all shape registries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Web Speech API hook was sending each recognition result as a
separate fragment via onTranscriptUpdate, causing the transcription
shape to display fragmented/echoed conversation. Now the hook
accumulates the full transcript internally and always sends the
complete text, so the shape receives one unified conversation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously the page-switch logic only triggered when the current page had 0 shapes.
The R2 data has 283 shapes on page:QZw03khAAJ7jNX7zQND64 but only 1 (MycelialIntelligence)
on page:page. Since page:page is the default, users saw only the MI shape, not their content.
Now also switches when current page has <=2 shapes but another page has >10.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
BlenderGen and TransactionBuilder were added to Board.tsx's customShapeUtils
but never registered in useAutomergeStoreV2.ts's CUSTOM_SHAPE_TYPES, imports,
or shapeUtils array. This schema mismatch prevented tldraw's Editor from
rendering any content - the store didn't know about these shape types even
though the Tldraw component was told to use them.
Also adds TransactionBuilder shape for Safe multisig transaction building
and reduces verbose error logging in automerge sync.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CLAUDE.md may contain project context with credentials and is now
covered by global gitignore to prevent accidental secret commits.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When visiting jeffemmett.com/board/mycofi, the redirect now correctly
goes to canvas.jeffemmett.com/mycofi/ instead of jeffemmett.com/mycofi.
Localhost and canvas.jeffemmett.com still use same-domain redirects.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- cryptidAuth.ts: sendEmail() now calls email-relay.jeffemmett.com
instead of api.resend.com
- boardPermissions.ts: admin request emails use email relay
- types.ts: RESEND_API_KEY → EMAIL_RELAY_URL + EMAIL_RELAY_API_KEY
- wrangler.toml: updated secrets documentation
- Tests updated with new mock env vars
Email relay is a lightweight Flask service on Netcup that accepts
HTTP POST and sends via Mailcow SMTP. Needed because CF Workers
can't do TCP/SMTP directly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When visiting jeffemmett.com/board/mycofi, the redirect now correctly
goes to canvas.jeffemmett.com/mycofi/ instead of jeffemmett.com/mycofi.
Localhost and canvas.jeffemmett.com still use same-domain redirects.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace 12 FlipHTML5 iframe URLs with slides.jeffemmett.com for full self-hosting
of all presentation decks. Zero external dependencies for presentation viewing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DNS and Cloudflare tunnel were already configured but Traefik was only
routing jeffemmett.com and www.jeffemmett.com to the canvas container.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move the standalone activity log toggle button (~) into the settings
gear dropdown as a collapsible accordion section. Simplify the board
permission display by removing the verbose "Access Levels" grid and
replacing it with a compact current-permission badge + request button.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>