diff --git a/content/800-guides/180-solid-start.mdx b/content/800-guides/180-solid-start.mdx new file mode 100644 index 0000000000..db872ba19f --- /dev/null +++ b/content/800-guides/180-solid-start.mdx @@ -0,0 +1,438 @@ +--- +title: 'How to use Prisma ORM with SolidStart' +metaTitle: 'How to use Prisma ORM and Prisma Postgres with SolidStart' +description: 'Learn how to use Prisma ORM in a SolidStart app' +sidebar_label: 'Set up SolidStart with Prisma ORM' +image: '/img/guides/prisma-solid-start-cover.png' +completion_time: '10 min' +community_section: true +--- + +## Introduction + +Prisma ORM streamlines database access with type-safe queries and a smooth developer experience. SolidStart, a modern framework for building reactive web apps with SolidJS, pairs well with Prisma and Postgres to create a clean and scalable full-stack architecture. + +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](https://github.com/prisma/prisma-examples/tree/latest/orm/solid-start). + +--- + +## Prerequisites + +Before getting started, make sure you have the following installed: + +- **Node.js 18+** installed + +--- + +## Step 1: Set Up a SolidStart Project + +Begin by creating a new SolidStart app. In your terminal, run: + +```terminal +npm init solid@latest +``` + +:::info +Use the following options when prompted: + +- **Project name:** `my-solid-prisma-app` *(or any name you prefer)* +- **Is this a SolidStart project:** `yes` +- **Template:** `bare` +- **Use TypeScript:** `yes` +::: + +Next, navigate into your new project, install dependencies, and start the development server: + +```terminal +cd my-solid-prisma-app +npm install +npm run dev +``` + +Once the dev server is running, open `http://localhost:3000` in your browser. You should see the SolidStart welcome screen. + +Let's clean up the default UI by editing the `app.tsx` file and replacing the header: + +```typescript file=src/app.tsx +//delete-next-line +import { createSignal } from "solid-js"; +import "./app.css"; + +export default function App() { +//delete-next-line + const [count, setCount] = createSignal(0); + + return ( +
+ //add-next-line +

SolidStart + Prisma

+ //delete-next-line +

Hello world!

+ //delete-start + +

+ Visit{" "} + + start.solidjs.com + {" "} + to learn how to build SolidStart apps. +

+ //delete-end +
+ ); +} +``` + +Your `app.tsx` file should now look like this: + +```typescript file=src/app.tsx +import "./app.css"; + +export default function App() { + return ( +
+

SolidStart + Prisma

+
+ ); +} +``` + +--- + +## Step 2: Install and Initialize Prisma + +To get started with Prisma, you'll need to install a few dependencies: + +```terminal +npm install prisma --save-dev +npm install tsx --save-dev +npm install @prisma/extension-accelerate +``` + +:::info +If you're not using a Prisma Postgres database, you can skip `@prisma/extension-accelerate`. +::: + +Once installed, initialize Prisma in your project: + +```terminal +npx prisma init --db +``` + +This will create: + +- A `prisma/` directory with a `schema.prisma` file +- A `.env` file with a `DATABASE_URL` already set + +--- + +### Step 2.1: Define Your Prisma Schema + +Open the `prisma/schema.prisma` file and add the following models: + +```prisma file=prisma/schema.prisma +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. + +Now, run the following command to create the database tables and generate the Prisma Client: + +```terminal +npx prisma migrate dev --name init +``` + +--- + +### Step 2.2: Seed the Database + +Let's add some seed data to populate the database with sample users and posts. + +Create a new file called `seed.ts` in the `prisma/` directory: + +```typescript file=prisma/seed.ts +import { PrismaClient, Prisma } from "@prisma/client"; + +const prisma = new PrismaClient(); + +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 `package.json`: + +```json file=package.json +"prisma": { + "seed": "tsx prisma/seed.ts" +} +``` + +Run the seed script: + +```terminal +npx prisma db seed +``` + +And open Prisma Studio to inspect your data: + +```terminal +npx prisma studio +``` + +--- + +## Step 3: Use Prisma Client in Your Application + +### Step 3.1: Create a Prisma Client + +At the root of your project, create a new `lib` folder and a `prisma.ts` file inside it: + +```terminal +mkdir -p lib && touch lib/prisma.ts +``` + +Add the following code to create a Prisma Client instance: + +```typescript file=lib/prisma.ts +import { PrismaClient } from "@prisma/client"; +import { withAccelerate } from "@prisma/extension-accelerate"; + +const prisma = new PrismaClient().$extends(withAccelerate()); + +export default prisma; +``` + +:::info +If you're not using Prisma Postgres, remove `.$extends(withAccelerate())`. +::: + +--- + +### Step 3.2: Create an API Route + +Now, let's fetch data from the database using an API route. + +Create a new file at `src/routes/api/users.ts`: + +```typescript file=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" }, + }); +} +``` + +--- + +## Step 4: Fetch Data in Your Component + +In your `app.tsx` file, use `createResource` to fetch data from your new API route: + +```typescript file=src/app.tsx +import "./app.css"; +//add-start +import { createResource } from "solid-js"; +import { User, Post } from "@prisma/client"; + +type UserWithPosts = User & { + posts: Post[]; +}; + +const fetchUsers = async () => { + const res = await fetch("http://localhost:3000/api/users"); + return res.json(); +}; +//add-end + +export default function App() { + //add-next-line + const [users, { mutate, refetch }] = createResource(fetchUsers); + + return ( +
+

SolidStart + Prisma

+
+ ); +} +``` + +:::info +`createResource` is a SolidJS hook for managing async data. It tracks loading and error states automatically. [Learn more](https://docs.solidjs.com/reference/basic-reactivity/create-resource#createresource). +::: + +--- + +## Step 5: Display the Data + +To show the users and their posts, use SolidJS's `` component: + +```typescript file=src/app.tsx +import "./app.css"; +//add-next-line +import { createResource, For } from "solid-js"; +import { User, Post } from "@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(fetchUsers); + + return ( +
+

SolidJS + Prisma

+//add-start + + {(user) => ( +
+

{user.name}

+ {(post) =>

{post.title}

}
+
+ )} +
+//add-end +
+ ); +} +``` + +:::info +`` loops through an array reactively. Think of it like `.map()` in React. [Learn more](https://docs.solidjs.com/reference/components/for) +::: + +--- + +## Step 6: Add Loading and Error States + +Use SolidJS's `` component to handle loading and error conditions: + +```typescript file=src/app.tsx +import "./app.css"; +import { createResource, For, Show } from "solid-js"; +import { User, Post } from "@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(fetchUsers); + + return ( +
+

SolidJS + Prisma

+ //add-start + Loading...

}> + Error loading data

}> + //add-end + + {(user) => ( +
+

{user.name}

+ {(post) =>

{post.title}

}
+
+ )} +
+ //add-start +
+
+ //add-end +
+ ); +} +``` + +:::info +`` conditionally renders content. It's similar to an `if` statement. [Learn more](https://docs.solidjs.com/reference/components/show) +::: + +--- + +## Next Steps + +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 + +--- + +## More Info + +- [Prisma ORM Docs](/orm/overview/introduction) +- [SolidStart Documentation](https://start.solidjs.com/) diff --git a/sidebars.ts b/sidebars.ts index 528895131b..c01258a251 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -419,6 +419,7 @@ const sidebars: SidebarsConfig = { "guides/nuxt", "guides/tanstack-start", "guides/react-router-7", + "guides/solid-start", ], }, { diff --git a/static/img/guides/prisma-solid-start-cover.png b/static/img/guides/prisma-solid-start-cover.png new file mode 100644 index 0000000000..0026116f82 Binary files /dev/null and b/static/img/guides/prisma-solid-start-cover.png differ