# How to Install Open-SEO Locally: Complete Development Setup Guide

> Install Open-SEO locally with our comprehensive guide. Clone the repo, set up dependencies, configure API keys, and launch your dev server for local SEO testing.

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

---

**To install Open-SEO locally, clone the repository, install dependencies with `pnpm`, initialize the SQLite database via Wrangler migrations, configure your DataForSEO API credentials, and launch the Vite development server.**

Open-SEO is a full-stack SEO platform built for Cloudflare Workers. Installing it locally allows you to run the frontend with hot-reload via Vite, execute server-side code in a Miniflare worker environment, and choose between the default Cloudflare D1 (SQLite) database or an optional PostgreSQL instance. The following steps reference the official `every-app/open-seo` repository structure and configuration files.

## Prerequisites

Before you install Open-SEO locally, ensure your environment meets these requirements:

- **Node.js 20+** – Required for the modern JavaScript runtime used by Vite, Wrangler, and build scripts
- **pnpm** – The deterministic package manager specified in [`package.json`](https://github.com/every-app/open-seo/blob/main/package.json) for dependency management
- **DataForSEO API credentials** – Essential for querying keyword data; you must base64-encode your `login:password` combination
- **Docker** (optional) – Only needed if you prefer running a local Postgres container instead of the default SQLite backend

All prerequisite details are documented in [`docs/LOCAL_DEVELOPMENT.md`](https://github.com/every-app/open-seo/blob/main/docs/LOCAL_DEVELOPMENT.md) lines 5-9 and [`docs/LOCAL_POSTGRES.md`](https://github.com/every-app/open-seo/blob/main/docs/LOCAL_POSTGRES.md) lines 13-15.

## Step-by-Step Installation

### 1. Clone the Repository

Start by cloning the Open-SEO repository and navigating into the project directory:

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

```

### 2. Install Dependencies

Install all required packages using pnpm. This command installs the Cloudflare Workers SDK, TanStack libraries, Drizzle ORM, and development tools:

```bash
pnpm install

```

### 3. Initialize the Database

You have two options for local database storage: the default SQLite (Cloudflare D1) or an optional PostgreSQL container.

**Option A: SQLite (Default)**

Run the migration script to apply D1 schema changes locally:

```bash
pnpm run db:migrate:local

```

This command invokes `wrangler d1 migrations apply DB --local` as defined in [`package.json`](https://github.com/every-app/open-seo/blob/main/package.json) under the `db:migrate:local` script.

**Option B: PostgreSQL (Optional)**

For larger storage requirements, start a Postgres container and run migrations:

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

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

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

```

Then configure the provider flag:

```bash
echo "DATABASE_PROVIDER=postgres" >> .env.local

```

### 4. Configure Environment Variables

Create your local environment file from the example template and add your DataForSEO credentials:

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

```

Generate the base64-encoded API key from your DataForSEO credentials:

```bash
printf '%s' 'your_login:your_password' | base64

```

Paste the resulting string as the `DATAFORSEO_API_KEY` value in `.env.local`. This binding is required by the worker configuration in [`package.json`](https://github.com/every-app/open-seo/blob/main/package.json) under `cloudflare.bindings`.

### 5. Launch the Development Server

Choose between two development modes:

**Standard Development Server:**

```bash
pnpm run dev

```

**Agent-Friendly Development Server (Recommended):**

```bash
mkdir -p .logs && pnpm dev:agents

```

The `dev:agents` script, defined in [`package.json`](https://github.com/every-app/open-seo/blob/main/package.json) lines 11-13, wraps Vite with portless and captures logs to `.logs/dev-server.log` for easier debugging.

Access the application at `http://open-seo.localhost:1355` by default. If using a Git worktree, portless automatically prefixes the URL with the branch name.

### 6. Verify the Setup

Open your browser to the local URL. You should see the Open-SEO interface where you can create projects, add keywords (triggering DataForSEO API calls), and view analytics stored in your local SQLite or Postgres database. The development scripts automatically set `AUTH_MODE=local_noauth` to bypass authentication during local development.

## Key Configuration Files

Understanding these paths helps troubleshoot your local installation:

- [`docs/LOCAL_DEVELOPMENT.md`](https://github.com/every-app/open-seo/blob/main/docs/LOCAL_DEVELOPMENT.md) – Primary documentation for prerequisites, environment handling, and development scripts
- [`docs/LOCAL_POSTGRES.md`](https://github.com/every-app/open-seo/blob/main/docs/LOCAL_POSTGRES.md) – Specific guide for PostgreSQL backend configuration
- [`package.json`](https://github.com/every-app/open-seo/blob/main/package.json) – Defines npm scripts including `dev`, `dev:agents`, `db:migrate:*`, and lists all dependencies
- `wrangler.jsonc` and `web/wrangler.jsonc` – Cloudflare Worker configuration files containing bindings for `DATAFORSEO_API_KEY`, `AUTH_MODE`, and Hyperdrive settings
- `src/db/` and `src/db/pg/` – Provider-aware Drizzle ORM layers for SQLite and PostgreSQL
- `scripts/` – Utility scripts including [`seed-rank-tracking.ts`](https://github.com/every-app/open-seo/blob/main/seed-rank-tracking.ts) and [`migrate-d1-to-postgres.ts`](https://github.com/every-app/open-seo/blob/main/migrate-d1-to-postgres.ts)

## Practical Code Examples

### Running Database Migrations

Generate updated schemas after modifying database structures:

```bash
pnpm db:generate      # Regenerate both D1 and Postgres schemas

pnpm db:generate:d1   # SQLite only

pnpm db:generate:pg   # Postgres only

```

### Seeding Test Data

Populate your local database with sample rank-tracking data:

```bash
tsx scripts/seed-rank-tracking.ts

```

### Testing Cloudflare Access Locally

Validate Cloudflare Access integration by overriding the default auth mode:

```bash
AUTH_MODE=cloudflare_access pnpm dev

```

## Summary

- **Clone** the `every-app/open-seo` repository and use `pnpm install` to fetch dependencies
- **Initialize** the database using `pnpm run db:migrate:local` for SQLite or Docker-based Postgres with `pnpm db:migrate:pg`
- **Configure** `DATAFORSEO_API_KEY` in `.env.local` after base64-encoding your credentials
- **Launch** via `pnpm run dev` (standard) or `pnpm dev:agents` (with logging)
- **Access** the UI at `http://open-seo.localhost:1355` with authentication disabled for local development

## Frequently Asked Questions

### Do I need a DataForSEO account to run Open-SEO locally?

Yes, you need active DataForSEO API credentials. The application queries DataForSEO for keyword data, and the local development server requires the `DATAFORSEO_API_KEY` environment variable to be set in `.env.local` before the application can fetch search rankings or keyword metrics.

### Can I use PostgreSQL instead of SQLite for local development?

Yes, while Open-SEO defaults to Cloudflare D1 (SQLite) for local development, you can run a Postgres container via Docker on port 5433, execute `pnpm db:migrate:pg` to apply schema migrations, and set `DATABASE_PROVIDER=postgres` in your `.env.local` file. This is documented in [`docs/LOCAL_POSTGRES.md`](https://github.com/every-app/open-seo/blob/main/docs/LOCAL_POSTGRES.md).

### What is the difference between `pnpm run dev` and `pnpm dev:agents`?

`pnpm run dev` starts the standard Vite development server directly, while `pnpm dev:agents` wraps the server with portless and pipes output to `.logs/dev-server.log`. The agent-friendly version is recommended for debugging and development environments where you need persistent log access or automatic port management.

### How do I troubleshoot database connection errors?

First, verify your database provider setting in `.env.local` matches your initialized backend (SQLite or Postgres). For SQLite, ensure you ran `pnpm run db:migrate:local`. For Postgres, confirm your Docker container is running with `docker exec openseo-postgres pg_isready -U openseo` and that `POSTGRES_DATABASE_URL` points to port 5433. Check `wrangler.jsonc` for binding configurations if errors persist.