How to Set Up a Development Environment for OpenSEO: Complete Developer Guide

Install Node 20+ and pnpm, clone the repository, install dependencies with pnpm install, initialize the SQLite database with pnpm run db:migrate:local, configure your DataForSEO API key in .env.local, and run pnpm dev:agents to start the Vite-powered development server.

OpenSEO is an open-source SEO platform built for Cloudflare Workers using Node 20+, pnpm workspaces, and Drizzle ORM. To set up a development environment for OpenSEO, you will configure a local SQLite database (or optional PostgreSQL), set up authentication modes, and run a Vite-powered worker that mimics the Cloudflare production runtime. This guide walks through the exact steps documented in the every-app/open-seo repository.

Prerequisites

Before you begin, ensure you have the following installed:

  • Node 20+ – Required runtime for the server code and tooling.
  • pnpm – The project uses pnpm workspaces for fast, lock-file-consistent installs.
  • DataForSEO API credentials – OpenSEO fetches SEO data from DataForSEO; you need a base64-encoded login:password token.
  • Docker (optional) – Needed only if you want to run the PostgreSQL backend locally instead of the default Cloudflare D1 SQLite.

Step-by-Step Setup

Clone the Repository

Start by cloning the OpenSEO repository and navigating into the project directory:

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

Install Dependencies

Run pnpm to install both the web UI (web/) and server (src/) workspace packages:

pnpm install

Initialize the Local Database

OpenSEO uses Drizzle ORM with a Cloudflare D1-compatible SQLite backend by default. Generate the schema and apply migrations:

pnpm run db:migrate:local

This command reads the schema definitions under src/db/ and creates a local SQLite file. It is safe to re-run, as the tool checks for already-applied migrations.

Configure Environment Variables

Copy the example environment file and add your DataForSEO credentials:

cp .env.example .env.local

Encode your DataForSEO login:password with base64 and add it to .env.local:

printf '%s' 'YOUR_LOGIN:YOUR_PASSWORD' | base64

Insert the resulting string into .env.local:

DATAFORSEO_API_KEY=dX...==

According to the docs/SELF_HOSTING_CLOUDFLARE.md file, this secret can also be configured via the Cloudflare dashboard when self-hosting.

Choose Authentication Mode

OpenSEO supports three authentication modes controlled via the AUTH_MODE environment variable:

  • local_noauth – No auth checks; injects a trusted admin@localhost identity. This is automatically set when using the development scripts.
  • cloudflare_access – Validates Cloudflare Access JWTs (cf-access-jwt-assertion). Requires TEAM_DOMAIN and POLICY_AUD for production-like testing.
  • hosted – Better Auth email/password flow; requires BETTER_AUTH_SECRET and BETTER_AUTH_URL.

To test Cloudflare Access locally, run:

AUTH_MODE=cloudflare_access pnpm dev

Run the Development Server

You have two options for running the local development server.

Option 1: Simple Vite dev server

pnpm run dev

This starts the worker at http://localhost:5173 but does not emulate Cloudflare’s routing model.

Option 2: Recommended portless workflow

mkdir -p .logs && touch .logs/dev-server.log
pnpm dev:agents

The portless tool proxies requests to http://open-seo.localhost:1355 and writes raw worker logs to .logs/dev-server.log. This mirrors the Cloudflare runtime, exposing the same environment bindings and hostnames used in production.

Switch to PostgreSQL (Optional)

If you prefer PostgreSQL over SQLite, or if you are testing scaling scenarios, you can run a local Postgres container.

Start the Docker container on port 5433 to avoid conflicts:

docker run --name openseo-postgres \
  -e POSTGRES_USER=openseo \
  -e POSTGRES_PASSWORD=openseo \
  -e POSTGRES_DB=openseo \
  -p 5433:5432 \
  -d postgres:16

Wait for readiness:

docker exec openseo-postgres pg_isready -U openseo -d openseo

Apply the Postgres migrations located under drizzle-pg/:

POSTGRES_DATABASE_URL=postgres://openseo:openseo@localhost:5433/openseo \
  pnpm db:migrate:pg

Update .env.local to switch the provider:

DATABASE_PROVIDER=postgres

The Vite runtime reads this flag from .env.local and maps the HYPERDRIVE binding to your connection string defined in wrangler.jsonc. To revert to D1, set DATABASE_PROVIDER=d1 and restart.

Common Development Commands

Here is a consolidated reference for the most frequent commands when developing OpenSEO:


# Install dependencies

pnpm install

# Initialize SQLite database

pnpm run db:migrate:local

# Copy environment template

cp .env.example .env.local

# Edit .env.local to add base64-encoded DATAFORSEO_API_KEY

# Start recommended dev server (with portless)

mkdir -p .logs && touch .logs/dev-server.log
pnpm dev:agents

# Test with Cloudflare Access auth

AUTH_MODE=cloudflare_access pnpm dev

# Start PostgreSQL locally (optional)

docker run --name openseo-postgres \
  -e POSTGRES_USER=openseo \
  -e POSTGRES_PASSWORD=openseo \
  -e POSTGRES_DB=openseo \
  -p 5433:5432 -d postgres:16

# Apply PostgreSQL migrations

POSTGRES_DATABASE_URL=postgres://openseo:openseo@localhost:5433/openseo \
  pnpm db:migrate:pg

Summary

  • Install prerequisites: Node 20+, pnpm, and optionally Docker.
  • Initialize the database: Run pnpm run db:migrate:local to create the SQLite schema from src/db/.
  • Configure secrets: Copy .env.example to .env.local and add your base64-encoded DataForSEO API key.
  • Start the server: Use pnpm dev:agents for the most accurate Cloudflare runtime simulation via portless.
  • Switch backends: Set DATABASE_PROVIDER=postgres and run pnpm db:migrate:pg after starting a Docker PostgreSQL container on port 5433.
  • Test auth flows: Set AUTH_MODE to cloudflare_access or hosted when testing specific authentication requirements.

Frequently Asked Questions

What are the minimum system requirements for OpenSEO development?

You need Node 20 or higher and pnpm installed on your system. The default database is SQLite (via Cloudflare D1 compatibility), so no additional database software is required unless you choose to run PostgreSQL locally. If using PostgreSQL, Docker is required to run the containerized database.

How do I obtain and configure the DataForSEO API key?

You must have a DataForSEO account to get login credentials. According to the docs/LOCAL_DEVELOPMENT.md, you encode your login:password string using base64 (e.g., printf '%s' 'login:pass' | base64) and paste the result into the DATAFORSEO_API_KEY field of your .env.local file. This token is required for the application to fetch SEO data.

What is the difference between pnpm dev and pnpm dev:agents?

pnpm dev starts a standard Vite development server at http://localhost:5173 and automatically sets AUTH_MODE=local_noauth. pnpm dev:agents runs the worker through portless, which mimics Cloudflare’s routing model and proxies to http://open-seo.localhost:1355. The portless method is recommended because it provides environment bindings identical to production and logs output to .logs/dev-server.log for easier debugging.

Can I switch between SQLite and PostgreSQL without changing code?

Yes. The application uses a provider-agnostic DB layer in src/db/. To switch backends, set the DATABASE_PROVIDER environment variable to postgres or d1 in your .env.local file. For PostgreSQL, you must also run pnpm db:migrate:pg after setting the POSTGRES_DATABASE_URL. The Vite runtime automatically maps the HYPERDRIVE binding in wrangler.jsonc based on this configuration, requiring no code changes.

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 →