import { pageMeta } from "../../meta" import { CodeBlock } from "../../highlight" // Pure content page — no React interactivity (TOC/copy/search are the layout enhancer + // the Nira island), so ship zero framework JS and avoid hydrating the inline-script DOM. export const hydrate = false export const meta = pageMeta( "Nifra — Edge & bindings", "Typed platform bindings in Nifra: c.env, Platform, c.waitUntil, KV/D1 on the edge.", ) const ENV = `// server() types the platform env end-to-end — c.env is your Env in every // handler AND in derive/decorate middleware, with no cast. interface Env { KV: KVNamespace; DB: D1Database } const app = server() .get("/u/:id", async (c) => { const cached = await c.env.KV.get(c.params.id) // c.env is typed Env return cached ?? "miss" }) export default { fetch: (req: Request, env: Env, ctx: ExecutionContext) => app.fetch(req, { env, waitUntil: ctx.waitUntil.bind(ctx) }) }` const WAIT = `// c.waitUntil keeps background work alive past the response (analytics, cache writes). app.post("/event", (c) => { c.waitUntil(c.env.KV.put("last", Date.now().toString())) return { ok: true } // returns immediately; the put finishes in the background })` const CRON = `// doc-check: skip — \`env.KV\` is typed by your app's \`Env\` (the ./app import), supplied by the reader. import { toFetchHandler } from "@nifrajs/core" import { app } from "./app" // Export fetch + a cron handler. Wire the schedule in wrangler.toml: [triggers] crons = ["0 * * * *"] export default toFetchHandler(app, { scheduled: (controller, { env, waitUntil }) => waitUntil(env.KV.put("last-run", String(controller.scheduledTime))), })` export default function Edge() { return (

Edge & bindings

On Cloudflare and other edge runtimes, your platform bindings (KV, D1, Durable Objects, secrets) reach handlers through a fully-typed c.env.

Typed c.env

server<Env>() threads your Env type through the whole app:{" "} c.env is Env in every handler and in{" "} derive/decorate middleware — read c.env.KV directly, no cast. app.fetch(req, {"{ env }"}) / toFetchHandler type-check the bindings too. In @nifrajs/web, a route's loader/action gets the same typed{" "} env.

Background work

c.waitUntil(promise) keeps work alive after the response is sent — cache writes, analytics, fan-out — without blocking the user. (Typing is not validation: platform bindings are trusted inputs; validate anything untrusted at the boundary.)

Validation on the edge

Edge runtimes block dynamic code generation (new Function), which trips many schema libraries. Nifra's t handles it transparently: it compiles a fast validator on Bun and Node, and falls back to an eval-free checker on Cloudflare Workers, Vercel Edge, and Deno Deploy — the same routes validate everywhere, with no edge-specific schema module. Because core validates any{" "} Standard Schema , you can also bring Zod, Valibot, or ArkType (all eval-free) — only t also emits OpenAPI from the same definition.

Scheduled (cron)

Pass scheduled to toFetchHandler to also export a Workers cron handler for a [triggers] schedule. It gets the platform controller plus the same typed env and waitUntil as your request handlers.

) }