# How to Contribute to the OpenSEO Project: A Complete Guide for Developers

> Learn how to contribute to the OpenSEO project with this developer's guide. Follow our 6-step Git workflow to submit changes to the React frontend or MCP API.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: how-to-guide
- Published: 2026-07-29

---

**You can contribute to the open-seo project by setting up a local Cloudflare Workers development environment, following the 6-step Git workflow (issue → branch → implement → test → PR → review), and submitting changes to the React frontend or MCP API server.**

OpenSEO is an open-source, pay-as-you-go SEO platform built by **every-app/open-seo** that lets you run workflows similar to Semrush or Ahrefs with full code control. Whether you want to fix bugs, improve the React UI, add new API endpoints to the Cloudflare Workers backend, or create AI agent skills, this guide covers the complete contribution workflow based on the actual source code architecture.

## Understanding the OpenSEO Architecture

Before writing code, familiarize yourself with the three-layer architecture defined in [`worker-configuration.d.ts`](https://github.com/every-app/open-seo/blob/main/worker-configuration.d.ts) and [`drizzle.config.ts`](https://github.com/every-app/open-seo/blob/main/drizzle.config.ts).

### API Layer (Cloudflare Workers)

The backend runs as a **Cloudflare Workers** service implementing an MCP (Micro-service Control-Plane) that exposes JSON-RPC-style endpoints. Located in the repository root, [`worker-configuration.d.ts`](https://github.com/every-app/open-seo/blob/main/worker-configuration.d.ts) defines the TypeScript interfaces for worker bindings, while `wrangler.jsonc` configures deployment routes and environment variables. The API integrates with **DataForSEO** as the external data provider and uses **Drizzle ORM** for database operations.

### Database Layer (Drizzle ORM)

OpenSEO supports both **SQLite** (via Cloudflare D1) and **PostgreSQL** (production). Schema migrations live in two directories:
- `drizzle/` – SQLite migrations
- `drizzle-pg/` – PostgreSQL migrations (e.g., [`drizzle-pg/0012_dashboard.sql`](https://github.com/every-app/open-seo/blob/main/drizzle-pg/0012_dashboard.sql))

Configuration files [`drizzle.config.ts`](https://github.com/every-app/open-seo/blob/main/drizzle.config.ts) and [`drizzle-prod.config.ts`](https://github.com/every-app/open-seo/blob/main/drizzle-prod.config.ts) manage connection settings for each environment.

### Frontend Stack (React + TanStack Query)

The UI is a **Vite**-powered React application using **Tailwind CSS** for styling. Key files include:
- [`src/app.tsx`](https://github.com/every-app/open-seo/blob/main/src/app.tsx) – Application entry point and routing
- [`src/lib/query.ts`](https://github.com/every-app/open-seo/blob/main/src/lib/query.ts) – TanStack Query configuration for server-state management

The frontend communicates with the Workers API via the MCP client, handling SEO data visualization and project management.

### AI Agent Integration

The platform exposes MCP endpoints designed for AI agents like Claude Code or OpenClaw. Reusable workflows are defined in [`docs/AGENTS.md`](https://github.com/every-app/open-seo/blob/main/docs/AGENTS.md), allowing agents to orchestrate SEO tasks through standardized skill definitions.

## Setting Up Local Development Environment

Follow these steps to run the full stack locally before contributing.

### Prerequisites

- **Node.js** and **PNPM** (the repository uses PNPM workspaces)
- A **DataForSEO API key** (required for fetching SEO data)
- **Cloudflare Wrangler** CLI for local worker emulation

### Installation Steps

1. **Clone the repository:**

```bash
git clone https://github.com/every-app/open-seo.git
cd open-seo

```

2. **Install dependencies:**

```bash
pnpm install

```

3. **Configure environment variables:**

```bash
cp .env.example .env.local

# Edit .env.local and set DATAFORSEO_API_KEY=your_key_here

```

4. **Start the development server:**

```bash
pnpm dev

```

This command launches the Vite dev server for the React frontend and a local wrapper for the Cloudflare Workers API. For detailed platform-specific instructions, see [`docs/LOCAL_DEVELOPMENT.md`](https://github.com/every-app/open-seo/blob/main/docs/LOCAL_DEVELOPMENT.md).

### Running the Test Suite

All contributions must pass the automated checks before submission:

```bash
pnpm ci:check   # Runs lint, type-check, and unit tests

pnpm test       # Runs Playwright e2e tests

```

## Contribution Workflow Step-by-Step

The [`docs/CONTRIBUTING.md`](https://github.com/every-app/open-seo/blob/main/docs/CONTRIBUTING.md) file defines the following standardized process:

1. **Open an Issue** – Create a GitHub issue describing the bug or feature. Include minimal reproduction steps for bugs and use the provided issue templates.

2. **Fork & Branch** – Fork the repository and create a focused branch (e.g., `feat/keyword-export` or `fix/dark-mode-toggle`).

3. **Implement** – Write your code following the project's Prettier and ESLint configuration. Update relevant documentation and add tests for new functionality.

4. **Test Locally** – Verify your changes using the local dev server and targeted Playwright tests:

```bash
pnpm test:e2e --grep "keyword-research"

```

5. **Submit PR** – Open a Pull Request against the `main` branch with a clear description explaining what changed and why.

6. **Review** – Address feedback from maintainers. CI automatically runs checks; the PR merges only after all tests pass.

## Common Contribution Patterns

### Adding a New API Endpoint

To extend the MCP server with new SEO functionality, modify the routes in the server directory:

```ts
// src/server/routes/seo.ts
import { json } from '@cloudflare/workers-types';
import { db } from '@/db';

// New endpoint: GET /api/v1/keywords/:projectId
export async function getProjectKeywords(request: Request) {
  const { projectId } = request.params;
  const keywords = await db.select().from('keywords').where({ projectId });
  return json(keywords);
}

```

Register the handler in [`src/server/index.ts`](https://github.com/every-app/open-seo/blob/main/src/server/index.ts) and add corresponding tests in [`e2e/keyword-research-navigation.spec.ts`](https://github.com/every-app/open-seo/blob/main/e2e/keyword-research-navigation.spec.ts).

### Creating a TanStack Query Hook

Frontend contributions typically involve new data fetching hooks:

```ts
// src/lib/useKeywords.ts
import { useQuery } from '@tanstack/react-query';
import { apiClient } from './apiClient';

export const useProjectKeywords = (projectId: string) =>
  useQuery(['keywords', projectId], async () => {
    const res = await apiClient.get(`/api/v1/keywords/${projectId}`);
    return res.json();
  });

```

Consume this hook in React components to display keyword data with automatic caching and background refetching.

### Defining an AI Skill

Create reusable agent workflows by adding YAML skill definitions:

```yaml

# docs/skills/keyword-research.yaml

name: KeywordResearch
description: Guide an AI agent through a full keyword-research workflow.
steps:
  - request: GetKeywordIdeas
    args:
      query: "{{ user_input }}"
  - request: GetSearchVolume
    args:
      keywords: "{{ previous_step.result }}"

```

AI agents consume these skills via the MCP endpoint documented at `https://openseo.so/docs/skills/setup`.

## Key Configuration Files and Scripts

Familiarize yourself with these critical paths when contributing:

- [`package.json`](https://github.com/every-app/open-seo/blob/main/package.json) – Workspace configuration and NPM scripts
- `wrangler.jsonc` – Cloudflare Workers bindings and routes
- [`drizzle.config.ts`](https://github.com/every-app/open-seo/blob/main/drizzle.config.ts) / [`drizzle-prod.config.ts`](https://github.com/every-app/open-seo/blob/main/drizzle-prod.config.ts) – Database connection settings
- [`scripts/migrate-d1-to-postgres.ts`](https://github.com/every-app/open-seo/blob/main/scripts/migrate-d1-to-postgres.ts) – Database migration utilities
- [`scripts/cli-utils.ts`](https://github.com/every-app/open-seo/blob/main/scripts/cli-utils.ts) – Development helper functions
- [`docs/SELF_HOSTING_DOCKER.md`](https://github.com/every-app/open-seo/blob/main/docs/SELF_HOSTING_DOCKER.md) – Docker deployment guide
- [`docs/SELF_HOSTING_CLOUDFLARE.md`](https://github.com/every-app/open-seo/blob/main/docs/SELF_HOSTING_CLOUDFLARE.md) – Cloudflare deployment guide
- [`docs/DATAFORSEO_API_KEY.md`](https://github.com/every-app/open-seo/blob/main/docs/DATAFORSEO_API_KEY.md) – API key acquisition guide

## Summary

- **OpenSEO** is a Cloudflare Workers-based SEO platform using Drizzle ORM for data and React for the frontend.
- Local setup requires **PNPM**, a **DataForSEO API key**, and the `pnpm dev` command to start the stack.
- Follow the **6-step workflow**: Issue → Branch → Implement → Test → PR → Review.
- Key contribution areas include **API endpoints** (`src/server/routes/`), **React hooks** (`src/lib/`), and **AI skills** (`docs/skills/`).
- Always run `pnpm ci:check` and `pnpm test` before submitting to ensure code quality.

## Frequently Asked Questions

### What programming languages and frameworks does OpenSEO use?

OpenSEO uses **TypeScript** throughout the stack. The backend runs on **Cloudflare Workers** with **Drizzle ORM** for database management, supporting both SQLite and PostgreSQL. The frontend uses **React** with **Vite**, **Tailwind CSS**, and **TanStack Query** for data fetching.

### Do I need a DataForSEO API key to contribute?

Yes, most features require a **DataForSEO API key** configured in `.env.local`. This external service provides the raw SEO data (rankings, keywords, backlinks) that powers the application. You can obtain a key by following the instructions in [`docs/DATAFORSEO_API_KEY.md`](https://github.com/every-app/open-seo/blob/main/docs/DATAFORSEO_API_KEY.md).

### How do I test my changes before submitting a PR?

Run the full validation suite with `pnpm ci:check` (linting and type-checking) followed by `pnpm test` (Playwright e2e tests). For specific features, use targeted testing like `pnpm test:e2e --grep "keyword-research"` to verify only relevant functionality.

### Can I contribute AI agent skills without modifying the core code?

Yes, you can contribute **AI skills** by creating YAML workflow files in the `docs/skills/` directory. These skills define reusable SEO workflows that AI agents consume through the MCP endpoint, allowing you to extend agent capabilities without changing the server code or database schema.