SolidStart
SolidStart is a full-stack framework for building reactive web apps with SolidJS. Its API routes run on the server, which is where you call Prisma ORM to read from a Prisma Postgres database.
In this guide, you'll learn how to integrate Prisma ORM with a Prisma Postgres database in a SolidStart project from scratch. You can find a complete example of this guide on GitHub.
Begin by creating a new SolidStart app. In your terminal, run:
bunx create-solidpnpm create solidyarn create solidnpm init solid@latestUse the following options when prompted:
Next, navigate into your new project, install dependencies, and start the development server:
cd my-solid-prisma-app
bun install
bun run devcd my-solid-prisma-app
pnpm install
pnpm run devcd my-solid-prisma-app
yarn install
yarn devcd my-solid-prisma-app
npm install
npm run devOnce the dev server is running, open http://localhost:3000 in your browser. You should see the SolidStart welcome screen.
Clean up the default UI by editing the app.tsx file and replacing its content with the following code:
import "./app.css";
export default function App() {
return (
<main>
<h1>SolidStart + Prisma</h1>
</main>
);
}Once the dev server is running, open http://localhost:3000 in your browser. You should see the SolidStart welcome screen.
Clean up the default UI by editing the app.tsx file and replacing its content with the following code:
import "./app.css";
export default function App() {
return (
<main>
<h1>SolidStart + Prisma</h1>
</main>
);
}To get started with Prisma, you'll need to install a few dependencies:
bun add prisma@prev tsx @types/pg --devpnpm add prisma@prev tsx @types/pg --save-devyarn add prisma@prev tsx @types/pg --devnpm install prisma@prev tsx @types/pg --save-devbun add @prisma/client@7 @prisma/adapter-pg dotenv pgpnpm add @prisma/client@7 @prisma/adapter-pg dotenv pgyarn add @prisma/client@7 @prisma/adapter-pg dotenv pgnpm install @prisma/client@7 @prisma/adapter-pg dotenv pg[!NOTE] If you are using a different database provider (MySQL, SQL Server, SQLite), install the corresponding driver adapter package instead of
@prisma/adapter-pg. For more information, see Database drivers.
Once installed, initialize Prisma in your project:
Once installed, initialize Prisma in your project:
bunx --bun prisma init --output ../src/generated/prismapnpm prisma init --output ../src/generated/prismayarn prisma init --output ../src/generated/prismanpx prisma init --output ../src/generated/prisma[!NOTE]
prisma initcreates the Prisma scaffolding and a localDATABASE_URL. In the next step, you will create a Prisma Postgres database and replace that value with a directpostgres://...connection string.
This will create:
- A
prismadirectory with aschema.prismafile. - A
prisma.config.tsfile for configuring Prisma - A
.envfile containing a localDATABASE_URLat the project root. - An
outputdirectory for the generated Prisma Client assrc/generated/prisma.
Create a Prisma Postgres database and replace the generated DATABASE_URL in your .env file with the postgres://... connection string from the CLI output:
This will create:
- A
prismadirectory with aschema.prismafile. - A
prisma.config.tsfile for configuring Prisma - A
.envfile containing a localDATABASE_URLat the project root. - An
outputdirectory for the generated Prisma Client assrc/generated/prisma.
Create a Prisma Postgres database and replace the generated DATABASE_URL in your .env file with the postgres://... connection string from the CLI output:
bunx create-dbpnpm dlx create-dbyarn dlx create-dbnpx create-dbIn the prisma/schema.prisma file, add the following models and change the generator to use the prisma-client provider:
generator client {
provider = "prisma-client"
output = "../src/generated/prisma"
}
datasource db {
provider = "postgresql"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id])
} This creates two models: User and Post, with a one-to-many relationship between them.
To get access to the variables in the .env file, they can either be loaded by your runtime, or by using dotenv. Include an import for dotenv at the top of the prisma.config.ts
import "dotenv/config";
import { defineConfig, env } from "prisma/config";
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
},
datasource: {
url: env("DATABASE_URL"),
},
});2.4. Configure the Prisma Client generator
Section titled “2.4. Configure the Prisma Client generator”Now, run the following command to create the database tables and generate the Prisma Client:
bunx prisma migrate dev --name initpnpm prisma migrate dev --name inityarn prisma migrate dev --name initnpx prisma migrate dev --name initbunx prisma generatepnpm prisma generateyarn prisma generatenpx prisma generateAdd some seed data to populate the database with sample users and posts.
Create a new file called seed.ts in the prisma/ directory:
import { PrismaClient, Prisma } from "../src/generated/prisma/client.js";
import { PrismaPg } from "@prisma/adapter-pg";
const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL!,
});
const prisma = new PrismaClient({
adapter,
});
const userData: Prisma.UserCreateInput[] = [
{
name: "Alice",
email: "alice@prisma.io",
posts: {
create: [
{
title: "Join the Prisma Discord",
content: "https://pris.ly/discord",
published: true,
},
{
title: "Prisma on YouTube",
content: "https://pris.ly/youtube",
},
],
},
},
{
name: "Bob",
email: "bob@prisma.io",
posts: {
create: [
{
title: "Follow Prisma on Twitter",
content: "https://www.twitter.com/prisma",
published: true,
},
],
},
},
];
export async function main() {
for (const u of userData) {
await prisma.user.create({ data: u });
}
}
main();Now, tell Prisma how to run this script by updating your prisma.config.ts:
import "dotenv/config";
import { defineConfig, env } from "prisma/config";
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
seed: `tsx prisma/seed.ts`,
},
datasource: {
url: env("DATABASE_URL"),
},
});Run the seed script:
bunx prisma db seedpnpm prisma db seedyarn prisma db seednpx prisma db seedAnd open Prisma Studio to inspect your data:
bunx prisma studiopnpm prisma studioyarn prisma studionpx prisma studioAt the root of your project, create a new lib folder and a prisma.ts file inside it:
mkdir -p lib && touch lib/prisma.tsAdd the following code to create a Prisma Client instance:
import { PrismaClient } from "../src/generated/prisma/client.js";
import { PrismaPg } from "@prisma/adapter-pg";
const adapter = new PrismaPg({
connectionString: process.env.DATABASE_URL!,
});
const prisma = new PrismaClient({
adapter,
});
export default prisma;Next, fetch data from the database through an API route.
Create a new file at src/routes/api/users.ts:
import prisma from "../../../lib/prisma";
export async function GET() {
const users = await prisma.user.findMany({
include: {
posts: true,
},
});
return new Response(JSON.stringify(users), {
headers: { "Content-Type": "application/json" },
});
}In your app.tsx file, use createResource to fetch data from your new API route:
import "./app.css";
import { createResource } from "solid-js";
import { User, Post } from "./generated/prisma/client";
type UserWithPosts = User & {
posts: Post[];
};
const fetchUsers = async () => {
const res = await fetch("http://localhost:3000/api/users");
return res.json();
};
export default function App() {
const [users, { mutate, refetch }] = createResource<UserWithPosts[]>(fetchUsers);
return (
<main>
<h1>SolidStart + Prisma</h1>
</main>
);
}To show the users and their posts, use SolidJS's <For> component:
import "./app.css";
import { createResource, For } from "solid-js";
import { User, Post } from "./generated/prisma/client";
type UserWithPosts = User & {
posts: Post[];
};
const fetchUsers = async () => {
const res = await fetch("http://localhost:3000/api/users");
return res.json();
};
export default function App() {
const [users, { mutate, refetch }] =
createResource<UserWithPosts[]>(fetchUsers);
return (
<main>
<h1>SolidJS + Prisma</h1>
<For each={users() ?? []}>
{(user) => (
<div>
<h3>{user.name}</h3>
<For each={user.posts}>{(post) => <p>{post.title}</p>}</For>
</div>
)}
</For>
</main>
);
}Use SolidJS's <Show> component to handle loading and error conditions:
import "./app.css";
import { createResource, For, Show } from "solid-js";
import { User, Post } from "./generated/prisma/client";
type UserWithPosts = User & {
posts: Post[];
};
const fetchUsers = async () => {
const res = await fetch("http://localhost:3000/api/users");
return res.json();
};
export default function App() {
const [users, { mutate, refetch }] =
createResource<UserWithPosts[]>(fetchUsers);
return (
<main>
<h1>SolidJS + Prisma</h1>
<Show when={!users.loading} fallback={<p>Loading...</p>}>
<Show when={!users.error} fallback={<p>Error loading data</p>}>
<For each={users()}>
{(user) => (
<div>
<h3>{user.name}</h3>
<For each={user.posts}>{(post) => <p>{post.title}</p>}</For>
</div>
)}
</For>
</Show>
</Show>
</main>
);
}Your SolidStart app now reads users and their posts from a Prisma Postgres database through the API route.
Now that you have a working SolidStart app connected to a Prisma Postgres database, you can:
- Extend your Prisma schema with more models and relationships
- Add create/update/delete routes and forms
- Explore authentication, validation, and optimistic updates