Public
Like
glimpse2-runbook-view-glimpse-save-login-react
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.
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 windowGlimpseView
component renders with initial data- Custom hooks initialize with data and start side effects
- Component renders UI based on hook states
- 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
- 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 NotionfetchAgentData
- Gets agent information for supportupdateViewingStatus
- Sends analytics datastartCobrowseSession
- Initializes screen sharing
extractUserEmail
- Parses email from Notion propertiesextractUserName
- Parses name/title from propertiesformatPageTitle
- Creates "Name for Email" format
checkAuthorization
- Email-based access controlgetUserEmailFromWindow
- Extracts injected user data
formatNotionDate
- Consistent date formattingextractPlainText
- Text from rich text arraysformatMultiSelect
- Comma-separated valuesformatBoolean
- Emoji-enhanced boolean display
- 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
- 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) {
// Handle success
} else {
// Handle error with data.error and data.details
}
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.