OpenSEO Project Structure Explained: Full-Stack TypeScript Architecture Guide
The OpenSEO project is a full-stack TypeScript application built on TanStack React-Start and Drizzle ORM, organized into clear layers for entry points, server handlers, routing, API surfaces, workflows, and database access.
This comprehensive guide examines how the OpenSEO project structure separates concerns across UI, server logic, data models, and infrastructure. Whether you're contributing to the codebase, self-hosting, or studying modern full-stack patterns, understanding this architecture reveals how the every-app/open-seo repository delivers SEO automation through a type-safe, maintainable design.
Entry Point and Application Bootstrap
The application boots from src/start.ts, which creates the TanStack React-Start instance with mandatory middleware.
// src/start.ts – creates startInstance with CSRF middleware
import { createStart, createCsrfMiddleware } from '@tanstack/react-start';
export const startInstance = createStart({
middleware: [createCsrfMiddleware()],
});
This file registers globalServerFunctionMiddleware, ensuring all server functions execute with consistent request wrapping and security headers before reaching business logic.
Server Handler and Request Routing
The Cloudflare Workers entry point lives in src/server.ts. This handler determines authentication mode and routes requests across four distinct paths.
Three authentication modes are supported:
hosted– full SaaS with OAuthcloudflare_access– Cloudflare Access integrationlocal_noauth– development bypass
The fetch function in src/server.ts implements this routing logic:
| Route prefix | Handler | Destination |
|---|---|---|
/agents/* |
routeChatAgents |
Durable Object chat agents |
/auth/* |
openSeoOAuthProvider |
Hosted OAuth flow |
/api/gsc/oauth/callback, /api/* |
handleSelfHostedOpenSeoMcpRequest |
Self-hosted MCP |
| All other paths | appFetch |
TanStack React UI |
Each request wraps the PostgreSQL client via withPgClient, ensuring database connections are managed consistently across all execution paths.
Typed Routing System
Navigation relies on src/routeTree.gen.ts, an auto-generated file providing compile-time type safety for every route.
// Using the typed route tree in components
import { useNavigate } from '@tanstack/react-router';
import { routeTree } from '@/routeTree.gen';
function ProjectNavigation() {
const navigate = useNavigate();
// TypeScript ensures 'routeTree.projects' exists
return (
<button onClick={() => navigate({ to: routeTree.projects })}>
View Projects
</button>
);
}
Route files map directly to src/routes/..., with the generator ensuring any file addition or rename propagates type changes immediately.
API Surface and Server Functions
The MCP (Meta Control Plane) exposes REST-like endpoints through files in src/serverFunctions/*.ts. These functions execute in the same Worker context as the requesting UI, sharing database connections and authentication state.
Key server function modules:
src/serverFunctions/keywords.ts– keyword research and suggestionssrc/serverFunctions/rank-tracking.ts– position monitoringsrc/serverFunctions/audit.ts– site audit triggers and results
// Calling a server function from client code
import { $keywords } from '@/serverFunctions/keywords';
async function fetchSuggestions(query: string) {
// Executes in Worker, returns typed response
const result = await $keywords.search({ query });
return result.suggestions;
}
The $ prefix convention distinguishes server-callable functions from regular utilities, with TypeScript enforcing parameter and return types across the network boundary.
Background Workflows
Long-running operations execute as workflow classes in src/server/workflows/*.ts. These handle CPU-intensive or time-delayed tasks without blocking user requests.
Core workflow implementations:
SiteAuditWorkflow.ts– comprehensive site crawling and analysisRankCheckWorkflow.ts– scheduled position checking across search engines
Workflows instantiate via direct API calls or the Worker's scheduled export in src/server.ts, enabling cron-like execution for recurring SEO monitoring.
// Scheduling a rank check from server code
import { runScheduledRankChecks } from '@/server/features/rank-tracking/services/scheduledRankChecks';
export const $rankTracking = {
async schedule(projectId: string) {
await runScheduledRankChecks({ PROJECT_ID: projectId });
return { status: 'queued' };
},
};
Database Layer and Schema
Drizzle ORM provides type-safe database access with dual-target support for SQLite (Cloudflare D1) and PostgreSQL.
| Component | Location | Purpose |
|---|---|---|
| Core schema | src/db/schema.ts |
Table definitions shared across dialects |
| Postgres client | src/db/pg/client.ts |
Connection pooling and query execution |
| D1/SQLite adapter | src/db/index.ts |
Edge runtime compatibility |
| Migrations | drizzle-pg/ |
PostgreSQL-specific migration files |
The schema duplication in drizzle-pg/ allows identical TypeScript types while optimizing for each database's capabilities—critical for supporting both Cloudflare's D1 (SQLite) in production and PostgreSQL in self-hosted deployments.
Shared Utilities and Authentication
Cross-cutting concerns live in dedicated directories with comprehensive test coverage.
Shared utilities (src/shared/*.ts):
keyword-locations.ts– geographic targeting logicgsc.ts– Google Search Console API wrappersbilling.ts– subscription and usage tracking
Authentication modules (src/lib/auth-*.ts):
auth-config.ts– OAuth provider creation viacreateOpenSeoOAuthProvider- Turnstile captcha validation for bot protection
- Session management across auth modes
Protected routes apply middleware from src/middleware/ensure-user/*.ts, enforcing authorization before handler execution.
Documentation, Testing, and Scripts
The repository includes operational guides and comprehensive test suites.
| Directory | Contents |
|---|---|
docs/*.md |
Self-hosting guides including SELF_HOSTING_DOCKER.md |
src/**/*.test.ts |
Unit tests for utilities and server functions |
e2e/*.spec.ts |
Playwright end-to-end tests for critical user flows |
scripts/*.ts |
Data seeding, migration utilities, and operational tools |
Summary
- OpenSEO project structure separates concerns across eight distinct layers: entry point, server handler, routing, API surface, workflows, database, shared utilities, and authentication
src/server.tsroutes requests across agents, OAuth, MCP, and UI paths withwithPgClientwrapping every database interaction- Server functions in
src/serverFunctions/*.tsexecute type-safe RPC calls within the same Worker context as the requesting UI - Background workflows in
src/server/workflows/*.tshandle audits and rank checks without blocking user requests - Drizzle ORM with dual schema support enables identical types across D1 (SQLite) and PostgreSQL deployments
- Auto-generated
src/routeTree.gen.tsprovides compile-time navigation safety throughout the React application
Frequently Asked Questions
What framework does OpenSEO use for its frontend and backend?
OpenSEO builds on TanStack React-Start for server-rendered React applications, with Drizzle ORM handling database operations. This combination provides type safety from database schema through API responses to UI components, all executing within Cloudflare Workers for edge deployment.
How does OpenSEO handle authentication for different deployment modes?
The src/server.ts handler determines authentication mode via getAuthMode, supporting three configurations: hosted for full SaaS OAuth, cloudflare_access for enterprise Cloudflare Access integration, and local_noauth for development environments. Each mode routes through appropriate handlers in src/lib/auth-*.ts files.
Where are API endpoints defined in the OpenSEO codebase?
API endpoints reside in src/serverFunctions/*.ts as TypeScript functions rather than traditional route handlers. These server functions—such as $keywords.search in src/serverFunctions/keywords.ts—are wrapped by globalServerFunctionMiddleware and callable from client code with full type safety via the $ prefix convention.
How does OpenSEO manage background jobs like site audits?
Long-running tasks execute as workflow classes in src/server/workflows/*.ts. The SiteAuditWorkflow.ts and RankCheckWorkflow.ts classes run either through direct invocation from server functions or via the scheduled export in src/server.ts for cron-triggered execution, leveraging Cloudflare Durable Objects for state persistence.
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 →