Zero-build Server-Side Rendering by compiling TSX natively. Acts as a custom JSX runtime (equivalent to @elysiajs/html), converting JSX elements and Async Components directly to HTML strings, with built-in XSS protection.
deno add jsr:@goddo/html
Ensure Deno uses the custom JSX compiler (deno.json):
jwt.sign(payload) returns a JWT string. jwt.verify(token) returns the payload object or false when the token is invalid or expired.
Bearer
@goddo/bearer
Extracts the token following RFC 6750: first from the Authorization: Bearer <token> header, with fallback to the access_token query param. Injected into the context as bearer.
deno add jsr:@goddo/bearer
import { Goddo } from '@goddo/core'
import { bearer } from '@goddo/bearer'
new Goddo()
.use(bearer())
.get('/protected', ({ bearer }) => bearer, {
beforeHandle({ bearer, set }) {
if (!bearer) {
set.status = 401
set.headers['www-authenticate'] = 'Bearer realm="sign"'
return 'Unauthorized'
}
},
})
.listen(3000)
Automatically injects standard HTTP security headers, such as X-Frame-Options, X-Content-Type-Options, and Strict-Transport-Security.
deno add jsr:@goddo/shield
import { shield } from '@goddo/shield'
app.use(shield())
CSRF
@goddo/csrf
Implements the Double Submit Cookie pattern to protect state-mutating endpoints from CSRF.
deno add jsr:@goddo/csrf
import { csrf } from '@goddo/csrf'
app.use(csrf())
Cron
@goddo/cron
Zero-dependency background task scheduling, with its own cron pattern parser (5 or 6 fields, lists, ranges, and steps).
deno add jsr:@goddo/cron
import { Goddo } from '@goddo/core'
import { cron } from '@goddo/cron'
new Goddo()
.use(
cron({
name: 'heartbeat',
pattern: '0-59/10 * * * * *', // every 10 seconds
run() {
console.log('Heartbeat')
},
}),
)
.get('/stop', ({ store }) => {
store.cron.heartbeat.stop()
return 'Stopped'
})
.listen(3000)
Server Timing
@goddo/server-timing
Measures the duration of each request lifecycle phase and reports it in the Server-Timing header, visible in the browser DevTools.
deno add jsr:@goddo/server-timing
import { Goddo } from '@goddo/core'
import { serverTiming } from '@goddo/server-timing'
new Goddo()
.use(serverTiming())
.get('/', () => 'Hello')
.listen(3000)
AI Docs (llms.txt)
@goddo/llms-txt
Generates an /llms.txt endpoint reusing the route tree and TypeBox schemas to produce LLM-friendly Markdown documentation for AI agents and LLMs.
deno add jsr:@goddo/llms-txt
import { Goddo, t } from '@goddo/core'
import { llmstxt } from '@goddo/llms-txt'
new Goddo()
.use(llmstxt({
title: 'My Custom API',
description: 'Documentation optimized for LLMs',
exclude: ['/docs', '/docs/json'],
}))
.get('/user/:id', ({ params: { id } }) => id, {
params: t.Object({ id: t.Numeric({ description: 'User ID' }) }),
detail: { summary: 'Fetch user' },
})
.listen(3000)
// AI Docs: GET /llms.txt
Options: path (default '/llms.txt'), title, description, and exclude (paths excluded from spec).
Treaty (client)
@goddo/treaty
End-to-end type-safe HTTP client generated at compile time from the app's route types — equivalent to Elysia Eden. No code generation: everything is inferred via TypeScript generics and a runtime Proxy.
deno add jsr:@goddo/treaty
import { treaty } from '@goddo/treaty'
import type { App } from './server.ts'
const client = treaty<App>('http://localhost:3000')
// GET /user/1
const { data, error } = await client.user({ id: '1' }).get()
// POST /user (body type enforced by the route schema)
const { data: created } = await client.user.post({
body: { name: 'Carlos', age: 25 },
})
Path Mapping
Route
Treaty call
GET /
client.get()
GET /user
client.user.get()
POST /user
client.user.post({ body: ... })
GET /user/:id
client.user({ id: '1' }).get()
GET /user/:id/posts
client.user({ id: '1' }).posts.get()
GET /api/v1/status
client.api.v1.status.get()
Coming from Elysia Eden?
Note two small syntax differences for better TypeScript predictability:
The root path (/) is called directly on the client (client.get()), not via client.index.get().
Request payloads must be explicitly wrapped in a body key (e.g., .post({ body: { ... } })), keeping them neatly separated from query and headers.
Reserved Path Segments
Because Goddo Treaty exposes HTTP methods directly at each level (e.g. client.get()), path segments matching HTTP methods ( get, post, put, delete, patch, head, options, subscribe) are reserved. Creating a route like .get('/api/get/users', ...) would silently collide with the .get() proxy method. To prevent this, Goddo enforces a compile-time type error if you attempt to register a route containing a reserved segment.
Response Shape
Every call returns Promise<{ data, error, status, headers, response }>:
const { data, error, status } = await client.user.get()
if (error) {
console.error(error.message, status) // error is an Error instance
} else {
console.log(data) // typed as the route's return type
}
Global Options
const client = treaty<App>('http://localhost:3000', {
headers: { Authorization: 'Bearer token' }, // merged into every request
})