Claude
Skills
Sign in
โ† Back

elysia

Included with Lifetime
$97 forever

Expert knowledge for building type-safe web applications with ElysiaJS, including validation, lifecycle hooks, Eden end-to-end type safety, and integrations

General

What this skill does


# Elysia Skill

Expert knowledge for building high-performance, type-safe web applications with **ElysiaJS** - a fast, ergonomic Bun web framework with end-to-end type safety.

This skill synthesizes knowledge from official Elysia documentation covering core concepts, patterns, plugins, and integrations.

## When to Use This Skill

This skill should be triggered when you are:

**Building Web APIs:**
- Creating RESTful APIs with Elysia
- Setting up HTTP routes (GET, POST, PUT, DELETE, etc.)
- Implementing request/response handlers
- Working with route parameters, query strings, or request bodies

**Type Safety & Validation:**
- Adding schema validation with Elysia.t (TypeBox)
- Using Standard Schema validators (Zod, Valibot, ArkType, etc.)
- Validating request bodies, queries, params, headers, or cookies
- Generating OpenAPI documentation from schemas

**Lifecycle Hooks & Middleware:**
- Implementing authentication/authorization checks
- Adding logging, error handling, or request preprocessing
- Using lifecycle hooks (beforeHandle, afterResponse, onError, etc.)
- Creating reusable route options with Macros

**End-to-End Type Safety:**
- Setting up Eden Treaty for type-safe client-server communication
- Exporting server types for frontend consumption
- Creating type-safe API clients (similar to tRPC)
- Testing with end-to-end type safety

**Framework Integrations:**
- Integrating Elysia with Next.js, Nuxt, SvelteKit, Astro, or Expo
- Setting up Drizzle ORM with Elysia
- Using AI SDK with Elysia for streaming responses
- Deploying to Netlify Edge Functions or other platforms

**Plugin Development:**
- Creating custom Elysia plugins
- Using official plugins (@elysiajs/*)
- Implementing OpenTelemetry for observability
- Working with HTML, CORS, JWT, GraphQL, or other plugins

## Key Concepts

### Method Chaining
Elysia uses method chaining extensively. Each method returns a new instance with updated types:

```typescript
new Elysia()
  .state('version', 1)
  .get('/', ({ store }) => store.version)
  .listen(3000)
```

**Important:** Always use method chaining - it's required for proper type inference, especially with Eden.

### Schema Validation
Elysia provides `t` (TypeBox) for runtime and compile-time type safety. Schemas automatically generate TypeScript types and OpenAPI documentation:

```typescript
import { Elysia, t } from 'elysia'

new Elysia()
  .post('/user', ({ body }) => body, {
    body: t.Object({
      name: t.String(),
      age: t.Number()
    })
  })
```

### Lifecycle Hooks
Hooks execute at specific points in the request-response cycle:

- **request** - when request is received
- **beforeHandle** - before executing handler (e.g., auth checks)
- **afterHandle** - after handler, before response
- **afterResponse** - after response is sent
- **onError** - when errors occur

Hooks can be **local** (specific route) or **interceptor** (all routes after registration).

### Eden Treaty
Eden provides end-to-end type safety between server and client, similar to tRPC but using Elysia's type system:

```typescript
// server.ts
const app = new Elysia()
  .get('/user/:id', ({ params: { id } }) => ({ id, name: 'John' }))
export type App = typeof app

// client.ts
import { treaty } from '@elysiajs/eden'
const api = treaty<App>('localhost:3000')
const { data } = await api.user({ id: '1' }).get()
// data is fully typed!
```

## Quick Reference

### 1. Basic Server Setup

```typescript
import { Elysia } from 'elysia'

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

console.log('๐ŸฆŠ Elysia is running at http://localhost:3000')
```

### 2. Route with Validation

```typescript
import { Elysia, t } from 'elysia'

new Elysia()
  .post('/user', ({ body }) => body, {
    body: t.Object({
      name: t.String(),
      email: t.String({ format: 'email' })
    })
  })
  .listen(3000)
```

### 3. Path Parameters & Query Strings

```typescript
import { Elysia, t } from 'elysia'

new Elysia()
  .get('/id/:id', ({ params: { id }, query }) => {
    return { id, query }
  }, {
    params: t.Object({
      id: t.Number() // Automatically coerced from string
    }),
    query: t.Object({
      name: t.String()
    })
  })
  .listen(3000)
```

### 4. Authentication with beforeHandle Hook

```typescript
import { Elysia } from 'elysia'

new Elysia()
  .onBeforeHandle(({ query: { name }, status }) => {
    if (!name) return status(401)
  })
  .get('/protected', ({ query: { name } }) => {
    return `Welcome ${name}!`
  })
  .listen(3000)
```

### 5. Local Hook for Specific Route

```typescript
import { Elysia } from 'elysia'

new Elysia()
  .get('/public', () => 'Public route')
  .get('/auth', () => 'Authenticated!', {
    beforeHandle({ request, status }) {
      if (Math.random() <= 0.5) return status(418)
    }
  })
  .listen(3000)
```

### 6. Guard for Multiple Routes

```typescript
import { Elysia, t } from 'elysia'

new Elysia()
  .get('/none', () => 'No validation')
  .guard({
    query: t.Object({
      name: t.String()
    })
  })
  .get('/query', ({ query: { name } }) => name)
  .get('/query2', ({ query: { name } }) => `Hello ${name}`)
  .listen(3000)
```

### 7. State Management

```typescript
import { Elysia } from 'elysia'

new Elysia()
  .state('count', 0)
  .get('/', ({ store }) => {
    store.count++
    return store.count
  })
  .listen(3000)
```

### 8. Custom Status & Redirect

```typescript
import { Elysia } from 'elysia'

new Elysia()
  .get('/teapot', ({ status }) => status(418, "I'm a teapot"))
  .get('/home', ({ redirect }) => redirect('https://elysiajs.com'))
  .listen(3000)
```

### 9. Reusable Macro

```typescript
import { Elysia, t } from 'elysia'

new Elysia()
  .macro('auth', {
    cookie: t.Object({
      session: t.String()
    }),
    beforeHandle({ cookie: { session }, status }) {
      if (!session.value) return status(401)
    }
  })
  .post('/user', ({ body }) => body, {
    auth: true // Applies auth macro
  })
  .listen(3000)
```

### 10. Eden Setup (End-to-End Type Safety)

**Server:**
```typescript
// server.ts
import { Elysia, t } from 'elysia'

const app = new Elysia()
  .get('/', () => 'Hi Elysia')
  .get('/id/:id', ({ params: { id } }) => id)
  .post('/mirror', ({ body }) => body, {
    body: t.Object({
      id: t.Number(),
      name: t.String()
    })
  })
  .listen(3000)

export type App = typeof app
```

**Client:**
```bash
bun add @elysiajs/eden
bun add -d elysia
```

```typescript
// client.ts
import { treaty } from '@elysiajs/eden'
import type { App } from './server'

const api = treaty<App>('localhost:3000')

const { data, error } = await api.mirror.post({
  id: 1,
  name: 'Elysia'
})

if (error) console.error(error.value)
else console.log(data) // Fully typed!
```

### 11. Error Handling

```typescript
import { Elysia, t } from 'elysia'

new Elysia()
  .get('/:id', ({ params: { id } }) => id, {
    params: t.Object({
      id: t.Number({
        error: 'id must be a number'
      })
    })
  })
  .onError(({ code, error, status }) => {
    if (code === 'VALIDATION')
      return status(400, error.message)

    return status(500, 'Internal Server Error')
  })
  .listen(3000)
```

### 12. Standard Schema (Zod Example)

```typescript
import { Elysia } from 'elysia'
import { z } from 'zod'

new Elysia()
  .post('/user', ({ body }) => body, {
    body: z.object({
      name: z.string(),
      age: z.number()
    })
  })
  .listen(3000)
```

### 13. Drizzle ORM Integration

```bash
bun add drizzle-orm drizzle-typebox
```

```typescript
import { Elysia } from 'elysia'
import { drizzle } from 'drizzle-orm/bun-sqlite'
import { createInsertSchema } from 'drizzle-typebox'
import { users } from './schema'

const db = drizzle(/* ... */)
const insertUserSchema = createInsertSchema(users)

new Elysia()
  .post('/user', async ({ body }) => {
    const user = await db.insert(users).values(body)
    return user
  }, {
    body: insertUserSchema
  })
  .listen(3000)
```

### 14. File Upload

```typescript
import { Elysia, t

Related in General