Deploy to Cloudflare Workers

Shapeless can be deployed to Cloudflare Workers, giving you a globally distributed, serverless runtime for your API. This guide walks you through the deployment.


Prerequisites

Everything is mostly setup and no need to actually set up much

  1. Install the Wrangler CLI:
npm install -g wrangler@latest
  1. Have a Cloudflare account: https://www.cloudflare.com/

Deployment Steps

  • Push your Shapeless project to GitHub.
  • Set up a Cloudflare Pages project connected to your repo.
  • Choose the OpenNext framework preset.
  • Cloudflare Pages will build and deploy your app automatically on every push.

2. Deploy locally using provided scripts

You can also deploy manually using Shapeless’s helper scripts which handle OpenNext build and deployment:

pnpm cf:build    # Builds your app for Cloudflare Workers
pnpm cf:deploy   # Deploys the built app to Cloudflare Workers

These scripts wrap Wrangler but also run the Next.js build process required for OpenNext.


Update your client

After deployment, update your API client to point to your deployed Worker URL:

// @/shapeless.client.ts
import type { AppRouter } from "@/resources/index"
import { createClient } from "shapeless"
 
export const client = createClient<AppRouter>({
  baseUrl: `${getBaseUrl()}/api`,
})
 
function getBaseUrl() {
  if (process.env.NODE_ENV === "production") {
    return "https://<YOUR_DEPLOYMENT>.workers.dev"
  }
  return "http://localhost:8787"
}

Environment Variables

Add environment variables to your Worker using Wrangler:

wrangler secret put <KEY>

For bulk updates, see Wrangler secret bulk commands.


Common Issues

CORS Configuration

If you experience CORS problems, verify your Worker is configured with CORS middleware correctly:

// resources/index.ts
import { app } from "./shapeless"
import { postRouter } from "./routers/post-router"
 
const api = app
  .router()
  .basePath("/api")
  .use(app.defaults.cors)
  .onError(app.defaults.errorHandler)
 
const appRouter = app.mergeRouters(api, {
  post: postRouter,
})
 
export type AppRouter = typeof appRouter
 
export default appRouter

→ More on CORS handling