Docs

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.

TS
// server<Env>() 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<Env>()
  .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) }) }

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.)

TS
// 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
})

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.

TS
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))),
})
Proudly built with Nifra — server-rendered on Cloudflare Pages.MIT