# How the Core Logic of Open-SEO Is Organized in the `src` Directory: A Complete Architecture Guide

> Explore the Open SEO src directory architecture. Understand the feature-first layered structure, separating entry points, API surfaces, business logic, data repositories, and more.

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

---

**The Open-SEO `src` directory follows a feature-first layered architecture separating entry points, API surfaces, business logic services, data repositories, shared utilities, database schema, middleware, and client-side code.**

This guide unpacks exactly how every-app/open-seo structures its TypeScript codebase. Whether you're contributing a new feature or tracing a bug, understanding this hierarchy will help you navigate the repository efficiently.

## Entry Point Layer: Bootstrapping the Application

Every request begins in two critical files at the root of `src`.

- **[`src/start.ts`](https://github.com/every-app/open-seo/blob/main/src/start.ts)** — Builds the TanStack React-Start handler that powers the application's routing and rendering.
- **[`src/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server.ts)** — Implements the Cloudflare Worker `fetch` entry point. This file routes incoming requests to API functions, OAuth handlers, self-hosted MCP endpoints, or Durable Object agents before falling back to the TanStack start handler.

In [`src/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server.ts), you'll find the central dispatch logic that distinguishes between `/agents/*` paths, OAuth flows, and standard page requests.

## API Surface Layer: Server Functions

The `src/serverFunctions/*.ts` files define the contract between client and server. Each file registers one or more server functions using `createServerFn` with explicit HTTP methods.

For example, [`src/serverFunctions/dashboard.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/dashboard.ts) demonstrates the standard pattern: apply middleware, validate with Zod, then delegate to a service. These functions are consumed by the front-end through TanStack Query hooks.

Key files in this layer include [`dashboard.ts`](https://github.com/every-app/open-seo/blob/main/dashboard.ts) and [`rank-tracking.ts`](https://github.com/every-app/open-seo/blob/main/rank-tracking.ts).

## Feature Modules: Where Business Logic Lives

The heart of Open-SEO lives under `src/server/features/<domain>/`. Each feature (rank-tracking, SAM, audit, backlinks) contains two subdirectories:

- **`services/`** — Pure business logic without I/O concerns
- **`repositories/`** — Typed database queries using the schema-generated types

### Rank-Tracking Service Example

[`src/server/features/rank-tracking/services/RankTrackingService.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/rank-tracking/services/RankTrackingService.ts) encapsulates the complete rank-tracking algorithm:

```typescript
// Core service implementation (excerpt)
async function addKeywords(
  configId: string,
  projectId: string,
  keywords: string[],
) {
  // Validate the config belongs to the project
  await getValidatedConfig(configId, projectId);

  // Remove duplicates, enforce limits
  const existing = await RankTrackingRepository.getKeywordsForConfig(configId);
  const available = MAX_KEYWORDS_PER_CONFIG - existing.length;
  const rows = keywords
    .map(k => k.trim().toLowerCase())
    .filter((k, i, arr) => k && arr.indexOf(k) === i && !existing.some(e => e.keyword === k))
    .slice(0, available)
    .map(k => ({ id: crypto.randomUUID(), configId, keyword: k }));

  // Insert new rows in a single DB transaction
  await RankTrackingRepository.insertKeywords(rows);
}

```

The corresponding `RankTrackingRepository` in [`src/server/features/rank-tracking/repositories/RankTrackingRepository.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/rank-tracking/repositories/RankTrackingRepository.ts) handles all SQL/D1 operations, keeping the service layer database-agnostic.

## Shared Utilities: Cross-Cutting Concerns

The `src/shared/*.ts` directory contains reusable helpers imported by multiple services and UI components. One critical example is [`src/shared/keyword-locations.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/keyword-locations.ts), which resolves market and location codes:

```typescript
import { resolveMarket } from "@/shared/keyword-locations";

```

These utilities enforce consistency across features—whether normalizing domains, mapping color scales, or calculating credit costs.

## Database Schema Layer

All PostgreSQL/D1 table definitions live in `src/db/*.ts`. Key files include:

- **[`src/db/schema.ts`](https://github.com/every-app/open-seo/blob/main/src/db/schema.ts)** — Centralized table definitions for projects, rank-tracking configurations, audit results, and more
- **[`src/db/provider.ts`](https://github.com/every-app/open-seo/blob/main/src/db/provider.ts)** — Creates a typed database client per request with proper connection handling

Services never interact with the database directly. They call repository functions, which use the schema-generated types for compile-time safety.

## Middleware Layer: Request Processing Pipeline

The `src/middleware/*.ts` files implement cross-cutting concerns:

- **[`src/middleware/ensureUser.ts`](https://github.com/every-app/open-seo/blob/main/src/middleware/ensureUser.ts)** — Validates Cloudflare Access tokens, local development mode, or self-hosted authentication tokens
- **`requireProjectContext`** — Injects the current project into handler context after authorization

Middleware is applied globally in [`src/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server.ts) or selectively to individual server functions via `.middleware(requireProjectContext)`.

## Client-Side Layer: React Components and Hooks

The user interface lives in `src/routes/*.tsx` and `src/client/**/*.ts`. Route files render pages, while client hooks like `useSearchHistory` call the server functions defined in `src/serverFunctions/`.

This separation ensures the client remains thin—complex logic stays on the server, exposed only through typed function calls.

## Complete Request Flow: From Browser to Database

Tracing a rank-tracking keyword addition illustrates how these layers interact:

```typescript
// Server-function exposed to the client
export const addKeywordsToConfig = createServerFn({ method: "POST" })
  .middleware(requireProjectContext)
  .validator(addKeywordsSchema)
  .handler(async ({ context, input }) => {
    await RankTrackingService.addKeywords(
      input.configId,
      context.projectId,
      input.keywords,
    );
    return { ok: true };
  });

```

1. **Front-end** calls `addKeywordsToConfig` via TanStack Query
2. **Middleware** (`requireProjectContext`) resolves and injects the project
3. **Service** (`RankTrackingService.addKeywords`) validates business rules, deduplicates keywords, enforces limits
4. **Repository** (`RankTrackingRepository.insertKeywords`) executes the database transaction
5. **Response** serializes `{ ok: true }` back to the client

This **server-function → middleware → service → repository → DB** pattern repeats consistently across every feature.

## Key Source Files Reference

| File | Purpose |
|------|---------|
| [`src/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server.ts) | Main request handler and router |
| [`src/serverFunctions/dashboard.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/dashboard.ts) | Example server-function with validation |
| [`src/server/features/rank-tracking/services/RankTrackingService.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/rank-tracking/services/RankTrackingService.ts) | Core rank-tracking algorithm |
| [`src/server/features/rank-tracking/repositories/RankTrackingRepository.ts`](https://github.com/every-app/open-seo/blob/main/src/server/features/rank-tracking/repositories/RankTrackingRepository.ts) | Rank-tracking data access |
| [`src/shared/keyword-locations.ts`](https://github.com/every-app/open-seo/blob/main/src/shared/keyword-locations.ts) | Market resolution utility |
| [`src/db/schema.ts`](https://github.com/every-app/open-seo/blob/main/src/db/schema.ts) | Centralized table definitions |
| [`src/middleware/ensureUser.ts`](https://github.com/every-app/open-seo/blob/main/src/middleware/ensureUser.ts) | Authentication validation |

## Summary

- **Feature-first organization** — Each domain lives under `src/server/features/<domain>/` with isolated services and repositories
- **Clear separation of concerns** — API surfaces are thin wrappers; business logic lives in services; data access is repository-only
- **Shared utilities centralized** — Cross-cutting helpers in `src/shared/` prevent duplication
- **Middleware pipeline** — Reusable auth and context injection applied consistently
- **End-to-end type safety** — Database schema feeds through repositories to services to server functions

This architecture makes Open-SEO maintainable at scale: locate any logic by feature, extend functionality without side effects, and trace requests through a predictable layered flow.

## Frequently Asked Questions

### What is the purpose of [`src/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server.ts) in Open-SEO?

[`src/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server.ts) serves as the Cloudflare Worker entry point that routes all incoming requests. It handles `/agents/*` paths for Durable Object chat agents, OAuth authentication flows, self-hosted MCP endpoints, and falls back to the TanStack React-Start handler for standard page requests. This single file orchestrates the entire request dispatch pipeline.

### How does Open-SEO separate business logic from database access?

Business logic lives in `src/server/features/<domain>/services/*.ts` files like [`RankTrackingService.ts`](https://github.com/every-app/open-seo/blob/main/RankTrackingService.ts), which contain pure algorithms with no direct database calls. These services delegate all I/O to repositories in `src/server/features/<domain>/repositories/*.ts`. This separation allows testing business rules in isolation and swapping database implementations without touching core logic.

### Where should I add a new feature in the Open-SEO codebase?

Create a new directory under `src/server/features/<your-feature>/` containing `services/` and `repositories/` subdirectories. Implement your business logic in a service file, data access in a repository file, then expose functionality through a new file in `src/serverFunctions/`. Add any cross-cutting utilities to `src/shared/` if multiple features need them.

### How does authentication work across the Open-SEO architecture?

Authentication is handled by [`src/middleware/ensureUser.ts`](https://github.com/every-app/open-seo/blob/main/src/middleware/ensureUser.ts), which validates Cloudflare Access tokens in production, bypasses checks in local development, or accepts self-hosted tokens. This middleware integrates into [`src/server.ts`](https://github.com/every-app/open-seo/blob/main/src/server.ts) for global protection and can be selectively applied to individual server functions via `.middleware(requireProjectContext)` or similar middleware chains.