elysia
Expert knowledge for building type-safe web applications with ElysiaJS, including validation, lifecycle hooks, Eden end-to-end type safety, and integrations
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, tRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.