Open-SEO Components Explained: A Full-Stack TypeScript Architecture Breakdown
Open-SEO is a full-stack SEO platform built with TanStack Router, React, and Cloudflare Workers, organized into seven core layers: routing and UI, typed server functions, database abstraction, middleware and auth, client feature modules, self-hosting utilities, and project management.
The every-app/open-seo repository implements a clean separation between frontend and backend concerns, using typed server functions as the primary communication bridge. This architecture enables deployment to Cloudflare's edge or self-hosted Node environments while maintaining full type safety across the stack.
Routing and UI Layout Components
The application's navigation and visual structure are centralized in two key files:
src/router.tsx— Defines the TanStack Router configuration, including lazy-loaded route modules and global middleware hookssrc/client/layout/AppShell.tsx— Provides the persistent UI frame (sidebar, header, navigation) wrapped around all route content
This pattern keeps routing logic decoupled from business logic, enabling true single-page-app behavior with code-splitting at the route level.
Server Functions: The Typed API Layer
All backend operations are implemented as self-contained server functions in src/serverFunctions/*.ts, exposed through createServerFn. Each function validates inputs with Zod and executes on the worker runtime.
Core Domain Server Functions
| Domain | File Path | Key Operations |
|---|---|---|
| Projects | src/serverFunctions/projects.ts |
createProject, getProjects, updateProject, archiveProject |
| Keyword Research | src/serverFunctions/keywords.ts |
researchKeywords, saveKeywords |
| Rank Tracking | src/serverFunctions/rank-tracking.ts |
getRankTrackingConfigs, addTrackingKeywords, getRankHistory |
| Search Performance | src/serverFunctions/searchPerformance.ts |
getSearchPerformanceReport |
| Backlinks | src/serverFunctions/backlinks.ts |
getBacklinksOverview, getBacklinksRows |
| Google Search Console | src/serverFunctions/gsc.ts |
listGscSites, setGscSite, verifyGscOwnership |
| Audits | src/serverFunctions/audit.ts |
startAudit, getAuditStatus |
| Lighthouse | src/serverFunctions/lighthouse.ts |
getAuditLighthouseIssues |
| AI Assist (SAM) | src/serverFunctions/sam.ts |
createSamSession, listSamSessions, sendSamMessage |
| Billing | src/serverFunctions/billing.ts |
getBillingUsageEvents, getCurrentPlan |
| Onboarding | src/serverFunctions/onboardingChat.ts |
getOnboardingChatState, advanceOnboardingStep |
These functions are consumed by the UI through TanStack Query, providing automatic caching, background refetching, and error handling.
Example: Calling a Server Function
import { useQuery } from "@tanstack/react-query";
import { getRankTrackingConfigs } from "@/serverFunctions/rank-tracking";
export function RankTrackingLoader({ projectId }: { projectId: string }) {
const { data, isLoading } = useQuery({
queryKey: ["rankTrackingConfigs", projectId],
queryFn: () => getRankTrackingConfigs({ data: { projectId } })
});
if (isLoading) return <Spinner />;
return <RankTrackingTable configs={data?.configs ?? []} />;
}
Database Layer with Drizzle ORM
Open-SEO abstracts database access through Drizzle ORM, supporting both SQLite (via Cloudflare D1) and PostgreSQL through dialect-specific schemas.
src/db/schema.ts— Shared table definitions and typessrc/db/pg/schema.ts— PostgreSQL-specific column typessrc/db/d1/schema.ts— D1 SQLite adaptationssrc/db/provider.ts— Runtime client creation based onDATABASE_URLsrc/db/telemetry.schema.ts— Observability tablessrc/db/audit.schema.ts— Audit log storage
All schemas are strongly typed, ensuring server functions receive correctly-shaped data without runtime surprises.
Schema Definition Example
// src/db/schema.ts
import { pgTable, serial, text, varchar } from "drizzle-orm/pg-core";
export const project = pgTable("project", {
id: serial("id").primaryKey(),
name: varchar("name", { length: 255 }).notNull(),
domain: varchar("domain", { length: 255 }).notNull(),
market: varchar("market", { length: 2 }).notNull(),
});
Middleware and Authentication Components
Request lifecycle management lives in dedicated middleware files:
src/middleware/errorHandling.ts— Global error capture and formattingsrc/middleware/ensure-user/hosted.ts— Self-hosted authentication flowsrc/middleware/ensure-user/delegated.ts— External identity provider integrationsrc/middleware/ensure-user/cloudflare-access.ts— Cloudflare Access headless authenticationsrc/lib/auth.ts— Core authentication utilitiessrc/lib/auth-session.ts— Session managementsrc/lib/auth-redirect.ts— Login flow routing
Every server function receives a validated authContext containing the authenticated user, active project, and subscription plan before executing business logic.
Client-Side Feature Modules
Product functionality is organized by vertical under src/client/features/, each with its own component tree and data-fetching logic:
| Feature | Primary Components |
|---|---|
| Rank Tracking | RankTrackingTable.tsx, RankTrackingChart.tsx, RankTrackingFilters.tsx |
| Keyword Research | SavedKeywordsTable.tsx, TagChip.tsx, SavedKeywordsFilters.tsx |
| Search Performance | SearchPerformancePage.tsx, SearchPerformanceColumns.tsx |
| Backlinks | BacklinksPage.tsx, BacklinksFilterPanel.tsx, BacklinksCharts.tsx |
| AI Assist (SAM) | SamChat.tsx, SamConversation.tsx |
| Onboarding | OnboardingChat.tsx, SearchConsoleOnboardingStep.tsx |
| Billing & Settings | billing.tsx, settings.tsx |
Components communicate with server functions exclusively through TanStack Query hooks, ensuring consistent loading, error, and caching behavior.
Example: Keyword Research Implementation
import { researchKeywords } from "@/serverFunctions/keywords";
export async function runKeywordResearch(
projectId: string,
seed: string
): Promise<Keyword[]> {
const result = await researchKeywords({
data: {
projectId,
seedKeyword: seed,
limit: 50
}
});
return result.keywords;
}
Self-Hosting and Deployment Components
For operators deploying outside Cloudflare, Open-SEO includes:
src/lib/selfhost-preflight.ts— Validates environment variables, database connectivity, and service dependencies before application startupwrangler.jsonc— Cloudflare Workers deployment configuration.env.example— Documented environment variables for local development and self-hosting
The preflight module prevents runtime failures by failing fast on misconfiguration.
Project and Settings Management
Projects serve as the top-level data container for all SEO operations. The project subsystem includes:
ProjectSwitcher— Cross-project navigationProjectSettings— Domain, market, and notification configurationProjectMarketFields— Regional targeting controls
All project operations route through src/serverFunctions/projects.ts with proper authorization checks.
Example: Creating a Project
import { createProject } from "@/serverFunctions/projects";
import { useMutation, useQueryClient } from "@tanstack/react-query";
function NewProjectForm() {
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: (payload: { name: string; domain: string }) =>
createProject({ data: payload }),
onSuccess: () => queryClient.invalidateQueries({ queryKey: ["projects"] })
});
// Form implementation omitted...
}
Summary
- Open-SEO components are organized into seven architectural layers: routing/layout, server functions, database, middleware/auth, client features, self-hosting, and project management
- Typed server functions in
src/serverFunctions/*.tsform the API layer, with Zod validation and Cloudflare Workers execution - Drizzle ORM provides database abstraction for both SQLite (D1) and PostgreSQL with full type safety
- Authentication middleware ensures every request carries a validated
authContext - React feature modules under
src/client/features/*implement vertical product functionality using TanStack Query - Self-hosting support includes preflight checks and environment configuration for Node-based deployment
Frequently Asked Questions
What framework does Open-SEO use for routing?
Open-SEO uses TanStack Router as its primary routing solution. The router is configured in src/router.tsx with lazy-loaded route modules and global middleware, providing type-safe routing and code-splitting for the React frontend.
Can Open-SEO run without Cloudflare?
Yes. While optimized for Cloudflare Workers, Open-SEO supports self-hosted Node.js deployment through src/lib/selfhost-preflight.ts, which validates all required environment variables and service connections before startup. The database layer abstracts D1 SQLite and PostgreSQL equally.
How are API endpoints secured in Open-SEO?
Every server function passes through authentication middleware in src/middleware/ensure-user/* before execution. The middleware validates the session and attaches an authContext object containing the user, project, and plan. There are no unauthenticated server function entry points.
What ORM does Open-SEO use for database operations?
Open-SEO uses Drizzle ORM with dialect-specific schemas in src/db/schema.ts, src/db/pg/schema.ts, and src/db/d1/schema.ts. The provider module at src/db/provider.ts instantiates the correct client based on the DATABASE_URL environment variable, enabling seamless switching between SQLite and PostgreSQL backends.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →