Skip to content

Astro

This guide demonstrates how to deploy an Astro application with server-side rendering to Cloudflare using Alchemy.

Create a new Astro Project

Start by creating a new Astro project:

sh
bun create astro@latest my-astro-app
cd my-astro-app
sh
npm create astro@latest my-astro-app
cd my-astro-app
sh
pnpm create astro@latest my-astro-app
cd my-astro-app
sh
yarn create astro@latest my-astro-app
cd my-astro-app

When prompted:

  • Choose "Just the basics" template
  • Select "Yes" for TypeScript
  • Choose "Strictest" for TypeScript configuration
  • Select "Yes" for install dependencies
  • Select "No" for git repository (we'll handle this separately)

Install Cloudflare Adapter

Install the Cloudflare adapter and Alchemy dependencies:

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

Configure Astro for Cloudflare

Update your astro.config.mjs to use the Cloudflare adapter:

js
import { defineConfig } from 'astro/config';
import cloudflare from '@astrojs/cloudflare';

// https://astro.build/config
export default defineConfig({
  output: 'server',
  adapter: cloudflare(),
});

Create alchemy.run.ts

Create alchemy.run.ts to configure your deployment using Alchemy's Astro resource:

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

import alchemy from "alchemy";
import { Astro, KVNamespace, R2Bucket } from "alchemy/cloudflare";

const app = await alchemy("cloudflare-astro", {
  phase: process.argv.includes("--destroy") ? "destroy" : "up",
});

// Create some Cloudflare resources for your app
export const [storage, cache] = await Promise.all([
  R2Bucket("astro-storage", {
    allowPublicAccess: false,
  }),
  KVNamespace("CACHE", {
    title: "astro-cache",
  }),
]);

export const website = await Astro("astro-website", {
  command: "bun run build",
  bindings: {
    STORAGE: storage,
    CACHE: cache,
  },
});

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

await app.finalize();

Configure Alchemy Types

Create src/env.d.ts to properly type your Cloudflare bindings:

ts
/// <reference types="astro/client" />

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

type CloudflareEnv = typeof website.Env;

declare namespace App {
  interface Locals extends CloudflareEnv {}
}

Add an API Route

Create src/pages/api/hello.ts to demonstrate server-side functionality:

ts
import type { APIRoute } from 'astro';

export const GET: APIRoute = async ({ request }) => {
  // Access Cloudflare runtime context
  const runtime = request.cf;
  
  return new Response(JSON.stringify({
    message: "Hello from Astro API on Cloudflare!",
    timestamp: new Date().toISOString(),
    colo: runtime?.colo || "unknown",
    country: runtime?.country || "unknown",
    city: runtime?.city || "unknown",
  }), {
    status: 200,
    headers: {
      'Content-Type': 'application/json',
    },
  });
};

Login 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

Run alchemy.run.ts script to deploy:

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

It should log out the URL of your deployed site:

sh
{
  url: "https://your-site.your-sub-domain.workers.dev",
}

Click the endpoint to see your site! Try visiting /api/hello to see the API endpoint in action.

Local Development

Run the Astro development server:

sh
bun run dev
sh
npm run dev
sh
pnpm run dev
sh
yarn run dev

The Astro dev server will start:

sh
🚀  astro  v5.1.3 ready in 892 ms

 Local    http://localhost:4321/
 Network  use --host to expose

 Watch mode enabled! Edit a file to see changes.

TIP

For production-like local development with Cloudflare Workers, you can use wrangler dev after building your Astro site.

Tear Down

That's it! You can now tear down the app (if you want to):

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