This Todo App is a project demonstrating the creation of an end-to-end type-safe web application quickly and cost-effectively by combining tRPC, Drizzle, Cloudflare Pages, Cloudflare Pages Functions, and Cloudflare D1.
- Host static content built by Vite on Cloudflare Pages
- Implement serverless functions for API endpoints using Cloudflare Pages Functions
- Utilize tRPC for type-safe communication between backend and frontend
- Use Cloudflare D1 as a lightweight, SQLite-based database solution
- Use Drizzle as a ORM and migration generator
- Node.js (v18 or higher)
- Cloudflare account
-
Create a repository from this template repository using the GitHub CLI
gh repo create todo-demo --clone --public --template toyamarinyon/trpc-d1-todo cd todo-demo
-
Instal dependencies
npm install
Note I prefer pnpm over npm but Cloudflare Pages builds do not yet support pnpm.
-
Expose your database name
Replace
<DATABASE_NAME>
to your database name. It will be use by following steps.DEMO_DATABASE_NAME=<DATABASE_NAME>
-
Create your database
Run the following command and give your database a name:
npx wrangler d1 create $DEMO_DATABASE_NAME
-
Configure database binding with wrangler.toml
You need to configure database binding to run it and test it locally with wrangler.toml
Add the following to your wrangler.toml file:
[[ d1_databases ]] binding = "<BINDING_NAME>" database_name = "<DATABASE_NAME>" database_id = "<UUID>"
Set your binding name by updating the <BINDING_NAME> value. Your binding is available in your Cloudflare Pages Functions at env.<BINDING_NAME>. You will find the values for database_name and database_id in your terminal after you run the create command in step 4.
-
Create table against your local database
Cloudflare D1 provides migration tools. You can use it to check list of unapplied migrations:
npx wrangler d1 migrations list $DEMO_DATABASE_NAME --local
Then you can see the following:
┌────────────────────────────┐ │ Name │ ├────────────────────────────┤ │ 0000_dusty_dragon_lord.sql │ └────────────────────────────┘
This migration creates a
tasks
table and inserts three tasks.$ cat migrations/0000_dusty_dragon_lord.sql CREATE TABLE tasks ( `id` integer PRIMARY KEY NOT NULL, `title` text NOT NULL, `description` text NOT NULL, `completion_at` integer ); INSERT INTO tasks (title, description) VALUES ('Buy milk', 'Buy milk from the store'), ('Buy eggs', 'Buy eggs from the store'), ('Buy bread', 'Buy bread from the store');
And you can use the following to apply any unapplied migrations:
npx wrangler d1 migrations apply $DEMO_DATABASE_NAME --local
Then validate your data is in your database by running:
npx wrangler d1 execute $DEMO_DATABASE_NAME --local --command='SELECT * FROM tasks'
You'll see the following:
┌────┬───────────┬──────────────────────────┬───────────────┐ │ id │ title │ description │ completion_at │ ├────┼───────────┼──────────────────────────┼───────────────┤ │ 1 │ Buy milk │ Buy milk from the store │ │ ├────┼───────────┼──────────────────────────┼───────────────┤ │ 2 │ Buy eggs │ Buy eggs from the store │ │ ├────┼───────────┼──────────────────────────┼───────────────┤ │ 3 │ Buy bread │ Buy bread from the store │ │ └────┴───────────┴──────────────────────────┴───────────────┘
This completes the creation of the local database. Now let's run the ToDo application locally.
-
Run locally with Wrangler
To run Cloudflare Pages locally, use the
wrangler pages dev
command; to run Cloudflare D1 as well, add the three options--local
,--persist
, and--d1=<DATABASE_NAME>
.Then add
npm run dev
to the end of the command to integrate Cloudflare Pages and Vite's dev server.npx wrangler pages dev --local --persist --d1=$DEMO_DATABASE_NAME -- npm run dev
This will then start serving your Pages project. You can press B to open the browser on your local site 🎉
-
Log in to the Cloudflare dashboard.
-
Select your account in Account Home > Pages.
-
Select Create a project > Connect to Git.
-
Select your new GitHub repository.
-
In the Set up builds and deployments, set
npm run build
as the Build command, anddist
as the Build output directory. -
Select Environment variables (advanced) > + Add variable > configure a
NODE_VERSION
variable with17
. -
The deployment will succeed, but database binding is not yet, so setting it is.
- Show Settings tab.
- Select Functions menu.
- Select D1 database bindings > Add binding > configure a
DB
variable with a value of<DATABASE_NAME>
-
Redeploy the latest deployment to apply the above settings.
-
Migrate the D1 database on Cloudflare
Show unapplied migrations as list:
npx wrangler d1 migrations list $DEMO_DATABASE_NAME
Then apply them:
npx wrangler d1 migrations apply $DEMO_DATABASE_NAME
Open the page, you'll be able to see ToDo App on Cloudflare.
-
Tutorial on changing table schema
Demonstrating how to add columns to the table with Drizzle.