docs: Add comprehensive implementation plans for all todo items

Created detailed markdown plans for all items in todo.md:

1. 01-playwright-scaffolding.md - Base Playwright infrastructure
2. 02-magnitude-tests-comprehensive.md - Complete test coverage
3. 03-stream-ai-to-deepgram-tts.md - TTS latency optimization
4. 04-fix-galaxy-node-clicking.md - Galaxy navigation bugs
5. 05-dark-light-mode-theme.md - Dark/light mode with dynamic favicons
6. 06-fix-double-border-desktop.md - UI polish
7. 07-delete-backup-files.md - Code cleanup
8. 08-ai-transition-to-edit.md - Intelligent node creation flow
9. 09-umap-minimum-nodes-analysis.md - Technical analysis

Each plan includes:
- Detailed problem analysis
- Proposed solutions with code examples
- Manual Playwright MCP testing strategy
- Magnitude test specifications
- Implementation steps
- Success criteria

Ready to implement in sequence.

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-09 21:07:42 +00:00
parent 346326e31f
commit b96159ec02
9 changed files with 2994 additions and 0 deletions

View File

@@ -0,0 +1,383 @@
# Plan: Fix Galaxy Node Clicking and Navigation
**Priority:** HIGH - Critical user experience issue
**Dependencies:** None
**Affects:** Galaxy visualization navigation, user frustration
## Overview
There are two critical bugs with galaxy node interaction:
1. When going directly to a node ID link (`/galaxy/node:xxx`), it redirects to `/chat`
2. When clicking on a node in `/galaxy` (either general or on a specific node ID URL), the modal closes automatically
Both issues severely impact the galaxy user experience and need immediate fixing.
## Current Broken Behavior
### Issue 1: Direct Node URL Redirects to Chat
```
User clicks: /galaxy/node:abc123
Expected: Shows node detail page with full content
Actual: Redirects to /chat
```
### Issue 2: Modal Auto-Closes on Node Click
```
User action: Click node sphere in galaxy visualization
Expected: Modal stays open showing node details
Actual: Modal opens briefly then closes immediately
```
## Root Cause Analysis
Let me investigate the current implementation:
### 1. Check `/app/galaxy/[node-id]/page.tsx`
Likely issues:
- Missing authentication check causing redirect
- Incorrect route parameter parsing
- Navigation logic in wrong place
### 2. Check Galaxy Modal Component
Likely issues:
- Event handler conflict (click bubbling to parent)
- State management issue (modal state reset)
- React Three Fiber event handling bug
## Proposed Fixes
### Fix 1: Node Detail Page Route
#### Current (broken):
```typescript
// app/galaxy/[node-id]/page.tsx
export default async function NodeDetailPage({ params }: { params: { 'node-id': string } }) {
// Redirects to /chat if not authenticated?
}
```
#### Fixed:
```typescript
// app/galaxy/[node-id]/page.tsx
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';
import { verifySurrealJwt } from '@/lib/auth/jwt';
import { connectToDB } from '@/lib/db';
export default async function NodeDetailPage({
params,
}: {
params: { 'node-id': string };
}) {
// 1. Verify authentication
const cookieStore = await cookies();
const surrealJwt = cookieStore.get('ponderants-auth')?.value;
if (!surrealJwt) {
// Redirect to login, preserving the intended destination
redirect(`/login?redirect=/galaxy/${params['node-id']}`);
}
const userSession = verifySurrealJwt(surrealJwt);
if (!userSession) {
redirect(`/login?redirect=/galaxy/${params['node-id']}`);
}
// 2. Fetch node data
const db = await connectToDB();
const nodeId = params['node-id'];
const nodes = await db.select<NodeData>(nodeId);
const node = nodes[0];
if (!node) {
// Node doesn't exist or user doesn't have access
redirect('/galaxy?error=node-not-found');
}
// 3. Verify user owns this node
if (node.user_did !== userSession.did) {
redirect('/galaxy?error=unauthorized');
}
// 4. Render node detail page
return (
<Stack p="xl">
<Title order={1}>{node.title}</Title>
<Text>{node.body}</Text>
{node.atp_uri && (
<Anchor href={node.atp_uri} target="_blank">
View on Bluesky
</Anchor>
)}
<Button component={Link} href="/galaxy">
Back to Galaxy
</Button>
</Stack>
);
}
```
### Fix 2: Galaxy Modal Component
#### Problem: Click event bubbling
When user clicks node in R3F, the click event might be:
- Bubbling to parent canvas
- Triggering canvas click handler that closes modal
- Or: React state update race condition
#### Solution: Stop event propagation
```typescript
// components/galaxy/NodeSphere.tsx
import { useRef } from 'react';
import { ThreeEvent } from '@react-three/fiber';
function NodeSphere({ node, onClick }: { node: NodeData; onClick: (node: NodeData) => void }) {
const meshRef = useRef();
const handleClick = (event: ThreeEvent<MouseEvent>) => {
// CRITICAL: Stop propagation to prevent canvas click handler
event.stopPropagation();
// Call parent onClick
onClick(node);
};
return (
<mesh
ref={meshRef}
position={node.coords_3d}
onClick={handleClick}
>
<sphereGeometry args={[0.1, 16, 16]} />
<meshStandardMaterial color="#fff" />
</mesh>
);
}
```
#### Problem: Modal state management
Modal might be controlled by both:
- Galaxy component state
- URL query params
- Leading to race condition
#### Solution: Single source of truth
```typescript
// app/galaxy/page.tsx
'use client';
import { useState, useEffect } from 'react';
import { useSearchParams, useRouter } from 'next/navigation';
export default function GalaxyPage() {
const searchParams = useSearchParams();
const router = useRouter();
// Modal state controlled ONLY by URL query param
const selectedNodeId = searchParams.get('node');
const handleNodeClick = (nodeId: string) => {
// Update URL to open modal
router.push(`/galaxy?node=${encodeURIComponent(nodeId)}`, { scroll: false });
};
const handleModalClose = () => {
// Remove query param to close modal
router.push('/galaxy', { scroll: false });
};
return (
<>
<ThoughtGalaxy
nodes={nodes}
links={links}
onNodeClick={handleNodeClick}
/>
<Modal
opened={!!selectedNodeId}
onClose={handleModalClose}
size="lg"
>
{selectedNodeId && <NodeDetailModal nodeId={selectedNodeId} />}
</Modal>
</>
);
}
```
### Fix 3: Canvas Click Handler
If canvas has a click handler that closes modal, remove it or add condition:
```typescript
// components/galaxy/ThoughtGalaxy.tsx
<Canvas
onClick={(e) => {
// Only close modal if clicking on background (not a node)
if (e.target === e.currentTarget) {
onBackgroundClick?.();
}
}}
>
{/* ... */}
</Canvas>
```
## Testing Strategy
### Manual Playwright MCP Testing
#### Test 1: Direct Node URL
```typescript
test('Direct node URL loads correctly', async ({ page }) => {
// Create a node first
const nodeId = await createTestNode(page);
// Navigate directly to node detail page
await page.goto(`/galaxy/${nodeId}`);
// Verify we're on the correct page
await expect(page).toHaveURL(/\/galaxy\/node:/);
await expect(page.getByRole('heading', { level: 1 })).toBeVisible();
await expect(page.getByText(/View on Bluesky/)).toBeVisible();
});
```
#### Test 2: Modal Stays Open
```typescript
test('Galaxy modal stays open when clicking node', async ({ page }) => {
await page.goto('/galaxy');
// Click on a node sphere
await page.evaluate(() => {
const event = new CustomEvent('node-click', { detail: { nodeId: 'node:123' } });
window.dispatchEvent(event);
});
// Modal should open
await expect(page.getByRole('dialog')).toBeVisible();
// Wait 2 seconds
await page.waitForTimeout(2000);
// Modal should still be open
await expect(page.getByRole('dialog')).toBeVisible();
});
```
#### Test 3: Modal Navigation
```typescript
test('Can navigate from galaxy to node detail page', async ({ page }) => {
await page.goto('/galaxy');
// Click node to open modal
await clickNode(page, 'node:123');
// Modal opens
await expect(page.getByRole('dialog')).toBeVisible();
// Click "View Full Detail"
await page.click('button:has-text("View Full Detail")');
// Navigate to detail page
await expect(page).toHaveURL(/\/galaxy\/node:123/);
await expect(page.getByRole('dialog')).not.toBeVisible();
});
```
### Magnitude Tests
```typescript
import { test } from 'magnitude-test';
test('User can navigate to node via direct URL', async (agent) => {
// Create a node first
await agent.open('http://localhost:3000/chat');
await agent.act('Create a test node');
const nodeUrl = await agent.getData('node-url');
// Navigate directly to node URL
await agent.open(nodeUrl);
await agent.check('Node detail page loads');
await agent.check('Node title is visible');
await agent.check('Node body is visible');
await agent.check('Bluesky link is visible');
});
test('Galaxy modal stays open when clicking nodes', async (agent) => {
await agent.open('http://localhost:3000/galaxy');
await agent.act('Click on a node sphere');
await agent.check('Modal opens');
await agent.wait(2000);
await agent.check('Modal is still open');
await agent.check('Node details are visible');
});
test('Can navigate from galaxy modal to node detail page', async (agent) => {
await agent.open('http://localhost:3000/galaxy');
await agent.act('Click on a node');
await agent.check('Modal opens');
await agent.act('Click "View Full Detail" button');
await agent.check('Navigated to node detail page');
await agent.check('URL contains node ID');
await agent.check('Full node content is visible');
});
```
## Implementation Steps
1. **Fix node detail page route**
- Add proper authentication check
- Add redirect with return URL
- Add node ownership verification
- Add error handling for missing nodes
2. **Fix modal event handling**
- Add `event.stopPropagation()` to node click handler
- Remove or condition any canvas-level click handlers
- Ensure modal state is controlled by URL query param
3. **Test with Playwright MCP**
- Test direct URL navigation
- Test modal stays open
- Test modal to detail page navigation
- Fix any issues found
4. **Add Magnitude tests**
- Write tests covering all 3 scenarios
- Ensure tests pass
5. **Deploy and verify in production**
## Success Criteria
- ✅ Direct node URLs (`/galaxy/node:xxx`) load correctly
- ✅ No redirect to `/chat` when accessing node URLs
- ✅ Galaxy modal stays open after clicking node
- ✅ Can navigate from modal to detail page
- ✅ Can navigate from detail page back to galaxy
- ✅ All Playwright MCP tests pass
- ✅ All Magnitude tests pass
- ✅ No console errors during navigation
## Files to Update
1. `app/galaxy/[node-id]/page.tsx` - Fix authentication and routing
2. `app/galaxy/page.tsx` - Fix modal state management
3. `components/galaxy/ThoughtGalaxy.tsx` - Fix canvas click handling
4. `components/galaxy/NodeSphere.tsx` - Fix node click event propagation
## Files to Create
1. `tests/playwright/galaxy-navigation.spec.ts` - Manual tests
2. `tests/magnitude/galaxy-navigation.mag.ts` - Magnitude tests