About elysiajs
A development skill that guides work on Elysia v2 projects, including version-aware API use, typing, validation, and testing. It helps developers follow the project's existing conventions and consult focused references for the task at hand.
Key features
- 01Check versions and project conventions
- 02Apply Elysia routing and lifecycle rules
- 03Use schemas and inferred types
- 04Compose plugins and typed dependencies
- 05Test routes and run type checks
Use cases
- 01Implement or modify an Elysia v2 route
- 02Diagnose validation and error handling behavior
- 03Test a route and check inferred types
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ elysiajs/ skills --skill elysiajsAfter installing, type/elysiajsin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
metadata.jsonreferences/ai-sdk.mdapi.mdbetter-auth.mdcheat-sheet.mdcomposition.mdcookie.mddeploy.mddrizzle.mdeden.mderrors.mdlifecycle.mdmigration.mdobservability.mdopenapi.mdplugins.mdprisma.mdproject-structure.mdreact-email.mdruntimes.mdtesting.mdvalidation.mdversions.mdwebsocket.mdDetails
From the project READMEElysia v2
Start here
- Inspect
package.json, the lockfile, runtime, and app structure. Keep existing versions and conventions unless the user requests a migration. - This skill describes 2.0.0-rc.0 or newer. For v1, use migration to recognize differences, not as permission to upgrade. Check installed types when a different beta disagrees.
- Read only the references the task needs. Versions lists the source revision, package baselines, and verification limits.
- Check types and exercise the affected route, including its rejection path. See testing.
Essential rules
- Options precede the handler.
.get(path, options, handler),.get(path, handler), and.get(path, staticValue)are valid. - Keep the returned type. Chain calls or bind the result to a new variable. Reassigning
let app = new Elysia()does not widen its inferred type. - Order hooks before routes. Parent hooks before
.use(child)reach the child's routes.onRequestruns before routing and is the exception to registration order. See lifecycle. - Declare typed dependencies. Each independently defined instance should
.use()its providers. Parent runtime inheritance does not give a child those static types. See composition. - Name shared plugins.
nameandseeddeduplicate hooks. Plugin factories still execute on each call. - Return expected failures.
status()andproblem()send ordinary responses. A returnedErrorenters error hooks and contributes to the route's return type. Thrown errors are absent from that inferred type. Explicit error details can remain public in production. See errors. - Infer types from schemas. Use
UnwrapSchemaorUnwrapModels. TypeBox 1.x has no schema.static. Keep handlers inline and pass plain values to services. - Choose context lifetime.
decorateandstateare shared.deriveruns per request after validation, in thebeforeHandlequeue. - Guard schemas override by default. A route replaces the corresponding inherited schema. Use
schema: 'merge'on the guard when both must apply. - Register optional capabilities. File MIME validation needs a detector. WebSockets need
elysia/websocket. Node needs@elysia/nodeand Node 22.18 or newer. - Always consult with an actual documentation for the latest features, examples, and references. The skill is a guide to the documentation, not a replacement.
For Elysia 1 use: https://elysiajs.com/llms.txt For Elysia 2 use: https://next.elysiajs.com/llms.txt
Minimal app and test
Use the project's test runner. This Bun example opens no port.
// src/app.ts
import { Elysia, t } from 'elysia'
export const app = new Elysia()
.get('/users/:id', {
params: t.Object({ id: t.Number() })
}, ({ params }) => ({ id: params.id }))
export type App = typeof app
// test/app.test.ts
import { expect, test } from 'bun:test'
import { app } from '../src/app'
test('coerces the id and rejects nonnumeric input', async () => {
const response = await app.handle('/users/42')
expect(response.status).toBe(200)
expect(await response.json()).toEqual({ id: 42 })
expect((await app.handle('/users/nope')).status).toBe(422)
})
Run bun test and the project's type check. For new projects, see runtime setup. Keep .listen() in the process entry. See project structure.
Choose a reference
| Task | Read |
|---|---|
| Versions, peer dependencies, source versus docs | Versions |
| Configuration, routing, context, files, streams | Core API |
| Hooks, parsing, derived context, disposal | Lifecycle |
| Plugins, hook scope, guards, macros | Composition |
| Schemas, coercion, uploads, inferred types | Validation |
| Expected errors, exception mapping, production responses | Errors |
| Folders, services, models, dependency injection | Project structure |
| Cookie values, validation, signing | Cookies |
| WebSocket routes | WebSockets |
| Route tests, type checks, lazy plugins | Testing |
| Typed client calls | Eden |
| OpenAPI schemas and documentation | OpenAPI |
| Bun, Node, Deno, Workers, frontend framework integration | Runtimes |
| Bundles, AOT, binaries, Docker, deployment | Deployment |
| Traces, spans, request timing | Observability |
| CORS, JWT, static files, cron, HTML, GraphQL | Official plugins |
| Databases and external libraries | Drizzle, Prisma, Better Auth, AI SDK, React Email |
| v1 syntax and migration | Migration |
| Find an example by pattern | Pattern index |
Defaults for a new project
Default to Bun and t schemas. Keep small apps in one file; split by feature as needed. Add Eden for typed clients and OpenAPI for API documentation.