Commit Graph

16 Commits

Author SHA1 Message Date
d656b06113 feat: Make galaxy viewable without login requirement
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>
2025-11-10 00:36:16 +00:00
d7f5988a4f refactor: Use Mantine CSS variables and modules for theme styling
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>
2025-11-09 22:54:15 +00:00
68728b2987 fix: Make ChatInterface theme-aware for light mode support
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>
2025-11-09 22:24:21 +00:00
9bf16fefaf feat: Add dark/light mode theme switching with dynamic favicons
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>
2025-11-09 22:04:26 +00:00
482ec9fff8 fix: Prevent state machine from navigating before URL initialization
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>
2025-11-09 21:49:42 +00:00
cde66978cd fix: Fix galaxy node clicking and navigation bugs
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>
2025-11-09 21:28:07 +00:00
9aa9035d78 fix: Correct OAuth localhost/127.0.0.1 config and fix grapheme counting for Bluesky posts
- 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>
2025-11-09 18:26:39 +00:00
7fe7ee314b fix: Implement proper fonts and visible logo
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>
2025-11-09 16:41:23 +00:00
b51cb1b516 wip: Font and logo fixes in progress
- 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>
2025-11-09 16:35:46 +00:00
2b47231e16 fix: Reduce logo scale to prevent overlap with app title
- 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>
2025-11-09 16:03:59 +00:00
032f6bc4be feat: Improve UI navigation and logo visibility
- 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>
2025-11-09 15:00:52 +00:00
0ed2d6c0b3 feat: Improve UI layout and navigation
- 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>
2025-11-09 14:43:11 +00:00
47b35b9caf fix: Implement working voice transcription with Deepgram API key
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>
2025-11-09 06:13:45 +00:00
5eec01a9d6 feat: Add user profile menu with logout functionality
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>
2025-11-09 05:11:54 +00:00
e1ee79a386 feat: Step 11 - 3D Thought Galaxy Visualization
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>
2025-11-09 02:40:50 +00:00
c2f2d10ee1 feat: Step 7 & 9 - AI Chat + Voice client integration
Implement AI-powered chat interface with voice input capabilities.

Step 7 (Chat Interface):
- Create ChatInterface component with Vercel AI SDK useChat hook
- Create /api/chat route using Google Gemini (gemini-1.5-flash)
- Implement thoughtful interviewer system prompt
- Add real-time message streaming
- Auto-scroll to latest messages

Step 9 (Voice Client):
- Create MicrophoneRecorder component
- Integrate real-time voice transcription via Deepgram
- Direct WebSocket connection using temporary tokens
- Real-time transcript display in chat input
- Auto-submit on speech_final event
- Add @tabler/icons-react for microphone icons

Architecture:
- Client requests temporary Deepgram token from /api/voice-token
- MediaRecorder captures audio in 250ms chunks
- WebSocket sends audio directly to Deepgram
- Transcripts update chat input in real-time
- Final transcript auto-submits to AI chat

Security:
- Deepgram API key never exposed to client
- Temporary tokens expire in 60 seconds
- Chat requires authentication via SurrealDB JWT

Testing:
- Add magnitude test for voice recording flow
- Tests cover happy path with mocked WebSocket

Known Issue:
- Page compilation needs debugging (useChat import path verified)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-09 00:27:40 +00:00