@lunora/vite
The recommended dev-time experience — codegen, HMR, overlay.
@lunora/vite is a Vite plugin factory. A single lunora() call wires up
codegen, wrangler validation, the error overlay, and the Cloudflare Vite
plugin so vite dev runs your Worker locally with full HMR.
// vite.config.ts
import { lunora } from "@lunora/vite";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [react(), lunora()],
});Options
| Option | Default | Purpose |
|---|---|---|
schemaDir | "lunora" | Directory containing schema.ts + function files |
generatedDir | "lunora/_generated" | Where to emit api.ts, server.ts, dataModel.ts |
apiSpec | "openapi" | API spec emitted into _generated/: "openapi"/"openrpc"/"both"/"none" |
studio | true | Serve the Lunora studio at /__lunora during dev, or false to skip |
cloudflare | true | Pass options to @cloudflare/vite-plugin, or false to skip |
overlay | true | Inject @visulima/vite-overlay for runtime errors; false to skip, or an options object to forward |
validateWrangler | true | Cross-check wrangler.jsonc bindings against the schema |
projectRoot | process.cwd() | Override for monorepo setups |
Codegen lifecycle
The plugin watches <schemaDir>/**/*.ts. On any change it parses the
schema with ts-morph, regenerates _generated/*.ts, and the Vite module
graph picks up the new types — your editor sees the change before you can
swap windows.
Wrangler validator
Compares the table tier modifiers in your schema with durable_objects.bindings,
d1_databases, and r2_buckets in wrangler.jsonc. Reports missing
bindings as Vite errors before they explode at deploy.
Studio
During dev the plugin mounts the Lunora studio at /__lunora so you can browse
your schema, data, logs, and advisors without leaving the dev server. Set
studio: false to turn it off.
Error overlay
The plugin injects @visulima/vite-overlay
so runtime and codegen failures show up in the browser instead of only the
terminal. On top of it Lunora registers solution finders that recognise
framework-specific failures and render an actionable fix hint in the overlay:
- a missing or non-object-literal
defineSchema(...) - a reserved or duplicate table name
- an invalid
.jurisdiction(...)value - a non-literal
uniqueindex flag - a container/workflow class that isn't re-exported by your worker entry
- runtime unique-constraint and optimistic-concurrency (
ConflictError) conflicts
Pass an options object to forward overlay configuration — including your own
solutionFinders, which run alongside Lunora's (each error resolves to the
highest-priority finder that recognises it):
lunora({
overlay: {
solutionFinders: [myCustomFinder],
},
});Set overlay: false to disable it entirely.
Dev-server state & AI agents
While vite dev runs, the plugin registers the server in .lunora/dev.json
(URL, PID, start time — per-checkout, gitignored, secret-free) and removes the
record on shutdown. That record is what lets lunora dev status, lunora dev stop, and lunora dev logs manage a Vite-based project, and what
lunora dev --background blocks on before reporting the URL and PID — so an
AI agent can start, health-check (GET /_lunora/status on the worker), and
stop your dev server without parsing terminal output or leaking zombie
processes.
When an AI agent is detected (or LUNORA_LOG_JSON=1 is set), the worker's
structured log events pass through as raw single-line JSON instead of the
pretty [lunora] terminal rendering, so machine consumers can parse them
directly. Set LUNORA_AGENT_MODE=0 to opt out of agent detection.