Open-SEO Project Structure: A Complete Guide to the Root Directory Layout

Open-SEO is a TypeScript monorepo that combines a Vite-based React frontend with Cloudflare Workers backend, organized into directories like src/, web/, drizzle/, and e2e/ at the repository root.

The every-app/open-seo repository implements a modern SEO analytics platform as a tightly-coupled full-stack application. Understanding the open-seo project structure is essential for contributors and self-hosters navigating the Cloudflare Workers ecosystem. The root layout separates concerns between frontend routing, serverless functions, database schema, and static assets while maintaining a unified build pipeline managed by Vite and Wrangler.

Root-Level Directory Overview

At the repository root, code is partitioned into functional groups that handle distinct architectural concerns:

  • src/ – Core application code including React components, TanStack Router configuration, server functions, database schema definitions, and shared utilities
  • web/ – Dedicated workspace for the Vite frontend containing its own package.json, pnpm workspace configuration, and Cloudflare-specific worker bindings
  • drizzle/ – Database migration scripts and schema evolution files for the D1 SQLite database used by the Workers runtime
  • e2e/ – End-to-end test suites executed with Playwright against the full stack
  • docs/ – Human-readable documentation covering self-hosting guides, local development setup, and maintainer notes
  • scripts/ – Utility scripts for data seeding, billing report generation, and operational tasks
  • public/ – Static assets served by the Vite dev server including icons, manifests, and other build-time resources
  • specs/ – Design specification documents that drive feature development
  • release-notes/ – Markdown changelogs documenting version history

Core Architectural Layers

The open-seo project structure implements five distinct layers that bridge frontend interactions with serverless backend operations.

Frontend Layer (React + Vite)

The user interface resides under src/routes/* and src/components/*, with the entry point at src/router.tsx. This file declares the client-side route tree using TanStack Router, enabling type-safe navigation throughout the application.

Backend Layer (Cloudflare Workers)

Server-side logic is exposed through Server Functions located in src/serverFunctions/*.ts. These TypeScript modules are automatically mapped to HTTP endpoints by the Workers runtime. When the frontend invokes these functions via fetch requests, Cloudflare handles the routing without requiring explicit API route definitions.

Database Layer (Drizzle ORM + D1)

Database schema definitions live in src/db/schema.ts alongside per-entity schema files. The drizzle/ directory contains SQL migration files that evolve the SQLite-compatible D1 database schema. Migrations are applied using Wrangler commands (npm run db:migrate:*).

Authentication & Authorization

Auth utilities are implemented in src/lib/*, supporting three distinct modes: local no-auth development, Cloudflare Access integration, and custom OAuth providers. Bindings are declared in package.json under the cloudflare.bindings key.

MCP (Machine-Client Protocol)

The MCP endpoint for AI agent integration is implemented in src/server/mcp/*, allowing programmatic access to Open-SEO functionality via standardized protocol handlers.

Key Configuration Files

Several root-level files orchestrate the build and deployment pipeline:

  • wrangler.jsonc – Configures Cloudflare Workers bindings, routes, and environment variables for the serverless runtime
  • vite.config.ts – Defines Vite build settings including the Cloudflare plugin that bridges frontend and backend during development
  • package.json – Declares workspace dependencies, scripts for database migrations, and Cloudflare-specific metadata
  • tsconfig.json – Establishes TypeScript compiler options for the entire monorepo

Working with the Codebase

Understanding how to navigate the open-seo project structure requires familiarity with its serverless function patterns and database workflows.

Importing Server Functions

Frontend components consume backend logic through direct imports of server function modules. The build system handles the network boundary automatically.

// src/routes/_app/projects.tsx
import { useQuery } from '@tanstack/react-query';
import { getProjects } from '~/serverFunctions/projects';

// Fetch the list of projects when the component mounts
const { data: projects, isLoading } = useQuery(['projects'], getProjects);

See src/serverFunctions/projects.ts for the implementation.

Defining New Server Functions

Creating new API endpoints involves exporting request handlers from the src/serverFunctions/ directory. These functions become accessible at /api/ routes automatically.

// src/serverFunctions/keywords.ts
import { json } from '@cloudflare/workers-types';
import { fetchKeywordData } from '~/shared/keyword-data';

// Exported function is auto-exposed as a route `/api/keywords`
export async function onRequest(context: any) {
  const { query } = await context.request.json();
  const result = await fetchKeywordData(query);
  return json(result);
}

The function becomes reachable at https://<your-domain>/api/keywords.

Running Database Migrations

Schema changes are managed through Drizzle ORM migration files stored in drizzle/:


# Apply all pending D1 migrations locally

npm run db:migrate:local

The migration files are orchestrated by wrangler d1 migrations and target the SQLite-compatible D1 database.

Summary

  • Open-SEO organizes code into src/ (application logic), web/ (frontend workspace), and drizzle/ (database migrations) at the repository root
  • The architecture combines React with TanStack Router on the frontend and Cloudflare Workers Server Functions on the backend
  • Database operations use Drizzle ORM with SQLite-compatible D1, with migration files stored in drizzle/
  • Configuration is centralized in wrangler.jsonc (Workers), vite.config.ts (build), and package.json (workspace)
  • End-to-end testing is handled by Playwright in the e2e/ directory, while unit tests reside alongside source files in src/**/*.test.ts

Frequently Asked Questions

What is the purpose of the web/ directory in Open-SEO?

The web/ directory serves as a dedicated workspace for the Vite frontend, containing its own package.json and Cloudflare-specific worker configuration. This separation allows the frontend build process to maintain independent dependency management while still integrating with the monorepo's shared configuration and build pipeline.

How are backend API routes defined in the Open-SEO project structure?

Backend routes are defined implicitly through Server Functions in src/serverFunctions/*.ts rather than explicit routing files. When you export an onRequest function from a module in this directory, the Cloudflare Workers runtime automatically exposes it as an HTTP endpoint accessible via /api/ paths, eliminating the need for separate route definitions.

Where are database schema changes managed in Open-SEO?

Database schema is defined in src/db/schema.ts using Drizzle ORM syntax, while migration files are stored in the drizzle/ directory at the repository root. The wrangler.jsonc configuration points to these migrations, which are applied to the D1 SQLite database using npm scripts like db:migrate:local or db:migrate:production.

What testing strategies does the Open-SEO project structure support?

The repository implements a two-tier testing approach: unit tests written alongside source code in src/**/*.test.ts and executed with Vitest, and end-to-end tests located in the e2e/ directory that use Playwright to verify complete user workflows across the React frontend and Cloudflare Workers backend integration.

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 →