Skip to main content
Prisma Documentation Docs

Search documentation

Type to search this documentation.

On this pageOverview

Astro

Astro is a web framework for content-driven sites. In this guide, an Astro API route is where you call Prisma ORM to read from a Prisma Postgres database.

In this guide, you'll learn to integrate Prisma ORM with a Prisma Postgres database in an Astro project from scratch. You can find a complete example of this guide on GitHub.

Run one command to scaffold an Astro project with Prisma ORM and Prisma Postgres ready to go:

title="bun"
bunx create-prisma@stable --template astro
pnpm
pnpm create prisma@stable --template astro
yarn
yarn create prisma@stable --template astro
npm
npm create prisma@stable -- --template astro

Or follow the steps below to set it up manually.

Create a new Astro project:

bunx create-astro@latest
Bash
pnpm dlx create-astro@latest
Bash
yarn dlx create-astro@latest
Bash
npx create-astro@latest

[!NOTE]

  • Where should we create your new project? astro-prisma
  • How would you like to start your new project? Use minimal (empty) template
  • Install dependencies? (recommended) Yes
  • Initialize a new git repository? (optional) Yes

Navigate into the newly created project directory:

Bash
cd astro-prisma

Navigate into the newly created project directory:

cd astro-prisma

To get started with Prisma, you'll need to install a few dependencies:

title="bun"
bun add prisma@prev tsx @types/pg --dev
pnpm
pnpm add prisma@prev tsx @types/pg --save-dev
yarn
yarn add prisma@prev tsx @types/pg --dev
npm
npm install prisma@prev tsx @types/pg --save-dev
bun add @prisma/client@7 @prisma/adapter-pg dotenv pg
Bash
pnpm add @prisma/client@7 @prisma/adapter-pg dotenv pg
Bash
yarn add @prisma/client@7 @prisma/adapter-pg dotenv pg
Bash
npm 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 ../prisma/generated
Bash
pnpm prisma init --output ../prisma/generated
Bash
yarn prisma init --output ../prisma/generated
Bash
npx prisma init --output ../prisma/generated

[!NOTE] prisma init creates the Prisma scaffolding and a local DATABASE_URL. In the next step, you will create a Prisma Postgres database and replace that value with a direct postgres://... connection string.

This will create:

  • A prisma/ directory with a schema.prisma file
  • A prisma.config.ts file for configuring Prisma
  • A .env file with a local DATABASE_URL already set

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 prisma/ directory with a schema.prisma file
  • A prisma.config.ts file for configuring Prisma
  • A .env file with a local DATABASE_URL already set

Create a Prisma Postgres database and replace the generated DATABASE_URL in your .env file with the postgres://... connection string from the CLI output:

title="bun"
bunx create-db
pnpm
pnpm dlx create-db
yarn
yarn dlx create-db
npm
npx create-db

In the prisma/schema.prisma file, add the following models and change the generator to use the prisma-client provider:

title="prisma/schema.prisma"
generator client {

  provider   = "prisma-client"

  output     = "../prisma/generated"

}

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"),

  },

});

Now, run the following command to create the database tables:

title="bun"
bunx prisma migrate dev --name init
pnpm
pnpm prisma migrate dev --name init
yarn
yarn prisma migrate dev --name init
npm
npx prisma migrate dev --name init

Then generate Prisma Client:

title="bun"
bunx prisma generate
pnpm
pnpm prisma generate
yarn
yarn prisma generate
npm
npx prisma generate

Add some seed data to populate the database with sample users and posts.

Create a new file called seed.ts in the prisma/ directory:

title="prisma/seed.ts"
import { PrismaClient, Prisma } from "../prisma/generated/client";

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() {

  console.log("Starting to seed...");

  for (const u of userData) {

    await prisma.user.upsert({

      where: { email: u.email },

      update: {},

      create: u,

    });

  }

  console.log("Seeding finished.");

}

main()

  .catch((e) => {

    console.error(e);

    process.exit(1);

  })

  .finally(async () => {

    await prisma.$disconnect();

  });

Now, tell Prisma how to run this script by updating your prisma.config.ts:

title="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:

title="bun"
bunx prisma db seed
pnpm
pnpm prisma db seed
yarn
yarn prisma db seed
npm
npx prisma db seed

And open Prisma Studio to inspect your data:

title="bun"
bunx prisma studio
pnpm
pnpm prisma studio
yarn
yarn prisma studio
npm
npx prisma studio

First, create an env.d.ts file in your src directory to provide TypeScript definitions for environment variables:

title="src/env.d.ts"
interface ImportMetaEnv {

  readonly DATABASE_URL: string;

}

interface ImportMeta {

  readonly env: ImportMetaEnv;

}

Inside of /src, create a lib directory and a prisma.ts file inside it. This file will be used to create and export your Prisma Client instance.

mkdir src/lib

touch src/lib/prisma.ts

Set up the Prisma client like this:

title="src/lib/prisma.ts"
import { PrismaClient } from "../../prisma/generated/client";

import { PrismaPg } from "@prisma/adapter-pg";

const adapter = new PrismaPg({

  connectionString: import.meta.env.DATABASE_URL,

});

const prisma = new PrismaClient({

  adapter,

});

export default prisma;

An API route lets you query the database on the server and reuse the result from your pages.

Create a new file called api/users.ts in the src/pages directory:

mkdir src/pages/api

touch src/pages/api/users.ts

Now, create a GET route that fetches the Users data from your database, making sure to include each user's Posts by adding them to the include field:

title="src/pages/api/users.ts"
import type { APIRoute } from "astro";

import prisma from "../../lib/prisma";

export const GET: APIRoute = async () => {

  const users = await prisma.user.findMany({

    include: { posts: true },

  });

  return new Response(JSON.stringify(users), {

    headers: { "Content-Type": "application/json" },

  });

};

Instead of using fetch() with HTTP requests, Astro recommends importing endpoint functions directly. This approach is more efficient and avoids URL parsing issues.

Start by creating a new type that combines the User and Post models called UserWithPosts:

title="src/pages/index.astro"
--import type { User, Post } from "../../prisma/generated/client"; import { GET } from "./api/users.ts"; type UserWithPosts = User & { posts: Post[] }; const response = await GET(Astro); const users: UserWithPosts[] = await response.json(); --<html lang="en">  <head>    <meta charset="utf-8" />    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />    <meta name="viewport" content="width=device-width" />    <meta name="generator" content={Astro.generator} />    <title>Astro + Prisma</title>  </head>  <body>    <h1>Astro + Prisma</h1>    <ul>      {users.map((user: UserWithPosts) => (         <li>          <h2>{user.name}</h2>          <ul>            {user.posts.map((post: Post) => (               <li>{post.title}</li>             ))}          </ul>        </li>       ))}    </ul>  </body></html>

Now start your development server to see your Astro app in action:

bun run dev
Bash
pnpm run dev
Bash
yarn dev
Bash
npm run dev

Open your browser at http://localhost:4321 to see the users and their posts displayed on the page.

Open your browser at http://localhost:4321 to see the users and their posts displayed on the page.

Your Astro app now reads users and their posts from a Prisma Postgres database through the API route.

Now that you have a working Astro 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 and validation
Suggest an edit

Propose a replacement for this page. The site team reviews it before applying any changes.

Export
Documentation menu