Build a Full-Stack CRUD App with SvelteKit and Prisma
Introduction
This article demonstrates how to build a basic CRUD (Create, Read, Update, Delete) application using SvelteKit and Prisma. SvelteKit provides a powerful framework for building web applications, and Prisma simplifies database interactions.
Prerequisites
- Node.js and npm (or pnpm, or yarn) installed
- Basic knowledge of Svelte and SvelteKit
- Docker (optional, for local database)
Setting up the Project
-
Create a new SvelteKit project:
npm create svelte@latest my-crud-app cd my-crud-app npm install
-
Install Prisma:
npm install @prisma/client prisma --save-dev npx prisma init --datasource-provider postgresql
(Adjust the datasource-provider as needed, e.g.,
mysql
,sqlite
.) -
Update your
.env
file with the database URL. If you are using Docker, you can use something like:DATABASE_URL="postgresql://user:password@localhost:5432/mydb?schema=public"
-
Define your data model in
prisma/schema.prisma
. For example, a simpleTodo
model:generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" // or your chosen provider url = env("DATABASE_URL") } model Todo { id Int @id @default(autoincrement()) text String completed Boolean @default(false) createdAt DateTime @default(now()) }
-
Generate the Prisma client and run migrations:
npx prisma generate npx prisma migrate dev --name init
Building the API Endpoints (SvelteKit Routes)
Create API endpoints in src/routes/api/todos/+server.ts
(GET and POST) and src/routes/api/todos/[id]/+server.ts
(GET, PUT, DELETE):
src/routes/api/todos/+server.ts
(GET & POST)
import { json } from '@sveltejs/kit';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export async function GET() {
const todos = await prisma.todo.findMany();
return json(todos);
}
export async function POST({ request }) {
const { text } = await request.json();
const todo = await prisma.todo.create({
data: { text },
});
return json(todo, { status: 201 });
}
src/routes/api/todos/[id]/+server.ts
(GET, PUT & DELETE)
import { json, error } from '@sveltejs/kit';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export async function GET({ params }) {
const { id } = params;
const todo = await prisma.todo.findUnique({
where: { id: parseInt(id) },
});
if (!todo) {
throw error(404, 'Todo not found');
}
return json(todo);
}
export async function PUT({ params, request }) {
const { id } = params;
const { text, completed } = await request.json();
const todo = await prisma.todo.update({
where: { id: parseInt(id) },
data: { text, completed },
});
return json(todo);
}
export async function DELETE({ params }) {
const { id } = params;
await prisma.todo.delete({
where: { id: parseInt(id) },
});
return json({ success: true });
}
Creating the Svelte Frontend
-
Displaying Todos (
src/routes/+page.svelte
)<script> import { onMount } from 'svelte'; let todos = []; let newTodo = ''; async function fetchTodos() { const response = await fetch('/api/todos'); todos = await response.json(); } async function addTodo() { if (newTodo.trim() === '') return; const response = await fetch('/api/todos', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ text: newTodo }), }); if (response.ok) { newTodo = ''; await fetchTodos(); } } async function deleteTodo(id) { const response = await fetch(`/api/todos/${id}`, { method: 'DELETE', }); if (response.ok) { await fetchTodos(); } } onMount(fetchTodos); </script> <h1>Todo App</h1> <input bind:value={newTodo} placeholder="Add a todo" /> <button on:click={addTodo}>Add</button> <ul> {#each todos as todo (todo.id)} <li> {todo.text} <button on:click={() => deleteTodo(todo.id)}>Delete</button> </li> {/each} </ul>
Running the Application
-
Start your SvelteKit development server:
npm run dev -- --open
Conclusion
This example provides a basic CRUD application using SvelteKit and Prisma. You can expand upon this foundation by adding features like editing todos, marking them as complete, and implementing user authentication. Remember to handle errors gracefully and add proper validation.