# Build Process for Open-SEO: Vite, TypeScript, and Cloudflare Workers Explained

> Learn the open-seo build process using Vite, TypeScript, and Cloudflare Workers. Discover a two-step pipeline with bundle size constraints and dependency stubbing.

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

---

**Open-SEO uses a two-step build pipeline where Vite bundles the React UI and Cloudflare Worker code, followed by TypeScript type-checking via `tsc --noEmit`, with a custom lean-worker plugin that enforces bundle size constraints by stubbing heavy dependencies and validating against a deny-list.**

The every-app/open-seo repository is a modern React application designed to run on Cloudflare's edge network. Understanding its build process is essential for contributors who need to optimize bundle sizes and ensure type safety before deployment.

## Build Pipeline Overview

The complete build sequence spans five distinct phases, orchestrated through [`package.json`](https://github.com/every-app/open-seo/blob/main/package.json) scripts and driven by [`vite.config.ts`](https://github.com/every-app/open-seo/blob/main/vite.config.ts), [`vite-plugin-lean-worker-bundle.ts`](https://github.com/every-app/open-seo/blob/main/vite-plugin-lean-worker-bundle.ts), and [`tsconfig.json`](https://github.com/every-app/open-seo/blob/main/tsconfig.json). The pipeline uses **pnpm** for dependency management and produces a lean Cloudflare Worker bundle optimized for edge execution.

- **Dependency installation** via `pnpm install`
- **Vite bundling** with custom lean-worker plugin
- **TypeScript validation** using `tsc --noEmit`
- **Optional source-map generation** for PostHog error tracking
- **Cloudflare deployment** via Wrangler CLI

## Step-by-Step Build Configuration

### 1. Dependency Installation with pnpm

Before building, install dependencies using the project's specified package manager. The [`package.json`](https://github.com/every-app/open-seo/blob/main/package.json) defines all scripts and dependency requirements for the build process.

```bash
pnpm install

```

### 2. Vite Build Process (vite.config.ts)

The core bundling logic resides in [`vite.config.ts`](https://github.com/every-app/open-seo/blob/main/vite.config.ts), which configures Vite to handle both the React UI and the Cloudflare Worker entry points. The configuration loads environment variables via `loadEnv` and registers a specific plugin sequence:

```typescript
// vite.config.ts (lines 45-60)
plugins: [
  leanWorkerBundle(),
  showDevtools ? devtools({ /* … */ }) : null,
  cloudflare({ inspectorPort: false, viteEnvironment: { name: "ssr" } }),
  tsConfigPaths(),
  tanstackStart(),
  viteReact(),
  tailwindcss(),
],

```

The build script in [`package.json`](https://github.com/every-app/open-seo/blob/main/package.json) (lines 13-14) invokes Vite with `"build": "vite build && tsc --noEmit"`. This command handles React component compilation, Tailwind CSS processing, and Worker-specific bundling through the `@cloudflare/vite-plugin`.

### 3. TypeScript Validation (tsconfig.json)

After Vite completes bundling, the pipeline runs TypeScript checking separately to ensure type safety without emitting additional files. The [`tsconfig.json`](https://github.com/every-app/open-seo/blob/main/tsconfig.json) specifies `"noEmit": true` (lines 21-22), guaranteeing that only type validation occurs while Vite handles all file generation.

```json
// tsconfig.json
"noEmit": true

```

This separation allows Vite to handle fast transformation and bundling while TypeScript enforces strict type checking as a final validation gate.

### 4. Source Map Generation (Optional)

The build conditionally generates source maps based on the `POSTHOG_SOURCEMAPS` environment variable. When set to `true`, Vite outputs to `dist-sourcemaps` instead of the standard `dist` directory.

```typescript
// vite.config.ts (lines 42-44)
build: {
  sourcemap: emitSourcemaps,
  outDir: emitSourcemaps ? "dist-sourcemaps" : "dist",
}

```

Enable source maps for production error tracking with:

```bash
POSTHOG_SOURCEMAPS=true npm run build

```

### 5. Cloudflare Worker Deployment

The final step uploads the bundle to Cloudflare's edge network. The [`package.json`](https://github.com/every-app/open-seo/blob/main/package.json) provides two deployment paths:

- **`npm run deploy`**: Runs database migrations, builds the project, and executes `wrangler deploy`
- **`npm run deploy:postgres`**: Uses the Alchemy CLI with a production `.env` file for staged deployments

## The Lean Worker Bundle Plugin

A critical component of the build process is the custom `leanWorkerBundle()` plugin defined in [`vite-plugin-lean-worker-bundle.ts`](https://github.com/every-app/open-seo/blob/main/vite-plugin-lean-worker-bundle.ts). This plugin ensures the Cloudflare Worker bundle remains small and fast by implementing three specific optimizations:

**Dependency Aliasing**: Heavy packages like `just-bash` and `workers-ai-provider` are replaced with stub files to prevent them from entering the eager bundle.

**Zod Locale Swapping**: The plugin replaces Zod's multilingual locale barrel with an English-only export to reduce bundle size:

```typescript
// Replaces with: export { default as en } from "./en.js"

```

**Eager-Denylist Enforcement**: During the `generateBundle` phase (lines 76-84), the plugin traverses the static import graph of worker entry chunks. If any module matches the deny-list (including `dataforseo-client`, `autumn-js`, or `cheerio`), the build immediately fails with an explicit error message.

The core validation logic appears at lines 65-66 (description) and 76-84 (deny-list generation) in [`vite-plugin-lean-worker-bundle.ts`](https://github.com/every-app/open-seo/blob/main/vite-plugin-lean-worker-bundle.ts).

## Build Commands Reference

Execute these commands from the repository root to manage the build lifecycle:

```bash

# Install dependencies (run once)

pnpm install

# Standard production build

npm run build

# Build with source maps for PostHog error tracking

POSTHOG_SOURCEMAPS=true npm run build

# Preview the production build locally

npm run preview

# Deploy to Cloudflare (after building)

npm run deploy

```

## Key Configuration Files

| File | Purpose | Location |
|------|---------|----------|
| **package.json** | Build scripts and dependency definitions | [`package.json`](https://github.com/every-app/open-seo/blob/main/package.json) |
| **vite.config.ts** | Vite configuration, environment handling, plugin registration | [`vite.config.ts`](https://github.com/every-app/open-seo/blob/main/vite.config.ts) |
| **vite-plugin-lean-worker-bundle.ts** | Custom plugin enforcing bundle size constraints | [`vite-plugin-lean-worker-bundle.ts`](https://github.com/every-app/open-seo/blob/main/vite-plugin-lean-worker-bundle.ts) |
| **tsconfig.json** | TypeScript compiler options with strict mode | [`tsconfig.json`](https://github.com/every-app/open-seo/blob/main/tsconfig.json) |
| **docs/LOCAL_DEVELOPMENT.md** | Local development and build instructions | [`docs/LOCAL_DEVELOPMENT.md`](https://github.com/every-app/open-seo/blob/main/docs/LOCAL_DEVELOPMENT.md) |

## Summary

- Open-SEO uses **Vite** for bundling and **TypeScript** (`tsc --noEmit`) for type validation in a sequential build pipeline defined in [`package.json`](https://github.com/every-app/open-seo/blob/main/package.json).
- The custom **lean-worker bundle plugin** stubs heavy dependencies, minimizes Zod locales to English-only, and enforces a deny-list that fails the build if bloated modules enter the worker bundle.
- Source maps are conditionally emitted to `dist-sourcemaps` when `POSTHOG_SOURCEMAPS=true`, otherwise output goes to `dist`.
- Deployment targets Cloudflare Workers via **Wrangler** or the Alchemy CLI for production environments.
- All configuration is centralized in [`vite.config.ts`](https://github.com/every-app/open-seo/blob/main/vite.config.ts), [`tsconfig.json`](https://github.com/every-app/open-seo/blob/main/tsconfig.json), and the custom plugin file at the repository root.

## Frequently Asked Questions

### What build tool does Open-SEO use?

Open-SEO uses **Vite** as its primary build tool and bundler. Vite handles the React UI compilation, Tailwind CSS processing, and Cloudflare Worker bundling through the `@cloudflare/vite-plugin`. The build process is orchestrated via npm scripts defined in [`package.json`](https://github.com/every-app/open-seo/blob/main/package.json) that execute `vite build` followed by TypeScript type-checking.

### How does Open-SEO keep the Cloudflare Worker bundle size small?

The repository implements a custom **lean-worker bundle plugin** ([`vite-plugin-lean-worker-bundle.ts`](https://github.com/every-app/open-seo/blob/main/vite-plugin-lean-worker-bundle.ts)) that stubs heavy dependencies (like `just-bash` and `workers-ai-provider`), replaces Zod's multilingual locales with an English-only barrel, and maintains an eager-denylist that aborts the build if prohibited modules (such as `cheerio` or `dataforseo-client`) are detected in the static import graph.

### What is the purpose of the TypeScript --noEmit flag in the build?

The `--noEmit` flag ensures TypeScript performs type-checking without generating output files. Since Vite handles all compilation and bundling, this flag prevents file system conflicts and keeps the build fast while maintaining strict type safety. The [`tsconfig.json`](https://github.com/every-app/open-seo/blob/main/tsconfig.json) explicitly sets `"noEmit": true` to enforce this behavior.

### How do I generate source maps for error tracking in Open-SEO?

Set the environment variable `POSTHOG_SOURCEMAPS` to `true` before running the build command: `POSTHOG_SOURCEMAPS=true npm run build`. This instructs Vite to emit source maps into the `dist-sourcemaps` directory rather than the standard `dist` folder, enabling detailed error tracking in PostHog or similar observability platforms.