# OpenSEO Project Structure: Full-Stack TanStack Architecture Explained

> Discover the OpenSEO project structure, a TanStack full-stack architecture with layered UI, server functions, background workflows, and database access deployed on Cloudflare Workers. Understand its organized approach.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: architecture
- Published: 2026-07-26

---

**OpenSEO is a full-stack TypeScript application built on TanStack React-Start and Drizzle ORM, organized into distinct layers for UI rendering, server functions, background workflows, and database access that deploys to Cloudflare Workers.**

OpenSEO is an open-source SEO platform that combines a React-based user interface with serverless backend architecture. Understanding the open-seo project structure helps developers navigate the codebase for self-hosting, contributions, or custom integrations. The repository follows a clear separation of concerns across entry points, routing, API functions, workflows, and data layers while maintaining end-to-end type safety.

## Entry Points and Application Bootstrap

The application initializes through two main entry points that handle different runtime contexts.

### TanStack React-Start Setup

The [`src/start.ts`](https://github.com/every-app/open-seo/blob/main/src/start.ts) file bootstraps the TanStack React-Start instance with CSRF middleware protection. It creates the `startInstance` using `createStart` and `createCsrfMiddleware` from `@tanstack/react-start`, establishing the foundation for server-rendered React applications.

### Cloudflare Workers Handler

The [`src/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server.ts) file serves as the Cloudflare Workers entry point, exposing the main `fetch` function that routes incoming requests. This handler supports three authentication modes—`hosted`, `cloudflare_access`, and `local_noauth`—and delegates requests to either the MCP (Meta Control Plane), OAuth provider, or the TanStack UI layer via `appFetch`.

## Routing and Type Safety

### Auto-Generated Route Tree

The routing system relies on [`src/routeTree.gen.ts`](https://github.com/every-app/open-seo/blob/main/src/routeTree.gen.ts), an auto-generated file produced by TanStack Router. This provides compile-time type safety for all routes defined in `src/routes/...`, enabling type-safe navigation and URL generation throughout the application.

The following example demonstrates type-safe navigation using the generated route tree:

```ts
// Use the typed route tree for navigation in a React component
import { Link, useNavigate } from '@tanstack/react-router';
import { routeTree } from '@/routeTree.gen';

function NavBar() {
  const navigate = useNavigate();

  return (
    <nav>
      <Link to={routeTree.projects}>Projects</Link>
      <button onClick={() => navigate({ to: routeTree.settings })}>
        Settings
      </button>
    </nav>
  );
}

```

## API Surface: Server Functions

### MCP-Integrated Endpoints

The API layer resides in `src/serverFunctions/*.ts` (e.g., [`keywords.ts`](https://github.com/every-app/open-seo/blob/main/keywords.ts), [`rank-tracking.ts`](https://github.com/every-app/open-seo/blob/main/rank-tracking.ts), [`audit.ts`](https://github.com/every-app/open-seo/blob/main/audit.ts)). These functions are wrapped by `globalServerFunctionMiddleware` (registered in [`src/start.ts`](https://github.com/every-app/open-seo/blob/main/src/start.ts)) and expose REST-like endpoints that the UI consumes via `await $someServerFunction(args)`. This pattern enables seamless client-server communication with full TypeScript inference.

Server functions execute within the same Worker context as the main application, sharing database connections and returning typed JSON responses.

```ts
// Call a server function from the UI (e.g., fetch keyword suggestions)
import { $keywords } from '@/serverFunctions/keywords';

async function getSuggestions(query: string) {
  const result = await $keywords.search({ query });
  return result.suggestions; // typed array of strings
}

```

## Background Processing Layer

### Workflow Implementations

Long-running operations like site audits and rank checks are implemented as workflow classes in `src/server/workflows/`. Files like [`SiteAuditWorkflow.ts`](https://github.com/every-app/open-seo/blob/main/SiteAuditWorkflow.ts) and [`RankCheckWorkflow.ts`](https://github.com/every-app/open-seo/blob/main/RankCheckWorkflow.ts) define background jobs that execute via Cloudflare Durable Objects or scheduled Workers (triggered through the `scheduled` export in [`src/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server.ts)).

You can trigger workflows directly from server functions:

```ts
// Schedule a rank-check workflow from a server function
import { runScheduledRankChecks } from '@/server/features/rank-tracking/services/scheduledRankChecks';

export const $rankTracking = {
  async schedule(projectId: string) {
    // This runs inside the Worker and uses the same DB connection
    await runScheduledRankChecks({ PROJECT_ID: projectId });
    return { status: 'queued' };
  },
};

```

## Database Architecture

### Drizzle Schema and Multi-Provider Support

The data layer uses **Drizzle ORM** with support for both SQLite (D1) and PostgreSQL. Key files include:

- [`src/db/schema.ts`](https://github.com/every-app/open-seo/blob/main/src/db/schema.ts) - Core schema definitions
- `src/db/pg/*.ts` - PostgreSQL-specific client implementations ([`pg/client.ts`](https://github.com/every-app/open-seo/blob/main/pg/client.ts))
- `drizzle-pg/` - Schema duplicates for PostgreSQL targets

All database interactions are typed, providing compile-time safety for queries executed within server functions and workflows.

## Authentication and Security

### Multi-Mode Auth System

Authentication is centralized in [`src/lib/auth-config.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/auth-config.ts) and related files, supporting:

- **Hosted SaaS authentication** via `createOpenSeoOAuthProvider`
- **Cloudflare Access** integration
- **Local development mode** (`local_noauth`)
- **Turnstile captcha** validation and session management

Middleware in `src/middleware/ensure-user/*.ts` handles route protection based on the active auth mode.

## Request Flow Through the Architecture

Understanding how requests traverse the open-seo project structure:

1. **Entry**: Cloudflare Workers invoke [`src/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server.ts), wrapping requests with PostgreSQL clients (`withPgClient`) and determining auth mode via `getAuthMode`.

2. **Routing Logic**: The server handler categorizes requests:
   - `/agents/*` → Durable Object chat agents (`routeChatAgents`)
   - `/auth/*` → OpenSEO OAuth provider (`openSeoOAuthProvider`)
   - `/api/*` or `/api/gsc/oauth/callback` → Self-hosted MCP handler (`handleSelfHostedOpenSeoMcpRequest`)
   - All others → TanStack React-Start UI (`appFetch`)

3. **Execution**: UI components call server functions which execute within the same Worker context, sharing database connections and returning typed JSON responses.

4. **Background Jobs**: Workflows trigger via direct API calls or the Worker's `scheduled` handler, processing tasks like site audits asynchronously.

## Shared Utilities and Documentation

### Cross-Cutting Concerns

Pure utility functions for SEO data processing, billing calculations, and Google Search Console integrations live in `src/shared/*.ts`. These modules are unit-tested with co-located `*.test.ts` files.

### Documentation and Deployment

Self-hosting guides in [`docs/SELF_HOSTING_DOCKER.md`](https://github.com/every-app/open-seo/blob/main/docs/SELF_HOSTING_DOCKER.md) provide Docker deployment instructions, while `scripts/*.ts` contains migration utilities and data seeding tools. End-to-end testing uses Playwright (`e2e/*.spec.ts`) to validate critical user flows.

## Summary

- **Layered Architecture**: OpenSEO separates UI (TanStack React-Start), API (Server Functions), background processing (Workflows), and data (Drizzle) into distinct, typed layers.
- **Cloudflare-Native**: The entire stack runs on Cloudflare Workers, using [`src/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server.ts) as the entry point with support for Durable Objects and scheduled jobs.
- **Type Safety**: Auto-generated routing ([`routeTree.gen.ts`](https://github.com/every-app/open-seo/blob/main/routeTree.gen.ts)) and Drizzle ORM provide end-to-end TypeScript safety from database to UI.
- **Flexible Auth**: Supports hosted SaaS, Cloudflare Access, and local development modes through centralized auth utilities in `src/lib/auth-*.ts`.
- **Self-Host Ready**: Comprehensive Docker documentation and modular server functions make deployment straightforward for self-hosted instances.

## Frequently Asked Questions

### What framework does OpenSEO use for the frontend?

OpenSEO uses **TanStack React-Start**, a server-rendered React framework that provides file-based routing and server functions. The entry point in [`src/start.ts`](https://github.com/every-app/open-seo/blob/main/src/start.ts) initializes the application with CSRF protection, while [`src/routeTree.gen.ts`](https://github.com/every-app/open-seo/blob/main/src/routeTree.gen.ts) provides compile-time type safety for all routes.

### How does OpenSEO handle background tasks like site audits?

Background tasks are implemented as **Workflows** in `src/server/workflows/`. Classes like [`SiteAuditWorkflow.ts`](https://github.com/every-app/open-seo/blob/main/SiteAuditWorkflow.ts) and [`RankCheckWorkflow.ts`](https://github.com/every-app/open-seo/blob/main/RankCheckWorkflow.ts) define long-running jobs that execute via Cloudflare Durable Objects or the Worker's `scheduled` export. These workflows share the same Drizzle database connection as the main application.

### Can I self-host OpenSEO without using the hosted version?

Yes. The codebase supports three authentication modes including `local_noauth` for development and self-hosted deployments. The repository includes [`docs/SELF_HOSTING_DOCKER.md`](https://github.com/every-app/open-seo/blob/main/docs/SELF_HOSTING_DOCKER.md) with Docker deployment instructions, and the MCP (Meta Control Plane) handlers in [`src/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server.ts) can process self-hosted API requests independently of the hosted SaaS infrastructure.

### How is the database structured in OpenSEO?

OpenSEO uses **Drizzle ORM** with a multi-provider architecture supporting both Cloudflare D1 (SQLite) and PostgreSQL. Schema definitions live in [`src/db/schema.ts`](https://github.com/every-app/open-seo/blob/main/src/db/schema.ts) with PostgreSQL-specific implementations in `src/db/pg/`. The database layer provides typed query APIs used by server functions and workflows, ensuring type safety across the entire data access layer.