This directory contains the frontend application with a clean, scalable architecture following React best practices and separation of concerns.
frontend/
├── components/ # React components (UI rendering only)
│ ├── GlimpseView.tsx # Main glimpse viewing component
│ ├── NotionBlock.tsx # Notion block rendering with semantic HTML
│ └── NotionProperty.tsx # Notion property rendering with type-specific formatting
├── hooks/ # Custom React hooks (stateful logic)
│ ├── useAuth.ts # Authentication and authorization
│ ├── useGlimpseData.ts # Glimpse data fetching and state
│ ├── useAgentData.ts # Agent data with polling
│ └── useViewingTracking.ts # Viewing status tracking
├── services/ # API calls and external integrations
│ ├── glimpseService.ts # Glimpse data API
│ ├── agentService.ts # Agent data API
│ ├── viewingService.ts # Viewing status API
│ └── cobrowseService.ts # Cobrowse session management
├── utils/ # Pure utility functions
│ ├── dataExtraction.ts # Notion data parsing
│ ├── validation.ts # Authorization logic
│ └── notionFormatting.ts # Property value formatting
├── types/ # TypeScript type definitions
│ ├── notion.ts # Notion data structures
│ ├── agent.ts # Agent data structures
│ ├── viewing.ts # Viewing status structures
│ └── hooks.ts # Hook return types
├── styles/ # CSS files
│ └── notion-content.css # Notion-specific styling
├── pages/ # Page entry points
│ └── glimpse.tsx # Glimpse page React entry point
└── *.html # HTML templates with semantic structure
Components : Pure UI rendering, minimal logic, focus on JSX
Hooks : Stateful logic, side effects, data management
Services : External API interactions, error handling
Utils : Pure functions, data transformations, no side effects
Types : TypeScript definitions, shared across all layers
HTML Template → React Entry Point → Components → Hooks → Services → Utils
↓ ↓ ↓ ↓ ↓
DOM Mount UI Rendering State API Calls Pure Logic
Components depend on hooks, utils, types
Hooks depend on services, utils, types
Services depend on utils, types
Utils depend only on types
Types have no dependencies
No circular dependencies
User visits /glimpse/{id}
URL
Server authentication checks user access
HTML template served with semantic structure (header/main/footer)
Initial data injection - glimpse data embedded in window.__GLIMPSE_DATA__
React entry point (glimpse.tsx
) mounts to #root
glimpse.tsx
extracts initial data from window
GlimpseView
component renders with initial data
Custom hooks initialize with data and start side effects
Component renders UI based on hook states
2. Component Architecture
GlimpseView (Main Component)
Orchestrates all data and UI logic
Uses custom hooks for all stateful operations
Renders header content via React portals to HTML header
Conditionally shows agent connection UI and page content
Handles loading/error states with user-friendly UI
NotionBlock & NotionProperty (Rendering Components)
Pure rendering components for Notion content
Semantic HTML output with proper accessibility
Smart list grouping - consecutive list items become proper <ul>/<ol>
Type-specific formatting using utility functions
Recursive rendering for nested block structures
Extracts user email from window data (injected by server)
Provides authorization function for page access control
Memoized for performance - doesn't re-run unnecessarily
Manages glimpse data state (loading, error, success)
Handles initial data or fetches from API if needed
Provides refetch function for error recovery
Centralized error handling with consistent error structures
Polls agent data every 5 seconds when authorized
Manages agent state and hasAgents boolean
Automatic cleanup of intervals on unmount
Conditional polling - only runs if user is authorized
Tracks viewing status with periodic updates (10 seconds)
Monitors page visibility changes (tab switching)
Sends viewing analytics to server
Proper cleanup on component unmount
Centralized API calls with consistent error handling
Type-safe responses using TypeScript interfaces
Silent failures where appropriate (viewing tracking)
User feedback for critical errors (glimpse loading)
fetchGlimpseData
- Gets page content from Notion
fetchAgentData
- Gets agent information for support
updateViewingStatus
- Sends analytics data
startCobrowseSession
- Initializes screen sharing
extractUserEmail
- Parses email from Notion properties
extractUserName
- Parses name/title from properties
formatPageTitle
- Creates "Name for Email" format
Validation (validation.ts
)
checkAuthorization
- Email-based access control
getUserEmailFromWindow
- Extracts injected user data
formatNotionDate
- Consistent date formatting
extractPlainText
- Text from rich text arrays
formatMultiSelect
- Comma-separated values
formatBoolean
- Emoji-enhanced boolean display
Comprehensive TypeScript Coverage
Notion types - Page data, properties, blocks
Agent types - Agent information and collections
Hook types - Return types for custom hooks
Viewing types - Analytics payload structures
Compile-time error checking
IDE autocomplete and IntelliSense
Self-documenting code
Refactoring safety
Glimpse Viewing Experience
Rich Notion content with semantic HTML rendering
Real-time agent integration with cobrowse functionality
Automatic viewing analytics for usage tracking
Email-based access control for security
Responsive design with mobile-friendly layout
Server-side data injection - eliminates loading states
React portals - dynamic header content population
Automatic polling - real-time agent data updates
Smart error handling - graceful degradation
Semantic HTML structure - accessibility and SEO friendly
Initial data injection - faster first render
Memoized hooks - prevents unnecessary re-renders
Conditional polling - only when authorized
Proper cleanup - prevents memory leaks
export function MyComponent ({ glimpseId }: Props ) {
const { userEmail, isAuthorized } = useAuth ();
const { data, loading, error } = useGlimpseData (glimpseId);
const { agentData, hasAgents } = useAgentData (glimpseId, isAuthorized (data?.properties ));
if (loading) return <Loading />;
if (error) return <Error error={error} />;
return <div>{/* Pure rendering logic */}</div>;
}
import { fetchGlimpseData } from "../services/glimpseService.ts" ;
const data = await fetchGlimpseData (glimpseId);
if (data.success ) {
} else {
}
import { extractUserEmail, formatPageTitle } from "../utils/dataExtraction.ts" ;
import { formatNotionDate, formatBoolean } from "../utils/notionFormatting.ts" ;
const email = extractUserEmail (properties);
const title = formatPageTitle (properties);
const date = formatNotionDate (dateString);
const status = formatBoolean (isActive);
Keep components pure - focus on rendering, minimal logic
Use custom hooks - extract all stateful logic
Leverage utilities - don't duplicate formatting logic
Type everything - use proper TypeScript interfaces
Handle loading/error states - provide good UX
Single responsibility - each hook has one clear purpose
Proper cleanup - clear intervals, remove listeners
Memoization - use useMemo/useCallback for performance
Error handling - consistent error structures
Type return values - use interfaces from types/
Centralize API calls - don't use fetch directly in components
Consistent error handling - return structured error objects
Type safety - use proper request/response types
Silent failures - where appropriate for UX
User feedback - for critical operations
Pure functions only - no side effects
Single responsibility - each function does one thing
Error handling - graceful degradation
Type safety - proper input/output types
Testability - easy to unit test
Create HTML template with same header/footer structure
Create React entry point following glimpse.tsx pattern
Reuse existing hooks for common functionality
Add page-specific components as needed
Types first - define data structures in types/
Services - add API integration functions
Hooks - create stateful logic hooks
Components - build UI components
Utils - extract reusable logic
Utils - Unit test pure functions
Services - Mock API responses
Hooks - Test with React Testing Library
Components - Test rendering with mocked dependencies
This architecture provides a solid foundation for building scalable, maintainable React applications with clear separation of concerns and excellent developer experience.