mono/packages/ui/docs/routes.md
2026-02-08 15:09:32 +01:00

14 KiB

PM-Pics Routes Reference

Purpose: Quick reference for LLM code assistants
Format: Structured mappings of routes → components → files


Route-to-Component Mapping

Top-Level Routes

/:
  component: Index
  file: src/pages/Index.tsx
  renders: PhotoGrid
  file: src/components/PhotoGrid.tsx
  auth: false
  
/auth:
  component: Auth
  file: src/pages/Auth.tsx
  auth: false
  
/profile:
  component: Profile
  file: src/pages/Profile.tsx
  auth: required
  
/post/:id:
  component: Post
  file: src/pages/Post.tsx
  auth: false
  child_components:
    - ImageLightbox: src/components/ImageLightbox.tsx
    - Comments: src/components/Comments.tsx
    - EditImageModal: src/components/EditImageModal.tsx
    - MagicWizardButton: src/components/MagicWizardButton.tsx
  
/user/:userId:
  component: UserProfile
  file: src/pages/UserProfile.tsx
  auth: false
  
/user/:userId/collections:
  component: UserCollections
  file: src/pages/UserCollections.tsx
  auth: false
  
/collections/new:
  component: NewCollection
  file: src/pages/NewCollection.tsx
  auth: required
  
/collections/:userId/:slug:
  component: Collections
  file: src/pages/Collections.tsx
  auth: conditional # private collections require ownership
  renders: PhotoGrid
  
/tags/:tag:
  component: TagPage
  file: src/pages/TagPage.tsx
  auth: false
  renders: PhotoGrid
  
/search:
  component: SearchResults
  file: src/pages/SearchResults.tsx
  auth: false
  query_params: [q]
  renders: PhotoGrid
  
/wizard:
  component: Wizard
  file: src/pages/Wizard.tsx
  renders: ImageWizard
  file: src/components/ImageWizard.tsx
  auth: required
  child_components:
    - ImageLightbox: src/components/ImageLightbox.tsx
    - ModelSelector: src/components/ImageWizard/components/ModelSelector.tsx
    - QuickActionsToolbar: src/components/ImageWizard/components/QuickActionsToolbar.tsx
    - ImageActionButtons: src/components/ImageWizard/components/ImageActionButtons.tsx
  
/new:
  component: NewPost
  file: src/pages/NewPost.tsx
  auth: required
  
/version-map/:id:
  component: VersionMap
  file: src/pages/VersionMap.tsx
  auth: false
  
/organizations:
  component: Organizations
  file: src/pages/Organizations.tsx
  auth: false

Organization-Scoped Routes

All routes above have org-scoped equivalents:

/org/:orgSlug/*:
  pattern: /org/:orgSlug + [any top-level route]
  examples:
    - /org/acme-corp
    - /org/acme-corp/post/:id
    - /org/acme-corp/wizard
  context: OrganizationContext
  file: src/contexts/OrganizationContext.tsx
  filtering: Content filtered by organization_id

Core Navigation Components

TopNavigation:
  file: src/components/TopNavigation.tsx
  provides_links:
    - Home: / or /org/:orgSlug
    - Organizations: /organizations
    - Wizard: /wizard
    - Profile: /profile
    - Auth: /auth
  uses_contexts:
    - OrganizationContext
    - AuthContext

PhotoGrid:
  file: src/components/PhotoGrid.tsx
  renders: PhotoCard[]
  sets_context: PostNavigationContext
  navigation_target: /post/:id
  
PhotoCard:
  file: src/components/PhotoCard.tsx
  navigation: onClick -> /post/:id
  
ImageLightbox:
  file: src/components/ImageLightbox.tsx
  navigation: prev/next via PostNavigationContext
  keyboard: [ArrowLeft, ArrowRight, Escape, Space]
  features: [Wizard mode, Templates, Voice, History]
  
MagicWizardButton:
  file: src/components/MagicWizardButton.tsx
  navigation: Current post -> /wizard
  persistence: sessionStorage[wizardInitialImage, postNavigationContext]

Navigation Contexts

PostNavigationContext:
  file: src/contexts/PostNavigationContext.tsx
  provider: PostNavigationProvider
  state:
    posts: Array<{id, title, image_url, user_id}>
    currentIndex: number
    source: home | collection | tag | search | user
    sourceId?: string
  methods:
    - setNavigationData(data)
    - preloadImage(url)
  persistence: sessionStorage (when navigating to wizard)
  
OrganizationContext:
  file: src/contexts/OrganizationContext.tsx
  provider: OrganizationProvider
  state:
    orgSlug: string | null
    isOrgContext: boolean
  usage: Filters content, prefixes routes with /org/:orgSlug
  
AuthContext:
  file: src/hooks/useAuth.tsx
  provider: AuthProvider
  state:
    user: User | null
  guards: Protects /profile, /wizard, /new, /collections/new
  
LogContext:
  file: src/contexts/LogContext.tsx
  provider: LogProvider
  state:
    logs: LogEntry[]
    isLoggerVisible: boolean
  usage: Debug logging in wizard and image generation

Navigation Mechanisms

1. React Router Navigation

// File: src/pages/*.tsx
import { useNavigate } from "react-router-dom";

const navigate = useNavigate();
navigate('/post/:id');        // Click navigation
navigate(-1);                 // Back navigation

2. PostNavigationContext (Prev/Next)

// File: src/pages/Post.tsx, src/components/ImageLightbox.tsx
const { navigationData, setNavigationData } = usePostNavigation();

// Navigate to next post
const newPost = navigationData.posts[navigationData.currentIndex + 1];
navigate(`/post/${newPost.id}`);

3. Session Storage Persistence

// File: src/components/MagicWizardButton.tsx
// Store before navigating to wizard
sessionStorage.setItem('wizardInitialImage', JSON.stringify(imageData));
sessionStorage.setItem('postNavigationContext', JSON.stringify(navigationData));

// File: src/pages/Post.tsx
// Restore on return from wizard
const storedData = sessionStorage.getItem('postNavigationContext');
setNavigationData(JSON.parse(storedData));
sessionStorage.removeItem('postNavigationContext');

4. Keyboard Navigation

// File: src/pages/Post.tsx
// Global keyboard listeners
ArrowLeft  -> handleNavigate('prev')  // Previous post
ArrowRight -> handleNavigate('next')  // Next post
Escape     -> navigate back           // Return to feed

// File: src/components/ImageLightbox.tsx
// Lightbox keyboard listeners
ArrowLeft    -> onNavigate('prev')      // Previous image
ArrowRight   -> onNavigate('next')      // Next image
Space        -> toggle prompt field     // Show/hide prompt
Escape       -> onClose()               // Close lightbox
Ctrl+ArrowUp -> navigate history up     // Previous prompt
Ctrl+ArrowDown -> navigate history down // Next prompt

5. Mouse Wheel Navigation

// File: src/pages/Post.tsx
// Scroll-based navigation at page boundaries
wheelDelta > THRESHOLD && isAtBottom -> handleNavigate('next')
wheelDelta < THRESHOLD && isAtTop -> handleNavigate('prev')

6. Touch Gestures

// File: src/components/ImageLightbox.tsx
// Swipe detection
swipe_left  -> onNavigate('next')  // Next image
swipe_right -> onNavigate('prev')  // Previous image
double_tap  -> open lightbox       // On Post page

Key Navigation Flows

1. Browse → View → Edit

Index (PhotoGrid)
  ↓ click photo
Post (/post/:id)
  ↓ click MagicWizardButton
  ↓ store context → sessionStorage
Wizard (/wizard)
  ↓ load from sessionStorage
  ↓ generate variations
  ↓ back button
Post (/post/:id)
  ↓ restore context ← sessionStorage
  ↓ resume at exact position

Files involved:

  • src/components/PhotoGrid.tsx - Sets navigation data
  • src/pages/Post.tsx - Stores/restores context
  • src/components/MagicWizardButton.tsx - Handles storage
  • src/pages/Wizard.tsx - Loads initial image
  • src/components/ImageWizard.tsx - Main wizard logic

2. Lightbox Prev/Next Navigation

PhotoGrid
  ↓ setNavigationData(posts[], currentIndex)
PostNavigationContext
  ↓ posts[0...N]
Post page opens
  ↓ opens ImageLightbox
ImageLightbox
  ↓ user presses ← or →
  ↓ onNavigate('prev' | 'next')
Post page
  ↓ navigate(/post/[newId])
  ↓ updates currentIndex

Files involved:

  • src/contexts/PostNavigationContext.tsx - Context provider
  • src/components/PhotoGrid.tsx - Sets initial data
  • src/pages/Post.tsx - Handles navigation
  • src/components/ImageLightbox.tsx - UI controls

3. Organization Context Navigation

Any page
  ↓ URL contains /org/:orgSlug
OrganizationProvider
  ↓ extracts orgSlug from useParams()
  ↓ provides {orgSlug, isOrgContext}
All components
  ↓ read context
  ↓ filter content by organization_id
  ↓ prefix all routes with /org/:orgSlug

Files involved:

  • src/contexts/OrganizationContext.tsx - Context provider
  • src/components/TopNavigation.tsx - Adjusts links
  • src/components/PhotoGrid.tsx - Filters content
  • src/pages/Post.tsx - Scoped navigation

Router Configuration

// File: src/App.tsx
<BrowserRouter>
  <AuthProvider>
    <LogProvider>
      <PostNavigationProvider>
        <OrganizationProvider>
          <Routes>
            {/* Top-level routes */}
            <Route path="/" element={<Index />} />
            <Route path="/post/:id" element={<Post />} />
            <Route path="/wizard" element={<Wizard />} />
            {/* ... all other routes */}
            
            {/* Organization-scoped routes */}
            <Route path="/org/:orgSlug" element={<Index />} />
            <Route path="/org/:orgSlug/post/:id" element={<Post />} />
            <Route path="/org/:orgSlug/wizard" element={<Wizard />} />
            {/* ... all other org routes */}
            
            <Route path="*" element={<NotFound />} />
          </Routes>
        </OrganizationProvider>
      </PostNavigationProvider>
    </LogProvider>
  </AuthProvider>
</BrowserRouter>

Provider Nesting Order (outer to inner):

  1. QueryClientProvider - React Query
  2. AuthProvider - Authentication state
  3. LogProvider - Debug logging
  4. PostNavigationProvider - Post navigation
  5. BrowserRouter - Routing
  6. OrganizationProvider - Organization context

Image Generation/Editing:
  router: src/lib/image-router.ts
  apis:
    - OpenAI: src/lib/openai.ts
    - Replicate: src/lib/replicate.ts
    - AIMLAPI: src/lib/aimlapi.ts
    - Bria: src/lib/bria.ts
  entry: src/image-api.ts
  
Wizard Handlers:
  base: src/components/ImageWizard/handlers/
  files:
    - imageHandlers.ts: Upload, selection, download
    - generationHandlers.ts: Image generation, optimization
    - publishHandlers.ts: Publishing to gallery
    - dataHandlers.ts: Loading versions, images
    - settingsHandlers.ts: Templates, presets, history
    - voiceHandlers.ts: Voice recording, transcription
    - agentHandlers.ts: AI agent generation
    
Wizard Components:
  base: src/components/ImageWizard/components/
  files:
    - ModelSelector.tsx: Model selection UI
    - QuickActionsToolbar.tsx: Quick action buttons
    - ImageActionButtons.tsx: Per-image actions

Authentication Guards

// Pattern used in protected routes
// Files: src/pages/Profile.tsx, src/pages/Wizard.tsx, src/pages/NewPost.tsx

import { Navigate } from "react-router-dom";
import { useAuth } from "@/hooks/useAuth";

if (!user) {
  return <Navigate to="/auth" replace />;
}

Protected Routes:

  • /profile/auth
  • /wizard/auth
  • /new/auth
  • /collections/new/auth

Common Patterns

Navigate to Post from Grid

// File: src/components/PhotoGrid.tsx
const handleImageClick = (pictureId: string) => {
  navigate(`/post/${pictureId}`);
};

Navigate with Org Context

// File: src/components/TopNavigation.tsx
const { orgSlug, isOrgContext } = useOrganization();
const basePath = isOrgContext ? `/org/${orgSlug}` : '';
navigate(`${basePath}/wizard`);

Preserve Navigation on Wizard Visit

// File: src/components/MagicWizardButton.tsx
// Before navigate
sessionStorage.setItem('postNavigationContext', JSON.stringify(navigationData));

// File: src/pages/Post.tsx  
// On mount
const stored = sessionStorage.getItem('postNavigationContext');
if (stored) {
  setNavigationData(JSON.parse(stored));
  sessionStorage.removeItem('postNavigationContext');
}

Lightbox Navigation Handler

// File: src/pages/Post.tsx
const handleNavigate = (direction: 'prev' | 'next') => {
  if (!navigationData) return;
  
  const newIndex = direction === 'next' 
    ? navigationData.currentIndex + 1 
    : navigationData.currentIndex - 1;
  
  if (newIndex >= 0 && newIndex < navigationData.posts.length) {
    const newPost = navigationData.posts[newIndex];
    setNavigationData({ ...navigationData, currentIndex: newIndex });
    navigate(`/post/${newPost.id}`);
  }
};

Quick Reference

Find Route Handler

  • Route definition: src/App.tsx
  • Page component: src/pages/[PageName].tsx
  • Navigation setup: src/components/TopNavigation.tsx

Find Context Usage

  • Auth: useAuth() from src/hooks/useAuth.tsx
  • Navigation: usePostNavigation() from src/contexts/PostNavigationContext.tsx
  • Organization: useOrganization() from src/contexts/OrganizationContext.tsx

Find Navigation Logic

  • Click navigation: src/components/PhotoGrid.tsx, src/components/TopNavigation.tsx
  • Keyboard navigation: src/pages/Post.tsx (global), src/components/ImageLightbox.tsx (lightbox)
  • Context persistence: src/components/MagicWizardButton.tsx, src/pages/Post.tsx

Version: 2.0
Last Updated: 2025-10-03
Format: LLM-optimized reference