Changes:
- Moved theme toggle from separate DesktopSidebar component into UserMenu dropdown
- Replaced simple light/dark toggle with SegmentedControl offering three options:
- Light (sun icon)
- Dark (moon icon)
- System/Auto (desktop icon)
- Uses icon-only labels for compact display in dropdown menu
- Defaults to 'auto' mode (respects system preference) as configured in layout.tsx
- Removed standalone ThemeToggle component from DesktopSidebar
Benefits:
- Cleaner navigation UI with one less separate control
- Better UX with system preference option
- More compact dropdown menu layout
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented public galaxy viewing feature that allows unauthenticated
users to view public thought galaxies via the ?user={did} parameter,
while maintaining privacy controls for node-level visibility.
Changes:
- Updated /api/galaxy/route.ts to support public access:
* Accept ?user={did} query parameter for viewing specific user's galaxy
* Show all nodes (including private) for authenticated user viewing own galaxy
* Filter to only public nodes when viewing someone else's galaxy
* Return empty state with helpful message when not authenticated
* Filter links to only show connections between visible nodes
- Added is_public field to database schema:
* Updated db/schema.surql with DEFAULT true (public by default)
* Created migration script scripts/add-is-public-field.ts
* Aligns with ATproto's public-by-default philosophy
- Enhanced ThoughtGalaxy component:
* Support viewing galaxies via ?user={did} parameter
* Display user info banner when viewing public galaxy
* Show appropriate empty state messages based on context
* Refetch data when user parameter changes
- Created comprehensive Magnitude tests:
* Test public galaxy viewing without authentication
* Verify private nodes are hidden from public view
* Test own galaxy access requires authentication
* Validate invalid user DID handling
* Test user info display and navigation between galaxies
- Documented implementation plan in plans/10-public-galaxy-viewing.md
This implements the "public by default" model while allowing future
node-level privacy controls. All canonical data remains on the user's
ATproto PDS, with SurrealDB serving as a high-performance cache.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replaced all hardcoded colors and JS template literal styling with Mantine's
canonical approach using CSS modules and CSS variables. This ensures colors
transition programmatically without JS interpolation.
- Updated globals.css to use data-mantine-color-scheme selectors
- Created CSS modules for all navigation components and chat page
- Removed useComputedColorScheme/useMantineTheme hooks where not needed
- Fixed body background to properly adapt to light/dark mode
- All borders, backgrounds, and colors now use CSS variables
- Maintained full theme support across all components
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated ChatInterface to use dynamic colors based on color scheme:
- Added useComputedColorScheme hook
- Chat message bubbles now use gray.1/gray.0 in light mode
- Chat message bubbles use dark.6/dark.7 in dark mode
- User messages vs AI messages have different shades in both modes
This fixes the issue where chat messages had hardcoded dark backgrounds
even when the app was in light mode.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented comprehensive dark/light mode support throughout the app:
- Added ColorSchemeScript to layout for auto-detection of system preference
- Updated MantineProvider to use 'auto' color scheme (respects system)
- Updated theme.ts with dynamic Paper component styles based on color scheme
- Created ThemeToggle component with sun/moon icons
- Added toggle to desktop sidebar navigation
- Created theme-specific favicons (favicon-light.svg, favicon-dark.svg)
- Made ThoughtGalaxy 3D visualization theme-aware:
- Dynamic node colors based on theme
- Theme-aware lighting intensity
- Theme-aware link colors
- Theme-aware text labels
- Added comprehensive Playwright tests for theme functionality
- Theme preference persists via localStorage
Tested manually with Playwright MCP:
- ✅ Theme toggle switches between light and dark modes
- ✅ Theme persists across page reloads
- ✅ Both modes render correctly with appropriate colors
- ✅ Icons change based on current theme (sun/moon)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed a race condition where the state machine would navigate to /chat
before initializing from the URL, causing direct navigation to /galaxy
URLs to redirect.
**The Problem:**
1. Component mounts, state machine starts in 'convo' state (default)
2. State-to-URL effect fires: "state is convo → navigate to /chat"
3. URL-to-state initialization fires: "we're on /galaxy → NAVIGATE_TO_GALAXY"
4. State transitions to 'galaxy'
5. State-to-URL effect fires again: "state is galaxy → navigate to /galaxy"
This caused a brief redirect to /chat before settling on /galaxy.
**The Solution:**
- Don't mark as initialized immediately after sending the initial event
- Add a second effect that watches for state to match the URL
- Only mark as initialized once state matches the target state for the URL
- This prevents the state-to-URL effect from running before initialization
**Changes:**
- Modified URL-to-state initialization to not mark as initialized immediately
- Added new effect to mark as initialized once state matches URL target
- Added console log: "State initialized from URL, marking as ready"
**Testing:**
Verified with Playwright MCP that navigating directly to /galaxy?node=xxx
no longer redirects to /chat.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit fixes two critical bugs in the galaxy navigation:
**Bug #1: Direct node URLs redirected to /chat**
- Updated AppStateMachine to recognize /galaxy/* paths (including query params) as galaxy state
- Changed line 55 from `pathname === '/galaxy'` to `pathname === '/galaxy' || pathname.startsWith('/galaxy/')`
- Changed line 89 to compare pathname instead of lastNavigatedPathRef to preserve query params
**Bug #2: Modal closed when clicking nodes**
- Refactored ThoughtGalaxy to use URL query params (?node=xxx) instead of route params (/galaxy/node:xxx)
- This prevents component unmounting when switching between nodes
- Deleted app/galaxy/[node-id]/page.tsx (no longer needed)
- Updated app/galaxy/page.tsx with documentation comment
- Modified ThoughtGalaxy to:
- Use useSearchParams() hook
- Get selectedNodeId from query params
- Update URL with query params on node click (doesn't cause remount)
- Clear query params when modal closes
**Testing:**
- Verified manually with Playwright MCP that /galaxy?node=xxx preserves query params
- Verified state machine correctly recognizes galaxy state
- Created comprehensive Playwright test suite in tests/playwright/galaxy.spec.ts
**Files changed:**
- components/AppStateMachine.tsx: Fixed state machine to handle /galaxy/* paths and preserve query params
- components/ThoughtGalaxy.tsx: Refactored to use query params instead of route params
- app/galaxy/page.tsx: Added documentation
- app/galaxy/[node-id]/page.tsx: Deleted (replaced with query param approach)
- tests/playwright/galaxy.spec.ts: Added comprehensive test suite
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed OAuth client configuration to properly use localhost for client_id and 127.0.0.1 for redirect_uris per RFC 8252 and ATproto spec
- Added proper grapheme counting using RichText API instead of character length
- Fixed thread splitting to account for link suffix and thread indicators in grapheme limits
- Added GOOGLE_EMBEDDING_DIMENSIONS env var to all env files
- Added clear-nodes.ts utility script for database management
- Added galaxy node detail page route
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Font fixes:
- Added Title component styles in theme.ts to apply Forum font
- Body uses Zalando Sans via theme fontFamily
- All headings (h1-h6) now use Forum via Title component styles
Logo fixes:
- Rewrote SVG with simplified paths at larger scale
- Removed complex transforms causing content to be outside viewBox
- Logo now renders at 32x32px with clearly visible wave graphic
- Save button now generates draft from conversation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Reverted logo SVG to original viewBox
- Applied forum.variable to body for CSS variable
- Updated Save button to generate draft from conversation
- Logo size and font variables still need fixes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Changed logo scale from 3.5x to 1.5x in MobileHeader
- Changed logo scale from 3.5x to 1.5x in DesktopSidebar
- Prevents logo from overlapping with "Ponderants" title text
- Maintains proper spacing and visual hierarchy
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update navigation labels: 'Navigation' → 'Ponderants', 'Edit Node' → 'Manual', 'Conversation' → 'Convo', 'Galaxy View' → 'Galaxy'
- Improve logo visibility with CSS transform scale(3.5) and higher contrast colors (#E0E0E0, #909296)
- Make logo square (viewBox 60x60) for better favicon display
- Enhance mobile UX with vertical navigation buttons and text labels
- Add 'Profile' label to user menu in navigation
- Improve sidebar highlighting with blue color, bold font, and rounded corners
- Fix layout issues: adjust chat padding for sidebar (260px) and bottom bar (90px)
- Make borders more subtle (#373A40 instead of #dee2e6)
- Increase sidebar width to 260px to accommodate logo and text
- Remove desktop top bar for cleaner layout
- Use IconChartBubbleFilled for galaxy navigation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Increase logo size (48x48 desktop, 56x56 mobile) for better visibility
- Add logo as favicon
- Add logo to mobile header
- Move user menu to navigation bars (sidebar on desktop, bottom bar on mobile)
- Fix desktop chat layout - container structure prevents voice controls cutoff
- Fix mobile bottom bar - use icon-only ActionIcons instead of truncated text buttons
- Hide Create Node/New Conversation buttons on mobile to save header space
- Make fixed header and voice controls work properly with containers
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
After testing, discovered that temporary tokens from grantToken() fail
with WebSocket connections. Switched to using API key directly, which
is the standard approach for client-side Deepgram WebSocket connections.
Changes:
- Simplified voice-token route to return API key directly
- Added comprehensive logging to MicrophoneRecorder for debugging
- Documented security considerations and mitigation strategies
- Verified working end-to-end voice transcription
This matches Deepgram's official Next.js starter pattern and is the
recommended approach for client-side real-time transcription.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented user profile display in the chat interface:
- Created UserMenu component with avatar, handle display, and dropdown
- Added /api/user/profile endpoint to fetch user data from Bluesky
- Added /api/auth/logout endpoint to clear auth cookie
- Integrated UserMenu into chat page header
- Shows user's ATproto avatar with initials fallback
- Dropdown menu displays user info and logout option
- Fixed JWT import to use verifySurrealJwt
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements interactive 3D visualization of user's thought network using
React Three Fiber and UMAP dimensionality reduction.
Key components:
- /api/calculate-graph: UMAP projection from 768-D embeddings to 3-D coords
- /galaxy page: UI with "Calculate My Graph" button and 3D canvas
- ThoughtGalaxy component: Interactive R3F scene with nodes and links
- Magnitude tests: Comprehensive test coverage for galaxy features
Technical implementation:
- Uses umap-js for dimensionality reduction (768-D → 3-D)
- React Three Fiber for WebGL 3D rendering
- CameraControls for smooth navigation
- Client-side SurrealDB connection for fetching nodes/links
- Hackathon workaround: API uses root credentials with user DID filtering
Note: Authentication fix applied - API route uses root SurrealDB credentials
with JWT-extracted user DID filtering to maintain security while working
around JWT authentication issues in hackathon timeframe.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>