- For TypeScript: Define routes with `app.get('/users/:id', ({ params, set }) => { set.status = 200; return db.findUser(params.id) })` — use the destructured context object for params, body, query, set, and store.
- Use `t.Object({ id: t.String(), name: t.String() })` from `@elysiajs/typebox` to declare request/response schemas — Elysia infers TypeScript types and performs runtime validation automatically.
- Group related routes with `new Elysia({ prefix: '/api' }).get('/users', ...).post('/users', ...)` and compose with `app.use(usersPlugin)`.
- Use `new Elysia().derive(({ request }) => ({ userId: verifyToken(request.headers.get('authorization')) }))` to inject derived context shared across scoped routes.
- Connect to Eden Treaty with `const api = treaty<App>('http://localhost:3000')` for fully typed client calls with no code generation.
- For TypeScript: Define typed routes: `app.post('/users', ({ body, set }) => { const user = createUser(body); set.status = 201; return user }, { body: t.Object({ name: t.String(), email: t.String({ format: 'email' }) }), response: UserSchema })` — Elysia validates body and response at runtime and infers TypeScript types.
- Group routes into Elysia plugins: `const usersPlugin = new Elysia({ prefix: '/users' }).get('/', listUsers).post('/', createUser, { body: CreateUserDto })` and mount with `app.use(usersPlugin)`.
- Use `onError` hook for centralized error handling: `app.onError(({ code, error, set }) => { set.status = code === 'NOT_FOUND' ? 404 : 500; return { error: error.message } })`.
- Inject shared context with `.derive()`: `new Elysia().derive(async ({ request, cookie }) => { const user = await verifyJWT(cookie.token.value); if (!user) throw new Error('Unauthorized'); return { user } })` — derived values are available in all downstream route handlers.
- Use `app.guard({ beforeHandle: authMiddleware })` to apply middleware to a group of routes without repeating it on every handler.