# How to Deploy SXO to Cloudflare Workers with Wrangler Configuration

> Deploy SXO to Cloudflare Workers using Wrangler. Configure ASSETS binding and map virtual imports in wrangler.jsonc for seamless static file serving and module management.

- Repository: [Víctor García/sxo](https://github.com/gc-victor/sxo)
- Tags: how-to-guide
- Published: 2026-03-02

---

**Deploy SXO to Cloudflare Workers by using the dedicated Cloudflare adapter in [`src/js/server/prod/cloudflare.js`](https://github.com/gc-victor/sxo/blob/main/src/js/server/prod/cloudflare.js), configuring the `ASSETS` binding for static files, and mapping virtual imports `sxo:routes` and `sxo:modules` in your `wrangler.jsonc` file.**

To deploy SXO to Cloudflare Workers, you leverage a specialized server adapter that bridges the framework’s SSR runtime with the Workers platform. This approach lets you serve both pre-rendered static assets and dynamic server-rendered pages from Cloudflare’s edge network using a single Wrangler configuration.

## Understanding the SXO Cloudflare Adapter

The core integration logic resides in [`src/js/server/prod/cloudflare.js`](https://github.com/gc-victor/sxo/blob/main/src/js/server/prod/cloudflare.js). This adapter creates a request handler that runs inside the Cloudflare Workers runtime and expects two virtual imports to function:

- **`sxo:routes`** – Points to the generated route manifest ([`dist/server/routes.json`](https://github.com/gc-victor/sxo/blob/main/dist/server/routes.json)).
- **`sxo:modules`** – Points to the compiled SSR bundle ([`dist/server/modules.js`](https://github.com/gc-victor/sxo/blob/main/dist/server/modules.js)).

When a request arrives, the adapter first executes any configured middleware, then attempts to serve static files from the `ASSETS` binding. If the request matches a pre-generated route (created via `sxo generate`), the adapter returns cached HTML with `Cache-Control: public, max-age=300`. All other requests fall back to the core SSR handler (`createCoreHandler`).

## Build Output Structure

Before deploying, you must build the SXO project. Running `pnpm run build` produces three critical directories:

1. **`dist/client/`** – Contains static assets (JavaScript, CSS, images) served via the `ASSETS` binding.
2. **[`dist/server/routes.json`](https://github.com/gc-victor/sxo/blob/main/dist/server/routes.json)** – The route manifest mapping URLs to page modules.
3. **[`dist/server/modules.js`](https://github.com/gc-victor/sxo/blob/main/dist/server/modules.js)** – The bundled server-side code imported by the adapter.

If you run `pnpm run generate`, SXO pre-renders specific routes to static HTML, storing them in `dist/client/` for optimal edge caching.

## Configuring wrangler.jsonc for SXO

To deploy SXO to Cloudflare Workers, create a `wrangler.jsonc` file at your project root. This configuration binds your static assets and maps the virtual imports required by the adapter.

### Asset Binding Configuration

The `assets` section tells Wrangler which directory contains your client build and creates the `ASSETS` binding used by the adapter:

```jsonc
"assets": {
  "binding": "ASSETS",
  "directory": "./dist/client/",
  "html_handling": "none"
}

```

### Virtual Import Aliases

The `alias` section resolves the virtual imports `sxo:routes` and `sxo:modules` to the actual files generated during the build:

```jsonc
"alias": {
  "sxo:routes": "./dist/server/routes.json",
  "sxo:modules": "./dist/server/modules.js"
}

```

### Compatibility Settings

SXO requires specific Workers compatibility flags, particularly `nodejs_compat` for runtime features:

```jsonc
"compatibility_date": "2024-01-01",
"compatibility_flags": ["nodejs_compat"]

```

### Complete Configuration Example

Here is the full `wrangler.jsonc` template found in `templates/workers/wrangler.jsonc`:

```jsonc
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "sxo-workers-example",
  "main": "src/index.js",
  "compatibility_date": "2024-01-01",
  "compatibility_flags": ["nodejs_compat"],
  "assets": {
    "binding": "ASSETS",
    "directory": "./dist/client/",
    "html_handling": "none"
  },
  "alias": {
    "sxo:routes": "./dist/server/routes.json",
    "sxo:modules": "./dist/server/modules.js"
  }
}

```

## Creating the Worker Entry Point

The Worker entry point imports the Cloudflare adapter and exports the handler. Create [`src/index.js`](https://github.com/gc-victor/sxo/blob/main/src/index.js) (or your configured `main` path) with the following:

```javascript
import { createHandler } from "sxo/cloudflare";

export default await createHandler({
  // Optional: custom publicPath, middleware, security headers, etc.
});

```

This file is the `main` entry referenced in `wrangler.jsonc`. When Wrangler bundles your Worker, it includes the `createHandler` logic from [`src/js/server/prod/cloudflare.js`](https://github.com/gc-victor/sxo/blob/main/src/js/server/prod/cloudflare.js), which manages routing, asset serving, and SSR.

## Deployment Workflow

Follow these steps to deploy SXO to Cloudflare Workers:

1. **Build the project** to generate client assets and server bundles:

   ```bash
   pnpm run build
   ```

2. **Generate static pages** (optional) for routes you want pre-rendered:

   ```bash
   pnpm run generate
   ```

3. **Authenticate with Cloudflare**:

   ```bash
   npx wrangler login
   ```

4. **Publish the Worker**:

   ```bash
   npx wrangler publish
   ```

Wrangler reads your `wrangler.jsonc`, uploads the `dist/client/` directory to the `ASSETS` binding, and deploys the Worker script containing your SSR handler.

## Summary

- **Use the Cloudflare adapter** located at [`src/js/server/prod/cloudflare.js`](https://github.com/gc-victor/sxo/blob/main/src/js/server/prod/cloudflare.js) to run SXO on Workers.
- **Configure `wrangler.jsonc`** with an `ASSETS` binding pointing to `dist/client/` and aliases for `sxo:routes` and `sxo:modules`.
- **Build the project** with `pnpm run build` to generate the required server manifests and client assets.
- **Deploy via Wrangler** using `npx wrangler publish` after logging in to Cloudflare.

## Frequently Asked Questions

### What is the role of the ASSETS binding in SXO Cloudflare deployments?

The `ASSETS` binding connects your Worker to the static files generated in `dist/client/`. When a request arrives, the Cloudflare adapter in [`src/js/server/prod/cloudflare.js`](https://github.com/gc-victor/sxo/blob/main/src/js/server/prod/cloudflare.js) first checks this binding for static files like CSS, JavaScript, or pre-rendered HTML. If the file exists, it is served directly from the edge without invoking the SSR runtime, improving performance and reducing compute costs.

### How does SXO handle pre-rendered static pages on Cloudflare Workers?

When you run `sxo generate`, SXO creates static HTML files for specified routes and stores them in `dist/client/`. During deployment, these files become part of the `ASSETS` binding. The adapter checks the route manifest (`sxo:routes`) to determine if a requested URL corresponds to a pre-generated page. If so, it fetches the HTML from `ASSETS` and returns it with a `Cache-Control: public, max-age=300` header, ensuring efficient edge caching.

### Can I use custom middleware when deploying SXO to Cloudflare Workers?

Yes, the `createHandler` function exported from `sxo/cloudflare` accepts an options object where you can configure middleware. The adapter in [`src/js/server/prod/cloudflare.js`](https://github.com/gc-victor/sxo/blob/main/src/js/server/prod/cloudflare.js) executes any configured middleware before attempting to serve static assets or falling back to SSR. This allows you to implement authentication, logging, security headers, or request transformation at the edge before SXO handles the response.

### What compatibility flags are required for SXO on Cloudflare Workers?

SXO requires the `nodejs_compat` compatibility flag to ensure the Workers runtime supports Node.js APIs used by the framework. You should set this in your `wrangler.jsonc` file along with a recent `compatibility_date` (e.g., `"2024-01-01"`). This configuration ensures the Cloudflare adapter can correctly execute the SSR bundles and handle virtual imports like `sxo:routes` and `sxo:modules`.