Help us improve
Share bugs, ideas, or general feedback.
From elysia-skill
Expert knowledge for building type-safe web applications with ElysiaJS, including validation, lifecycle hooks, Eden end-to-end type safety, and integrations
npx claudepluginhub joel611/claude-plugins --plugin elysia-specialistHow this skill is triggered โ by the user, by Claude, or both
Slash command
/elysia-skill:elysiaThe summary Claude sees in its skill listing โ used to decide when to auto-load this 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.
Builds ultra-fast web APIs and full-stack apps with Hono on Cloudflare Workers, Deno, Bun, Node.js. Covers routing, middleware, JSX support, RPC client for edge and BFFs.
Designs RESTful API routes with Next.js App Router, Zod validation, auth guards, and typed responses. Activates when discussing API endpoints, route structure, or request/response schemas.
Builds Hono web apps with inline API reference for constructors, routing patterns, middleware, JSX, validation, testing, streaming, and error handling. Tests endpoints via `npx hono request`. Triggers on Hono imports or mentions.
Share bugs, ideas, or general feedback.
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.
This skill should be triggered when you are:
Building Web APIs:
Type Safety & Validation:
Lifecycle Hooks & Middleware:
End-to-End Type Safety:
Framework Integrations:
Plugin Development:
Elysia uses method chaining extensively. Each method returns a new instance with updated types:
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.
Elysia provides t (TypeBox) for runtime and compile-time type safety. Schemas automatically generate TypeScript types and OpenAPI documentation:
import { Elysia, t } from 'elysia'
new Elysia()
.post('/user', ({ body }) => body, {
body: t.Object({
name: t.String(),
age: t.Number()
})
})
Hooks execute at specific points in the request-response cycle:
Hooks can be local (specific route) or interceptor (all routes after registration).
Eden provides end-to-end type safety between server and client, similar to tRPC but using Elysia's type system:
// 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!
import { Elysia } from 'elysia'
new Elysia()
.get('/', () => 'Hello Elysia')
.listen(3000)
console.log('๐ฆ Elysia is running at http://localhost:3000')
import { Elysia, t } from 'elysia'
new Elysia()
.post('/user', ({ body }) => body, {
body: t.Object({
name: t.String(),
email: t.String({ format: 'email' })
})
})
.listen(3000)
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)
import { Elysia } from 'elysia'
new Elysia()
.onBeforeHandle(({ query: { name }, status }) => {
if (!name) return status(401)
})
.get('/protected', ({ query: { name } }) => {
return `Welcome ${name}!`
})
.listen(3000)
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)
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)
import { Elysia } from 'elysia'
new Elysia()
.state('count', 0)
.get('/', ({ store }) => {
store.count++
return store.count
})
.listen(3000)
import { Elysia } from 'elysia'
new Elysia()
.get('/teapot', ({ status }) => status(418, "I'm a teapot"))
.get('/home', ({ redirect }) => redirect('https://elysiajs.com'))
.listen(3000)
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)
Server:
// 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:
bun add @elysiajs/eden
bun add -d elysia
// 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!
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)
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)
bun add drizzle-orm drizzle-typebox
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)
import { Elysia, t } from 'elysia'
new Elysia()
.post('/upload', async ({ body: { file } }) => {
return `Uploaded: ${file.name}`
}, {
body: t.Object({
file: t.File()
})
})
.listen(3000)
import { Elysia } from 'elysia'
const myPlugin = new Elysia({ name: 'my-plugin' })
.state('pluginVersion', '1.0.0')
.get('/plugin', ({ store }) => store.pluginVersion)
new Elysia()
.use(myPlugin)
.listen(3000)
This skill includes comprehensive documentation extracted from official Elysia sources. All examples and information come from official documentation (medium-high confidence).
references/essential.md (6 pages)Core Elysia concepts including:
references/eden.md (11 pages)End-to-end type safety with Eden:
references/tutorial.md (14 pages)Step-by-step guides including:
references/patterns.md (21 pages)Advanced patterns including:
references/plugins.md (13 pages)Official plugins documentation:
references/integrations.md (17 pages)Framework integrations:
references/other.mdAdditional topics and utilities.
references/tutorial.md for getting started guidesreferences/essential.md for schema validationreferences/essential.mdreferences/eden.mdreferences/integrations.mdreferences/plugins.mdreferences/patterns.mdreferences/tutorial.mdtsconfig.jsonmethod chaining - required for type inference@sinclair/typebox version if using Drizzlet.File() for file uploads (sets content-type automatically)All content synthesized from official Elysia documentation:
No conflicts detected between sources. All examples and patterns come directly from official Elysia documentation and are considered authoritative.
bun add elysia
# Eden (type-safe client)
bun add @elysiajs/eden
# HTML rendering
bun add @elysiajs/html
# CORS
bun add @elysiajs/cors
# JWT
bun add @elysiajs/jwt
# GraphQL
bun add @elysiajs/graphql-yoga
# OpenTelemetry
bun add @elysiajs/opentelemetry
This skill was automatically generated from official Elysia documentation. To refresh: