How to Contribute to Open-SEO: A Complete Guide for New Contributors

Start by opening a well-written issue describing the problem and desired behavior, then use the provided Docker Compose setup for local development and reference the public roadmap before proposing features.

Open-SEO is a TypeScript-first SEO SaaS platform built on Cloudflare Workers, offering server-side APIs for rank tracking, keyword research, and site audits. Contributing to this project requires understanding its opinionated architecture and the maintainers' workflow preferences. This guide walks you through the codebase structure, development setup, and submission process based on the every-app/open-seo source code.

Understanding the Open-SEO Architecture

Before contributing to Open-SEO, you need to map where your changes belong. The repository enforces a strict separation of concerns across distinct layers:

Layer Purpose Key Source Files
Entry point Cloudflare Worker bootstrap and route registration [src/start.ts](https://github.com/every-app/open-seo/blob/main/src/start.ts)
Server functions TanStack-style API handlers for all public operations [src/serverFunctions/workspace.ts](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/workspace.ts), [src/serverFunctions/keywords.ts](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/keywords.ts), [src/serverFunctions/rank-tracking.ts](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/rank-tracking.ts)
Business logic Service orchestration and external API integration src/shared/gsc.ts, src/shared/ga4.ts
Data layer Drizzle ORM with SQLite/Postgres compatibility [drizzle.config.ts](https://github.com/every-app/open-seo/blob/main/drizzle.config.ts), drizzle/ migrations
Frontend Vite + React with TanStack Query [web/vite.config.ts](https://github.com/every-app/open-seo/blob/main/web/vite.config.ts), web/ source tree
Infrastructure Docker self-hosting and CI Dockerfile.selfhost, [compose.yaml](https://github.com/every-app/open-seo/blob/main/compose.yaml)

Every public operation lives in a server function under src/serverFunctions/*.ts. These functions receive Zod-validated input and return JSON consumed by the React frontend via TanStack Query.

Setting Up Your Local Open-SEO Development Environment

The fastest way to contribute to Open-SEO is through the Docker Compose self-hosting configuration.

Prerequisites

  • Docker and Docker Compose
  • Node.js 20+ (for running tests outside containers)

Initial Setup

Clone the repository and prepare your environment:

git clone https://github.com/every-app/open-seo.git
cd open-seo
cp .env.example .env

Then launch the full stack:

docker compose up --build

This brings up a local Cloudflare-compatible Worker and a Postgres instance, mirroring production conditions without requiring actual Cloudflare credentials.

Running Tests

Validate your changes before submission:

npm run test

The test suite includes:

  • Unit tests under src/**/*.test.ts (Vitest)
  • End-to-end specs in e2e/ (Playwright)

The Open-SEO Contribution Workflow

Step 1: Start With an Issue

The maintainers prioritize well-written issues over surprise pull requests. A succinct, clearly written issue describing the problem and desired behavior is worth its weight in gold according to the docs/CONTRIBUTING.md guidelines.

Before opening, check the public roadmap to avoid duplicate feature requests.

Step 2: Use the Simple Issue Description Skill

If you have the CLI installed, enforce consistent formatting:

npx skills add every-app/open-seo --skill simple-issue-description

Apply this skill to your issue to match the project's documentation standards.

Step 3: Understand the PR Policy

Pull requests are not merged automatically. In docs/CONTRIBUTING.md, the maintainers explain that PRs serve mainly as proof-of-concepts to improve the associated issue. They may pull changes themselves or prioritize features based on PR quality.

This means your issue quality matters more than your PR code—focus your energy there first.

Contributing New Features to Open-SEO

Adding a Server Function

New API endpoints require a server function in src/serverFunctions/. Here's the pattern from src/serverFunctions/example.ts:

import { z } from "zod";
import { createServerFn } from "@tanstack/start/server";
import { db } from "../shared/db";

// Input validation
const ExampleInput = z.object({
  projectId: z.string().uuid(),
  payload: z.string(),
});

export const example = createServerFn()
  .input(ExampleInput)
  .handler(async ({ input }) => {
    // Business logic – interact with DB via Drizzle
    await db.exampleTable.insert({
      projectId: input.projectId,
      data: input.payload,
    });

    return { success: true };
  });

Key requirements:

  • Zod schemas for all inputs
  • Drizzle ORM for database operations
  • JSON responses for TanStack Query consumption

Consuming Server Functions from the Frontend

The React frontend uses TanStack Query to call server functions. Here's how to use the example function in a component:

import { useMutation } from "@tanstack/react-query";
import { example } from "@/serverFunctions/example";

export const ExampleForm = () => {
  const mutation = useMutation(example);

  const onSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    const form = e.target as HTMLFormElement;
    const payload = new FormData(form).get("payload") as string;

    mutation.mutate({ projectId: "…", payload });
  };

  return (
    <form onSubmit={onSubmit}>
      <textarea name="payload" required />
      <button type="submit" disabled={mutation.isLoading}>
        Save
      </button>
    </form>
  );
};

Integrating External SEO APIs

For features requiring Google Search Console, GA4, or Ahrefs data, add logic to the appropriate src/shared/ service:

These services are thin orchestration layers that keep server functions clean.

Submitting Your Open-SEO Contribution

Once your changes pass locally:

  1. Push to your fork
  2. Open a PR referencing the original issue number
  3. Include screenshots or short videos for UI changes (strongly recommended in the contribution guide)

The maintainers will review your PR as a reference implementation, potentially integrating it directly or using it to prioritize the feature.

Summary

  • Architecture: All public operations live in src/serverFunctions/*.ts with Zod validation and Drizzle persistence
  • Development: Use docker compose up --build for local setup and npm run test for validation
  • Workflow: Open detailed issues first, use the simple-issue-description skill, and treat PRs as proof-of-concepts
  • Requirements: Check the roadmap before features, include media for UI changes, and ensure tests pass

Frequently Asked Questions

Does Open-SEO accept direct pull requests?

Not automatically. According to docs/CONTRIBUTING.md, PRs serve as proof-of-concepts to improve issues rather than direct merge candidates. Maintainers may pull changes themselves or prioritize features based on PR quality. Focus on writing excellent issues first.

What database does Open-SEO use for local development?

SQLite via Drizzle ORM, with Postgres for production. The drizzle.config.ts configuration and Docker Compose setup handle the abstraction, so your code works identically in both environments without modification.

How do I add a new API endpoint to Open-SEO?

Create a server function in src/serverFunctions/ using createServerFn() from TanStack Start. Define a Zod schema for input validation, implement your handler with Drizzle for database operations, and export the function. The frontend consumes it via TanStack Query.

Where is the Open-SEO contribution guide located?

The complete guidelines are in [docs/CONTRIBUTING.md](https://github.com/every-app/open-seo/blob/main/docs/CONTRIBUTING.md), covering issue formatting, the PR policy, roadmap links, and development setup instructions.

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 →