40 KiB
IGNY8 Frontend Architecture Documentation
Last Updated: 2025-01-XX
Version: 1.0
Purpose: Master-level architecture and functional documentation for the IGNY8 frontend application, covering structure, routing, state management, build system, and all functional details.
Table of Contents
- Executive Summary
- Prerequisites
- Technology Stack
- Application Architecture Overview
- Project Structure
- Dual Application Architecture
- Routing Architecture
- State Management
- Component Architecture
- Template System
- API Integration Layer
- Build System & Configuration
- Development Workflow
- Deployment Architecture
- Key Features & Functions
- Performance Optimizations
- Security Considerations
Executive Summary
The IGNY8 frontend is a modern, dual-application React-based system consisting of:
- Main Application (
app.igny8.com): A full-featured SaaS platform for SEO content management with authentication, multi-tenancy, and complex workflows - Marketing Site (
igny8.com): A public-facing marketing website with SEO-optimized pages
Both applications share the same codebase but are built and deployed separately, using different entry points, routing, and build configurations.
Key Characteristics
- Framework: React 19 with TypeScript
- Build Tool: Vite 6.1.0
- Styling: Tailwind CSS 4.0
- State Management: Zustand with persistence
- Routing: React Router v7
- Code Splitting: Lazy loading for optimal performance
- Architecture: Component-based with template system
Prerequisites
Development Environment
| Requirement | Version | Purpose |
|---|---|---|
| Node.js | 18+ | JavaScript runtime |
| npm | 9+ | Package manager |
| TypeScript | 5.7+ | Type checking |
| Docker | 20+ | Containerization (optional) |
| Git | 2.30+ | Version control |
Runtime Dependencies
| Dependency | Version | Purpose |
|---|---|---|
| React | 19.0.0 | UI library |
| React DOM | 19.0.0 | DOM rendering |
| React Router | 7.9.5 | Client-side routing |
| Zustand | 5.0.8 | State management |
| Vite | 6.1.0 | Build tool & dev server |
External Services
- Backend API: Django REST Framework API (default:
https://api.igny8.com/api) - Authentication: JWT-based (access + refresh tokens)
- Reverse Proxy: Caddy (for production HTTPS)
Technology Stack
Core Framework & Libraries
{
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-router-dom": "^7.9.5",
"zustand": "^5.0.8",
"typescript": "~5.7.2"
}
UI & Styling
| Library | Version | Purpose |
|---|---|---|
| Tailwind CSS | 4.0.8 | Utility-first CSS framework |
| @heroicons/react | 2.2.0 | Icon library |
| clsx | 2.1.1 | Conditional class names |
| tailwind-merge | 3.0.1 | Merge Tailwind classes |
Data Visualization
| Library | Version | Purpose |
|---|---|---|
| apexcharts | 4.1.0 | Chart library |
| react-apexcharts | 1.7.0 | React wrapper for ApexCharts |
Forms & Inputs
| Library | Version | Purpose |
|---|---|---|
| flatpickr | 4.6.13 | Date/time picker |
| react-dropzone | 14.3.5 | File upload component |
| react-dnd | 16.0.1 | Drag and drop |
SEO & Meta Tags
| Library | Version | Purpose |
|---|---|---|
| react-helmet-async | 2.0.5 | Dynamic head management |
Build & Development Tools
| Tool | Version | Purpose |
|---|---|---|
| Vite | 6.1.0 | Build tool & dev server |
| @vitejs/plugin-react | 4.3.4 | React plugin for Vite |
| vite-plugin-svgr | 4.3.0 | SVG as React components |
| ESLint | 9.19.0 | Code linting |
| TypeScript ESLint | 8.22.0 | TypeScript linting |
Application Architecture Overview
High-Level Architecture
┌─────────────────────────────────────────────────────────────┐
│ Frontend Application │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────┐ ┌──────────────────────┐ │
│ │ Main Application │ │ Marketing Site │ │
│ │ (app.igny8.com) │ │ (igny8.com) │ │
│ ├──────────────────────┤ ├──────────────────────┤ │
│ │ • Authentication │ │ • Public Pages │ │
│ │ • Multi-tenant │ │ • SEO Optimized │ │
│ │ • Protected Routes │ │ • No Authentication │ │
│ │ • Complex Workflows │ │ • Static Content │ │
│ └──────────────────────┘ └──────────────────────┘ │
│ │ │ │
│ └──────────┬───────────────────┘ │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ Shared Components │ │
│ │ & Utilities │ │
│ └──────────┬──────────┘ │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ API Service Layer │ │
│ │ (services/api.ts) │ │
│ └──────────┬──────────┘ │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ Backend API │ │
│ │ (Django REST) │ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Application Entry Points
Main Application Entry
- File:
src/main.tsx - HTML:
index.html - Port: 5173 (dev), 8021 (Docker)
- Domain:
app.igny8.com
Marketing Site Entry
- File:
src/marketing/index.tsx - HTML:
marketing.html - Port: 5174 (dev), 8023 (Docker)
- Domain:
igny8.com
Project Structure
Directory Hierarchy
frontend/
├── public/ # Static assets
│ ├── favicon.png
│ └── images/
├── src/ # Source code
│ ├── components/ # Reusable UI components
│ │ ├── auth/ # Authentication components
│ │ ├── charts/ # Chart components
│ │ ├── common/ # Common utilities
│ │ ├── dashboard/ # Dashboard-specific
│ │ ├── form/ # Form components
│ │ ├── header/ # Header components
│ │ ├── tables/ # Table components
│ │ ├── tasks/ # Task-related
│ │ ├── ui/ # Base UI components
│ │ └── UserProfile/ # User profile
│ ├── config/ # Configuration files
│ │ ├── forms/ # Form configurations
│ │ ├── pages/ # Page configurations
│ │ ├── routes.config.ts # Route metadata
│ │ └── snippets/ # Code snippets
│ ├── context/ # React contexts
│ │ ├── ThemeContext.tsx
│ │ ├── SidebarContext.tsx
│ │ └── HeaderMetricsContext.tsx
│ ├── hooks/ # Custom React hooks
│ ├── icons/ # Icon components
│ ├── layout/ # Layout components
│ │ ├── AppLayout.tsx # Main app layout
│ │ ├── AppHeader.tsx # Header component
│ │ └── AppSidebar.tsx # Sidebar navigation
│ ├── marketing/ # Marketing site
│ │ ├── components/ # Marketing components
│ │ ├── config/ # Marketing config
│ │ ├── data/ # Marketing data
│ │ ├── layout/ # Marketing layout
│ │ ├── pages/ # Marketing pages
│ │ ├ ├── Home.tsx
│ │ ├ ├── Product.tsx
│ │ ├ ├── Solutions.tsx
│ │ ├ ├── Pricing.tsx
│ │ └ └── ...
│ │ ├── styles/ # Marketing styles
│ │ ├── index.tsx # Marketing entry
│ │ └── MarketingApp.tsx # Marketing router
│ ├── pages/ # Main app pages
│ │ ├── AuthPages/ # Login/Signup
│ │ ├── Dashboard/ # Dashboard pages
│ │ ├── Planner/ # Planner module
│ │ ├── Writer/ # Writer module
│ │ ├── Thinker/ # Thinker module
│ │ ├── Billing/ # Billing module
│ │ ├── Settings/ # Settings pages
│ │ └── Help/ # Help pages
│ ├── services/ # API services
│ │ └── api.ts # Centralized API client
│ ├── store/ # Zustand stores
│ │ ├── authStore.ts # Authentication state
│ │ ├── siteStore.ts # Site management
│ │ ├── sectorStore.ts # Sector management
│ │ ├── plannerStore.ts # Planner state
│ │ ├── billingStore.ts # Billing state
│ │ └── ...
│ ├── styles/ # Global styles
│ │ ├── index.css # Main styles
│ │ └── igny8-colors.css # Custom colors
│ ├── templates/ # Page templates
│ │ ├── DashboardTemplate.tsx
│ │ ├── TablePageTemplate.tsx
│ │ ├── FormPageTemplate.tsx
│ │ ├── SystemPageTemplate.tsx
│ │ └── ContentViewTemplate.tsx
│ ├── utils/ # Utility functions
│ ├── App.tsx # Main app router
│ └── main.tsx # Main entry point
├── index.html # Main app HTML
├── marketing.html # Marketing HTML
├── vite.config.ts # Vite configuration
├── tsconfig.json # TypeScript config
├── package.json # Dependencies
└── Dockerfile* # Docker files
Dual Application Architecture
Main Application (app.igny8.com)
Purpose: Authenticated SaaS platform for content management
Characteristics:
- Requires authentication (JWT tokens)
- Multi-tenant architecture
- Protected routes with role-based access
- Complex state management
- Real-time data updates
- Module-based organization (Planner, Writer, Thinker, Billing)
Entry Point: src/main.tsx → src/App.tsx
Provider Hierarchy:
<StrictMode>
<ErrorBoundary>
<ThemeProvider>
<HeaderMetricsProvider>
<ToastProvider>
<App />
</ToastProvider>
</HeaderMetricsProvider>
</ThemeProvider>
</ErrorBoundary>
</StrictMode>
Global Components:
GlobalErrorDisplay- Displays global errorsLoadingStateMonitor- Tracks loading statesScrollToTop- Scrolls to top on route changeProtectedRoute- Route protection wrapper
Key Features:
- User authentication & authorization
- Site & sector management
- Keyword management (Planner)
- Content generation (Writer)
- AI configuration (Thinker)
- Billing & credits
- Settings & integrations
Marketing Site (igny8.com)
Purpose: Public-facing marketing website
Characteristics:
- No authentication required
- Static content with SEO optimization
- Simple routing
- Minimal state management
- Fast loading times
- SEO meta tags
Entry Point: src/marketing/index.tsx → src/marketing/MarketingApp.tsx
Pages:
/- Home/product- Product overview/solutions- Solutions by industry/pricing- Pricing plans/tour- Product tour/resources- Resources & guides/case-studies- Case studies/partners- Partner program/contact- Contact page/waitlist- Waitlist signup
SEO Features:
- Dynamic meta tags via
react-helmet-async - SEO component for each page
- Optimized meta descriptions
- Open Graph tags
- Twitter Card tags
Routing Architecture
Main Application Routing
Router: React Router v7 (BrowserRouter)
Structure:
<Router>
<Routes>
{/* Public Routes */}
<Route path="/signin" element={<SignIn />} />
<Route path="/signup" element={<SignUp />} />
{/* Protected Routes */}
<Route element={<ProtectedRoute><AppLayout /></ProtectedRoute>}>
<Route path="/" element={<Home />} />
{/* Planner Module */}
<Route path="/planner" element={<PlannerDashboard />} />
<Route path="/planner/keywords" element={<Keywords />} />
<Route path="/planner/clusters" element={<Clusters />} />
<Route path="/planner/ideas" element={<Ideas />} />
<Route path="/planner/keyword-opportunities" element={<KeywordOpportunities />} />
{/* Writer Module */}
<Route path="/writer" element={<WriterDashboard />} />
<Route path="/writer/tasks" element={<Tasks />} />
<Route path="/writer/content" element={<Content />} />
<Route path="/writer/content/:id" element={<ContentView />} />
<Route path="/writer/drafts" element={<Navigate to="/writer/content" />} />
<Route path="/writer/images" element={<Images />} />
<Route path="/writer/published" element={<Published />} />
{/* Thinker Module */}
<Route path="/thinker" element={<ThinkerDashboard />} />
<Route path="/thinker/prompts" element={<Prompts />} />
<Route path="/thinker/author-profiles" element={<AuthorProfiles />} />
<Route path="/thinker/profile" element={<ThinkerProfile />} />
<Route path="/thinker/strategies" element={<Strategies />} />
<Route path="/thinker/image-testing" element={<ImageTesting />} />
{/* Billing Module */}
<Route path="/billing/credits" element={<Credits />} />
<Route path="/billing/transactions" element={<Transactions />} />
<Route path="/billing/usage" element={<Usage />} />
{/* Reference Data */}
<Route path="/reference/seed-keywords" element={<SeedKeywords />} />
<Route path="/reference/industries" element={<ReferenceIndustries />} />
{/* Automation & Schedules */}
<Route path="/automation" element={<AutomationDashboard />} />
<Route path="/schedules" element={<Schedules />} />
{/* Settings */}
<Route path="/settings" element={<GeneralSettings />} />
<Route path="/settings/users" element={<Users />} />
<Route path="/settings/subscriptions" element={<Subscriptions />} />
<Route path="/settings/system" element={<SystemSettings />} />
<Route path="/settings/account" element={<AccountSettings />} />
<Route path="/settings/modules" element={<ModuleSettings />} />
<Route path="/settings/ai" element={<AISettings />} />
<Route path="/settings/plans" element={<Plans />} />
<Route path="/settings/industries" element={<Industries />} />
<Route path="/settings/status" element={<Status />} />
<Route path="/settings/integration" element={<Integration />} />
<Route path="/settings/sites" element={<Sites />} />
<Route path="/settings/import-export" element={<ImportExport />} />
{/* Help */}
<Route path="/help" element={<Help />} />
<Route path="/help/docs" element={<Docs />} />
<Route path="/help/system-testing" element={<SystemTesting />} />
<Route path="/help/function-testing" element={<FunctionTesting />} />
{/* UI Elements Showcase */}
<Route path="/ui-elements/*" element={<UIElements />} />
<Route path="/components" element={<Components />} />
<Route path="/notifications" element={<Notifications />} />
{/* Fallback */}
<Route path="*" element={<NotFound />} />
</Route>
</Routes>
</Router>
Route Protection:
ProtectedRoutecomponent checks authentication- Redirects to
/signinif not authenticated - Validates JWT token on route access
Lazy Loading:
- All page components are lazy-loaded using
React.lazy() - Reduces initial bundle size
- Improves time-to-interactive
Marketing Site Routing
Router: React Router v7 (BrowserRouter)
Structure:
<BrowserRouter>
<MarketingLayout>
<ScrollToTop />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/product" element={<Product />} />
<Route path="/solutions" element={<Solutions />} />
{/* ... more routes ... */}
</Routes>
</MarketingLayout>
</BrowserRouter>
SPA Routing:
- Client-side routing for all pages
- Server configuration (Caddy/Vite) serves
marketing.htmlfor all routes - Enables direct URL access and browser navigation
ScrollToTop Component:
- Automatically scrolls to top on route change
- Ensures proper navigation experience
State Management
Zustand Architecture
Library: Zustand 5.0.8 with persistence middleware
Store Structure:
store/
├── authStore.ts # Authentication & user
├── siteStore.ts # Active site management
├── sectorStore.ts # Active sector management
├── plannerStore.ts # Planner module state
├── billingStore.ts # Billing & credits
├── settingsStore.ts # Application settings
├── pageSizeStore.ts # Table pagination
└── columnVisibilityStore.ts # Table column visibility
Context Providers
React Context Architecture:
The application uses React Context for cross-component state sharing:
1. ThemeContext (src/context/ThemeContext.tsx):
- Manages light/dark theme
- Persists theme preference in localStorage
- Applies theme class to document root
- Provides
useTheme()hook
2. SidebarContext (src/context/SidebarContext.tsx):
- Manages sidebar state (expanded/collapsed, mobile open/closed)
- Tracks active menu items and submenus
- Provides
useSidebar()hook - Wrapped in
SidebarProvidercomponent
3. HeaderMetricsContext (src/context/HeaderMetricsContext.tsx):
- Manages header metrics and statistics
- Provides metrics display functionality
- Used for dashboard KPIs and statistics
4. ToastProvider (src/components/ui/toast/ToastContainer.tsx):
- Global toast notification system
- Provides
useToast()hook - Methods:
success(),error(),warning(),info()
Context Provider Hierarchy:
<ErrorBoundary>
<ThemeProvider>
<HeaderMetricsProvider>
<ToastProvider>
<App />
</ToastProvider>
</HeaderMetricsProvider>
</ThemeProvider>
</ErrorBoundary>
Custom Hooks
Hook Library (src/hooks/):
1. useErrorHandler:
- Global error handling system
- Tracks errors with source and timestamp
- Provides
addError(),clearError(),clearAllErrors() - Maintains last 10 errors
2. usePageDataLoader:
- Standardized data loading pattern
- Handles loading states and errors
- Auto-load and manual load modes
- Dependency-based reloading
3. useModal:
- Modal state management
- Open/close functionality
- Modal data management
4. useGoBack:
- Navigation history management
- Back button functionality
5. usePersistentToggle:
- Toggle state with localStorage persistence
- Remembers user preferences
6. useProgressModal:
- Progress tracking for long operations
- Multi-step progress display
7. useResourceDebug:
- Resource tracking and debugging
- Development/debugging utilities
Store Patterns
Authentication Store (authStore.ts)
State:
interface AuthState {
user: User | null;
token: string | null;
refreshToken: string | null;
isAuthenticated: boolean;
loading: boolean;
}
Actions:
login(email, password)- Authenticate userlogout()- Clear authenticationregister(data)- Create new accountrefreshToken()- Refresh JWT tokenrefreshUser()- Update user data
Persistence: LocalStorage (auth-storage)
Site Store (siteStore.ts)
State:
interface SiteState {
sites: Site[];
activeSite: Site | null;
loading: boolean;
}
Actions:
loadSites()- Fetch all sitesloadActiveSite()- Load current active sitesetActiveSite(site)- Switch active sitecreateSite(data)- Create new siteupdateSite(id, data)- Update sitedeleteSite(id)- Delete site
Persistence: LocalStorage (site-storage)
Sector Store (sectorStore.ts)
State:
interface SectorState {
sectors: Sector[];
activeSector: Sector | null;
loading: boolean;
}
Actions:
loadSectorsForSite(siteId)- Load sectors for sitesetActiveSector(sector)- Switch active sectorcreateSector(data)- Create new sectorupdateSector(id, data)- Update sectordeleteSector(id)- Delete sectorclearActiveSector()- Clear active sector
Persistence: LocalStorage (sector-storage)
Settings Store (settingsStore.ts)
State:
interface SettingsState {
accountSettings: Record<string, AccountSetting>;
moduleSettings: Record<string, Record<string, ModuleSetting>>;
loading: boolean;
error: string | null;
}
Actions:
loadAccountSettings()- Load all account settingsloadAccountSetting(key)- Load specific account settingupdateAccountSetting(key, value)- Update account settingloadModuleSettings(moduleName)- Load module settingsupdateModuleSetting(moduleName, key, value)- Update module settingreset()- Reset store state
Persistence: LocalStorage (settings-storage)
Page Size Store (pageSizeStore.ts)
State:
interface PageSizeStore {
pageSizes: Record<string, number>;
setPageSize: (key: string, size: number) => void;
getPageSize: (key: string) => number;
}
Purpose: Manages pagination page sizes per table/page
Persistence: LocalStorage (page-size-storage)
Column Visibility Store (columnVisibilityStore.ts)
State:
interface ColumnVisibilityState {
visibleColumns: Record<string, string[]>;
setVisibleColumns: (key: string, columns: string[]) => void;
toggleColumn: (key: string, column: string) => void;
}
Purpose: Manages table column visibility preferences
Persistence: LocalStorage (column-visibility-storage)
Store Usage Pattern
// In components
import { useAuthStore } from '../store/authStore';
import { useSiteStore } from '../store/siteStore';
function MyComponent() {
const { user, isAuthenticated } = useAuthStore();
const { activeSite, setActiveSite } = useSiteStore();
// Component logic
}
Component Architecture
Component Hierarchy
App
├── ErrorBoundary
├── ThemeProvider
├── HeaderMetricsProvider
├── ToastProvider
└── Router
├── GlobalErrorDisplay
├── LoadingStateMonitor
└── Routes
├── Public Routes (SignIn, SignUp)
└── Protected Routes
└── AppLayout
├── AppHeader
├── AppSidebar
└── Outlet (Page Content)
└── Page Components
└── Template Components
└── UI Components
Component Categories
1. Layout Components (src/layout/)
AppLayout.tsx:
- Main application layout wrapper
- Manages sidebar, header, and content area
- Handles site/sector initialization
- Provides context for child components
Key Features:
- Site Initialization: Automatically loads active site on mount
- Sector Loading: Loads sectors when active site changes
- User Refresh: Periodic user data refresh (every 2 minutes, on visibility change, on focus)
- Version Detection: Detects app version changes and refreshes user data
- Timeout Handling: 35-second timeout for site/sector loading
- Error Handling: Integrated error handling with useErrorHandler
- Debug Overlay: Resource tracking overlay (enabled via localStorage flag)
- Loading State Tracking: Integrates with LoadingStateMonitor
- Responsive Layout: Adapts to sidebar state (expanded/collapsed, mobile)
AppHeader.tsx:
- Top navigation bar
- User menu, notifications, site selector
- Breadcrumbs and page title
AppSidebar.tsx:
- Left navigation menu
- Module navigation (Planner, Writer, Thinker, Billing)
- Collapsible/expandable
- Mobile-responsive
2. Page Components (src/pages/)
Organization:
- Module-based folders (Planner/, Writer/, Thinker/, Billing/)
- Feature-based pages within modules
- Shared pages (Dashboard/, Settings/, Help/)
Pattern:
- Pages use templates for consistent structure
- Pages handle data fetching and business logic
- Pages compose UI components
3. Template Components (src/templates/)
DashboardTemplate.tsx:
- Module dashboard pages
- KPI cards, workflow steps, charts
- Recent activity sections
TablePageTemplate.tsx:
- CRUD table pages
- Filtering, sorting, pagination
- Bulk actions, export
- Column visibility controls
FormPageTemplate.tsx:
- Settings and form pages
- Sectioned forms
- Save/cancel actions
- Validation display
SystemPageTemplate.tsx:
- System/admin pages
- Status cards, logs, monitoring
- System information
ContentViewTemplate.tsx:
- Individual content view
- Metadata display
- Content rendering
4. UI Components (src/components/ui/)
Base Components:
- Button, Input, Select, Checkbox, Radio
- Table, Modal, Dropdown, Toast
- Card, Badge, Avatar, Spinner
- Pagination, Tabs, Tooltip
Pattern: Reusable, styled with Tailwind CSS
5. Common Components (src/components/common/)
Utilities:
- ScrollToTop - Route change scroll
- GlobalErrorDisplay - Error handling
- LoadingStateMonitor - Loading states
- ErrorBoundary - React error boundaries
- ColumnSelector - Table column management
Template System
Template Architecture
The application uses 4 universal templates for consistent page structure:
1. DashboardTemplate
Purpose: Module home pages
Features:
- KPI cards with metrics
- Workflow step indicators
- Charts and visualizations
- Recent activity feeds
Usage:
<DashboardTemplate
title="Planner Dashboard"
subtitle="Manage your content planning workflow"
kpiCards={kpiConfig}
workflowSteps={workflowConfig}
charts={chartsConfig}
recentActivity={activityConfig}
/>
2. TablePageTemplate
Purpose: CRUD table pages
Features:
- Data table with sorting
- Filtering and search
- Pagination
- Bulk actions
- Export functionality
- Column visibility controls
Usage:
<TablePageTemplate
title="Keywords"
subtitle="Manage and organize SEO keywords"
columns={columns}
data={data}
filters={filterConfig}
onSort={handleSort}
onBulkAction={handleBulkAction}
/>
3. FormPageTemplate
Purpose: Settings and form pages
Features:
- Sectioned form layout
- Field grouping
- Save/cancel actions
- Validation display
- Loading states
Usage:
<FormPageTemplate
title="General Settings"
subtitle="Configure your application settings"
sections={formSections}
onSave={handleSave}
onCancel={handleCancel}
/>
4. SystemPageTemplate
Purpose: System/admin pages
Features:
- Status cards
- Log displays
- System metrics
- Monitoring dashboards
Usage:
<SystemPageTemplate
title="System Status"
subtitle="Monitor system health"
statusCards={statusConfig}
logs={logData}
charts={metricsConfig}
/>
API Integration Layer
API Service Architecture
File: src/services/api.ts
Purpose: Centralized API client with automatic configuration
API Configuration
Base URL Detection:
function getApiBaseUrl(): string {
// 1. Check environment variables
const envUrl = import.meta.env.VITE_BACKEND_URL;
if (envUrl) return envUrl;
// 2. Auto-detect from origin
const origin = window.location.origin;
// 3. Localhost/IP detection
if (origin.includes('localhost')) {
return origin.replace(':3000', ':8011') + '/api';
}
// 4. Production default
return 'https://api.igny8.com/api';
}
Authentication:
- JWT tokens from Zustand store
- Automatic token injection in headers
- Token refresh on 401 responses
- Site/sector context injection
API Functions
Pattern: Module-based function organization
Example Structure:
// Keywords API
export const keywordsApi = {
list: (params) => fetch('/api/v1/planner/keywords/', { params }),
create: (data) => fetch('/api/v1/planner/keywords/', { method: 'POST', body: data }),
update: (id, data) => fetch(`/api/v1/planner/keywords/${id}/`, { method: 'PATCH', body: data }),
delete: (id) => fetch(`/api/v1/planner/keywords/${id}/`, { method: 'DELETE' }),
};
// Content API
export const contentApi = {
list: (params) => fetch('/api/v1/writer/content/', { params }),
create: (data) => fetch('/api/v1/writer/content/', { method: 'POST', body: data }),
// ... more functions
};
Request Interceptors:
- Automatic site/sector context injection
- JWT token attachment
- Error handling
- Loading state management
Response Handling:
- JSON parsing
- Error extraction
- Status code handling
- Token refresh on 401
Build System & Configuration
Vite Configuration
File: vite.config.ts
Key Features:
1. Dual Build Support
const isMarketingBuild = mode === "marketing";
build: {
rollupOptions: {
input: isMarketingBuild
? { marketing: resolve(__dirname, "marketing.html") }
: {
main: resolve(__dirname, "index.html"),
marketing: resolve(__dirname, "marketing.html"),
},
},
}
2. Code Splitting
- Automatic code splitting by route
- Lazy-loaded components
- Vendor chunk separation
- CSS code splitting
3. Development Server
Main App (Port 5173):
- Hot Module Replacement (HMR)
- WebSocket for live updates
- Proxy configuration for API
Marketing Site (Port 5174):
- SPA routing plugin
- Marketing-specific configuration
- SEO-friendly development
4. Custom Plugins
bypassHostCheck:
- Workaround for Vite 6.1.0 host check bug
- Allows external connections in Docker
serveMarketingSPA:
- SPA routing for marketing dev server
- Serves
marketing.htmlfor all routes - Enables direct URL access
5. Optimization
Dependency Pre-bundling:
- Frequently used dependencies pre-bundled
- Heavy dependencies excluded (lazy-loaded)
- ESBuild for fast bundling
Build Optimization:
- Minification with ESBuild
- Source maps in dev only
- Chunk size warnings
- Compressed size reporting
TypeScript Configuration
Files:
tsconfig.json- Base configurationtsconfig.app.json- Application configtsconfig.node.json- Node/build config
Settings:
- Strict type checking
- ES2020 target
- React JSX support
- Path aliases
Environment Variables
Development:
VITE_BACKEND_URL=https://api.igny8.com/api
VITE_ALLOWED_HOSTS=igny8.com,localhost
Production:
- Set via Docker environment
- Caddy reverse proxy configuration
- Domain-based routing
Development Workflow
Local Development Setup
1. Install Dependencies
cd frontend
npm install
2. Start Development Server
Main Application:
npm run dev
# Runs on http://localhost:5173
Marketing Site:
npm run dev:marketing
# Runs on http://localhost:5174
3. Build for Production
Main Application:
npm run build
# Output: dist/
Marketing Site:
npm run build:marketing
# Output: dist/marketing.html
Docker Development
Main App Container
# Build image
docker build -t igny8-frontend-dev -f Dockerfile.dev frontend/
# Run container
docker run -p 8021:5173 \
-v $(pwd)/frontend:/app \
-e VITE_BACKEND_URL=https://api.igny8.com/api \
igny8-frontend-dev
Marketing Container
# Build image
docker build -t igny8-marketing-dev -f Dockerfile.marketing.dev frontend/
# Run container
docker run -p 8023:5174 \
-v $(pwd)/frontend:/app \
igny8-marketing-dev
Development Scripts
| Script | Command | Purpose |
|---|---|---|
dev |
vite |
Start main app dev server |
dev:marketing |
PORT=5174 vite --port 5174 |
Start marketing dev server |
build |
vite build |
Build main app |
build:marketing |
vite build --mode marketing |
Build marketing site |
type-check |
tsc -b --noEmit |
Type checking |
lint |
eslint . |
Lint code |
Deployment Architecture
Production Build
Main Application
Build Output:
dist/
├── index.html
├── assets/
│ ├── js/
│ │ ├── main-[hash].js
│ │ └── vendor-[hash].js
│ └── css/
│ └── main-[hash].css
└── marketing.html (optional)
Deployment:
- Served via Caddy reverse proxy
- Static file serving
- SPA routing fallback
Marketing Site
Build Output:
dist/
├── marketing.html
├── assets/
│ ├── js/
│ │ └── marketing-[hash].js
│ └── css/
│ └── marketing-[hash].css
Deployment:
- Separate Caddy configuration
- SPA routing enabled
- SEO optimization
Docker Deployment
Production Dockerfile
Main App (Dockerfile):
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM caddy:latest
COPY --from=builder /app/dist /usr/share/caddy
COPY Caddyfile /etc/caddy/Caddyfile
EXPOSE 8020
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile"]
Marketing (Dockerfile.marketing):
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build:marketing
FROM caddy:latest
COPY --from=builder /app/dist /usr/share/caddy
COPY Caddyfile.marketing /etc/caddy/Caddyfile
EXPOSE 8020
CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile"]
Caddy Configuration
Main App (Caddyfile)
:8020 {
root * /usr/share/caddy
encode gzip zstd
# SPA routing
handle {
try_files {path} /index.html
file_server
}
}
Marketing Site (Caddyfile.marketing)
:8020 {
root * /usr/share/caddy
encode gzip zstd
# SPA routing for marketing
handle {
try_files {path} /marketing.html
file_server
}
}
Key Features & Functions
Authentication & Authorization
Features:
- JWT-based authentication
- Access + refresh tokens
- Automatic token refresh
- Role-based access control (RBAC)
- Protected route guards
Implementation:
ProtectedRoutecomponentauthStorefor state management- API interceptors for token injection
Multi-Tenancy
Features:
- Site-based isolation
- Sector organization within sites
- Active site/sector context
- Automatic context injection in API calls
Implementation:
siteStoreandsectorStore- Site/sector selectors in header
- Context-aware API functions
Module System
Modules:
- Planner: Keywords, clusters, ideas
- Writer: Tasks, content, images
- Thinker: Prompts, profiles, strategies
- Billing: Credits, transactions, usage
Features:
- Module-based routing
- Module-specific dashboards
- Module-specific stores
- Module-specific templates
Data Management
Features:
- CRUD operations for all entities
- Filtering and sorting
- Pagination
- Bulk operations
- Export functionality
- Real-time updates
Implementation:
- TablePageTemplate for lists
- API service layer
- Zustand stores for state
Error Handling
Features:
- Global error boundary
- API error handling
- User-friendly error messages
- Error logging
- Retry mechanisms
Implementation:
ErrorBoundarycomponentGlobalErrorDisplaycomponentuseErrorHandlerhook- API error interceptors
Loading States
Features:
- Loading indicators
- Skeleton screens
- Progress tracking
- Loading state monitoring
Implementation:
LoadingStateMonitorcomponent- Loading states in stores
- Suspense boundaries
Performance Optimizations
Code Splitting
Strategy:
- Route-based code splitting
- Lazy loading of page components
- Vendor chunk separation
- Dynamic imports for heavy dependencies
Implementation:
const Keywords = lazy(() => import("./pages/Planner/Keywords"));
Bundle Optimization
Techniques:
- Tree shaking
- Dead code elimination
- Minification (ESBuild)
- CSS code splitting
- Asset optimization
Runtime Performance
Optimizations:
- Memoization with
useMemoanduseCallback - Virtual scrolling for large lists
- Debounced search/filter
- Optimistic UI updates
- Request deduplication
Caching Strategy
Client-Side:
- Zustand persistence (LocalStorage)
- API response caching
- Asset caching (browser cache)
Server-Side:
- Static asset caching (Caddy)
- CDN for assets (if configured)
Security Considerations
Authentication Security
Measures:
- JWT tokens stored securely
- Token refresh mechanism
- Automatic logout on token expiry
- Secure token transmission (HTTPS)
API Security
Measures:
- HTTPS enforcement
- CORS configuration
- API key protection
- Request validation
- Rate limiting (backend)
Data Security
Measures:
- No sensitive data in client code
- Secure storage of tokens
- XSS prevention
- CSRF protection (backend)
- Input sanitization
Content Security
Measures:
- React's built-in XSS protection
- Sanitized user input
- Safe HTML rendering
- Secure file uploads
Conclusion
The IGNY8 frontend architecture is designed for:
- Scalability: Modular structure supports growth
- Maintainability: Clear separation of concerns
- Performance: Optimized builds and lazy loading
- Developer Experience: TypeScript, hot reload, clear patterns
- User Experience: Fast loading, smooth navigation, responsive design
The dual-application architecture allows for:
- Separate deployment of marketing and app
- Independent scaling
- Different optimization strategies
- Clear separation of public and authenticated content
This architecture provides a solid foundation for continued development and scaling of the IGNY8 platform.
Document Version: 1.0
Last Updated: 2025-01-XX
Maintained By: IGNY8 Development Team