Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/elysiajs/documentation/llms.txt

Use this file to discover all available pages before exploring further.

A handler is a function that receives an HTTP request and returns a response. In Elysia, every route is backed by a handler — either a function you define or an inline literal value.
import { Elysia } from 'elysia'

new Elysia()
    .get('/', () => 'hello world')  // function handler
    .get('/static', 'Hello Elysia') // inline literal handler
    .listen(3000)
Inline values are compiled ahead of time and are ideal for static resources. Elysia can optimise them without running the function on every request.

Context

Every handler receives a single argument — the context — which carries all information about the current request. The context is unique per request; it is never shared between concurrent requests (except for store, the global mutable state).
import { Elysia } from 'elysia'

new Elysia()
    .get('/', (context) => context.path)
    .listen(3000)

Context properties

PropertyDescription
bodyHTTP message body: JSON, form data, or file upload
queryParsed query-string as a plain object
paramsPath parameters parsed as a plain object
headersRequest headers as a plain object
cookieMutable signal store for reading and writing cookies
storeGlobal mutable state shared across all requests
requestThe raw Web Standard Request
serverBun server instance (Bun only)
pathPathname of the request

Utility functions

FunctionDescription
status(code, body?)Return a response with a specific HTTP status
redirect(url, status?)Redirect to another URL
set.headersAppend or remove response headers

Returning a status code

Use the status function to return a response with a specific HTTP status code. This is the recommended approach because TypeScript can verify that the returned value matches your response schema.
import { Elysia } from 'elysia'

new Elysia()
    .get('/', ({ status }) => status(418, 'Kirifuji Nagisa'))
    .listen(3000)
Prefer status() over the legacy set.status assignment. The status function enables TypeScript to narrow the return type per status code, which unlocks end-to-end type safety with Eden.

set — mutating the response

set is a mutable object on the context that controls the outgoing response.

set.headers

Append or remove response headers before the response is sent.
import { Elysia } from 'elysia'

new Elysia()
    .get('/', ({ set }) => {
        set.headers['x-powered-by'] = 'Elysia'

        return 'a mimir'
    })
    .listen(3000)
Elysia auto-completes header names in lowercase for consistency. Use set-cookie rather than Set-Cookie.
Combining set.headers with status:
import { Elysia } from 'elysia'

new Elysia()
    .get('/', ({ set, status }) => {
        set.headers = { 'X-Teapot': 'true' }

        return status(418, 'I am a teapot')
    })
    .listen(3000)

Cookies

Elysia exposes cookies as a mutable signal store. Read and write a cookie by accessing its name directly — no explicit get/set calls required.
import { Elysia } from 'elysia'

new Elysia()
    .get('/set', ({ cookie: { name } }) => {
        // Read
        const current = name.value

        // Write
        name.value = 'New Value'
    })
    .listen(3000)

Redirect

Redirect the client to another resource. When redirect() is returned, Elysia ignores any other returned value.
import { Elysia } from 'elysia'

new Elysia()
    .get('/', ({ redirect }) => {
        return redirect('https://youtu.be/whpVWVWBW4U?&t=8')
    })
    .get('/custom-status', ({ redirect }) => {
        return redirect('https://youtu.be/whpVWVWBW4U?&t=8', 302)
    })
    .listen(3000)

File responses

Return a single file using the file utility, or build a multipart form response with form.
import { Elysia, file } from 'elysia'

new Elysia()
    .get('/', file('nagi.webp'))
    .listen(3000)

Streaming responses

Return a streaming response by using a generator function with yield. Elysia automatically sets the appropriate transfer-encoding headers.
import { Elysia } from 'elysia'

const app = new Elysia()
    .get('/ok', function* () {
        yield 1
        yield 2
        yield 3
    })
If you return a value without ever yielding, Elysia downgrades the response to a normal (non-streamed) reply.
import { Elysia } from 'elysia'

const app = new Elysia()
    .get('/ok', function* () {
        if (Math.random() > 0.5) return 'ok'

        yield 1
        yield 2
        yield 3
    })
Headers can only be set before the first yield. Any set.headers mutations after the first chunk is sent are silently ignored because headers have already been flushed.
import { Elysia } from 'elysia'

const app = new Elysia()
    .get('/ok', function* ({ set }) {
        set.headers['x-name'] = 'Elysia' // applied ✅
        yield 1
        yield 2

        set.headers['x-id'] = '1' // ignored ❌
        yield 3
    })

Server-Sent Events

Wrap yielded values with sse to produce a proper text/event-stream response.
import { Elysia, sse } from 'elysia'

new Elysia()
    .get('/sse', function* () {
        yield sse('hello world')
        yield sse({
            event: 'message',
            data: {
                message: 'This is a message',
                timestamp: new Date().toISOString()
            },
        })
    })

Consuming streams with Eden

When using the Eden treaty client, a streaming route is exposed as an AsyncGenerator that you iterate with for await.
import { Elysia } from 'elysia'
import { treaty } from '@elysia/eden'

const app = new Elysia()
    .get('/ok', function* () {
        yield 1
        yield 2
        yield 3
    })

const { data, error } = await treaty(app).ok.get()
if (error) throw error

for await (const chunk of data)
    console.log(chunk)

Low-level request access

The raw Web Standard Request is available on the context for cases where you need headers, body streams, or other low-level details not exposed by Elysia’s helpers.
import { Elysia } from 'elysia'

new Elysia()
    .get('/user-agent', ({ request }) => {
        return request.headers.get('user-agent')
    })
    .listen(3000)

Server instance (Bun only)

The Bun server instance is available on the context after .listen() is called.
import { Elysia } from 'elysia'

new Elysia()
    .get('/port', ({ server }) => server?.port)
    .get('/ip', ({ server, request }) => server?.requestIP(request))
    .listen(3000)

Build docs developers (and LLMs) love