@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, so 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 a 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. An AI
agent can then 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.