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:
bun create astro@latest my-astro-app
cd my-astro-app
npm create astro@latest my-astro-app
cd my-astro-app
pnpm create astro@latest my-astro-app
cd my-astro-app
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:
bun add @astrojs/cloudflare
bun add -D alchemy cloudflare @cloudflare/workers-types
npm install @astrojs/cloudflare
npm install --save-dev alchemy cloudflare @cloudflare/workers-types
pnpm add @astrojs/cloudflare
pnpm add -D alchemy cloudflare @cloudflare/workers-types
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:
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:
/// <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:
/// <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:
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
.
bun wrangler login
npx wrangler login
pnpm wrangler login
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:
bun ./alchemy.run
npx tsx ./alchemy.run
pnpm tsx ./alchemy.run
yarn tsx ./alchemy.run
It should log out the URL of your deployed site:
{
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:
bun run dev
npm run dev
pnpm run dev
yarn run dev
The Astro dev server will start:
🚀 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):
bun ./alchemy.run --destroy
npx tsx ./alchemy.run --destroy
pnpm tsx ./alchemy.run --destroy
yarn tsx ./alchemy.run --destroy