SvelteKit & Prisma - A match made in digital heaven
Key Takeaways
- Most production applications need to persist & retrieve data. Prisma is a pretty genius way to achieve that.
- With SvelteKit, you get client & server-side data fetching - the best of both worlds.
- This all even works if JavaScript is disabled in the browser.
- Template GitHub repo: https://github.com/mootoday/sveltekit-prisma
đŁÂ SvelteKit & Prisma video course
Hold on a sec â! Josh Nussbaum created a 33-lesson video course all about the topic you are interested in - SvelteKit & Prisma.
If this is of interest to you, read my summary below and head over to Joshâs course to dive deeper.
What are you going to learn?
We are going to start with a default SvelteKit application. Once initialized, we will learn how to install and configure Prisma before we will use the PrismaClient to perform create, read, update & delete (CRUD) actions against a local SQLite database.
Things you need to know
In order to get the most out of this post, I expect you are aware of the following technologies:
The foundation
Letâs start with the basics: A SvelteKit demo app.
I recommend you first create a GitHub, GitLab or Bitbucket project and start a development environment with Gitpod. Alternatively, you can follow along on your local computer.
npm init svelte@next svelte-with-prisma
When prompted, select the following options:
- âWhich Svelte app template?â
SvelteKit demo app
- âUse TypeScript?â
Yes
- âAdd ESLint for code linting?â
No
- âAdd Prettier for code formatting?â
Yes
When complete, please follow the âNext stepsâ listed in the terminal to install dependencies and start the SvelteKit demo app.
If youâve followed along so far, you can copy & paste the following commands:
cd svelte-with-prisma
npm install
npm run dev -- --open
Thatâs how quickly you get started with SvelteKit. In your browser, you notice the âTODOSâ navigation item. If you play with this list, items are persisted on svelte.dev and deleted after a while.
Next, we are going to add Prisma to persist todo items in a local SQLite database.
Add Prisma
Prisma.io states âPrisma helps app developers build faster and make fewer errors with an open source ORM for PostgreSQL, MySQL and SQLite.â
From my personal experience, this statement is certainly true. Letâs go and experience it for yourself.
Install & initialize Prisma
First things first: npm i -D prisma
because, well⊠without dependencies we wonât get very far đ.
Next, we are going to initialize Prisma. For that, we use npx
to execute commands.
npx prisma init
â ïž This currently overwrites an existing
.gitignore
file. Keep an eye on 8496.
This creates a prisma
directory at the root of the project. In it, you find the schema.prisma
file.
At this point, I recommend you install the prisma.prisma
VS Code extension. It adds syntax highlighting, formatting, auto-completion, jump-to-definition and linting for .prisma
files.
Define the Todo
model
Open the prisma/schema.prisma
file and add the following model definition to the end of the file:
model Todo {
uid String @id @default(cuid())
created_at DateTime
text String
done Boolean
}
Psst⊠How do we know what fields to define? Well, we take a peek at the Todo
type definition in src/routes/todos/index.svelte
đ.
Configure a SQLite database
Open the .env
file (that file was created by the npx prisma init
command earlier). In it, set the DATABASE_URL
to "file:./dev.db"
We also have to open the prisma/schema.prisma
file to update the datasource.db.provider
to sqlite
.
Check the reference docs for more details on the above two values and what other databases are supported.
Create the database and tables
Weâre making great progress! Letâs now use the Prisma CLI to create our SQLite database and create a schema based on the Todo
model we defined earlier.
Itâs easy:
npx prisma db push
Give that five seconds âł.
I recommend you read through the console output, I find it highly interesting. For one, it gives us a good deal of detail about whatâs going on. However, it also contains the following output which is one of the reasons Iâm mind-blown by Prisma:
â Generated Prisma Client (2.28.0) to ./node_modules/@prisma/client
So much goodness! Basically, they use the Todo
model to auto-generate a bunch of TypeScript definitions and Javascript code which we are going to import in just a second. In other words, the âPrisma helps app developers build faster and make fewer errorsâ sentence on the Prisma website is not just some marketing speech, it is truly genius!
Ok, Iâm done being a fanboy about it, letâs move on and thanks for your patience there with me đ .
One last thing, please add prisma/dev.db
to your .gitignore
file since we donât want to commit the dev database to version control.
Use the PrismaClient
to interact with the database
The SvelteKit demo app nicely encapsulates all API features in the src/routes/todos/_api.ts
file. To be more precise, the actual CRUD logic happens at https://api.svelte.dev/todos. We are going to modify the _api.ts
file slightly to deal with CRUD right there and use the PrismaClient
instead of delegating to a backend API.
Move the Todo
type so we can reuse it
First and foremost, letâs move the Todo
Typescript type. By default, itâs defined and used in the src/routes/todos/index.svelte
file. However, with the changes weâre going to make to the API, we are also going to need that type in the src/routes/todos/_api.ts
file.
- Cut the
Todo
type fromsrc/routes/todos/index.svelte
- Paste it below the
import
statements insrc/routes/todos/_api.ts
, and prefix it withexport
- Use the following import in the
src/routes/todos/index.svelte
file:import type { Todo } from "./_api";
Update the API to use Prisma
Open the src/routes/todos/_api.ts
file and add the following import:
import { PrismaClient } from '@prisma/client';
Remember? Thatâs the generated code I was so excited about earlier đ.
Next, we need a new instance of the PrismaClient
(add this below the import
statements):
const prisma = new PrismaClient();
Moving right along, itâs time to update the api
method signature to tell Typescript that the data
parameter is of type Todo
.
export async function api(request: Request<Locals>, resource: string, data?: Todo) {
The following code:
const res = await fetch(`${base}/${resource}`, {
method: request.method,
headers: {
'content-type': 'application/json'
},
body: data && JSON.stringify(data)
});
needs to be replaced with this:
let body = {};
let status = 500;
switch (request.method.toUpperCase()) {
case 'DELETE':
await prisma.todo.delete({
where: {
uid: resource.split('/').pop()
}
});
status = 200;
break;
case 'GET':
body = await prisma.todo.findMany();
status = 200;
break;
case 'PATCH':
body = await prisma.todo.update({
data: {
done: data.done,
text: data.text
},
where: {
uid: resource.split('/').pop()
}
});
status = 200;
break;
case 'POST':
body = await prisma.todo.create({
data: {
created_at: new Date(),
done: false,
text: data.text
}
});
status = 201;
break;
}
Weâre getting there đȘ. In the if
statement right below the code weâve just added, remove the res.ok &&
since we no longer have a res
variable.
Lastly, change the return
statement to the following:
return {
status,
body
};
Letâs test
Start your SvelteKit demo app with npm run dev
and navigate to http://localhost:3000 in your browser. If you use Gitpod, hold CTRL / CMD pressed and click on the http://localhost:3000 URL in the terminal, itâll open a new browser window with the SvelteKit demo app.
Click on the âTODOSâ navigation link and add a few todos, rename some, mark others as done.
In a new terminal, open the Prisma Studio with npx prisma studio
. The studio opens in a new browser tab. Click on the Todo
model and validate that the data matches what you see in the SvelteKit demo app.
Congratulations đ!
Bonus - definitely read this
Disable JavaScript in your browser and test the todo list again. This is how the web is supposed to work - without JavaScript!
We used to develop websites like that, then we spent a decade thinking itâs a great idea to move everything into JavaScript and thanks to Svelte & SvelteKit, we now once again develop web applications that work the way the web was intended to work.
JavaScriptâs purpose is to enhance the web experience, not break everything if JavaScript is disabled.
Conclusion
With a few modifications to a default SvelteKit demo app, we managed to configure Prisma to persist todo items. There is of course a lot more you can do with Prisma, and with SvelteKit for that matter. The source code at https://github.com/mootoday/sveltekit-prisma should get you a long way towards your own web app.
If you found this interesting, you may also like (wow⊠is this an e-commerce website đ?!) my current project called Webstone. Webstone is a full-stack web application boilerplate with a CLI to automate tedious tasks like adding new pages, updating the database (of course it uses Prisma đ). Itâs in early development, but do hit that star button on GitHub which helps me get motivated to spend more time on the project đ.
đ