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>
Removed the purple "Connect Vault" button from shape mode rendering.
The no-vault case is now handled only by the early return section which
shows the working "Select Folder" design.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
BlenderGen was registered as a tool but missing from overrides.tsx,
causing an empty space in the context menu between VideoGen and Markdown.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The sanitizeIndex function was incorrectly expecting decimal digits
after the prefix letter (e.g., "b10"), but tldraw uses base-62
alphanumeric fractional indexing (e.g., "bBE6lP", "aKB7V" are valid).
This was causing all shapes to be reset to 'a1' z-index, flooding
the console with invalid index warnings.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add noteContentStore.ts for storing full note content in IndexedDB
- Avoids Automerge WASM capacity limits and localStorage quota (~5MB)
- Only metadata (id, title, tags, links) syncs via Automerge
- Full content stays local and loads on-demand
- Handle ephemeral messages in AutomergeDurableObject for cursor sync
- Improvements to ObsidianVaultBrowser component
- Enhanced obsidianImporter functionality
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Daily.co Cleanup:
- Remove @daily-co/daily-js and @daily-co/daily-react packages
- Remove DailyProvider wrapper from App.tsx
- Remove ~380 lines of Daily API endpoints from worker.ts
- Remove DAILY_DOMAIN from wrangler configs
- Remove Daily env vars from .env.example
- Video chat now uses self-hosted Jitsi (meet.jeffemmett.com)
Sync Logic Fix:
- Fix stale IndexedDB cache preventing server data from loading
- Changed threshold from "10x more shapes" to "more shapes"
- Server data now properly updates local cache on initial load
- Keeps local-only records for offline work
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Enable pointer events on iframe for direct mouse/touch/pen interaction
- Room names now use canvas slug (e.g., mycofi-jeffsi-meet for /mycofi)
- All video chats in same canvas room share the same Jitsi room
- Support both /:slug and /board/:slug URL patterns
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fixed variable scope issue with totalMerged counter
- Added syncVersion to return type declaration
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added syncVersion state that increments when server data is merged,
ensuring the UI updates to show the loaded board content.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updated vitest from 3.2.4 to 4.0.16 to match @vitest/coverage-v8 4.0.16
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add canvas.jeffemmett.com to CORS allowed origins
- Fix IndexedDB sync to prefer server data when local has no shapes
- Handle case where local cache has stale/minimal data but server has full board
- Add console logging for sync debugging
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add conditional pointer-events to iframe - only enabled when shape is
selected, allowing normal canvas pan/zoom when not interacting with video.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove Daily.co API dependencies
- Use self-hosted Jeffsi Meet (Jitsi fork) at meet.jeffemmett.com
- Simplify room creation (Jitsi creates rooms on-the-fly)
- Add Copy Link and Pop Out buttons for sharing
- Configure Jitsi embed with custom branding settings
- No recurring per-minute costs with self-hosted solution
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add "Last Visited" section to Dashboard showing recent board visits
- Add per-board activity logging that tracks shape creates/deletes/updates
- Activity panel with collapsible sidebar, grouped by date
- Debounced update logging to skip tiny movements
- Full dark mode support for both features
New files:
- src/lib/visitedBoards.ts - Visit tracking service
- src/lib/activityLogger.ts - Activity logging service
- src/components/ActivityPanel.tsx - Activity panel UI
- src/css/activity-panel.css - Activity panel styles
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed RedirectBoardSlug to use React Router's Navigate instead of
window.location.href to a non-existent domain. Now /board/:slug
redirects to /:slug/ within the same domain.
Production (main branch) keeps /board/:slug unchanged.
Staging (dev branch) supports both /board/:slug and /:slug patterns.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
TypeScript requires index signature for Automerge.Doc generic constraint.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use double type assertion for TLStoreSnapshot → Record<string, unknown>
to satisfy Automerge.from() type constraints.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updated the security visual indicator to use slate/steel colors (#64748b)
instead of green (#22c55e) for a more professional look.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The frontend expects jeffemmett-canvas-automerge-dev but wrangler.dev.toml
had jeffemmett-canvas-dev, causing 404 errors for wallet API endpoints.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Drawfast was always included in overrides.tsx but is conditional in
Board.tsx (dev-only). This caused "l is not a function" errors when
users tried to select tools in production since the Drawfast tool
wasn't registered.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove WalletConnect connector to fix TypeScript build error
- Only injected wallets (MetaMask, etc.) are supported for now
- WalletConnect can be re-added when valid project ID is configured
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add ENABLE_WORKFLOW and ENABLE_CALENDAR flags to overrides.tsx
- Conditionally include tool menu entries only in dev mode
- Disable WalletConnect QR modal to fix web3modal initialization errors
- Users can still connect via injected wallets (MetaMask, etc.)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Old links like jeffemmett.com/board/ccc now redirect to /ccc/
- Both /board/:slug and /board/:slug/ redirect to clean URLs
- Boards served directly at /:slug/ without /board prefix
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Skip WalletConnect connector if VITE_WALLETCONNECT_PROJECT_ID is not set
- MetaMask and other injected wallets still work without WalletConnect
- Add helpful console warning in dev mode when WalletConnect is disabled
- Prevents 401 errors from WalletConnect API with placeholder project ID
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add WalletLinkPanel integration to CryptIDDropdown
- Add security header with lock icon and encryption tooltip
- Add green border around menu to indicate secure zone
- Move Web3 Wallet to top of integrations list
- Wallet modal opens from "Manage Wallets" button
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Renamed all user-facing "CryptID" references to "enCryptID"
- Updated emails, error messages, UI text, and onboarding tour
- Enhanced BoardSettingsDropdown with section headers, icons, and
alternating background colors for better visual hierarchy
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changed catch-all route to render Board component directly instead
of redirecting to /board/:slug/. Now canvas.jeffemmett.com/ccc shows
the board without changing the URL.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added wagmi, viem, and related packages for wallet integration:
- wagmi: React hooks for Ethereum
- viem: Low-level Ethereum interactions
- @tanstack/react-query: Data fetching for wallet state
- @web3modal/wagmi: WalletConnect modal
- @noble/hashes, @noble/secp256k1: Cryptographic utilities
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The providers directory was untracked, causing build failures on the server.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added routes to handle direct slug URLs like canvas.jeffemmett.com/ccc
These now redirect to /board/ccc/ to maintain backward compatibility
with old links from jeffemmett.com/board/ccc
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>