# Elysia (/docs/guides/frameworks/elysia)

Location: Guides > Frameworks > Elysia

Introduction [#introduction]

[Elysia](https://elysiajs.com/) is an ergonomic web framework for building high-performance backend servers with Bun. It offers end-to-end type safety, an expressive API, and exceptional performance. Combined with Prisma ORM and [Prisma Postgres](https://www.prisma.io/postgres), you get a fast, type-safe backend stack.

In this guide, you'll learn to integrate Prisma ORM with a Prisma Postgres database in an Elysia application. You can find a complete example of this guide on [GitHub](https://github.com/prisma/prisma-examples/tree/latest/orm/elysia).

Quick start [#quick-start]

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

  

#### npm

```bash
npm create prisma@latest -- --template elysia
```

#### pnpm

```bash
pnpm create prisma@latest --template elysia
```

#### yarn

```bash
yarn create prisma@latest --template elysia
```

#### bun

```bash
bun create prisma@latest --template elysia
```

Or follow the steps below to set it up manually.

Prerequisites [#prerequisites]

* [Bun](https://bun.sh/docs/installation) installed on your system

1. Set up your project [#1-set-up-your-project]

Create a new Elysia project using the Bun scaffolding command:

```bash
bun create elysia elysia-prisma
```

Navigate to the project directory:

```bash
cd elysia-prisma
```

2. Install and configure Prisma [#2-install-and-configure-prisma]

2.1. Install dependencies [#21-install-dependencies]

Install the required Prisma packages, database adapter, and Prismabox (for generated TypeBox schemas):

```bash
bun add -d prisma bun-types
bun add @prisma/client @prisma/adapter-pg pg prismabox
```

> [!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](/orm/core-concepts/supported-databases/database-drivers).

Once installed, initialize Prisma in your project:

```bash
bunx --bun prisma init --output ../src/generated/prisma
```

> [!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:

  

#### npm

```bash
npx create-db
```

#### pnpm

```bash
pnpm dlx create-db
```

#### yarn

```bash
yarn dlx create-db
```

#### bun

```bash
bunx --bun create-db
```

2.2. Define your Prisma Schema [#22-define-your-prisma-schema]

In the `prisma/schema.prisma` file, mirror the example app structure with Prismabox TypeBox generators and a `Todo` model:

```prisma title="prisma/schema.prisma"
generator client {
  provider = "prisma-client"
  output   = "../src/generated/prisma"
}

generator prismabox {
  provider                    = "prismabox"
  typeboxImportDependencyName = "elysia"
  typeboxImportVariableName   = "t"
  inputModel                  = true
  output                      = "../src/generated/prismabox"
}

datasource db {
  provider = "postgresql"
}

model Todo { // [!code ++]
  id        Int      @id @default(autoincrement()) // [!code ++]
  title     String // [!code ++]
  completed Boolean  @default(false) // [!code ++]
  createdAt DateTime @default(now()) // [!code ++]
  updatedAt DateTime @updatedAt // [!code ++]
} // [!code ++]
```

This matches the Prisma Elysia example: it generates Prisma Client to `src/generated/prisma` and Prismabox TypeBox schemas to `src/generated/prismabox`.

What is Prismabox? [#what-is-prismabox]

* A Prisma generator that reads your Prisma schema and emits Elysia-friendly TypeBox models.
* Generates files like `src/generated/prismabox/Todo.ts` (and one per model) with `TodoPlain`, `TodoPlainInputCreate`, etc.
* Use those generated models in routes to validate requests/responses and keep Elysia types in sync with your Prisma schema (also useful for OpenAPI/Eden).

2.3. Run migrations and generate Prisma Client [#23-run-migrations-and-generate-prisma-client]

Run the following commands to create the database tables and generate the Prisma Client:

```bash
bunx --bun prisma migrate dev --name init
bunx --bun prisma generate
```

2.4. Seed the database [#24-seed-the-database]

Add some seed data to populate the database with sample todos (mirrors the example repo).

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

```typescript title="prisma/seed.ts"
import { PrismaClient } from "../src/generated/prisma/client.js";
import { PrismaPg } from "@prisma/adapter-pg";

if (!process.env.DATABASE_URL) {
  throw new Error("DATABASE_URL is not set");
}

const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL });
const prisma = new PrismaClient({ adapter });

const todoData = [
  { title: "Learn Elysia" },
  { title: "Learn Prisma" },
  { title: "Build something awesome", completed: true },
];

async function main() {
  console.log("Start seeding...");
  for (const todo of todoData) {
    const created = await prisma.todo.create({
      data: todo,
    });
    console.log(`Created todo with id: ${created.id}`);
  }
  console.log("Seeding finished.");
}

main()
  .then(async () => {
    await prisma.$disconnect();
  })
  .catch(async (e) => {
    console.error(e);
    await prisma.$disconnect();
    process.exit(1);
  });
```

Run the seed script:

```bash
bunx --bun prisma db seed
```

And open Prisma Studio to inspect your data:

```bash
bunx --bun prisma studio
```

3. Integrate Prisma into Elysia [#3-integrate-prisma-into-elysia]

3.1. Create a Prisma Client instance [#31-create-a-prisma-client-instance]

Inside the `src/` directory, create a `lib` directory with a `prisma.ts` file. This file will create and export your Prisma Client instance and add the following code:

```typescript title="src/lib/prisma.ts"
import { PrismaClient } from "../generated/prisma/client.js";
import { PrismaPg } from "@prisma/adapter-pg";

const databaseUrl = process.env.DATABASE_URL;

if (!databaseUrl) {
  throw new Error("DATABASE_URL is not set");
}

const adapter = new PrismaPg({ connectionString: databaseUrl });
export const prisma = new PrismaClient({ adapter });
```

3.2. Create API routes [#32-create-api-routes]

Update your `src/index.ts` file to match the Prisma Elysia example, including Prismabox-generated validation types:

```typescript title="src/index.ts"
import { Elysia, t } from "elysia";
import { prisma } from "./lib/prisma";
import { TodoPlain, TodoPlainInputCreate, TodoPlainInputUpdate } from "./generated/prismabox/Todo";

const app = new Elysia()
  // Health check
  .get("/", () => {
    return { message: "Hello Elysia with Prisma!" };
  })

  // Get all todos
  .get(
    "/todos",
    async () => {
      const todos = await prisma.todo.findMany({
        orderBy: { createdAt: "desc" },
      });
      return todos;
    },
    {
      response: t.Array(TodoPlain),
    },
  )

  // Get a single todo by ID
  .get(
    "/todos/:id",
    async ({ params, set }) => {
      const id = Number(params.id);
      const todo = await prisma.todo.findUnique({
        where: { id },
      });

      if (!todo) {
        set.status = 404;
        return { error: "Todo not found" };
      }

      return todo;
    },
    {
      params: t.Object({
        id: t.Numeric(),
      }),
      response: {
        200: TodoPlain,
        404: t.Object({
          error: t.String(),
        }),
      },
    },
  )

  // Create a new todo
  .post(
    "/todos",
    async ({ body }) => {
      const todo = await prisma.todo.create({
        data: {
          title: body.title,
        },
      });
      return todo;
    },
    {
      body: TodoPlainInputCreate,
      response: TodoPlain,
    },
  )

  // Update a todo
  .put(
    "/todos/:id",
    async ({ params, body, set }) => {
      const id = Number(params.id);

      try {
        const todo = await prisma.todo.update({
          where: { id },
          data: {
            title: body.title,
            completed: body.completed,
          },
        });
        return todo;
      } catch {
        set.status = 404;
        return { error: "Todo not found" };
      }
    },
    {
      params: t.Object({
        id: t.Numeric(),
      }),
      body: TodoPlainInputUpdate,
      response: {
        200: TodoPlain,
        404: t.Object({
          error: t.String(),
        }),
      },
    },
  )

  // Toggle todo completion
  .patch(
    "/todos/:id/toggle",
    async ({ params, set }) => {
      const id = Number(params.id);

      try {
        const todo = await prisma.todo.findUnique({
          where: { id },
        });

        if (!todo) {
          set.status = 404;
          return { error: "Todo not found" };
        }

        const updated = await prisma.todo.update({
          where: { id },
          data: { completed: !todo.completed },
        });

        return updated;
      } catch {
        set.status = 404;
        return { error: "Todo not found" };
      }
    },
    {
      params: t.Object({
        id: t.Numeric(),
      }),
      response: {
        200: TodoPlain,
        404: t.Object({
          error: t.String(),
        }),
      },
    },
  )

  // Delete a todo
  .delete(
    "/todos/:id",
    async ({ params, set }) => {
      const id = Number(params.id);

      try {
        const todo = await prisma.todo.delete({
          where: { id },
        });
        return todo;
      } catch {
        set.status = 404;
        return { error: "Todo not found" };
      }
    },
    {
      params: t.Object({
        id: t.Numeric(),
      }),
      response: {
        200: TodoPlain,
        404: t.Object({
          error: t.String(),
        }),
      },
    },
  )

  .listen(3000);

console.log(`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`);
```

This creates the same endpoints as the official example:

* `GET /` - Health check
* `GET /todos` - Fetch all todos (newest first)
* `GET /todos/:id` - Fetch a single todo
* `POST /todos` - Create a todo
* `PUT /todos/:id` - Update a todo
* `PATCH /todos/:id/toggle` - Toggle completion
* `DELETE /todos/:id` - Delete a todo

Prismabox generates the `TodoPlain`/`TodoPlainInput*` TypeBox schemas so responses and request bodies are validated and typed.

3.3. Run the application [#33-run-the-application]

Start your Elysia server:

```bash
bun run dev
```

You should see `🦊 Elysia is running at localhost:3000` in the console.

3.4. Test the API [#34-test-the-api]

Test the endpoints using `curl`:

```bash
# Health check
curl http://localhost:3000/ | jq

# Get all todos
curl http://localhost:3000/todos | jq

# Get a single todo
curl http://localhost:3000/todos/1 | jq

# Create a new todo
curl -X POST http://localhost:3000/todos \
  -H "Content-Type: application/json" \
  -d '{"title": "Ship the Prisma + Elysia guide"}' | jq

# Toggle completion
curl -X PATCH http://localhost:3000/todos/1/toggle | jq

# Update a todo
curl -X PUT http://localhost:3000/todos/1 \
  -H "Content-Type: application/json" \
  -d '{"title": "Updated title", "completed": true}' | jq

# Delete a todo
curl -X DELETE http://localhost:3000/todos/1 | jq
```

You're done! You've created an Elysia app with Prisma that's connected to a Prisma Postgres database.

Next steps [#next-steps]

Now that you have a working Elysia app connected to a Prisma Postgres database, you can:

* Extend your Prisma schema with more models and relationships
* Add update and delete endpoints
* Explore authentication with [Elysia plugins](https://elysiajs.com/plugins/overview.html)
* Use [Eden](https://elysiajs.com/eden/overview.html) for end-to-end type-safe API calls

More info [#more-info]

* [Prisma Documentation](/orm)
* [Elysia Documentation](https://elysiajs.com/)
* [Elysia with Prisma Guide](https://elysiajs.com/integrations/prisma.html)

## Related pages

- [`Astro`](https://www.prisma.io/docs/guides/frameworks/astro): Learn how to use Prisma ORM in an Astro app
- [`Hono`](https://www.prisma.io/docs/guides/frameworks/hono): Learn how to use Prisma ORM in a Hono app
- [`NestJS`](https://www.prisma.io/docs/guides/frameworks/nestjs): Learn how to use Prisma ORM in a NestJS app
- [`Next.js`](https://www.prisma.io/docs/guides/frameworks/nextjs): Learn how to use Prisma ORM in a Next.js app and deploy it to Vercel
- [`Nuxt`](https://www.prisma.io/docs/guides/frameworks/nuxt): A step-by-step guide to setting up and using Prisma ORM and Prisma Postgres in a Nuxt app