RedwoodJS on Cloudflare Example
This example demonstrates deploying a RedwoodJS full-stack application to Cloudflare with D1 database integration.Features
- RedwoodJS: Full-stack React framework
- D1 Database: SQLite database at the edge
- Drizzle Migrations: Type-safe database schema
- Local Development: Integrated dev server
Project Setup
import alchemy from "alchemy";
import { D1Database, Redwood } from "alchemy/cloudflare";
const app = await alchemy("cloudflare-redwood");
const database = await D1Database("database", {
name: `${app.name}-${app.stage}-db`,
migrationsDir: "drizzle",
adopt: true,
});
export const website = await Redwood("website", {
name: `${app.name}-${app.stage}-website`,
adopt: true,
bindings: {
DB: database,
},
dev: {
command: "vite dev --port 5004",
},
});
console.log({
url: website.url,
});
await app.finalize();
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core";
export const posts = sqliteTable("posts", {
id: integer("id").primaryKey({ autoIncrement: true }),
title: text("title").notNull(),
body: text("body").notNull(),
createdAt: integer("created_at", { mode: "timestamp" }).notNull(),
});
CREATE TABLE posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
body TEXT NOT NULL,
created_at INTEGER NOT NULL
);
import { db } from 'src/lib/db';
import { posts } from '../../../drizzle/schema';
export const posts = async () => {
return await db.select().from(posts);
};
export const post = async ({ id }: { id: number }) => {
return await db.select().from(posts).where(eq(posts.id, id)).get();
};
export const createPost = async (input: {
title: string;
body: string;
}) => {
return await db.insert(posts).values({
...input,
createdAt: new Date(),
}).returning().get();
};
import { drizzle } from 'drizzle-orm/d1';
import { context } from '@redwoodjs/graphql-server';
export const db = drizzle(context.env.DB);
export const schema = gql`
type Post {
id: Int!
title: String!
body: String!
createdAt: DateTime!
}
type Query {
posts: [Post!]! @skipAuth
post(id: Int!): Post @skipAuth
}
type Mutation {
createPost(title: String!, body: String!): Post! @skipAuth
}
`;