How to Install Open-SEO Locally: Complete Development Setup Guide
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.jsonfor dependency management - DataForSEO API credentials – Essential for querying keyword data; you must base64-encode your
login:passwordcombination - 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 lines 5-9 and 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:
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:
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:
pnpm run db:migrate:local
This command invokes wrangler d1 migrations apply DB --local as defined in package.json under the db:migrate:local script.
Option B: PostgreSQL (Optional)
For larger storage requirements, start a Postgres container and run migrations:
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:
echo "DATABASE_PROVIDER=postgres" >> .env.local
4. Configure Environment Variables
Create your local environment file from the example template and add your DataForSEO credentials:
cp .env.example .env.local
Generate the base64-encoded API key from your DataForSEO credentials:
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 under cloudflare.bindings.
5. Launch the Development Server
Choose between two development modes:
Standard Development Server:
pnpm run dev
Agent-Friendly Development Server (Recommended):
mkdir -p .logs && pnpm dev:agents
The dev:agents script, defined in 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– Primary documentation for prerequisites, environment handling, and development scriptsdocs/LOCAL_POSTGRES.md– Specific guide for PostgreSQL backend configurationpackage.json– Defines npm scripts includingdev,dev:agents,db:migrate:*, and lists all dependencieswrangler.jsoncandweb/wrangler.jsonc– Cloudflare Worker configuration files containing bindings forDATAFORSEO_API_KEY,AUTH_MODE, and Hyperdrive settingssrc/db/andsrc/db/pg/– Provider-aware Drizzle ORM layers for SQLite and PostgreSQLscripts/– Utility scripts includingseed-rank-tracking.tsandmigrate-d1-to-postgres.ts
Practical Code Examples
Running Database Migrations
Generate updated schemas after modifying database structures:
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:
tsx scripts/seed-rank-tracking.ts
Testing Cloudflare Access Locally
Validate Cloudflare Access integration by overriding the default auth mode:
AUTH_MODE=cloudflare_access pnpm dev
Summary
- Clone the
every-app/open-seorepository and usepnpm installto fetch dependencies - Initialize the database using
pnpm run db:migrate:localfor SQLite or Docker-based Postgres withpnpm db:migrate:pg - Configure
DATAFORSEO_API_KEYin.env.localafter base64-encoding your credentials - Launch via
pnpm run dev(standard) orpnpm dev:agents(with logging) - Access the UI at
http://open-seo.localhost:1355with 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.
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.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →