Skip to content

React Router ​

This guide demonstrates how to deploy a React Router (formerly Remix.js) application to Cloudflare with Alchemy.

Create a new React Router Project ​

Start by creating new React Router project using the Cloudflare template.

NOTE

This template assumes you're using wrangler. We will adapt it to Alchemy (and learn some Alchemy concepts along the way).

sh
bun create cloudflare@latest my-react-router-app --framework=react-router
sh
npm create cloudflare@latest -- my-react-router-app --framework=react-router
sh
pnpm create cloudflare@latest my-react-router-app --framework=react-router
sh
yarn create cloudflare my-react-router-app --framework=react-router

Remove Unnecessary files ​

Cloudflare's React Router template uses wrangler.jsonc and wrangler types to generate types which are not used by Alchemy. Let's remove these.

sh
cd ./my-react-router-app
rm -rf worker-configuration.d.ts wrangler.jsonc

Install Dependenices ​

Now install the alchemy and cloudflare dependencies.

sh
bun add alchemy cloudflare
bun add -D @cloudflare/workers-types
sh
npm install alchemy cloudflare
bun install --save-dev @cloudflare/workers-types
sh
pnpm add alchemy cloudflare
pnpm add -D @cloudflare/workers-types
sh
yarn add alchemy cloudflare
yarn add -D @cloudflare/workers-types

Create alchemy.run.ts ​

alchemy.run.ts can be thought of as kinda like the wrangler.jsonc except in pure TypeScript code.

Let's create it and use the ReactRouter from alchemy/cloudflare to build and deploy our React Router project.

ts
/// <reference types="node" />

import alchemy from "alchemy";
import { ReactRouter } from "alchemy/cloudflare";

const app = await alchemy("my-react-router-app", {
  stage: process.env.USER ?? "dev",
  phase: process.argv.includes("--destroy") ? "destroy" : "up",
});

export const website = await ReactRouter("website", {
  main: "./workers/app.ts",
  command: "bun run build",
});

console.log({
  url: website.url,
});

await app.finalize();

Configure Alchemy Types ​

As mentioned, Alchemy does not use wrangler types to generate worker-configuration.d.ts types. Instead, types are inferred from your Alchemy code directly.

To configure this, first create ./workers/env.ts with the following content:

ts
import type { website } from "../alchemy.run.ts";

export type CloudflareEnv = typeof website.Env;

declare global {
  type Env = CloudflareEnv
}

declare module "cloudflare:workers" {
  namespace Cloudflare {
    export interface Env extends CloudflareEnv {}
  }
}

Then, update tsconfig.json to include ./workers/env.ts and @cloudflare/workers-types as global types:

json
{
  "files": [],
  "references": [
    { "path": "./tsconfig.node.json" },
    { "path": "./tsconfig.cloudflare.json" }
  ],
  "compilerOptions": {
    "checkJs": true,
    "verbatimModuleSyntax": true,
    "skipLibCheck": true,
    "strict": true,
    "noEmit": true,
    // register Alchemy and Cloudflare types globally
    "types": ["./workers/env.ts", "@cloudflare/workers-types"]
  }
}

Log in to Cloudflare ​

Before you can deploy, you need to authenticate by running wrangler login.

sh
bun wrangler login
sh
npx wrangler login
sh
pnpm wrangler login
sh
yarn wrangler login

TIP

Alchemy will by default try and use your wrangler OAuth token and Refresh Token to connect but see the Cloudflare Auth for other methods.

Deploy ​

Now we can run and deploy our Alchemy stack:

sh
bun ./alchemy.run
sh
npx tsx ./alchemy.run
sh
pnpm tsx ./alchemy.run
sh
yarn tsx ./alchemy.run

It will log out the URL of your new React Router website hosted on Cloudflare:

{
  url: "https://website.${your-sub-domain}.workers.dev",
}

Destroy ​

For illustrative purposes, let's destroy the Alchemy stack.

sh
bun ./alchemy.run.ts --destroy

You're done! Happy React-Router'ing 😎