Integrating Turso and Drizzle: A Comprehensive Guide
Written on
Chapter 1: Introduction to Turso and Drizzle
Setting up Turso and Drizzle has never been easier. After PlanetScale discontinued its free tier, many developers, myself included, sought alternative database solutions that work seamlessly with Drizzle ORM. This led me to Turso DB, a scalable SQLite-based database that not only fills the gaps left by PlanetScale but also offers enhanced compatibility with Drizzle, easy setup, and additional features.
Let’s get started with the setup process!
Table of Contents
- Setting Up a Next.js 14 Project
- Installing Dependencies
- Configuring Turso
- Integrating Turso with Drizzle
- Testing in Next.js
Section 1.1: Setting Up a Next.js 14 Project
To initiate a Next.js project, follow the instructions available on the official website. Typically, you will execute the following command in your terminal:
Section 1.2: Installing Dependencies
Open your terminal in the project directory and run one of the following commands to install the required dependencies:
npm install drizzle-orm drizzle-kit @libsql/client dotenv
yarn add drizzle-orm drizzle-kit @libsql/client dotenv
pnpm add drizzle-orm drizzle-kit @libsql/client dotenv
bun add drizzle-orm drizzle-kit @libsql/client dotenv
Section 1.3: Configuring Turso
Before diving into Next.js, we first need to:
- Create a Turso database.
- Acquire the necessary environment variables.
Open your UNIX terminal and run the following command (note: this will not work on Windows):
For Windows users, you will need to install WSL to run a Linux environment.
For additional guidance, refer to the article linked below:
- After Turso is installed, authenticate yourself to create and manage databases:
turso auth signup
For WSL users, you can use the headless option to simplify authentication:
turso auth signup --headless
- Once authenticated, create a new database with the following command:
turso db create [database-name]
You can list your created databases with:
turso db list
- Generate the required environment variables, including the database URL and authentication token:
turso db list # Copy the "URL" value.
turso db tokens create [database-name] -e # Prevent token expiry.
- In your Next.js project, create a file named .env.local and paste your environment variables:
# Turso
TURSO_DATABASE_URL=
TURSO_AUTH_TOKEN=
Chapter 2: Integrating Turso with Drizzle
To integrate Turso with Drizzle, create a drizzle-config.ts file in the root of your project containing the following code:
// drizzle.config.ts
import dotenv from "dotenv"
import type { Config } from "drizzle-kit"
dotenv.config({ path: ".env.local" })
export default {
schema: "./src/db/schema.ts",
out: "./src/db/migrations",
dbCredentials: {
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!,
},
driver: "turso",
} satisfies Config
Next, create the database instance for use throughout your Next.js application:
// src/db/index.ts
import { createClient } from "@libsql/client"
import { drizzle } from "drizzle-orm/libsql"
const turso = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN,
})
export const db = drizzle(turso)
export type DbClient = typeof db
Optionally, you may update your package.json to include scripts for managing database migrations:
"scripts": {
"generate": "drizzle-kit generate:sqlite",
"push": "drizzle-kit push:sqlite",
"drop": "drizzle-kit drop"
},
Chapter 3: Testing in Next.js
Congratulations! You have successfully configured Turso and Drizzle within a Next.js application. Let’s create a simple posts schema to test our setup:
// src/db/schema.ts
import { randomUUID } from "crypto"
import { sqliteTable, text } from "drizzle-orm/sqlite-core"
export const posts = sqliteTable("posts", {
id: text("id", { length: 255 })
.notNull()
.primaryKey()
.$defaultFn(() => randomUUID()),
title: text("title").notNull(),
content: text("content").notNull(),
})
Next, develop server actions to handle retrieving and adding posts:
// src/app/_actions/postActions.ts
"use server"
import { db } from "@/db"
import { posts } from "@/db/schema"
import { InferSelectModel } from "drizzle-orm"
import { revalidatePath } from "next/cache"
export type Post = InferSelectModel
export const getPosts = async () => {
return await db.select().from(posts)
}
export const addPost = async ({ title, content }: Post) => {
await db.insert(posts).values({ title, content })
revalidatePath("/")
}
Finally, create the frontend code to display and submit posts:
import { getPosts, addPost, Post } from "./_actions/postActions"
export default async function Home() {
async function submitPost(formData: FormData) {
"use server"
const title = formData.get("title")
const content = formData.get("content")
await addPost({ title, content } as Post)
}
return (
<div>
<h1>Posts:</h1>
{(await getPosts()).map((post) => (
<div key={post.id}>
<h2>Title: {post.title}</h2>
<p>Content: {post.content}</p>
</div>
))}
<form onSubmit={submitPost}>
<input name="title" placeholder="Title" required />
<textarea name="content" placeholder="Content" required />
<button type="submit">Add Post</button>
</form>
</div>
)
}
Here’s a visual representation of the application:
If you found this guide helpful, don’t forget to subscribe, like, and connect with me! 🌐
Featured Articles
- Figma Home: The UI design tool for all your projects.
- Figma Professional: The essential UI design tool.
- FigJam: Intuitive diagramming and brainstorming.
- Notion: The ultimate organization tool.
- Notion AI: The AI tool to supercharge your Notion workflow.
References
Chapter 4: Additional Resources
Explore the easiest way to set up a database in Next.js 14 with Turso and Drizzle in this informative video.
Learn how to master Drizzle ORM in just 60 minutes with this quick tutorial.