nifra_contextRead the live app
Routes, schemas, middleware, package versions, and project conventions in a compact payload.
Nifra gives agents the live map they need: MCP context, route-aware scaffolds, self-verifying tools, and a no-codegen typed client. Start with a fast API, grow into SSR across React, Solid, Vue, Preact, or Svelte, and deploy on Bun, Node, Deno, or the edge.
No generated SDK. No stale route docs. No framework lock-in.
nifra_contextRoutes, schemas, middleware, package versions, and project conventions in a compact payload.
nifra_scaffoldURL patterns resolve to framework-correct files, handlers, loaders, and typed clients.
nifra_runHTTP, SSR, WebSocket, and subprocess checks run against the current workspace.
nifra_checkTypecheck, route-contract checks, and conservative fix suggestions before CI goes green.
Run nifra mcp and point Claude Code or Cursor at it: an integrated MCP server plus a conventions file expose your project's live routes, schemas, examples, and drift checks, so the agent reads the real API surface directly.
$ nifra context # the project's live API surface — pipe into any agent prompt
GET /users/:id → response { id: string, name: string }
POST /users body { name: string } → response { id: string, name: string }
$ nifra mcp # same data as an MCP server — Claude Code & Cursor read it automatically
# The typed client is the safety lock — an agent physically can't call a route that changed:
const res = await api.users({ id: "42" }).get()
if (res.ok) res.data.name
// ^ tsc error here the moment the route or response shape changes
$ nifra check # CI gate: typecheck + typed-client lint — drift fails the buildNo code generators, no build steps, and no stale SDKs. client<typeof app> infers paths, parameters, request bodies, and responses directly from your server type. Any mismatch fails the build.
import { client } from "@nifrajs/client"
import type { app } from "./server" // a type import — server code never ships to the client
const api = client<typeof app>("https://api.example.com")
// The path autocompletes. Params and body are typed. No codegen, ever.
const res = await api.users({ id: "42" }).get()
if (res.ok) {
res.data.name // typed from the route return or response schema
} else {
res.error // client-call failures are returned, never thrown
}React, Solid, Vue, Preact, and Svelte all sit on the same render engine. Loaders, actions, streaming, prefetching, and islands are identical across all five — switching is a single import. No meta-framework lock-in.
Compare the adapters →// The adapter is the one line that changes per framework:
import { reactAdapter } from "@nifrajs/web-react"
export default createWebApp({ adapter: reactAdapter, manifest, clientEntry })
// routes/hello.tsx — your page, written in React
export function Page({ data }: { data: { name: string } }) {
return <h1>Hello {data.name}</h1>
}// The adapter is the one line that changes per framework:
import { solidAdapter } from "@nifrajs/web-solid"
export default createWebApp({ adapter: solidAdapter, manifest, clientEntry })
// routes/hello.tsx — same page, Solid's fine-grained JSX
export function Page(props: { data: { name: string } }) {
return <h1>Hello {props.data.name}</h1>
}// The adapter is the one line that changes per framework:
import { vueAdapter } from "@nifrajs/web-vue"
export default createWebApp({ adapter: vueAdapter, manifest, clientEntry })
<!-- routes/hello.vue — same page, as a Vue SFC -->
<script setup lang="ts">defineProps<{ data: { name: string } }>()</script>
<template><h1>Hello {{ data.name }}</h1></template>// The adapter is the one line that changes per framework:
import { preactAdapter } from "@nifrajs/web-preact"
export default createWebApp({ adapter: preactAdapter, manifest, clientEntry })
// routes/hello.tsx — same page; Preact's 3 KB runtime, identical React API
export function Page({ data }: { data: { name: string } }) {
return <h1>Hello {data.name}</h1>
}// The adapter is the one line that changes per framework:
import { svelteAdapter } from "@nifrajs/web-svelte"
export default createWebApp({ adapter: svelteAdapter, manifest, clientEntry })
<!-- routes/hello.svelte — same page, as a Svelte component -->
<script lang="ts">export let data: { name: string }</script>
<h1>Hello {data.name}</h1>Nifra is built on Web-standard routing and fetch APIs. Run on Bun for blazing-fast development, then deploy to Node, Deno, Cloudflare Workers, or Vercel Edge with a single line of adapter code.
View deployment targets →import { app } from "./app" // one app, defined once
// Bun
export default { port: 3000, fetch: app.fetch }
// Node import { serve } from "@nifrajs/node" → serve(app, { port: 3000 })
// Deno import { serve } from "@nifrajs/deno" → serve(app, { port: 3000 })
// Cloudflare Workers / Pages · Vercel edge
import { toFetchHandler } from "@nifrajs/core"
export default toFetchHandler(app)export default { fetch: app.fetch }serve(app, { port: 3000 })serve(app, { port: 3000 })export default toFetchHandler(app)export default toFetchHandler(app)Zero-dependency middleware for security headers, cookies, CSRF, JWT authentication, rate limiting, CORS, and WebSocket topic pub/sub ships in the box. Compose it at the app or route boundary.
View Middleware options →import { server } from "@nifrajs/core"
import { t } from "@nifrajs/schema"
// A typed API — no frontend required. Use nifra like Hono or Elysia.
export const app = server()
.get("/users/:id", (c) => ({ id: c.params.id }))
.post("/users", { body: t.object({ name: t.string() }) }, (c) => {
// c.body is validated + typed — invalid input is rejected before this runs.
return { id: crypto.randomUUID(), name: c.body.name }
})
export default { fetch: app.fetch } // Bun. Node, Deno, and the edge are one line each.Nifra isn't just a router—it's a modular suite of type-safe packages built for high performance, edge scalability, and robust developer ergonomics.
Common combos: auth + uploads for user content · cron + otel for observable background jobs · env + i18n + content for a localized site.
@nifrajs/authBetter-AuthFirst-class integration with Better-Auth. Preconfigured session middlewares, social logins, and typed roles.
import { auth } from "@nifrajs/auth"
export const app = server()
.use(auth.session())
.get("/me", (c) => c.session.user)@nifrajs/uploadsStorageSecure direct-to-cloud file uploads. Generates signed URLs for S3, Cloudflare R2, or Backblaze without proxying heavy buffers.
import { storage } from "@nifrajs/uploads"
const url = await storage.presign("avatars", {
key: "user-42.png",
maxSize: "5mb"
})@nifrajs/cronSchedulerDefine periodic cron tasks alongside HTTP handlers. Runs on serverless (Cloudflare triggers) and standalone Node/Bun.
import { cron } from "@nifrajs/cron"
export const job = cron("0 0 * * *", async () => {
await db.sessions.deleteExpired()
})@nifrajs/otelObservabilityRequest tracing and custom spans. Export traces to Honeycomb, Datadog, or Grafana Tempo with zero complex boilerplates.
import { otel } from "@nifrajs/otel"
const app = server()
.use(otel.trace({ serviceName: "nifra-api" }))@nifrajs/envValidationVerify environment variables at startup. Validates that API keys and configurations are present and correctly typed at boot.
import { checkEnv } from "@nifrajs/env"
import { t } from "@nifrajs/schema"
export const env = checkEnv({
DATABASE_URL: t.string(),
PORT: t.number({ default: 3000 })
})@nifrajs/imageMediaOn-the-fly resizing, WebP/AVIF formatting, quality compression, and CDN caching to optimize LCP load priority.
import { Image } from "@nifrajs/image"
// optimized image component
<Image src="/logo.png" width={800} height={400} priority />@nifrajs/i18nLocalizationDynamic pluralization and translations dictionary with automatic HTTP header language negotiation.
import { i18n } from "@nifrajs/i18n"
const { t } = i18n(c.locale)
return { msg: t("welcome", { name: "Ada" }) }@nifrajs/contentMDX EngineRead Markdown/MDX files, parse frontmatter, validate schemas, and compile them to interactive UI components.
import { content } from "@nifrajs/content"
const posts = await content("posts")
.where({ status: "published" })
.all()@nifrajs/isletsPerformanceStatic HTML pages with dynamic island scripts. Restores client interactivity without large JS hydration overhead.
import { islet } from "@nifrajs/islets"
// zero client runtime by default
export const hydrate = false
export const islandScripts = [counter]Nifra runs close to raw Bun/Node speed. Full-stack SSR renders 3× to 22× faster than standard meta-frameworks on Node, while the backend router matches the fastest Node frameworks — tens of thousands of requests per second on a single core.
See detailed memory, cold-boot, and payload size metrics on the benchmarks page.
Define a contract once. Nifra keeps validation, types, the typed client, OpenAPI, and your agents in sync with it across the stack.
t.object({…})one schema@nifrajs/schemaModel request inputs and response payloads with compiled validation. A single schema handles runtime validation, exports TypeScript types, and builds OpenAPI specifications automatically.
import { t } from "@nifrajs/schema"
// A contract schema for your routes
export const GetUserSchema = {
params: t.object({ id: t.string() }),
response: t.object({
id: t.string(),
name: t.string(),
role: t.union([t.literal("admin"), t.literal("user")])
})
}@nifrajs/coreImplement the endpoint. Path parameters are automatically parsed from the literal path, and the incoming request body and query parameters are typechecked at the runtime boundary.
import { server } from "@nifrajs/core"
import { GetUserSchema } from "./schema"
export const app = server()
.get("/users/:id", GetUserSchema, (c) => {
// c.params.id is typed as string
return { id: c.params.id, name: "Ada", role: "admin" }
})@nifrajs/clientBuild the client using only the server's type signature. Autocomplete handles the paths, parameters, and payloads, while TypeScript ensures the frontend never goes out of sync with the backend.
import { client } from "@nifrajs/client"
import type { app } from "./server"
const api = client<typeof app>("https://api.example.com")
// Typed call, autocompleted paths, compile-time checked
const res = await api.users({ id: "123" }).get()
if (res.ok) console.log(res.data.name)nifra mcpCoding agents write better code when they know the actual codebase rules. Nifra feeds Claude Code, Cursor, or Copilot your live routes and call signatures directly through a Model Context Protocol (MCP) server.
# Run once to register the Nifra MCP server with Claude Code
$ claude mcp add nifra -- bunx nifra mcp
# Claude can now query:
# - nifra_context (live routes & schemas)
# - nifra_run (in-process verification)nifra checkBlock breaking changes from merging. The nifra linter analyzes client-server bindings and flags frontend-backend drift in a single command, keeping your pipeline green.
# Run linter and typecheck in your GitHub actions
$ nifra check
# Fails CI if a route signature was changed on the backend
# but remains un-updated on the frontend client.One command scaffolds a typed Nifra app — start as a fast API, grow into full-stack SSR, and let your agents read the live contract instead of guessing.