@agent-native/core 0.7.52 → 0.7.53

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.
@@ -5,315 +5,347 @@ description: "How to create and publish your own agent-native app templates."
5
5
 
6
6
  # Creating Templates
7
7
 
8
- How to build and publish your own agent-native app template.
8
+ Templates are complete, forkable agent-native apps that solve a real workflow. The first-party templates are built with the same framework surface you use: React routes for the UI, Drizzle SQL for data, actions for operations, workspace resources for agent behavior, and polling sync so the agent and UI stay aligned.
9
9
 
10
- ## Overview {#overview}
10
+ A good template:
11
11
 
12
- Templates are complete, forkable agent-native apps that solve a specific use case. The analytics, content, slides, and video templates that ship with Agent-Native are all built this way. Anyone can create a template and share it with the community.
12
+ - Solves one workflow end-to-end, with useful seed data or an empty-state flow.
13
+ - Stores durable state in SQL, not JSON files.
14
+ - Defines app operations as `defineAction()` actions.
15
+ - Exposes navigation and selection through application state.
16
+ - Ships a clear `AGENTS.md` plus focused skills for non-obvious workflows.
17
+ - Registers onboarding steps for required providers and secrets.
18
+ - Works as a standalone app and as part of a multi-app workspace.
13
19
 
14
- A good template:
20
+ ## Start from Starter {#start-from-starter}
15
21
 
16
- - Solves a real workflow end-to-end (not a toy demo)
17
- - Works out of the box with example data
18
- - Has a comprehensive `AGENTS.md` so the AI agent understands the architecture
19
- - Includes actions for key operations the agent can call
20
- - Follows the core rules: data in SQL, all AI through agent chat, actions for operations, real-time sync, agent can modify code
22
+ Use the CLI-only Starter scaffold when you want a blank app with the framework wiring already in place:
21
23
 
22
- ## Start from the starter {#start-from-starter}
24
+ ```bash
25
+ pnpm dlx @agent-native/core create my-template --template starter --standalone
26
+ ```
23
27
 
24
- The fastest way to start is with the built-in starter template:
28
+ For a workspace with multiple apps, run the picker and include Starter with any domain templates you want:
25
29
 
26
30
  ```bash
27
- npx @agent-native/core create my-template
31
+ pnpm dlx @agent-native/core create my-platform
28
32
  ```
29
33
 
30
- This scaffolds a minimal agent-native app with the standard directory structure, a working dev server, file watching, SSE, and an example action. Build your template on top of this.
34
+ Starter gives you auth, the agent sidebar, SQL-backed resources, tools, application state, actions, and polling sync. You add the domain model and product UI.
31
35
 
32
- ## Project structure {#project-structure}
36
+ ## Project Structure {#project-structure}
33
37
 
34
- Every template follows the same convention:
38
+ Every template follows the same broad layout:
35
39
 
36
40
  ```text
37
41
  my-template/
38
- app/ # React frontend
39
- routes/ # File-based page routes (auto-discovered)
40
- _index.tsx # / (home page)
41
- settings.tsx # /settings
42
- root.tsx # App shell <html>, <head>, <body>, providers
43
- entry.client.tsx # Client hydration entry
44
- routes.ts # Route config — flatRoutes()
45
- components/ # UI components
46
- components/ui/ # Reusable primitives (shadcn/ui)
47
- hooks/ # React hooks
48
- lib/utils.ts # cn() utility
49
-
50
- server/ # Nitro API server
51
- routes/ # File-based API routes (auto-discovered by Nitro)
52
- [...page].get.ts # SSR catch-all (delegates to React Router)
53
- plugins/ # Server plugins (startup logic)
54
- lib/ # Shared server modules
55
-
56
- shared/ # Isomorphic types (imported by client & server)
57
- api.ts # Shared interfaces
58
-
59
- actions/ # Agent-callable actions
60
- run.ts # Action dispatcher (don't modify)
61
- *.ts # Your actions — one per operation
62
-
63
- data/ # File-based state (watched by SSE)
64
- .gitkeep # Or seed data for the template
65
-
66
- .agents/skills/ # Agent skills — detailed guidance per topic
67
-
68
- AGENTS.md # Master agent instructions
69
- react-router.config.ts # React Router config (ssr, appDirectory)
70
- package.json # Scripts: dev, build, start, action, typecheck
71
- vite.config.ts # Vite config (React Router + Nitro)
72
- tsconfig.json # TypeScript config
42
+ app/
43
+ root.tsx # HTML shell and providers
44
+ routes/ # React Router file routes
45
+ components/ # Template UI
46
+ hooks/ # UI state and data hooks
47
+
48
+ actions/
49
+ *.ts # defineAction operations
50
+
51
+ server/
52
+ db/schema.ts # Drizzle schema
53
+ plugins/db.ts # additive migrations
54
+ plugins/*.ts # startup integrations
55
+ routes/api/*.ts # custom routes only when actions are not enough
56
+
57
+ shared/
58
+ types.ts # shared client/server types
59
+
60
+ .agents/skills/
61
+ <skill>/SKILL.md # agent guidance for complex workflows
62
+
63
+ AGENTS.md # template-specific agent instructions
64
+ package.json
65
+ react-router.config.ts
66
+ vite.config.ts
73
67
  ```
74
68
 
75
- ## Build your client {#build-your-client}
76
-
77
- The client uses React Router v7 framework mode with file-based routing. Pages go in `app/routes/`, global providers live in `app/root.tsx`, and React Query handles data fetching.
69
+ Do not add a `data/` directory for application state. Durable app data belongs in SQL, and the UI reads it through actions or typed server handlers.
78
70
 
79
- ```ts
80
- // app/root.tsx — App shell with providers
81
- import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router";
82
- import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
83
- import { useDbSync } from "@agent-native/core";
71
+ ## Model Data In SQL {#data-models}
84
72
 
85
- const queryClient = new QueryClient();
73
+ Define domain tables with the framework Drizzle helpers so schemas stay portable across SQLite, Postgres, D1, Turso, Supabase, and Neon:
86
74
 
87
- export function Layout({ children }: { children: React.ReactNode }) {
88
- return (
89
- <html lang="en">
90
- <head>
91
- <meta charSet="utf-8" />
92
- <meta name="viewport" content="width=device-width, initial-scale=1" />
93
- <Meta />
94
- <Links />
95
- </head>
96
- <body>
97
- {children}
98
- <ScrollRestoration />
99
- <Scripts />
100
- </body>
101
- </html>
102
- );
103
- }
75
+ ```ts
76
+ // server/db/schema.ts
77
+ import {
78
+ table,
79
+ text,
80
+ integer,
81
+ now,
82
+ ownableColumns,
83
+ createSharesTable,
84
+ } from "@agent-native/core/db/schema";
85
+
86
+ export const projects = table("projects", {
87
+ id: text("id").primaryKey(),
88
+ title: text("title").notNull(),
89
+ status: text("status", {
90
+ enum: ["draft", "active", "archived"],
91
+ })
92
+ .notNull()
93
+ .default("draft"),
94
+ sortOrder: integer("sort_order").notNull().default(0),
95
+ ...ownableColumns(),
96
+ createdAt: text("created_at").notNull().default(now()),
97
+ updatedAt: text("updated_at").notNull().default(now()),
98
+ });
104
99
 
105
- export default function Root() {
106
- useDbSync({ queryClient, queryKeys: ["items", "projects"] });
107
- return (
108
- <QueryClientProvider client={queryClient}>
109
- <Outlet />
110
- </QueryClientProvider>
111
- );
112
- }
100
+ export const projectShares = createSharesTable("project_shares", "project");
113
101
  ```
114
102
 
115
- Routes are auto-discovered from `app/routes/` via `flatRoutes()`. Create a file to add a page:
103
+ Schema changes must be additive. Add tables and columns through `runMigrations()` in `server/plugins/db.ts`; never use destructive SQL, `drizzle-kit push`, table renames, or column drops.
116
104
 
117
105
  ```ts
118
- // app/routes/_index.tsx → /
119
- export default function Dashboard() {
120
- return <div>Home page</div>;
121
- }
122
-
123
- // app/routes/settings.tsx → /settings
124
- export default function Settings() {
125
- return <div>Settings page</div>;
126
- }
106
+ // server/plugins/db.ts
107
+ import { runMigrations } from "@agent-native/core/db/migrations";
108
+
109
+ export default runMigrations([
110
+ {
111
+ id: "001_create_projects",
112
+ sql: `CREATE TABLE IF NOT EXISTS projects (
113
+ id TEXT PRIMARY KEY,
114
+ title TEXT NOT NULL,
115
+ status TEXT NOT NULL DEFAULT 'draft',
116
+ sort_order INTEGER NOT NULL DEFAULT 0,
117
+ owner_email TEXT NOT NULL,
118
+ org_id TEXT,
119
+ visibility TEXT NOT NULL DEFAULT 'private',
120
+ created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
121
+ updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
122
+ )`,
123
+ },
124
+ ]);
127
125
  ```
128
126
 
129
- The `useDbSync` hook (formerly `useFileWatcher`) polls `/_agent-native/poll` and invalidates react-query caches when data changes. This is how the UI stays in sync when the agent modifies data.
127
+ Use the [Database](/docs/database) and [Security](/docs/security) docs before adding schemas that hold user or org data.
130
128
 
131
- ## Add API routes {#add-api-routes}
129
+ ## Define Operations As Actions {#actions}
132
130
 
133
- API routes serve data from files and handle mutations. They go in `server/routes/` as file-based routes:
131
+ Actions are the single source of truth for app behavior. The agent calls them as tools, the frontend calls them through hooks or HTTP, and other apps can reach them through MCP/A2A.
134
132
 
135
133
  ```ts
136
- // server/routes/api/items/index.get.ts
137
- import { defineEventHandler } from "h3";
138
- import { readdir, readFile, mkdir } from "node:fs/promises";
139
- import path from "node:path";
140
-
141
- export default defineEventHandler(async () => {
142
- const dir = "./data/items";
143
- await mkdir(dir, { recursive: true });
144
- const files = await readdir(dir);
145
- return Promise.all(
146
- files
147
- .filter((f) => f.endsWith(".json"))
148
- .map(async (f) => {
149
- const content = await readFile(path.join(dir, f), "utf-8");
150
- return JSON.parse(content);
151
- }),
152
- );
134
+ // actions/create-project.ts
135
+ import { defineAction } from "@agent-native/core";
136
+ import { getDb } from "@agent-native/core/db";
137
+ import { nanoid } from "nanoid";
138
+ import { z } from "zod";
139
+ import * as schema from "../server/db/schema";
140
+
141
+ export default defineAction({
142
+ description: "Create a project.",
143
+ schema: z.object({
144
+ title: z.string().min(1).describe("Project title"),
145
+ }),
146
+ run: async ({ title }, ctx) => {
147
+ const db = getDb();
148
+ const id = nanoid();
149
+ await db.insert(schema.projects).values({
150
+ id,
151
+ title,
152
+ ownerEmail: ctx.userEmail,
153
+ orgId: ctx.orgId,
154
+ });
155
+ return { id, title };
156
+ },
153
157
  });
154
158
  ```
155
159
 
156
- Each route file exports a default `defineEventHandler`. Both the UI and the agent can create items — the UI via `POST /api/items`, the agent by writing directly to `data/items/`. The SSE watcher ensures both paths trigger UI updates.
160
+ Use `http: { method: "GET" }` or `readOnly: true` for read-only actions. Use `toolCallable: false` for high-blast-radius actions that should not run from sandboxed tools.
157
161
 
158
- ## Add actions {#add-actions}
162
+ ## Build The UI {#ui}
159
163
 
160
- Actions are the agent's toolbox. Each action handles one operation fetching data from an API, generating content, processing files, etc:
164
+ Routes live in `app/routes/` and use React Router v7 file routing. Query data through actions or API handlers, and make mutations optimistic by default.
161
165
 
162
- ```typescript
163
- // actions/import-data.ts
164
- import { parseArgs } from "@agent-native/core";
165
- import { writeFile, mkdir } from "node:fs/promises";
166
+ ```tsx
167
+ import { useActionMutation, useActionQuery } from "@agent-native/core/client";
166
168
 
167
- export default async function importData(args: string[]) {
168
- const { url, name } = parseArgs(args);
169
- if (!url) {
170
- console.error("--url is required");
171
- process.exit(1);
172
- }
169
+ export default function ProjectsPage() {
170
+ const { data: projects = [] } = useActionQuery("list-projects", {});
171
+ const create = useActionMutation("create-project");
173
172
 
174
- const res = await fetch(url);
175
- const data = await res.json();
176
-
177
- const slug = name ?? "imported";
178
- await mkdir("./data/imports", { recursive: true });
179
- await writeFile(`./data/imports/${slug}.json`, JSON.stringify(data, null, 2));
180
- console.log(
181
- `Imported ${Array.isArray(data) ? data.length + " records" : "data"} to data/imports/${slug}.json`,
173
+ return (
174
+ <button onClick={() => create.mutate({ title: "Launch plan" })}>
175
+ New project ({projects.length})
176
+ </button>
182
177
  );
183
178
  }
184
179
  ```
185
180
 
186
- ```bash
187
- # The agent can run this
188
- pnpm action import-data --url https://api.example.com/data --name users
181
+ Wire polling once near the app shell so React Query caches refresh when the agent, another tab, or an action changes data:
182
+
183
+ ```tsx
184
+ import { useDbSync } from "@agent-native/core/client";
185
+ import { useQueryClient } from "@tanstack/react-query";
186
+
187
+ export function AppSync() {
188
+ const queryClient = useQueryClient();
189
+ useDbSync({ queryClient });
190
+ return null;
191
+ }
189
192
  ```
190
193
 
191
- Scripts should write their output to `data/` — the SSE watcher will notify the UI. Use `console.log` for output the agent can see. Use `console.error` and `process.exit(1)` for errors.
194
+ ## Add Application State {#application-state}
192
195
 
193
- ## Add data models {#add-data-models}
196
+ Application state is how the agent knows what the user is seeing. At minimum, add:
194
197
 
195
- Seed your template with example data so it works immediately. Put JSON files in `data/` matching the structure your API routes expect:
198
+ - A UI hook that writes `navigation` state when routes, selected records, filters, or editor selections change.
199
+ - A `view-screen` action that reads that state and returns the current screen snapshot.
200
+ - A `navigate` action that writes a one-shot `navigate` command for the UI to consume.
196
201
 
197
- ```text
198
- data/
199
- items/
200
- example-1.json # {"id": "example-1", "title": "...", "status": "active"}
201
- example-2.json
202
- config.json # App-level config
203
- sync-config.json # (optional) Firestore sync glob patterns
202
+ ```ts
203
+ // actions/navigate.ts
204
+ import { defineAction } from "@agent-native/core";
205
+ import { writeAppState } from "@agent-native/core/application-state";
206
+ import { z } from "zod";
207
+
208
+ export default defineAction({
209
+ description: "Navigate the UI.",
210
+ schema: z.object({
211
+ view: z.enum(["home", "project"]),
212
+ projectId: z.string().optional(),
213
+ }),
214
+ run: async (args) => {
215
+ await writeAppState("navigate", args);
216
+ return { ok: true };
217
+ },
218
+ });
204
219
  ```
205
220
 
206
- Keep your data models simple — flat JSON files, one per entity. The agent can grep, read, and modify them. Deeply nested structures or binary formats make it harder for the agent to work with the data.
221
+ See [Context Awareness](/docs/context-awareness) for the full pattern.
207
222
 
208
- ## Write AGENTS.md {#write-agents-md}
223
+ ## Use API Routes Sparingly {#api-routes}
209
224
 
210
- This is the most important file in your template. `AGENTS.md` tells the AI agent how your app works, what it can and can't do, and how to make changes:
225
+ Prefer actions for app operations. Create custom Nitro routes only for surfaces that cannot be actions cleanly:
211
226
 
212
- ```markdown
213
- # My Template Agent-Native App
227
+ - File upload or binary streaming.
228
+ - Public anonymous pages and webhooks.
229
+ - OAuth callbacks and provider-specific protocol handlers.
230
+ - Server-rendered public content.
214
231
 
215
- ## Architecture
232
+ Custom routes that touch ownable data must call `getSession(event)` and wrap database work in `runWithRequestContext({ userEmail, orgId }, fn)` before using access helpers.
216
233
 
217
- This is an **@agent-native/core** application.
234
+ ## Write Agent Instructions {#write-agents-md}
218
235
 
219
- ### Core Principles
236
+ `AGENTS.md` is the agent's map of your app. Keep it specific and operational:
220
237
 
221
- 1. **Data lives in SQL** — All state in SQL via Drizzle ORM.
222
- 2. **All AI through agent chat** — No inline LLM calls.
223
- 3. **Actions for operations** — `pnpm action <name>` for complex work.
224
- 4. **Real-time sync** — Polling keeps UI in sync with agent changes.
225
- 5. **Agent can update code** — Edit components, routes, actions.
226
-
227
- ### Directory Structure
238
+ ```markdown
239
+ # My Template
228
240
 
229
- app/ # React frontend (file-based routing in app/routes/)
230
- server/ # Nitro API server
231
- actions/ # Agent-callable actions
232
- data/ # File-based state
241
+ ## Product Model
233
242
 
234
- ### Available Actions
243
+ Projects are the top-level resource. They contain tasks and notes.
235
244
 
236
- - `pnpm action import-data --url <url>` — Import data from API
237
- - `pnpm action generate-report --id <id>` — Generate a report
245
+ ## Navigation State
238
246
 
239
- ### Data Model
247
+ - `navigation.view`: `home` or `project`
248
+ - `navigation.projectId`: selected project when on a project page
240
249
 
241
- Items are stored as `data/items/<id>.json`:
250
+ ## Actions
242
251
 
243
- { "id": "...", "title": "...", "status": "active" }
252
+ | Action | Purpose |
253
+ | ---------------- | --------------------------- |
254
+ | `list-projects` | List accessible projects |
255
+ | `create-project` | Create a project |
256
+ | `update-project` | Rename or archive a project |
244
257
 
245
- ### Key Patterns
258
+ ## Rules
246
259
 
247
- - API routes in `server/routes/` serve files from `data/`
248
- - UI delegates AI work via `sendToAgentChat()`
249
- - Actions write results to `data/` SSE updates the UI
260
+ - Use `view-screen` before acting on "this project" if the current screen is unclear.
261
+ - Use actions for project changes; do not write raw SQL unless debugging.
262
+ - For shared projects, check access through framework sharing helpers.
250
263
  ```
251
264
 
252
- > Code blocks inside `AGENTS.md` would normally be fenced with triple backticks they're shown as indented code here to keep this outer example readable.
265
+ Update `AGENTS.md` whenever you add a new action, route, state key, or recurring workflow.
253
266
 
254
- Be specific about your data models, available actions, and key patterns. The better your `AGENTS.md`, the better the agent will work with your template.
267
+ ## Add Skills {#skills}
255
268
 
256
- ## Add skills {#add-skills}
257
-
258
- For complex topics that don't fit in `AGENTS.md`, create skills in `.agents/skills/`. Each skill is a Markdown file with detailed guidance for a specific topic:
269
+ Use skills for detailed patterns that would bloat `AGENTS.md`: provider-specific APIs, import/export formats, complex editing flows, or domain terminology.
259
270
 
260
271
  ```markdown
261
- # .agents/skills/bigquery/SKILL.md
262
-
263
- ## BigQuery Integration
264
-
265
- ### Column Reference
266
-
267
- - `event_name` — The event type (string)
268
- - `event_timestamp` — Microsecond timestamp (int64)
269
- - `user_pseudo_id` — Anonymous user ID (string)
272
+ ---
273
+ name: project-imports
274
+ description: How to import projects from the legacy CSV export.
275
+ ---
270
276
 
271
- ### Common Queries
277
+ # Project Imports
272
278
 
273
- ...
279
+ Use this skill when the user uploads a legacy project CSV.
274
280
 
275
- ### Gotchas
281
+ ## Rules
276
282
 
277
- - Always use `event_date` partition filter to avoid full table scans
278
- - Timestamps are in microseconds, not milliseconds
283
+ - Validate required columns before creating rows.
284
+ - Use `create-project` for each project so ownership and sync are correct.
285
+ - Save rejected rows as a note attached to the import summary.
279
286
  ```
280
287
 
281
- Skills let you give the agent deep domain knowledge for specific integrations or patterns without bloating your main `AGENTS.md`.
288
+ Store template skills in `.agents/skills/<name>/SKILL.md`. If users should be able to edit the guidance at runtime, surface it through workspace resources as well.
282
289
 
283
- ## Onboarding & API keys {#onboarding}
290
+ ## Register Setup Steps {#onboarding}
284
291
 
285
- If your template needs API keys or external service configuration, document them in a `.env.example` file:
292
+ If a template needs an API key, OAuth connection, or provider account, register an onboarding step instead of burying the requirement in a README.
286
293
 
287
- ```bash
288
- # .env.example
289
- BIGQUERY_PROJECT_ID=your-project-id
290
- STRIPE_SECRET_KEY=sk_live_...
291
- OPENAI_API_KEY=sk-...
294
+ ```ts
295
+ // server/plugins/onboarding.ts
296
+ import { defineNitroPlugin } from "@agent-native/core/server";
297
+ import { registerOnboardingStep } from "@agent-native/core/onboarding";
298
+
299
+ export default defineNitroPlugin(() => {
300
+ registerOnboardingStep({
301
+ id: "github",
302
+ title: "Connect GitHub",
303
+ description: "Needed to import repositories and pull requests.",
304
+ order: 100,
305
+ methods: [
306
+ {
307
+ id: "token",
308
+ kind: "form",
309
+ primary: true,
310
+ label: "Save token",
311
+ payload: {
312
+ fields: [
313
+ { key: "GITHUB_TOKEN", label: "GitHub token", secret: true },
314
+ ],
315
+ },
316
+ },
317
+ ],
318
+ isComplete: () => !!process.env.GITHUB_TOKEN,
319
+ });
320
+ });
292
321
  ```
293
322
 
294
- When users fork your template, they copy `.env.example` to `.env` and fill in their own values. Keep the number of required keys minimal — the template should work with example data before any keys are configured.
323
+ See [Onboarding & API Keys](/docs/onboarding).
295
324
 
296
- ## Make your template multi-app-workspace ready {#workspace-ready}
325
+ ## Make It Workspace-Ready {#workspace-ready}
297
326
 
298
- Templates rarely live in isolation — most users will scaffold yours alongside other apps in a [multi-app workspace](/docs/multi-app-workspace), often coordinated by [Dispatch](/docs/dispatch). Three checkpoints make your template a good citizen:
327
+ Templates should fit naturally into [Multi-App Workspaces](/docs/multi-app-workspace), usually coordinated by [Dispatch](/docs/dispatch).
299
328
 
300
- 1. **Mount A2A so other apps can call yours.** Add `mountA2A()` in a server plugin so your actions are reachable over the agent-to-agent protocol. Other apps in the workspace (and Dispatch's orchestrator) discover and invoke them automatically. See [A2A Protocol](/docs/a2a-protocol).
301
- 2. **Publish an agent card with skill metadata.** Your A2A peer exposes a manifest describing what your template does and which actions it offers. Dispatch reads these cards to decide which specialist to route a request to — clear, specific skill descriptions make routing accurate.
302
- 3. **Register secrets through onboarding.** Any third-party API keys your template needs (OpenAI, Stripe, SendGrid, etc.) should be registered via the [onboarding](/docs/onboarding) system. They show up in the workspace setup checklist and the Dispatch secrets vault, instead of forcing every user to hand-edit `.env`.
329
+ Checklist:
303
330
 
304
- Hit those three and your template drops into any workspace cleanly.
331
+ - Mount A2A through the framework agent chat plugin or `mountA2A()` so sibling apps can call your agent.
332
+ - Keep the agent card descriptions specific enough for Dispatch to route work accurately.
333
+ - Register required secrets/onboarding so setup appears in the sidebar and Dispatch can manage shared credentials.
334
+ - Keep cross-cutting instructions in workspace `AGENTS.md` or workspace resources, not copied into every app.
335
+ - Use sharing/access helpers for all ownable resources so org-scoped workspaces stay isolated.
305
336
 
306
- ## Publishing {#publishing}
337
+ ## Publish A Template {#publishing}
307
338
 
308
- To share your template:
339
+ Before sharing:
309
340
 
310
- 1. Push your template to a public GitHub repo
311
- 2. Make sure it works with `pnpm install && pnpm dev`
312
- 3. Include seed data in `data/` so it works without API keys
313
- 4. Write a clear README explaining what the template does and how to configure it
341
+ 1. Run `pnpm install`, `pnpm typecheck`, and the template's tests.
342
+ 2. Verify it works with no optional provider keys configured.
343
+ 3. Check auth, sharing, and two-user data isolation.
344
+ 4. Document required env vars and onboarding steps.
345
+ 5. Include examples or seed rows through additive migrations, not tracked runtime data files.
314
346
 
315
- Community templates can be shared via GitHub. The agent-native CLI supports creating from any git repo:
347
+ Community templates can be created from a GitHub repo:
316
348
 
317
349
  ```bash
318
- npx @agent-native/core create my-app --template github:user/repo
350
+ pnpm dlx @agent-native/core create my-app --template github:user/repo
319
351
  ```
@@ -67,7 +67,7 @@ The framework ships with production-ready templates you can use as daily drivers
67
67
  - **[Video](/templates/video)** — video composition with Remotion
68
68
  - **[Analytics](/templates/analytics)** — data platform (like Amplitude/Mixpanel)
69
69
  - **[Clips](/templates/clips)** — async screen + camera recording (replaces Loom)
70
- - **[Design](/templates/design)** — agent-native design tool (like Figma/Canva)
70
+ - **[Design](/templates/design)** — agent-native HTML prototyping studio
71
71
  - **[Forms](/templates/forms)** — form builder (like Typeform)
72
72
  - **[Dispatch](/templates/dispatch)** — workspace control plane: shared secrets, integrations, jobs
73
73
 
@@ -123,7 +123,7 @@ Anywhere. The server runs on Nitro, which compiles to any deployment target: Nod
123
123
 
124
124
  ### Why polling instead of WebSockets? {#why-polling-not-websockets}
125
125
 
126
- Polling works in every deployment environment — including serverless, edge, and container platforms where persistent connections aren't available. The framework polls every 2 seconds using a lightweight version counter. When changes are detected, React Query caches are invalidated and components re-render. It's simple, reliable, and universal. SSE is also supported as an alternative.
126
+ Polling works in every deployment environment — including serverless, edge, and container platforms where persistent connections aren't available. The framework polls every 2 seconds using a lightweight version counter. When changes are detected, React Query caches are invalidated and components re-render. It's simple, reliable, and universal.
127
127
 
128
128
  ### Why can't the UI call an LLM directly? {#why-no-inline-llm-calls}
129
129
 
@@ -41,7 +41,7 @@ The framework provides type-safe APIs so you never deal with raw messaging:
41
41
 
42
42
  1. **Agent chat** — use `sendToAgentChat()` to send messages to the agent
43
43
  2. **Generation state** — use `useAgentChatGenerating()` to track when the agent is running
44
- 3. **File watching** — SSE endpoint keeps UI in sync when the agent modifies files
44
+ 3. **Polling sync** — database-backed sync keeps UI caches fresh when the agent changes state
45
45
  4. **Action system** — `pnpm action <name>` dispatches to callable actions
46
46
 
47
47
  Your app code is identical regardless of how the agent is provided.
@@ -72,7 +72,7 @@ Each template is a complete app with UI, agent actions, database schema, and AI
72
72
  | [Video](/templates/video) | video editing |
73
73
  | [Analytics](/templates/analytics) | Amplitude, Mixpanel, Looker |
74
74
  | [Clips](/templates/clips) | Replaces Loom — screen + camera recording |
75
- | [Design](/templates/design) | Figma, Canva |
75
+ | [Design](/templates/design) | HTML prototyping studios |
76
76
  | [Forms](/docs/template-forms) | Typeform |
77
77
  | [Dispatch](/docs/template-dispatch) | Workspace control plane — secrets, routing, jobs |
78
78
  | [Starter](/docs/template-starter) | Minimal scaffold — build from scratch |
@@ -46,7 +46,7 @@ Six rules govern the architecture:
46
46
  Adopting the framework is valuable mostly because of what you stop having to build. The moment your app follows the six rules, you inherit:
47
47
 
48
48
  - **One action = four surfaces.** Every action defined with `defineAction()` is simultaneously an agent tool, a typesafe frontend mutation (`useActionMutation("name")`), an HTTP endpoint at `/_agent-native/actions/:name`, and an MCP tool (when MCP is enabled). External agents can call it over [A2A](/docs/a2a-protocol) too. One implementation, four consumers.
49
- - **A full workspace per user.** Skills, memory (`learnings.md`), `AGENTS.md`, custom sub-agents, scheduled jobs, connected MCP servers — all SQL-backed, per-user, no dev-box required. See [Workspace](/docs/workspace).
49
+ - **A full workspace per user.** Skills, shared `LEARNINGS.md`, personal `memory/MEMORY.md`, `AGENTS.md`, custom sub-agents, scheduled jobs, connected MCP servers — all SQL-backed, no dev-box required. See [Workspace](/docs/workspace).
50
50
  - **Drop-in React components.** `<AgentPanel />` and `<AgentSidebar />` render chat + workspace anywhere in your app. See [Drop-in Agent](/docs/drop-in-agent).
51
51
  - **Live sync between agent and UI.** A 2-second poll invalidates React Query caches whenever the agent writes to the DB. No WebSockets, no serverless-unfriendly long-lived connections. See [Polling Sync](#polling-sync) below.
52
52
  - **Auth, orgs, RBAC.** Better Auth with orgs/members/roles is wired in for every template. See [Authentication](/docs/authentication).