Frameworks
Nuxt, SolidStart, TanStack Start, SvelteKit, Astro, React Router and Next.js.
Each framework's adapter builds the app as it would for any server, then deploys it as the SDK says: pages rendered on request, the prerendered ones and the static files as public files, and API routes. The bindings reach your code where each framework keeps a platform's.
Nitro
Nuxt, SolidStart and TanStack Start build their servers with Nitro.
zeroko() from @zeroko-io/nitro is Nitro's options for Zeroko, for
Nitro 2 and 3.
npm install -D @zeroko-io/nitro// nuxt.config.ts
import { zeroko } from "@zeroko-io/nitro"
export default defineNuxtConfig({ nitro: zeroko() })// vite.config.ts, SolidStart (TanStack Start alike, with its plugin)
import { solidStart } from "@solidjs/start/config"
import { zeroko } from "@zeroko-io/nitro"
import { nitro } from "nitro/vite"
import { defineConfig } from "vite"
export default defineConfig({ plugins: [solidStart(), nitro(zeroko())] })The bindings: with Nitro 2 (Nuxt), in event.context.cloudflare.env; with
Nitro 3, in the request's runtime.cloudflare.env.
// server/api/notes.get.ts, in Nuxt
import type { Database } from "@zeroko-io/core"
export default defineEventHandler(async (event) => {
const { DB } = event.context.cloudflare.env as { DB: Database }
return DB.query("SELECT * FROM notes")
})SvelteKit
npm install -D @zeroko-io/sveltekit// vite.config.js
import { sveltekit } from "@sveltejs/kit/vite"
import zeroko from "@zeroko-io/sveltekit"
import { defineConfig } from "vite"
export default defineConfig({ plugins: [sveltekit({ adapter: zeroko() })] })The bindings are in event.platform.env, in load functions, actions and
endpoints. Declare them in src/app.d.ts:
import type { Database } from "@zeroko-io/core"
declare global {
namespace App {
interface Platform {
env: { DB: Database }
}
}
}Astro
npm install -D @zeroko-io/astro// astro.config.mjs
import zeroko from "@zeroko-io/astro"
import { defineConfig } from "astro/config"
export default defineConfig({ output: "server", adapter: zeroko() })The bindings are in Astro.locals.runtime.env, and in an endpoint's
locals.runtime.env. Pages with export const prerender = true, and a
whole static site, are public files. Images go as they are: Sharp doesn't
run in a worker.
React Router
npm install -D @zeroko-io/react-router// react-router.config.ts
import type { Config } from "@react-router/dev/config"
import zeroko from "@zeroko-io/react-router"
export default { ssr: true, buildEnd: zeroko() } satisfies ConfigThe bindings are in the router's context, in loaders and actions:
import { zeroko } from "@zeroko-io/react-router/context"
export async function loader({ context }: LoaderFunctionArgs) {
const { env } = context.get(zeroko)
return env.DB.query("SELECT * FROM notes")
}Next.js
Through OpenNext, which builds
Next.js for workers, the runtime Zeroko runs on. @zeroko-io/next runs it
after Next's own build, with its settings of its own: no wrangler.jsonc
or open-next.config.ts in your project.
npm install -D @zeroko-io/next @opennextjs/cloudflare wrangler// next.config.mjs
import { withZeroko } from "@zeroko-io/next"
export default withZeroko({})// zeroko.build.js, run after Next's build:
// "build": "next build && node zeroko.build.js"
import { build } from "@zeroko-io/next"
await build()The bindings are in OpenNext's context, in server components, route handlers and server actions:
import { getCloudflareContext } from "@opennextjs/cloudflare"
export async function GET() {
const { env } = await getCloudflareContext({ async: true })
return Response.json(await env.DB.query("SELECT * FROM notes"))
}What runs on workers runs here: OpenNext's limits apply, such as no Node-only image optimization.