@lunora/cli 1.0.0-alpha.362 → 1.0.0-alpha.363

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,48 +1,33 @@
1
1
  ---
2
2
  name: lunora-quickstart
3
- description: Creates or adds Lunora to an app. Use for new Lunora projects, `lunora init`,
4
- framework/provider wiring, the first `lunora dev` run, env vars, or writing
5
- the first schema + query/mutation round-trip.
3
+ description: Creates a new Lunora project or adds Lunora to an existing app, then gets
4
+ the first schema + query/mutation round-trip running. Use when the user asks
5
+ to "start a Lunora app", "add Lunora to my Vite/Next/Nuxt/SvelteKit/Astro
6
+ app", runs `lunora init` (`--vite`, `-t`, `--here`, `--add`), needs the
7
+ client provider wired (`LunoraClient` + `LunoraProvider`), or is running
8
+ `lunora dev` for the first time (background mode, `lunora dev status`/`logs`/
9
+ `stop`, `VITE_LUNORA_URL`).
6
10
  ---
7
11
 
8
12
  # Lunora Quickstart
9
13
 
10
- Set up a working Lunora project as fast as possible.
14
+ Get a working Lunora project with one live query/mutation round-trip.
11
15
 
12
- ## When to Use
13
-
14
- - Starting a brand new project with Lunora.
15
- - Adding Lunora to an existing Vite, Next.js, Astro, Nuxt, SvelteKit, or
16
- TanStack Start app.
17
- - Scaffolding a Lunora app for prototyping.
18
-
19
- ## When Not to Use
20
-
21
- - The project already has Lunora installed and `lunora/` exists — just build,
22
- and run `lunora codegen` after schema/function edits.
23
- - You only need to add auth to an existing Lunora app — use the
24
- `lunora-setup-auth` skill.
16
+ Skip this skill when `lunora/` already exists (just build, and run
17
+ `lunora codegen` after edits) or when the task is only auth
18
+ (`lunora-setup-auth`).
25
19
 
26
20
  ## Workflow
27
21
 
28
- 1. Determine the starting point: new project or existing app.
29
- 2. New project: scaffold with `lunora init` and pick a template.
30
- 3. Existing app: run `lunora init --here` to patch the Vite config and wire
31
- Lunora into the current project.
32
- 4. Run `lunora codegen` to generate `lunora/_generated/` and typecheck the
33
- schema + functions. This is the agent's feedback loop.
34
- 5. Start the dev loop. As an agent, run `lunora dev --background` — it starts
35
- the server as a managed detached process, blocks until it accepts requests,
36
- prints the URL + PID, and returns (under a detected AI agent, plain
37
- `lunora dev` does this automatically, with JSON logs). Never leave a bare
38
- `lunora dev` running in your own shell — it is long-running and does not
39
- exit.
40
- 6. Verify a query/mutation round-trip works end to end.
41
-
42
- ## Path 1: New Project (Recommended)
43
-
44
- `lunora init` fetches a whole-project template (frontend + worker entry + Vite
45
- plugin + `lunora/` already wired together).
22
+ 1. New project: `lunora init <name> --vite <framework>` or `-t <template>`.
23
+ Existing app: `lunora init --here`.
24
+ 2. `lunora codegen` to generate `lunora/_generated/`.
25
+ 3. Start the dev server in the background (`lunora dev --background`).
26
+ 4. Write or adapt a query + mutation and use them from a component.
27
+ 5. `lunora verify` (wrangler config + codegen dry-run + `tsc --noEmit`) passes,
28
+ and the client re-renders live after a mutation.
29
+
30
+ ## Path 1: new project
46
31
 
47
32
  ```bash
48
33
  lunora init my-app --vite react
@@ -50,133 +35,85 @@ cd my-app
50
35
  pnpm install
51
36
  ```
52
37
 
53
- ### Pick a stack: `--vite` (SPA) or `-t` (bespoke template)
38
+ Two scaffold paths take different flags.
54
39
 
55
- There are **two scaffold paths**, and they take different flags:
40
+ `--vite <framework>` applies the Lunora layer over the official create-vite
41
+ base. Use it for a plain SPA: `react` (the default), `vue`, `solid`, `svelte`,
42
+ or `vanilla` (overlay-only, not in the picker). `-t react|vue|solid|svelte` is
43
+ accepted as an alias for the same overlay.
56
44
 
57
- **`--vite <framework>` — the create-vite overlay.** Fetches the official
58
- create-vite base and applies the Lunora layer on top. Use it for a plain SPA:
59
-
60
- | `--vite` value | Stack |
61
- | -------------- | ----------------------------------------------- |
62
- | `react` | React SPA (**the default**) |
63
- | `vue` | Vue SPA |
64
- | `solid` | Solid SPA |
65
- | `svelte` | Svelte SPA |
66
- | `vanilla` | No framework (overlay-only — not in the picker) |
67
-
68
- **`-t` / `--template <type>` — a bespoke Lunora template.** Whole-project
69
- templates fetched remotely (via `giget`) from
45
+ `-t` / `--template <type>` fetches a whole-project template from
70
46
  `gh:anolilab/lunora/templates/<type>`:
71
47
 
72
- | `-t` value | Stack |
73
- | ----------------------------- | ---------------------------------------------------------- |
74
- | `next` | Next.js (App Router, OpenNext on Cloudflare) |
75
- | `tanstack-start-react` | TanStack Start (React) — SSR with live-loader routes |
76
- | `tanstack-start-solid` | TanStack Start (Solid) |
77
- | `tanstack-start-react-rspack` | TanStack Start (React) on Rsbuild, single worker |
78
- | `solid-v2` | Solid 2.0 SPA (`@solidjs/web`, `vite-plugin-solid` 3) |
79
- | `rspack-react` | React SPA on Rsbuild (`@lunora/rspack`) |
80
- | `react-router` | React Router v7 (framework mode), SSR in the Lunora worker |
81
- | `astro` | Astro + a standalone Lunora worker |
82
- | `analog` | AnalogJS (Angular) — single worker, Lunora in Nitro |
83
- | `nuxt` | Nuxt (Vue) — single worker, Lunora in Nitro |
84
- | `sveltekit` | SvelteKit + a standalone Lunora worker |
85
- | `expo` | React Native (Expo) — iOS/Android/web + a Lunora worker |
86
- | `standalone` | Worker-only Lunora backend, no frontend |
87
-
88
- > There is **no `--template vite`.** SPAs go through `--vite <framework>`; `-t`
89
- > is only for the bespoke templates above. The one exception is `solid-v2`:
90
- > create-vite's Solid base is still 1.x, and Solid 2.0 needs its own renderer
91
- > package, `jsxImportSource`, and Vite plugin major — so it ships as a template
92
- > rather than an overlay. `--vite solid` stays on Solid 1.x.
93
-
94
- With neither flag, an interactive run shows the framework picker (defaulting to
95
- the React overlay) and a **non-interactive run errors out** — so as an agent,
96
- always pass `--vite` or `-t` explicitly. If the user stated no preference,
97
- use `--vite react`.
98
-
99
- ### Useful `init` flags
48
+ | `-t` value | Stack |
49
+ | ----------------------------- | ---------------------------------------------------------------- |
50
+ | `next` | Next.js App Router (OpenNext) + a standalone Lunora worker |
51
+ | `vinext` | Next.js App Router on Vite (vinext), one worker (experimental) |
52
+ | `vinext-pages` | Next.js Pages Router on Vite (vinext), one worker (experimental) |
53
+ | `tanstack-start-react` | TanStack Start (React), SSR with live-loader routes |
54
+ | `tanstack-start-solid` | TanStack Start (Solid) |
55
+ | `tanstack-start-react-rspack` | TanStack Start (React) on Rsbuild, one worker |
56
+ | `rspack-react` | React SPA on Rsbuild (`@lunora/rspack`) |
57
+ | `solid-v2` | Solid 2.0 SPA (`@solidjs/web`, `vite-plugin-solid` 3) |
58
+ | `react-router` | React Router v7 framework mode, SSR in the Lunora worker |
59
+ | `astro` | Astro, Lunora composed into the adapter worker |
60
+ | `sveltekit` | SvelteKit, Lunora composed into the adapter worker |
61
+ | `nuxt` | Nuxt (Vue), Lunora mounted in Nitro |
62
+ | `analog` | AnalogJS (Angular), Lunora mounted in Nitro |
63
+ | `expo` | React Native (Expo) app + a Lunora worker |
64
+ | `standalone` | Worker-only backend, no frontend |
65
+
66
+ There is no `vite` template value; `-t vite` errors. Solid 2.0 is a template
67
+ rather than an overlay because create-vite's Solid base is still 1.x, so
68
+ `--vite solid` stays on Solid 1.x.
69
+
70
+ In a non-interactive shell, `init` errors unless it gets a name and a framework
71
+ (or `--yes`, which takes the React overlay). As an agent, pass `--vite` or `-t`
72
+ explicitly; if the user stated no preference, use `--vite react`.
73
+
74
+ Other flags:
100
75
 
101
76
  ```bash
102
- lunora init my-app --vite react --ci github # + a GitHub Actions deploy pipeline (or --ci gitlab)
103
- lunora init my-app -t next --add auth,email # scaffold capabilities non-interactively
77
+ lunora init my-app --vite react --ci github # add a deploy pipeline (or --ci gitlab)
78
+ lunora init my-app -t next --add auth,email # add capabilities without prompting
104
79
  lunora init my-app --vite react --yes # skip the interactive auth/email offer
105
80
  lunora init my-app --vite react --dry-run # walk every step, write nothing
106
81
  ```
107
82
 
108
- `--add` accepts a comma-separated list of `ai | auth | backup | browser |
109
- cloudflare-access | crons | email | flags | hyperdrive | payment | presence |
83
+ `--add` takes a comma-separated list of `ai | auth | auth-ui | backup | browser
84
+ | cloudflare-access | crons | email | flags | hyperdrive | payment | presence |
110
85
  queue | storage | workflow`. `--ref <branch|tag|commit>` pins the template
111
- source (e.g. `--ref alpha`); `--from <dir>` copies from a local templates root
112
- offline (expects `<type>/` subdirs).
113
-
114
- ### Generate types and push the first run
115
-
116
- Run this yourself — it is one-shot and exits cleanly:
117
-
118
- ```bash
119
- lunora codegen
120
- ```
121
-
122
- It writes `lunora/_generated/` and typechecks your schema + functions. Read its
123
- output to find out whether the code you just wrote is valid.
124
-
125
- ### Start the dev loop
126
-
127
- ```bash
128
- lunora dev
129
- ```
130
-
131
- `lunora dev` runs the Vite dev server with the Cloudflare Worker on the same
132
- origin, plus codegen-on-save and the Lunora Studio. It is long-running and does
133
- not exit, so:
86
+ source (e.g. `--ref alpha`); `--from <dir>` copies from a local templates root.
134
87
 
135
- - **Local development (user at the keyboard):** ask the user to run `lunora dev`
136
- in a terminal.
137
- - **Agents:** run `lunora dev --background`. It detaches the server, waits until
138
- it answers HTTP, prints `Dev server running at <url> (pid <n>)`, and exits —
139
- no orphaned shell, no PID bookkeeping. When Lunora detects an AI agent
140
- (Claude Code, Cursor, Codex, …), plain `lunora dev` flips into this mode
141
- automatically with JSON logs; `LUNORA_AGENT_MODE=0` opts out.
142
-
143
- Manage the running server afterwards:
144
-
145
- ```bash
146
- lunora dev status --json # machine-readable: url, pid, uptime, logFile
147
- lunora dev logs --lines 50 # tail the captured output (.lunora/dev.log)
148
- lunora dev stop # idempotent — succeeds even if nothing runs
149
- ```
150
-
151
- A second `lunora dev` never double-starts: it reports the existing instance
152
- (`.lunora/dev.json` is the lockfile). Probe readiness or liveness at
153
- `GET /_lunora/status` (`{"ok":true}`).
154
-
155
- Vite serves on `http://localhost:5173` by default; the Worker is served on the
156
- same origin via `@cloudflare/vite-plugin`.
157
-
158
- ## Path 2: Add Lunora to an Existing App
159
-
160
- Use this when the user already has a Vite-based frontend and wants Lunora as the
161
- backend.
88
+ ## Path 2: add Lunora to an existing app
162
89
 
163
90
  ```bash
164
91
  lunora init --here
165
92
  ```
166
93
 
167
- This finds the existing `vite.config.*` (or creates a minimal one), patches in
168
- the Lunora Vite plugin, and scaffolds a starter `lunora/`. Then run
169
- `lunora codegen` and `lunora dev` as above.
94
+ This detects the framework from `package.json`, scaffolds `lunora/schema.ts` and
95
+ `lunora/messages.ts` (skipped if a schema exists), and patches or creates the
96
+ Vite config with the `lunora()` plugin. SvelteKit, Nuxt and Astro wire Lunora
97
+ through their server entry instead, so their Vite config is left alone. It then
98
+ prints framework-specific next steps: the packages to install, the provider to
99
+ mount, and how to compose the worker. Follow those; the CLI does not edit
100
+ framework-owned files.
170
101
 
171
- ### Wire up the client provider
102
+ Templates and `--vite` overlays map `#lunora/*` to `./lunora/*` in
103
+ `package.json` `imports`, which is why their function files import
104
+ `#lunora/_generated/server.js`. A `--here` project has no such mapping; its
105
+ starter uses the relative `./_generated/server`. Match whichever the project
106
+ already uses.
172
107
 
173
- Create the `LunoraClient` once at module scope (never inside a component) and
174
- wrap the app with the framework provider. React example:
108
+ ### Client provider
109
+
110
+ Create the `LunoraClient` once at module scope (not inside a component, or every
111
+ render opens a new socket) and wrap the app in the framework provider:
175
112
 
176
113
  ```tsx
177
114
  // src/client/main.tsx
178
- import { LunoraClient } from "@lunora/client";
179
115
  import { LunoraProvider } from "@lunora/react";
116
+ import { LunoraClient } from "lunorash/client";
180
117
  import { StrictMode } from "react";
181
118
  import { createRoot } from "react-dom/client";
182
119
 
@@ -195,16 +132,14 @@ createRoot(document.querySelector("#root")!).render(
195
132
  );
196
133
  ```
197
134
 
198
- Every client adapter has a matching provider: `@lunora/vue`, `@lunora/solid`,
199
- `@lunora/svelte`, `@lunora/angular` (`provideLunora` / `injectLunoraClient`),
200
- and `@lunora/react-native` (`createLunoraClient`, re-exporting `@lunora/react`).
201
- For meta-frameworks, `@lunora/astro` and `@lunora/nuxt` mount Lunora on the
202
- server side. `VITE_LUNORA_URL` is optional — it defaults to `location.origin`,
203
- which is correct for the single-origin dev setup.
204
-
205
- ## Writing Your First Function
135
+ `LunoraClient` is also exported by `@lunora/client`. Other adapters:
136
+ `@lunora/vue`, `@lunora/solid`, `@lunora/svelte`, `@lunora/angular`
137
+ (`provideLunora` / `injectLunoraClient`), and `@lunora/react-native`
138
+ (`createLunoraClient`, re-exporting `@lunora/react`). `@lunora/astro` and
139
+ `@lunora/nuxt` mount Lunora server-side. `VITE_LUNORA_URL` is optional; the
140
+ same-origin default is right for local dev.
206
141
 
207
- Create a schema and a query/mutation to verify the full loop.
142
+ ## First function
208
143
 
209
144
  `lunora/schema.ts`:
210
145
 
@@ -223,27 +158,25 @@ export default defineSchema({
223
158
  `lunora/todos.ts`:
224
159
 
225
160
  ```ts
226
- import type { Id } from "#lunora/_generated/server.js";
227
161
  import { mutation, query, v } from "#lunora/_generated/server.js";
228
162
 
229
163
  export const list = query.query(async ({ ctx }) => ctx.db.query("todos").withIndex("by_creation").collect());
230
164
 
231
165
  export const add = mutation
232
- .input({ text: v.string() })
233
- .mutation(async ({ ctx, args: { text } }): Promise<Id<"todos">> => ctx.db.insert("todos", { text, done: false, createdAt: Date.now() }));
166
+ .input({ text: v.string().max(4096) })
167
+ .mutation(async ({ ctx, args }) => ctx.db.insert("todos", { text: args.text, done: false, createdAt: Date.now() }));
234
168
  ```
235
169
 
236
- Run `lunora codegen`, then use it in a component. The `api` object and `Doc` /
237
- `Id` types come from `lunora/_generated/`:
170
+ Run `lunora codegen`, then call it from a component. Argument and return types
171
+ are inferred from the generated `api`, so no casts are needed:
238
172
 
239
173
  ```tsx
240
174
  import { useMutation, useQuery } from "@lunora/react";
241
175
 
242
176
  import { api } from "../../lunora/_generated/api";
243
- import type { Doc } from "../../lunora/_generated/dataModel";
244
177
 
245
- function Todos() {
246
- const todos = useQuery(api.todos.list, {}) as Doc<"todos">[] | undefined;
178
+ export const Todos = () => {
179
+ const todos = useQuery(api.todos.list, {});
247
180
  const { mutate: add, pending } = useMutation(api.todos.add);
248
181
 
249
182
  return (
@@ -251,58 +184,58 @@ function Todos() {
251
184
  <button disabled={pending} onClick={() => add({ text: "New todo" })}>
252
185
  Add
253
186
  </button>
254
- {todos?.map((t) => (
255
- <div key={t._id}>{t.text}</div>
187
+ {todos?.map((todo) => (
188
+ <div key={todo._id}>{todo.text}</div>
256
189
  ))}
257
190
  </div>
258
191
  );
259
- }
192
+ };
260
193
  ```
261
194
 
262
- `useQuery` opens a live subscription: the list re-renders the instant any
263
- mutation changes the queried rows.
195
+ `useQuery` returns `undefined` while loading, then re-renders whenever a
196
+ mutation changes the queried rows. A function in a folder nests in `api`:
197
+ `lunora/billing/invoices.ts` is `api.billing.invoices.*`.
264
198
 
265
- ## Development vs Production
199
+ ## Dev server
266
200
 
267
- Use `lunora dev` during development. When ready to ship:
201
+ `lunora dev` runs the worker (behind Vite via `@cloudflare/vite-plugin` in Vite
202
+ projects), codegen-on-save, and the embedded Studio at `/__lunora`. It does not
203
+ exit on its own.
204
+
205
+ - User at the keyboard: ask them to run `lunora dev` in a terminal.
206
+ - Agent: run `lunora dev --background`. It detaches, waits until the server
207
+ answers, prints `Dev server running at <url> (pid <n>)`, and exits. When an AI
208
+ agent is detected (Claude Code, Cursor, Codex, …), plain `lunora dev` does
209
+ this automatically with JSON logs; `LUNORA_AGENT_MODE=0` opts out. Avoid a
210
+ bare foreground `lunora dev` in your own shell, since it blocks until killed.
268
211
 
269
212
  ```bash
270
- lunora deploy
213
+ lunora dev status --json # url, pid, uptime, logFile
214
+ lunora dev logs --lines 50 # tail .lunora/dev.log
215
+ lunora dev stop # idempotent
271
216
  ```
272
217
 
273
- `lunora deploy` runs codegen, the schema-drift gate, and `wrangler deploy`. Do
274
- not use it during day-to-day development.
218
+ A second `lunora dev` reports the running instance instead of starting another
219
+ (`.lunora/dev.json` is the lockfile). `GET /_lunora/status` returns
220
+ `{"ok":true}` once the worker is up. Vite defaults to `http://localhost:5173`.
221
+ `lunora dev --tunnel` shares the worker on a public `*.trycloudflare.com` URL
222
+ (needs `cloudflared`).
275
223
 
276
- Before deploying, run the preflight:
224
+ ## Shipping
277
225
 
278
226
  ```bash
279
- lunora doctor
227
+ lunora doctor # preflight: SHARD DO binding, placeholder D1 ids, .dev.vars secrets, container exports
228
+ lunora deploy # codegen + schema-drift gate + wrangler deploy
280
229
  ```
281
230
 
282
- It checks `wrangler.jsonc` (the `SHARD` durable-object binding), D1 placeholder
283
- ids, `.dev.vars` secrets, and container exports.
284
-
285
- ## Next Steps
286
-
287
- - Add authentication: use the `lunora-setup-auth` skill.
288
- - Add a prebuilt capability (mail, presence, storage, rate limit, crons):
289
- `lunora registry add <item>` (see `lunora registry list`). For capabilities
290
- with a dedicated skill, use it: `lunora-setup-mail`, `lunora-setup-storage`,
291
- `lunora-setup-scheduler`. See the `lunora` router's capability entry for the
292
- full routing.
293
- - Build your own reusable capability: use the `lunora-create-package` skill.
294
- - Plan a schema change: use the `lunora-migration-helper` skill.
295
- - Scaffold more functions: `vis generate lunora-query --name=listMessages`,
296
- `lunora-mutation`, `lunora-action`, `lunora-table`, `lunora-cron` (always use
297
- the `--name=value` form).
298
-
299
- ## Checklist
300
-
301
- - [ ] Determined starting point: new project or existing app.
302
- - [ ] New project: scaffolded with `lunora init --vite <framework>` (SPA) or
303
- `lunora init -t <template>` (bespoke) — never `--template vite`.
304
- - [ ] Existing app: ran `lunora init --here` and wired `LunoraProvider`.
305
- - [ ] Ran `lunora codegen`: `lunora/_generated/` exists and typecheck is clean.
306
- - [ ] Dev server is running — user terminal, or `lunora dev --background`
307
- (check with `lunora dev status`).
308
- - [ ] Verified a query/mutation round-trip re-renders the client live.
231
+ Use `lunora-deploy` for bindings, secrets and environments.
232
+
233
+ ## Next steps
234
+
235
+ - Auth: `lunora-setup-auth`.
236
+ - Add-ons: `lunora add <feature>` (e.g. `email`, `storage`, `crons`,
237
+ `presence`; `lunora registry list` for all). Mail, storage and scheduling have
238
+ their own skills: `lunora-setup-mail`, `lunora-setup-storage`,
239
+ `lunora-setup-scheduler`.
240
+ - Schema and function rules: `lunora-functions`. Schema changes on live data:
241
+ `lunora-migration-helper`.