Database, Nuxt··x·x

Connect a Turso DB to Your Nuxt Project with Drizzle

Elevate your Nuxt application by connecting it to a Turso database with Drizzle ORM for efficient data management and querying.

Introduction

This guide is part of the DB series on the Foundry, focusing on Nuxt and compatible databases and ORMs. We'll walk through connecting a Turso database to your Nuxt project using Drizzle as the ORM.

Before starting, set up your Turso DB and obtain your database tokens. You'll need the token and database URL for your .env file later.

Click here to start setting up a new Turso DB

You can also find the complete code on GitHub if you prefer.

Setup

Step 1: Create a new Nuxt project

Open a terminal and run:

pnpm dlx nuxi@latest init <your-project-name>

Step 2: Install dependencies

Install the necessary packages:

pnpm add drizzle-orm @libsql/client drizzle-kit
pnpm add -D @nuxtjs/tailwindcss

Step 3: Set up environment variables

Create a .env file in your project root with the following content:

TURSO_DB_URL=
TURSO_DB_AUTH_TOKEN=

Backend Configuration

Step 4: Create server folders

Create the following folder structure in your project root:

  • server
    • utils
    • database

Step 5: Configure database connection

Create server/utils/db.ts:

import { drizzle } from "drizzle-orm/libsql";
import { createClient } from "@libsql/client";

export const database = createClient({
  url: process.env.DATABASE_URL!,
  authToken: process.env.DATABASE_AUTH_TOKEN!,
});

export const orm = drizzle(database);

Step 6: Define database schema

Create server/database/schema.ts:

import { InferModel } from 'drizzle-orm'
import { sqliteTable, text, integer, unique } from 'drizzle-orm/sqlite-core'

export const tickets = sqliteTable('messages', {
  id: integer('id').primaryKey(),
  name: text('name').notNull(),
  email: text('email').notNull(),
  body: text('body').notNull()
})

export type Ticket = InferModel<typeof tickets>;
export type InsertTicket = InferModel<typeof tickets, "insert">;
Note: InferModel from drizzle-orm is deprecated. Replace it with a more up-to-date method for production use.

Steps 7-8: Set up API routes

Create the following folder structure:

  • server
    • api
      • tickets

Step 9: Implement GET endpoint

Create server/api/tickets/index.get.ts:

import { tickets } from "../../database/schema";
import { orm } from "../../utils/db";

export default defineEventHandler(async () => {
  try {
    const allTickets = orm.select().from(tickets).all();
    return { "tickets" : allTickets}
  } catch (e: any) {
    throw createError({
      statusCode: 400,
      statusMessage: e.message,
    });
  }
});

Step 10: Implement POST endpoint

Create server/api/tickets/createTicket.post.ts:

import { tickets, InsertTicket } from "../../database/schema";
import { orm } from "../../utils/db";

export default defineEventHandler(async (event) => {
  try {
    const body = await readBody(event);
    const newTicket: InsertTicket = {
      ...body
    }
    const result = orm.insert(tickets).values(newTicket).run();
    return { newTicket : result}
  } catch (e: any) {
    throw createError({
      statusCode: 400,
      statusMessage: e.message,
    });
  }
});

Step 11 (Optional): Implement DELETE endpoint

Create server/api/tickets/deleteById/[...id].ts:

import { tickets } from "../../../database/schema";
import { orm } from "../../../utils/db";
import { eq } from "drizzle-orm";

export default defineEventHandler(async (event) => {
  try {
    const ticketId = event.context.params?.id as string;
    if(!ticketId) throw createError({
      statusCode: 400,
      statusMessage: "Ticket ID is required",
    });
    const allTickets = orm
      .delete(tickets)
      .where(eq(tickets.id, parseInt(ticketId)))
      .run();
    return { tickets: allTickets };
  } catch (e: any) {
    throw createError({
      statusCode: 400,
      statusMessage: e.message,
    });
  }
});

Database Deployment

Step 12: Configure Drizzle

Create drizzle.config.ts in your project root:

import type { Config } from "drizzle-kit";

export default {
  schema: "./server/utils/db/schema.ts",
  driver: "turso",
  dbCredentials: {
    url: process.env.TURSO_DB_URL as string,
    authToken: process.env.TURSO_DB_AUTH_TOKEN as string,
  },
} satisfies Config;

Step 13: Push schema to Turso

Run the following command:

pnpm drizzle-kit push:sqlite --config=drizzle.config.ts

Frontend Implementation

Step 14: Update app.vue

Edit app.vue:

<template>
  <div>
    <NuxtPage />
  </div>
</template>

Step 15: Create index page

Create pages/index.vue with a form to create new tickets.

Step 16: Create tickets page

Create pages/tickets.vue to display all tickets.

Conclusion

You've now successfully connected a Turso database to your Nuxt project using Drizzle! This setup provides a solid foundation for building database-driven applications with Nuxt.

Remember to replace relative paths in API endpoints with '~' for better maintainability.

For the complete implementation and more details, check out the GitHub repository.


Services

Copyright © 2024. All rights reserved.