OpenSEO Architecture: A Deep Dive Into Its Core Components

OpenSEO is a Cloudflare-edge application built from eight modular layers: a Workers runtime engine, three Durable Object families for stateful workflows, a Workflow orchestration system, type-safe server functions, a dual-database abstraction, flexible authentication modes, self-hosting utilities, and a React-based front end.

The every-app/open-seo repository implements a cloud-native SEO platform designed for scalability, low latency, and flexible deployment. Understanding its architecture is essential for contributors customizing the platform or teams evaluating it for production use.

Cloudflare Workers Runtime

OpenSEO executes all server-side logic on Cloudflare's edge network. The entry point in src/server.ts initializes the worker environment (env) and registers server functions.

This design eliminates cold starts and places compute geographically close to users. Every public endpoint routes through TanStack React-Start server functions created with createServerFn.

// src/server.ts — worker bootstrap and server function registration
export default {
  async fetch(request, env, ctx) {
    // wires env and registers all server functions
  }
};

Durable Objects: The State Layer

Three Durable Object (DO) families provide persistent, low-latency state for long-running operations. Unlike ephemeral Workers, DOs maintain memory across requests.

AuditScratchpad

The AuditScratchpad DO holds crawl frontier state, link graphs, and page mirrors during site audits. It isolates heavy crawl data from the workflow runner, preventing memory exhaustion.

// src/server/features/audit/AuditScratchpad.ts
export class AuditScratchpad extends DurableObject {
  constructor(ctx: DurableObjectState, workerEnv: Env) {
    super(ctx);
    // SQLite storage initialization
  }

  async leaseChunk(chunkSize: number): Promise<string[]> {
    // fetch pending URLs and mark as leased
  }
}

Namespaces are declared in src/env.d.ts:

// src/env.d.ts
interface Env {
  AUDIT_SCRATCHPAD: DurableObjectNamespace<AuditScratchpad>;
  ONBOARDING_CHAT: DurableObjectNamespace<OnboardingChatAgent>;
  SAM_CHAT: DurableObjectNamespace<SamChatAgent>;
}

OnboardingChatAgent and SamChatAgent

These DOs persist multi-turn conversations for the onboarding flow and the in-app SAM agent respectively. Each conversation maintains independent state without database round-trips.

Workflow Orchestration

The SiteAuditWorkflow in src/server/workflows/SiteAuditWorkflow.ts orchestrates multi-step crawls using Cloudflare Workflows. It leases work from the AuditScratchpad DO, executes chunks in parallel, and updates progress counters.

This architecture separates memory (the workflow runner) from heavy state (the DO), eliminating OOM errors and step-output limits.

// src/server/workflows/SiteAuditWorkflow.ts
export default {
  async crawlChunk(step) {
    const scratchpad = env.AUDIT_SCRATCHPAD.get(step.auditId);
    const urls = await scratchpad.leaseChunk(200);
    const results = await fetchPages(urls);
    await scratchpad.savePages(results);
    return { crawled: results.length };
  },
};

The design is documented in specs/0009-site-audit-crawl-architecture.md.

Server Functions (API Layer)

All business logic exposes thin, type-safe wrappers consumed by the front end. These live in src/serverFunctions/ and cover domains including projects, keywords, Lighthouse audits, GA4/GSC integrations, rank tracking, and billing.

// src/serverFunctions/workspace.ts
export const getWorkspaceMergeStatus = createServerFn({ method: "POST" })
  .middleware(requireAuthenticatedContext)
  .handler(async () => {
    if (!isCloudflareAccessMode()) {
      return { legacyWorkspaceCount: 0 };
    }
    return {
      legacyWorkspaceCount: await WorkspaceMergeService.countLegacyWorkspaces(),
    };
  });

Database Abstraction with Drizzle

OpenSEO uses Drizzle ORM to generate schemas compatible with both Cloudflare D1 (SQLite) and PostgreSQL. Product data—projects, audits, pages, backlinks—lives in these tables, while transient crawl data remains in Durable Objects.

// src/db/schema.ts
export const projects = pgTable("projects", {
  id: serial("id").primaryKey(),
  name: text("name").notNull(),
  createdAt: timestamp("created_at").defaultNow(),
});

Generated migration files appear in drizzle/ (SQLite) and drizzle-pg/ (PostgreSQL).

Authentication and Authorization

The auth stack supports three deployment modes:

  • cloudflare_access — Cloudflare Access for enterprise SSO
  • local_noauth — development convenience
  • hosted — traditional OAuth flows

Additional security layers include Turnstile CAPTCHAs, API key handling for DataForSEO, and OpenRouter integration for AI agents.

Implementation spans src/lib/auth.ts, src/lib/auth-mode.ts, and environment declarations in src/env.d.ts.

Self-Hosting Utilities

OpenSEO includes comprehensive self-hosting support:

Component Purpose
src/lib/selfhost-preflight.ts Environment validation before startup
docker-entrypoint.sh Container initialization
docs/SELF_HOSTING_*.md Deployment guides

These tools enable private Cloudflare Workers deployments without vendor lock-in.

Front-End: React with TanStack Query

The UI layer uses React, TanStack Query for data fetching, and Tailwind CSS. It consumes server functions through generated types, maintaining type safety across the API boundary.

The entry point src/start.ts bootstraps the application.

Summary

  • Edge runtime: Cloudflare Workers with TanStack server functions in src/server.ts
  • Stateful compute: Three Durable Object families (AuditScratchpad, OnboardingChatAgent, SamChatAgent)
  • Job orchestration: Workflows in src/server/workflows/SiteAuditWorkflow.ts separate compute from state
  • Type-safe API: Server functions in src/serverFunctions/ bridge front end and business logic
  • Flexible storage: Drizzle abstracts D1 SQLite and PostgreSQL in src/db/schema.ts
  • Multi-mode auth: cloudflare_access, local_noauth, and hosted via src/lib/auth.ts
  • Deployment flexibility: Self-hosting utilities in src/lib/selfhost-preflight.ts and documentation

Frequently Asked Questions

What database does OpenSEO use?

OpenSEO supports dual database backends through Drizzle ORM. Cloudflare D1 (SQLite) provides a serverless default for edge deployments, while PostgreSQL accommodates workloads requiring traditional relational features. Schema definitions in src/db/schema.ts compile to both targets.

How does OpenSEO handle large site crawls without memory issues?

The platform uses Workflows combined with Durable Objects. The SiteAuditWorkflow leases URL chunks from the AuditScratchpad DO, processes them, and stores results back in the DO. This architecture isolates transient crawl state from the workflow's memory, preventing OOM failures and step-limit violations.

Can OpenSEO run outside Cloudflare's ecosystem?

Yes. The repository includes self-hosting utilities including environment validation (src/lib/selfhost-preflight.ts), Docker support, and comprehensive documentation. While optimized for Cloudflare Workers, the modular architecture permits alternative deployments with adjusted infrastructure adapters.

What authentication methods does OpenSEO support?

Three modes are implemented: Cloudflare Access for enterprise SSO, local_noauth for development, and hosted for traditional OAuth flows. The auth system in src/lib/auth.ts and src/lib/auth-mode.ts dynamically selects behavior based on environment configuration.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →