Data Flow & Integration Architecture
Overview
This document details the data flow patterns, API integrations, and state management architecture for the LeadFive website.
Data Flow Patterns
1. Content Flow Architecture
graph TD
WP[WordPress CMS] -->|REST API| CACHE[Next.js Cache Layer]
CACHE -->|ISR| STATIC[Static Pages]
CACHE -->|Dynamic| API[API Routes]
API -->|JSON| CLIENT[React Client]
CLIENT -->|Hydration| UI[User Interface]
WP -->|Webhook| REVAL[Revalidation]
REVAL -->|Trigger| CACHE
2. AI Integration Flow
graph LR
USER[User Input] -->|Request| EDGE[Edge Function]
EDGE -->|Validate| RATE[Rate Limiter]
RATE -->|Check| QUEUE[Request Queue]
QUEUE -->|Process| OPENAI[OpenAI API]
OPENAI -->|Stream| TRANSFORM[Response Transform]
TRANSFORM -->|Format| CLIENT[Client UI]
EDGE -->|Log| ANALYTICS[Analytics]
OPENAI -->|Error| FALLBACK[Fallback Handler]
3. State Management Flow
graph TD
COMP[React Component] -->|Action| STORE[Zustand Store]
STORE -->|Update| STATE[Global State]
STATE -->|Subscribe| COMP
STORE -->|Persist| LOCAL[LocalStorage]
STORE -->|Sync| API[API Sync]
API -->|Update| STORE
API Architecture
REST API Endpoints
Blog Content API
// GET /api/blog/posts
interface BlogPostsResponse {
posts: BlogPost[]
pagination: {
page: number
perPage: number
total: number
totalPages: number
}
}
// GET /api/blog/posts/[slug]
interface BlogPostResponse {
post: BlogPost
related: BlogPost[]
}
// GET /api/blog/categories
interface CategoriesResponse {
categories: Category[]
}
AI Services API
// POST /api/ai/chat
interface ChatRequest {
message: string
context?: Message[]
sessionId?: string
}
interface ChatResponse {
reply: string
tokens: number
sessionId: string
}
// POST /api/ai/generate
interface GenerateRequest {
type: 'blog' | 'summary' | 'title'
prompt: string
parameters?: {
length?: number
tone?: string
keywords?: string[]
}
}
interface GenerateResponse {
content: string
metadata: {
model: string
tokens: number
duration: number
}
}
Contact Form API
// POST /api/contact
interface ContactRequest {
name: string
email: string
company?: string
message: string
interests: string[]
source?: string
}
interface ContactResponse {
success: boolean
messageId: string
nextSteps?: string
}
GraphQL Schema (Alternative)
type Query {
posts(page: Int, perPage: Int, category: ID): PostConnection!
post(slug: String!): Post
categories: [Category!]!
aiChat(message: String!, sessionId: ID): ChatResponse!
}
type Mutation {
submitContact(input: ContactInput!): ContactResponse!
generateContent(type: ContentType!, prompt: String!): GeneratedContent!
}
type Post {
id: ID!
title: String!
slug: String!
content: String!
excerpt: String!
featuredImage: Image
author: Author!
categories: [Category!]!
publishedAt: DateTime!
seo: SEOMeta!
}
type ChatResponse {
reply: String!
sessionId: ID!
tokens: Int!
}
State Management Architecture
Zustand Store Structure
// stores/useAppStore.ts
interface AppState {
// UI State
ui: {
isMenuOpen: boolean
isAIChatOpen: boolean
activeModal: string | null
theme: 'light' | 'dark' | 'system'
}
// User State
user: {
preferences: UserPreferences
sessionId: string
consentStatus: ConsentStatus
}
// Content State
content: {
posts: BlogPost[]
categories: Category[]
isLoading: boolean
error: Error | null
}
// AI State
ai: {
chatHistory: Message[]
isProcessing: boolean
sessionData: Record<string, any>
}
// Actions
actions: {
// UI Actions
toggleMenu: () => void
toggleAIChat: () => void
openModal: (modalId: string) => void
closeModal: () => void
// Content Actions
fetchPosts: (params?: FetchParams) => Promise<void>
fetchPost: (slug: string) => Promise<void>
// AI Actions
sendChatMessage: (message: string) => Promise<void>
clearChatHistory: () => void
}
}
State Persistence Strategy
// lib/state-persistence.ts
const persistConfig = {
name: 'leadfive-app-state',
version: 1,
partialize: (state: AppState) => ({
user: {
preferences: state.user.preferences,
consentStatus: state.user.consentStatus
},
ai: {
sessionData: state.ai.sessionData
}
}),
storage: createJSONStorage(() => localStorage)
}
Caching Strategy
Content Caching Layers
1. Build-Time Cache (SSG)
// Static pages generated at build time
export async function getStaticProps() {
const posts = await fetchPosts({ limit: 10 })
return {
props: { posts },
revalidate: 3600 // Revalidate every hour
}
}
2. Request-Time Cache (ISR)
// Incremental Static Regeneration
export async function getStaticProps({ params }) {
const post = await fetchPost(params.slug)
return {
props: { post },
revalidate: 300 // Revalidate every 5 minutes
}
}
3. Client-Side Cache (SWR)
// Client-side data fetching with cache
import useSWR from 'swr'
function usePost(slug: string) {
const { data, error, isLoading } = useSWR(
`/api/blog/posts/${slug}`,
fetcher,
{
revalidateOnFocus: false,
revalidateOnReconnect: false,
dedupingInterval: 60000 // 1 minute
}
)
return { post: data, error, isLoading }
}
4. Edge Cache (CDN)
// Edge caching headers
export async function GET(request: Request) {
const response = await fetchData()
return new Response(JSON.stringify(response), {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, s-maxage=300, stale-while-revalidate=600'
}
})
}
Real-time Data Synchronization
WebSocket Connection for AI Chat
// lib/websocket.ts
class ChatWebSocket {
private ws: WebSocket
private reconnectAttempts = 0
private maxReconnectAttempts = 5
constructor(private url: string) {
this.connect()
}
private connect() {
this.ws = new WebSocket(this.url)
this.ws.onopen = () => {
console.log('WebSocket connected')
this.reconnectAttempts = 0
}
this.ws.onmessage = (event) => {
const data = JSON.parse(event.data)
this.handleMessage(data)
}
this.ws.onclose = () => {
this.handleReconnect()
}
}
private handleReconnect() {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
setTimeout(() => {
this.reconnectAttempts++
this.connect()
}, Math.min(1000 * Math.pow(2, this.reconnectAttempts), 30000))
}
}
sendMessage(message: any) {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(message))
}
}
}
Server-Sent Events for Live Updates
// app/api/updates/route.ts
export async function GET(request: Request) {
const encoder = new TextEncoder()
const stream = new ReadableStream({
async start(controller) {
const interval = setInterval(() => {
const data = `data: ${JSON.stringify({
type: 'update',
timestamp: new Date().toISOString(),
content: getLatestUpdate()
})}\n\n`
controller.enqueue(encoder.encode(data))
}, 5000)
request.signal.addEventListener('abort', () => {
clearInterval(interval)
controller.close()
})
}
})
return new Response(stream, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
}
})
}
Data Validation & Transformation
Input Validation Schema (Zod)
// schemas/validation.ts
import { z } from 'zod'
export const ContactFormSchema = z.object({
name: z.string().min(2).max(100),
email: z.string().email(),
company: z.string().optional(),
message: z.string().min(10).max(1000),
interests: z.array(z.string()).min(1),
source: z.string().optional()
})
export const ChatMessageSchema = z.object({
message: z.string().min(1).max(500),
context: z.array(z.object({
role: z.enum(['user', 'assistant']),
content: z.string()
})).optional()
})
Data Transformation Pipeline
// lib/transformers.ts
export class DataTransformer {
static transformWordPressPost(wpPost: any): BlogPost {
return {
id: wpPost.id,
title: this.decodeHTML(wpPost.title.rendered),
slug: wpPost.slug,
content: wpPost.content.rendered,
excerpt: this.stripHTML(wpPost.excerpt.rendered),
featuredImage: this.extractFeaturedImage(wpPost),
author: this.transformAuthor(wpPost._embedded?.author?.[0]),
categories: this.transformCategories(wpPost._embedded?.['wp:term']?.[0]),
publishedAt: new Date(wpPost.date),
modifiedAt: new Date(wpPost.modified),
seo: this.extractSEOData(wpPost)
}
}
static transformAIResponse(response: any): AIResponse {
return {
content: response.choices[0].message.content,
tokens: response.usage.total_tokens,
model: response.model,
finishReason: response.choices[0].finish_reason
}
}
}
Error Handling & Recovery
Global Error Boundary
// components/ErrorBoundary.tsx
export class ErrorBoundary extends React.Component<Props, State> {
state = { hasError: false, error: null }
static getDerivedStateFromError(error: Error) {
return { hasError: true, error }
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
// Log to error tracking service
console.error('Error caught by boundary:', error, errorInfo)
trackError(error, errorInfo)
}
render() {
if (this.state.hasError) {
return <ErrorFallback error={this.state.error} />
}
return this.props.children
}
}
API Error Handling
// lib/api-client.ts
export class APIClient {
private async request<T>(
url: string,
options?: RequestInit
): Promise<T> {
try {
const response = await fetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
...options?.headers
}
})
if (!response.ok) {
throw new APIError(response.status, await response.text())
}
return await response.json()
} catch (error) {
if (error instanceof APIError) {
throw error
}
// Network error
throw new NetworkError('Failed to connect to server')
}
}
async retry<T>(
fn: () => Promise<T>,
retries = 3,
delay = 1000
): Promise<T> {
try {
return await fn()
} catch (error) {
if (retries === 0) throw error
await new Promise(resolve => setTimeout(resolve, delay))
return this.retry(fn, retries - 1, delay * 2)
}
}
}
Performance Monitoring
Custom Performance Metrics
// lib/performance.ts
export class PerformanceTracker {
private marks = new Map<string, number>()
mark(name: string) {
this.marks.set(name, performance.now())
}
measure(name: string, startMark: string, endMark?: string) {
const start = this.marks.get(startMark)
const end = endMark ? this.marks.get(endMark) : performance.now()
if (!start) throw new Error(`Mark ${startMark} not found`)
const duration = end - start
// Send to analytics
trackMetric('performance', {
metric: name,
value: duration,
unit: 'ms'
})
return duration
}
trackWebVitals() {
if ('web-vital' in window) {
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
trackMetric('web-vitals', {
name: entry.name,
value: entry.value,
rating: entry.rating
})
}
}).observe({ entryTypes: ['web-vital'] })
}
}
}
Document Version: 1.0
Date: 2025-08-05
Status: Data Flow Architecture