Blog
Feb 24, 2026 - 3 MIN READ
Astro + Elysia in a hurry

Astro + Elysia in a hurry

A quick guide to integrating Elysia as your API layer inside an Astro project

Bryan Ferreira

Bryan Ferreira

Why use Elysia inside Astro?

Basically, you get a Bun powered API, end-to-end type safe via Eden Treaty, with automatic OpenAPI docs, and minimal config.

The steps

For the full reference, check the official Elysia + Astro docs.

1. Set output to server in astro.config.mjs

Check the official setup guide to create a new Astro project if you don't have one already.

// astro.config.mjs
import { defineConfig } from "astro/config";

export default defineConfig({
  output: "server",
});

2. Install Elysia

bun add elysia @elysiajs/eden

3. Create the catch-all route

Create a file in src/pages/ that catches every /api/* request and hands it off to Elysia.

// src/pages/[...slugs].ts
import { Elysia } from "elysia";

const app = new Elysia({ prefix: "/api" })
  .get("/health", () => ({ status: "ok" }))
  .get("/hello", () => ({ message: "Hello from Elysia!" }));

const handle = app.handle;

export const GET = handle;
export const POST = handle;
export const PUT = handle;
export const PATCH = handle;
export const DELETE = handle;

export type App = typeof app;

4. Add OpenAPI

Install the plugin:

bun add @elysiajs/openapi

Then plug it into your app. Use enabled: import.meta.env.DEV so the Swagger UI only shows up in development.

// src/pages/[...slugs].ts
import { Elysia } from "elysia";
import { openapi } from "@elysiajs/openapi";

const app = new Elysia({ prefix: "/api" })
  .use(
    openapi({
      provider: "swagger-ui",
      enabled: import.meta.env.DEV,
    }),
  )
  .get("/health", () => ({ status: "ok" }))
  .get("/hello", () => ({ message: "Hello from Elysia!" }));

Once running:

  • OpenAPI endpoint → /api/openapi

5. Set up the Eden client

Eden Treaty gives you full type safety when calling your API — no codegen needed.

// src/lib/eden.ts
import { treaty } from "@elysiajs/eden";
import type { App } from "../pages/[...slugs]";

export const client = treaty<App>(import.meta.env.PUBLIC_API_URL);

Set the variable in your .env file:

# .env
PUBLIC_API_URL=localhost:4321  # in dev, this points to your local Astro server

6. Call the API from an Astro page

// src/pages/index.astro (frontmatter)
import { client } from "../lib/eden";

const { data } = await client.api.hello.get();

<h1>{data?.message}</h1>

Now you have Elysia inside Astro!

© 2026