Architecture Guide
Deep dive into Constellation's system design, patterns, and architectural decisions.
System Architecture
High-Level Overview
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ User Browser (Client) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Next.js 15 + React 19 Single Page Application โ
โ โโ Client Components (Interactive) โ
โ โโ Server Components (SSR/SSG) โ
โ โโ API Routes โ
โโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ โ
โผ โผ โผ
โโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
โ API โ โ SSE โ โ WebSocket โ
โ Server โ โ Service โ โ (Hocuspocus) โ
โโโโโโโโโโค โโโโโโโโโโโโค โโโโโโโโโโโโโโโโโโโโค
โ:8001 โ โ:8002 โ โ:8003 โ
โโโโโโโโโโ โโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Backend Services โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โข Business Logic โ
โ โข Database โ
โ โข Authentication โ
โ โข File Storage โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ
Layered Architecture
1. Presentation Layer
Location: src/app/ and src/components/
Components organized by domain:
- Pages (
src/app/) - Route-based page components - Features (
src/features/) - Feature-specific layouts - Components (
src/components/) - Reusable UI components - Plate UI (
src/components/plate-ui/) - Editor plugins
Responsibility: - Render UI - Handle user interactions - Display data
2. Business Logic Layer
Location: src/hooks/, src/features/
- Custom Hooks - State management and side effects
- Feature Logic - Feature-specific business rules
- Context Providers - Global state
Responsibility: - Process user actions - Manage component state - Coordinate feature workflows
3. Data Access Layer
Location: src/services/, src/lib/
- API Client - HTTP communication
- Services - Domain-specific API calls
- Utilities - Helper functions
Responsibility: - Communicate with backend - Format data for frontend - Handle errors
Component Architecture
Component Types
Components
โโโ Page Components (src/app/)
โ โโ Full page layouts with layout.tsx
โ
โโโ Feature Components (src/features/)
โ โโ Feature-specific containers
โ
โโโ Smart Components (src/components/**/)
โ โโ Connected to services/hooks
โ
โโโ Presentational Components (src/components/ui/)
โ โโ Pure UI, no logic
โ
โโโ Layout Components (src/components/common/)
โโ Navigation, header, footer
Component Hierarchy
App (Root Layout)
โโโ Navigation
โโโ Providers (Auth, i18n, Theme)
โโโ Routes
โ โโโ Homepage
โ โโโ Dashboard
โ โ โโโ Workspace List
โ โ โโโ Recent Items
โ โ โโโ Analytics
โ โโโ Workspace
โ โ โโโ Editor
โ โ โ โโโ Toolbar
โ โ โ โโโ PlateEditor
โ โ โ โโโ Sidebar
โ โ โโโ Graph Viewer
โ โ โโโ Collaborators
โ โโโ Admin Panel
โ โ โโโ User Management
โ โ โโโ Content Moderation
โ โ โโโ System Settings
โ โโโ Profile Settings
โโโ Footer
Data Flow Patterns
1. Server Components (SSR)
For pages that don't need interactivity:
// src/app/dashboard/page.tsx
import { getUserData } from '@/src/services/userService';
export default async function DashboardPage() {
const user = await getUserData();
return (
<div>
<h1>Welcome, {user.name}</h1>
</div>
);
}
Benefits: - Faster initial load - No JavaScript sent to client - Direct database access
2. Client Components with Hooks
For interactive features:
// src/components/workspace/WorkspaceEditor.tsx
'use client';
import { useWorkspace } from '@/src/hooks/use-workspace';
export function WorkspaceEditor() {
const { workspace, updateContent } = useWorkspace();
return (
<Editor
content={workspace.content}
onChange={updateContent}
/>
);
}
Flow:
User Action โ Hook State Update โ Re-render โ UI Update
3. API Route Pattern
For backend communication:
// src/app/api/workspace/[id]/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function GET(
request: NextRequest,
{ params }: { params: { id: string } }
) {
const data = await apiClient.get(`/workspace/${params.id}`);
return NextResponse.json(data);
}
Request Flow:
Frontend โ Next.js API Route โ Backend API โ Database โ Response
4. Real-time Updates (SSE)
For live notifications:
'use client';
import { useSSE } from '@/src/hooks/use-sse';
export function NotificationCenter() {
const { notifications } = useSSE('/events');
return (
<div>
{notifications.map(notification => (
<Notification key={notification.id} {...notification} />
))}
</div>
);
}
State Management Strategy
Local Component State
const [count, setCount] = useState(0);
Use for: Form inputs, toggle states, temporary UI state
Context API
// src/components/context/WorkspaceContext.tsx
export const WorkspaceContext = createContext();
export function WorkspaceProvider({ children }) {
const [workspace, setWorkspace] = useState(null);
return (
<WorkspaceContext.Provider value={{ workspace, setWorkspace }}>
{children}
</WorkspaceContext.Provider>
);
}
Use for: Global app state, authentication, user preferences
Custom Hooks
// src/hooks/use-workspace.ts
export function useWorkspace() {
const [workspace, setWorkspace] = useState(null);
useEffect(() => {
fetchWorkspace();
}, []);
return { workspace, updateWorkspace: setWorkspace };
}
Use for: Reusable stateful logic shared across components
Server-side Caching
// src/lib/cache.ts
import { cache } from 'react';
export const getUserData = cache(async (userId: string) => {
return await apiClient.get(`/users/${userId}`);
});
Use for: Expensive operations, database queries
Routing Architecture
App Router Structure
src/app/
โโโ layout.tsx # Root layout
โโโ page.tsx # Home page (/)
โโโ (www)/ # Public route group
โ โโโ about/page.tsx # /about
โ โโโ pricing/page.tsx # /pricing
โโโ (admin)/ # Protected admin routes
โ โโโ layout.tsx # Admin layout
โ โโโ users/page.tsx # /admin/users
โ โโโ settings/page.tsx # /admin/settings
โโโ dashboard/ # Dashboard route
โ โโโ layout.tsx # Dashboard layout
โ โโโ page.tsx # /dashboard
โ โโโ [workspaceId]/ # Dynamic route
โ โโโ page.tsx # /dashboard/[workspaceId]
โโโ workspace/ # Workspace route
โ โโโ [id]/
โ โ โโโ page.tsx # /workspace/[id]
โ โ โโโ editor/page.tsx # /workspace/[id]/editor
โ โ โโโ settings/page.tsx
โ โโโ ...
โโโ api/ # API routes
โ โโโ workspace/
โ โ โโโ route.ts # /api/workspace
โ โ โโโ [id]/route.ts # /api/workspace/[id]
โ โโโ ...
โโโ [404].tsx # Not found
Route Protection
// src/components/context/ProtectedRoute.tsx
import { redirect } from 'next/navigation';
import { isAdmin } from '@/src/lib/auth';
export async function ProtectedAdminRoute({ children }) {
const admin = await isAdmin();
if (!admin) {
redirect('/');
}
return children;
}
Error Handling Strategy
Global Error Boundary
// src/app/error.tsx
'use client';
export default function Error({
error,
reset,
}: {
error: Error;
reset: () => void;
}) {
return (
<div className="p-4">
<h1>Something went wrong!</h1>
<button onClick={() => reset()}>Try again</button>
</div>
);
}
API Error Handling
// src/lib/api.ts
class APIClient {
async request(url: string, options: RequestInit) {
try {
const response = await fetch(url, options);
if (!response.ok) {
const error = await response.json();
throw new APIError(error.message, response.status);
}
return response.json();
} catch (error) {
logger.error('API request failed', error);
throw error;
}
}
}
User-facing Error Display
// src/components/common/ErrorNotification.tsx
'use client';
import { useEffect, useState } from 'react';
import { useError } from '@/src/hooks/use-error';
export function ErrorNotification() {
const { error, clearError } = useError();
const [visible, setVisible] = useState(false);
useEffect(() => {
if (error) setVisible(true);
}, [error]);
if (!visible) return null;
return (
<div className="fixed top-4 right-4 bg-red-500 text-white p-4 rounded">
{error?.message}
<button onClick={() => {
setVisible(false);
clearError();
}}>
Dismiss
</button>
</div>
);
}
Async Patterns
Server Components Async
// src/app/workspace/[id]/page.tsx
export default async function WorkspacePage({
params: { id }
}: {
params: { id: string }
}) {
const workspace = await fetchWorkspace(id);
return (
<WorkspaceDetail workspace={workspace} />
);
}
Client Components with useEffect
// src/components/WorkspaceViewer.tsx
'use client';
import { useEffect, useState } from 'react';
export function WorkspaceViewer({ id }: { id: string }) {
const [workspace, setWorkspace] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
(async () => {
try {
const data = await apiClient.get(`/workspace/${id}`);
setWorkspace(data);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
})();
}, [id]);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return <WorkspaceDetail workspace={workspace} />;
}
Performance Optimization
Code Splitting
// Automatic route-based splitting
// Each route gets its own bundle
// Manual component splitting
import dynamic from 'next/dynamic';
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
loading: () => <div>Loading...</div>,
});
Memoization
// Memoize expensive component
import { memo } from 'react';
export const MemoizedList = memo(function List({ items }) {
return items.map(item => <Item key={item.id} {...item} />);
});
Image Optimization
// Use Next.js Image component
import Image from 'next/image';
export function OptimizedImage() {
return (
<Image
src="/image.jpg"
alt="Description"
width={800}
height={600}
priority // For above-fold images
/>
);
}
Dependency Injection Pattern
// src/lib/dependencies.ts
export const dependencies = {
apiClient: new APIClient(),
authService: new AuthService(),
notificationService: new NotificationService(),
};
// Usage in hooks
export function useWorkspace() {
const api = dependencies.apiClient;
// ...
}
Testing Architecture
Unit Tests
// Test individual functions
describe('formatDate', () => {
it('should format date correctly', () => {
expect(formatDate(new Date('2024-01-15'))).toBe('Jan 15, 2024');
});
});
Component Tests
// Test component behavior
describe('WorkspaceCard', () => {
it('should render workspace name', () => {
render(<WorkspaceCard workspace={{ name: 'My Workspace' }} />);
expect(screen.getByText('My Workspace')).toBeInTheDocument();
});
});
Integration Tests
// Test feature workflows
describe('Workspace Creation Flow', () => {
it('should create new workspace', async () => {
// Mock API, render component, simulate user action, assert result
});
});
Related Documentation
- ๐ COMPONENTS.md - Component reference
- ๐ฃ HOOKS.md - Custom hooks reference
- ๐ ๏ธ SERVICES.md - Service layer
- ๐งช TESTING.md - Testing strategies
Last Updated: January 2026