Package entry points
| Entry | Exports and purpose |
|---|---|
goribu | Link, NavLink, navigate, Form, Stylesheet, ClientEntry, and UI/metadata types. |
goribu/server | defineConfig, low-level createApp, and request, response, config, data, and middleware types. |
goribu/client | Side-effect browser bootstrap. Import once from the client entry. |
goribu/vite | goribu() Vite plugin for development and build integration. |
- Runtime boundary: Keep server runtime imports out of browser-reachable components.
- Type-only imports: Type-only imports do not create runtime dependencies.
Route exports
| Export | Contract |
|---|---|
default | React page component. Receives the props passed to res.render(). |
GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS | (req, res) => ResponseResult, optionally async. |
meta | Metadata object or synchronous ({ props, url }) => metadata. |
prerender | Optional boolean. False requires Worker rendering; true requires successful static output. |
- Implicit methods: A page has an implicit GET when no explicit GET exists. Goribu derives HEAD and OPTIONS when needed.
- Special routes:
_404,_500, and_middlewarehave special roles under routes. - Document location: The optional app-wide Document lives in
src/setup/_documentwith a supported JavaScript or TypeScript extension. - Middleware export: A middleware default export is one function or an array. Return nothing to continue or a response result to stop.
Request
Handlers and middleware share one request object.
| Member | Type or result |
|---|---|
method | HTTP method string. |
path | URL pathname string. |
url | Absolute URL of the handled route; on client navigation, the target page's URL (available since 0.9.2). |
params | Named dynamic segments, each a string. |
query | URLSearchParams. |
headers | Headers. |
env | Worker environment and bindings. |
cookies | Cookie jar described below. |
d1 | D1 query facade described below. |
kv | KV facade described below. |
cache | JSON cache described below (available since 0.9.0). |
body() | Promise of an object or string, according to Content-Type. Both form encodings return objects. |
rawBody() | Promise of Uint8Array bytes, sharing the cached read with body(). |
waitUntil(promise) | Register background work with the Worker execution context. |
Middleware may attach its own fields to req, such as req.user, for later middleware and the handler; declare them for TypeScript on AppRequestFields. See Request handlers.
- JSON bodies: JSON bodies must have an object root.
- Form bodies: URL-encoded and multipart forms return field objects. Uploads are File values, repeated names become arrays, and missing fields are absent.
- Text bodies: Text returns a string.
- Unsupported bodies: Empty or unsupported bodies return an empty object.
- Parse failures: Malformed supported bodies produce 400. See Request handlers.
import type { Handler } from "goribu/server";
export const POST: Handler = async (req, res) => {
const { name } = await req.body() as Record<string, unknown>;
if (typeof name !== "string" || !name.trim()) {
return res.invalid({ name: "Enter your name." });
}
return res.json({ name: name.trim() });
};
export const POST = async (req, res) => {
const { name } = await req.body();
if (typeof name !== "string" || !name.trim()) {
return res.invalid({ name: "Enter your name." });
}
return res.json({ name: name.trim() });
};
Response
Return one terminal result from every handler. status() and headers() configure the builder and return it for chaining.
| Method | Contract |
|---|---|
status(code) | Set the HTTP status. Default is 200, except helper-specific defaults. |
headers(object) | Add header strings or arrays of strings. |
render(props = {}) | Render this route's page with serializable object props. |
json(data) | JSON response. |
text(body) | Plain text response. |
stream(body) | Bytes from a ReadableStream, ArrayBuffer, typed array, or Blob; application/octet-stream unless you set content-type (available since 0.9.2). |
invalid(errors, status = 422) | Field-error object or string mapped to root. |
redirect(location) | Redirect with default status 303. Explicit allowed statuses: 301, 302, 303, 307, 308. |
notFound(props = {}) | Render the 404 page with optional props. |
- Return values: Handlers cannot return raw Response objects or JSX. Use
stream()for binary or streamed bodies. - Streamed routes: A streamed route is never prerendered. Client navigation to it loads the document.
- Bodyless statuses: Bodyless statuses reject a body.
- Form outcomes: Enhanced Form outcomes are JSON, invalid, redirect, and same-page render. See Forms.
Cookies
| Method | Contract |
|---|---|
req.cookies.get(name) | Incoming string value or null. |
req.cookies.set(name, value, options?) | Queue a Set-Cookie header. |
req.cookies.delete(name, { path?, domain? }?) | Queue deletion using matching scope. |
- Cookie options:
domain,path,expires(Date),maxAge(seconds),httpOnly,secure, andsameSite. - SameSite values:
sameSiteacceptsLax,Strict, orNone, also lowercase. - Security defaults: Cookie security options have no implicit defaults.
- Cookie encoding: Encode structured or Unicode data before setting a cookie.
Navigation
| API | Extra props or arguments |
|---|---|
Link | Normal anchor props, replace = false, prefetch = true. |
NavLink | Link props plus end = false and a string or ({ isActive }) => className callback. Goribu owns aria-current. |
navigate(target, { replace? }?) | Returns Promise<void>. Requires a browser and an HTTP(S) destination. |
- Active matching: NavLink matches pathname boundaries, ignoring query and hash. Root is exact-only.
- Native links: Link enhancement preserves native behavior for external links, downloads, modifier clicks, and same-document anchors. See Links & navigation.
- Static navigation: Production static navigation and prefetch reuse saved build-time data without invoking the Worker.
- Current static URL: Clicking the exact current URL scrolls a confirmed static page without fetching or rerendering.
- Current dynamic URL: Clicking the exact current URL of a dynamic page fetches fresh data.
- Current-URL history: Neither static nor dynamic navigation to the exact current URL adds a history entry.
import { NavLink } from "goribu";
export default function SettingsLink() {
return (
<NavLink
href="/settings"
end
className={({ isActive }) => isActive ? "active" : undefined}
>
Settings
</NavLink>
);
}
import { NavLink } from "goribu";
export default function SettingsLink() {
return (
<NavLink
href="/settings"
end
className={({ isActive }) => isActive ? "active" : undefined}
>
Settings
</NavLink>
);
}
Form
Import Form from goribu. It accepts ordinary form props except that Goribu owns encoding and defines its method/action behavior.
| Prop | Contract |
|---|---|
method | Required: get, post, put, patch, or delete, in upper or lower case. |
action | Defaults to the current URL when submitted. |
children | React children or ({ pending, errors, data }) => children. |
replace | Replace history during enhanced navigation; defaults false. |
reset | Reset controls after successful JSON or same-page render; defaults false. |
onSubmit | Runs first and may cancel with preventDefault(). |
onResult | Runs after state/render commit and before redirect navigation. |
ref | Receives the HTML form; extended-method forms expose it after hydration. |
- Initial Form state:
{ pending: false, errors: null, data: null }. - Form errors:
errorsis an object of message strings. - Result callback:
onResultreceives{ ok: true, data?, response? }or{ ok: false, errors, data?, response? }. - Encoding ownership: Do not pass
encTypeto Form. - Hydration: GET/POST work natively. PUT/PATCH/DELETE require hydration.
- Submitter overrides: A submitter's
formMethodsupports only GET/POST. Declare extended methods on Form itself. See Forms.
Metadata
meta is a RouteMetadata object or synchronous function receiving { props, url }, where url is a URL object.
| Field | Shape |
|---|---|
title | String. Missing title produces an empty managed title. |
description, canonical, robots | Strings. |
meta | Array of { name, content } or { property, content }. |
links | Array of descriptors with required rel and href. |
- Optional link fields:
as,type,media,sizes,hrefLang,crossOrigin,referrerPolicy,fetchPriority,imageSrcSet,imageSizes, andcolorare all strings. - Rejected metadata: Unknown fields, event handlers, async results, and duplicate canonical/description representations are rejected.
Document and browser entry
DocumentProps contains { children, head, nonce? }. Keep children under #root and head inside the document head.
- Stylesheet:
Stylesheet()renders the current graph's styles and takes no public props. - Client entry:
ClientEntry({ src, nonce? })renders the browser entry.srcis the development fallback; production resolves the built asset. - Custom Document: Keep one
Stylesheetand oneClientEntryin a custom Document. - Browser bootstrap: Import
goribu/clientonce to hydrate and install navigation and Forms. - Browser environment: Only
import.meta.env.PUBLIC_*values are browser-visible. See Rendering.
D1
Use the req.d1 tagged template in handlers or middleware. Values become parameters. A statement is lazy until a terminal runs.
| API | Result or purpose |
|---|---|
.get() | Promise of first row or null. |
.all() | Promise of row array. |
.value() | Promise of first column of first row or null. |
.run() | Promise of { changes, lastRowId }. |
req.d1.atomic(statements) | Atomic batch of unexecuted statements; entries have rows, changes, and lastRowId. |
req.d1.unsafe(text, params?) | Statement from application-controlled SQL structure and explicit values. |
req.d1.fresh | Query facade that starts each tagged terminal at the primary. |
req.d1.public | Query facade without the visitor's bookmark. |
.session | Session object for integrations; raw binding when replication is disabled. |
.binding | Plain Cloudflare D1Database binding. |
- Tagged D1 values: Strings, numbers, booleans, null, ArrayBuffer, ArrayBufferView, and non-empty arrays of those scalars are supported.
- Unsafe parameters:
unsafe()parameters are a flat scalar array. - Rejected D1 values: Undefined, dates, objects, nested/empty arrays, functions, symbols, and bigints are rejected.
- Default consistency: Default D1 queries use the visitor session when replication is enabled.
- Facade restrictions: Fresh/public cannot be chained. Atomic belongs to the default facade.
- Batch session: A batch rebinds passed statements to its own session. See D1.
// Inside a handler; D1 and the posts table must exist.
type Post = { id: number; title: string };
const posts = await req.d1<Post>`
SELECT id, title FROM posts ORDER BY id DESC
`.all();
const posts = await req.d1`
SELECT id, title FROM posts ORDER BY id DESC
`.all();
KV
| API | Options |
|---|---|
get(key, options?) | type: text/json/arrayBuffer/stream; cacheTtl; metadata: boolean. |
put(key, value, options?) | expiration, expirationTtl, JSON-serializable metadata. |
delete(key) | No options. |
list(options?) | prefix, limit, cursor. |
- Default KV reads: Reads return text or null. JSON is parsed only when requested.
- Metadata result: Metadata reads return
{ value, metadata, cacheStatus }. Missing value and metadata are null. - List result: Lists return keys, list_complete, and an optional cursor.
- KV completion: Await all operations.
- KV keys: Keys for get/put/delete are non-empty strings.
- JSON writes: JSON writes need explicit stringification.
- Unsupported KV calls: There is no bulk-get array, string shorthand for options, or separate getWithMetadata method.
- KV consistency: KV is eventually consistent, including cached misses. See KV store.
Cache
Available in Goribu 0.9.0. req.cache needs no binding or configuration. The GoribuCache type is exported from goribu/server.
| API | Result or options |
|---|---|
get<Value = unknown>(key) | Promise of parsed JSON or null on a miss. The type argument does not validate stored data. |
set(key, value, options?) | Promise of undefined. JSON serialization; optional positive safe-integer ttl in seconds, default 60. |
delete(...keys) | Promise of undefined. Attempts deletion of the supplied keys in the current data center. |
- Cache keys: Literal strings starting with
/, scoped by origin and execution location. - Cache failures: Invalid inputs reject. Platform failures warn and become misses or skipped operations.
- Pre-rendering: Pre-rendering bypasses the cache.
- Background writes: Use
req.waitUntilexplicitly. See Cache for freshness, Smart Placement, and deployment support.
Configuration
defineConfig(config) validates and returns a frozen configuration. The fields are name, compatibilityDate, optional compatibilityFlags, database, kv, r2, domain, workersDev, and responseHeaders.
Available in Goribu 0.9.0. Optional top-level domain connects one application hostname during deployment. Available in Goribu 0.9.2: workersDev: false turns off the workers.dev address and requires domain.
- D1 declaration:
{ type: "d1", name, replication? }. - KV declaration:
{ name }. - Header callback: Receives
{ request, env, mode, nonce }and synchronously returns a plain object of strings or string arrays. See Configuration for defaults, allowed names, environment files, and header restrictions.
CLI
Run from the application directory. The app scripts wrap the installed Goribu CLI.
| Command | Behavior |
|---|---|
pnpm dev [--port <number>] [--host] | Local Worker development with Vite. --port listens on exactly that port and fails if it is taken; --host listens on every network interface (available since 0.9.2). |
pnpm build | Production bundles and static output. |
pnpm check | Read-only production deployment plan. |
pnpm run deploy | Authenticate, build, provision, migrate, and upload. |
pnpm exec goribu cloudflare-login | Log in to Cloudflare through Goribu's installed Wrangler. |
pnpm exec goribu tail | Stream live logs from the deployed Worker. |
pnpm exec goribu wrangler <args> | Run Goribu's installed Wrangler with the account deploy uses. A real deploy is refused (available since 0.9.2). |
pnpm exec goribu d1 "<sql>" | Run SQL against local D1. With --remote, a single SELECT runs directly and other SQL needs the database name typed in a terminal (available since 0.9.2). |
pnpm exec goribu migrate:new <name> | Create the next numbered SQL migration. |
pnpm exec goribu migrate | Apply pending local migrations. |
pnpm exec goribu migrate:status | Read migration status. |
pnpm exec goribu migrate:down | Roll back one migration. |
pnpm exec goribu migrate:seed | Run local seed.sql; cannot target production. |
pnpm exec goribu --help | Print usage. |
pnpm exec goribu --version | Print the installed version. |
- Production targets: Migrate, status, down, and d1 accept
--remote. - Development arguments: Dev accepts only
--portand--host. - Argument-free commands: Build, check, deploy, tail, and cloudflare-login take no arguments.
- CLI failures: Failures exit non-zero. Recognized Goribu failures print their repair message without a stack trace.
- Type checking:
pnpm typecheckis the TypeScript starter's separatetsc --noEmitscript. - Scaffolding:
pnpm create goribu@latest <name>creates an app. - Scaffolder options:
--js,--help, and--goribu-tarball <path>for a matching local framework archive. - Scaffolder scope: Scaffolding never installs, authenticates, or deploys for you.
TypeScript
Use import type. Types annotate behavior; they do not validate request input or stored JSON.
| Entry | Public types |
|---|---|
goribu | LinkProps, NavLinkProps, FormProps, FormMethod, FormState, FormResult, FormErrors, DocumentProps, RouteMetadata, Meta. |
goribu/server | ApplicationConfig, AppRequestFields, DefinedConfig, ResponseHeaders, CookieOptions, Cookies, D1Value, D1WriteResult, D1Statement, D1Queries, D1, KV, GoribuRequest, GoribuResponse, ResponseResult, Handler, Middleware, ServerErrorProps, WorkerContext, WorkerApp, RouteManifestEntry, ClientAsset, AppOptions. |
- Handler types:
Handler<Props, Env, Params>andMiddleware<Env>. - UI types:
Meta<Props>andForm<Data>. - Data types:
req.d1<Row>andreq.kv.get<Value>(key, { type: "json" }). - Body validation: Request body values still need narrowing and validation.
Low-level app creation
createApp(options) from goribu/server returns a Worker app with fetch(request, env, ctx): Promise<Response>. Normal applications use goribu() in Vite; the build supplies the route graph and calls this API for them.
- Required app options:
manifest,modules, anderrorPages. - Optional app options:
documentId,middlewareByRoute,mode,clientAssetManifest,clientAssetBase, andapplicationConfig. - Compiled inputs: App options describe compiled routes, error pages, assets, and validated config. They are not additional
goribu.config.jsfields.