@agent-native/core 0.49.11 → 0.49.13
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.
- package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.js +1 -1
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
- package/dist/cli/recap.d.ts +37 -0
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +240 -0
- package/dist/cli/recap.js.map +1 -1
- package/dist/client/MultiTabAssistantChat.d.ts.map +1 -1
- package/dist/client/MultiTabAssistantChat.js +5 -10
- package/dist/client/MultiTabAssistantChat.js.map +1 -1
- package/dist/client/blocks/library/question-form.js +1 -1
- package/dist/client/blocks/library/question-form.js.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.d.ts.map +1 -1
- package/dist/client/extensions/EmbeddedExtension.js +4 -0
- package/dist/client/extensions/EmbeddedExtension.js.map +1 -1
- package/dist/client/extensions/ExtensionViewer.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionViewer.js +12 -4
- package/dist/client/extensions/ExtensionViewer.js.map +1 -1
- package/dist/client/extensions/ExtensionsListPage.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsListPage.js +14 -9
- package/dist/client/extensions/ExtensionsListPage.js.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.d.ts.map +1 -1
- package/dist/client/extensions/ExtensionsSidebarSection.js +6 -4
- package/dist/client/extensions/ExtensionsSidebarSection.js.map +1 -1
- package/dist/client/extensions/iframe-bridge.d.ts +8 -0
- package/dist/client/extensions/iframe-bridge.d.ts.map +1 -1
- package/dist/client/extensions/iframe-bridge.js +54 -0
- package/dist/client/extensions/iframe-bridge.js.map +1 -1
- package/dist/client/progress/RunsTray.d.ts.map +1 -1
- package/dist/client/progress/RunsTray.js +12 -3
- package/dist/client/progress/RunsTray.js.map +1 -1
- package/dist/client/resources/ResourceEditor.d.ts +1 -3
- package/dist/client/resources/ResourceEditor.d.ts.map +1 -1
- package/dist/client/resources/ResourceEditor.js +8 -23
- package/dist/client/resources/ResourceEditor.js.map +1 -1
- package/dist/client/resources/ResourcesPanel.d.ts.map +1 -1
- package/dist/client/resources/ResourcesPanel.js +4 -9
- package/dist/client/resources/ResourcesPanel.js.map +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.d.ts.map +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.js +1 -1
- package/dist/client/settings/VoiceTranscriptionSection.js.map +1 -1
- package/dist/client/sharing/ShareButton.d.ts +5 -1
- package/dist/client/sharing/ShareButton.d.ts.map +1 -1
- package/dist/client/sharing/ShareButton.js +15 -7
- package/dist/client/sharing/ShareButton.js.map +1 -1
- package/dist/client/sharing/ShareDialog.d.ts.map +1 -1
- package/dist/client/sharing/ShareDialog.js +6 -2
- package/dist/client/sharing/ShareDialog.js.map +1 -1
- package/dist/extensions/actions.d.ts.map +1 -1
- package/dist/extensions/actions.js +70 -2
- package/dist/extensions/actions.js.map +1 -1
- package/dist/extensions/html-shell.d.ts +12 -0
- package/dist/extensions/html-shell.d.ts.map +1 -1
- package/dist/extensions/html-shell.js.map +1 -1
- package/dist/extensions/local.d.ts +35 -0
- package/dist/extensions/local.d.ts.map +1 -0
- package/dist/extensions/local.js +334 -0
- package/dist/extensions/local.js.map +1 -0
- package/dist/extensions/routes.d.ts.map +1 -1
- package/dist/extensions/routes.js +92 -12
- package/dist/extensions/routes.js.map +1 -1
- package/dist/extensions/slots/store.d.ts.map +1 -1
- package/dist/extensions/slots/store.js +72 -4
- package/dist/extensions/slots/store.js.map +1 -1
- package/dist/local-artifacts/index.d.ts +4 -0
- package/dist/local-artifacts/index.d.ts.map +1 -1
- package/dist/local-artifacts/index.js +60 -35
- package/dist/local-artifacts/index.js.map +1 -1
- package/dist/vite/client.d.ts +11 -1
- package/dist/vite/client.d.ts.map +1 -1
- package/dist/vite/client.js +26 -1
- package/dist/vite/client.js.map +1 -1
- package/docs/content/extensions.md +65 -0
- package/docs/content/local-file-mode.md +378 -0
- package/docs/content/template-content.md +53 -4
- package/package.json +1 -1
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Local File Mode"
|
|
3
|
+
description: "Run agent-native apps with local Markdown, MDX, and other repo files as the source of truth instead of SQL-backed records."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Local File Mode
|
|
7
|
+
|
|
8
|
+
Local File Mode lets an agent-native app attach its normal UI and action surface
|
|
9
|
+
directly to files in a repo or workspace. The app still feels like the hosted
|
|
10
|
+
product, but its list views, editor, and agent tools read and write local files
|
|
11
|
+
instead of SQL-backed app records.
|
|
12
|
+
|
|
13
|
+
The first implementation is in the Content template: the left sidebar is
|
|
14
|
+
populated from local `.md` and `.mdx` files, selecting a page opens the standard
|
|
15
|
+
Content editor, and saving writes back to the selected file. The same files can
|
|
16
|
+
also be edited by Codex, Claude Code, the Agent-Native sidebar agent, or a normal
|
|
17
|
+
editor.
|
|
18
|
+
|
|
19
|
+
Use Local File Mode when you want a repo-first workflow:
|
|
20
|
+
|
|
21
|
+
- a docs repo with `docs/*.mdx`
|
|
22
|
+
- a blog with `blog/*.mdx`
|
|
23
|
+
- resources such as positioning, messaging, or team notes in `resources/*.md`
|
|
24
|
+
- a personal Obsidian-style knowledge base with a richer MDX editor
|
|
25
|
+
- app artifacts that should be easy for coding agents to inspect and patch
|
|
26
|
+
|
|
27
|
+
Use database mode when you want the hosted collaborative app experience:
|
|
28
|
+
multi-user sharing, SQL-backed permissions, comments, version history, and
|
|
29
|
+
production hosting without local filesystem access.
|
|
30
|
+
|
|
31
|
+
## The Mental Model
|
|
32
|
+
|
|
33
|
+
There are two source-of-truth modes:
|
|
34
|
+
|
|
35
|
+
| Mode | Source of truth | Best for |
|
|
36
|
+
| --------------- | ------------------------------------------ | ------------------------------------------------------------------------ |
|
|
37
|
+
| Database mode | SQL rows through Drizzle | Hosted apps, collaboration, sharing, comments, version history |
|
|
38
|
+
| Local File Mode | Repo files declared by `agent-native.json` | Local/dev workflows, Git review, coding-agent edits, file-native content |
|
|
39
|
+
|
|
40
|
+
The UI and agent actions should stay the same shape in both modes. A Content
|
|
41
|
+
editor still edits documents; the difference is whether those documents resolve
|
|
42
|
+
to SQL rows or local files.
|
|
43
|
+
|
|
44
|
+
## Example Repo
|
|
45
|
+
|
|
46
|
+
A Content workspace can be as small as this:
|
|
47
|
+
|
|
48
|
+
```txt
|
|
49
|
+
my-content-repo/
|
|
50
|
+
agent-native.json
|
|
51
|
+
docs/
|
|
52
|
+
getting-started.mdx
|
|
53
|
+
guides/
|
|
54
|
+
custom-components.mdx
|
|
55
|
+
blog/
|
|
56
|
+
launch-post.mdx
|
|
57
|
+
resources/
|
|
58
|
+
messaging/
|
|
59
|
+
positioning.md
|
|
60
|
+
components/
|
|
61
|
+
FrameworkTabs.tsx
|
|
62
|
+
Callout.tsx
|
|
63
|
+
extensions/
|
|
64
|
+
doc-status/
|
|
65
|
+
extension.json
|
|
66
|
+
index.html
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
In Local File Mode, the Content sidebar shows the `docs/`, `blog/`, and
|
|
70
|
+
`resources/` trees as pages. Selecting `docs/getting-started.mdx` opens that
|
|
71
|
+
file in the standard Content editor; editing in the UI writes back to
|
|
72
|
+
`docs/getting-started.mdx`.
|
|
73
|
+
|
|
74
|
+
`components/` is not a content root. It is a preview component library that MDX
|
|
75
|
+
files can import or reference. The editor can render simple local MDX components
|
|
76
|
+
without requiring you to clone or fork the entire Content app.
|
|
77
|
+
|
|
78
|
+
`extensions/` is also not a content root. It is a local extension library:
|
|
79
|
+
small sandboxed widgets that can render in app slots while their source stays in
|
|
80
|
+
the repo.
|
|
81
|
+
|
|
82
|
+
## Configuration
|
|
83
|
+
|
|
84
|
+
Add `agent-native.json` to the repo or workspace root:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"version": 1,
|
|
89
|
+
"apps": {
|
|
90
|
+
"content": {
|
|
91
|
+
"mode": "local-files",
|
|
92
|
+
"roots": [
|
|
93
|
+
{
|
|
94
|
+
"name": "Docs",
|
|
95
|
+
"path": "docs",
|
|
96
|
+
"kind": "docs",
|
|
97
|
+
"extensions": [".md", ".mdx"]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"name": "Blog",
|
|
101
|
+
"path": "blog",
|
|
102
|
+
"kind": "blog",
|
|
103
|
+
"extensions": [".md", ".mdx"]
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"name": "Resources",
|
|
107
|
+
"path": "resources",
|
|
108
|
+
"kind": "resources",
|
|
109
|
+
"extensions": [".md", ".mdx"]
|
|
110
|
+
}
|
|
111
|
+
],
|
|
112
|
+
"components": "components",
|
|
113
|
+
"extensions": "extensions",
|
|
114
|
+
"hide": ["**/_*.md", "**/_*.mdx"]
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
You can also enable local files with `AGENT_NATIVE_MODE=local-files` or
|
|
121
|
+
`AGENT_NATIVE_DATA_MODE=local-files`; the manifest is preferred because it
|
|
122
|
+
documents the folder contract in the repo itself.
|
|
123
|
+
|
|
124
|
+
## Content File Format
|
|
125
|
+
|
|
126
|
+
Content reads Markdown and MDX. Frontmatter holds page metadata, and the body is
|
|
127
|
+
the editable document:
|
|
128
|
+
|
|
129
|
+
```mdx
|
|
130
|
+
---
|
|
131
|
+
title: "Getting Started"
|
|
132
|
+
icon: "sparkles"
|
|
133
|
+
isFavorite: true
|
|
134
|
+
updatedAt: "2026-06-12T20:00:00.000Z"
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
# Getting Started
|
|
138
|
+
|
|
139
|
+
Use <FrameworkTabs value="react" /> to show framework-specific code.
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The title comes from `title` frontmatter when present, otherwise from the
|
|
143
|
+
filename. The editor preserves MDX source that it cannot visually edit yet, so
|
|
144
|
+
coding agents and normal text editors remain safe escape hatches.
|
|
145
|
+
|
|
146
|
+
## Custom MDX Components
|
|
147
|
+
|
|
148
|
+
Content can preview local components from the configured `components` folder.
|
|
149
|
+
This is meant for docs-style MDX components such as tabs, callouts, package
|
|
150
|
+
install snippets, or framework-specific code blocks.
|
|
151
|
+
|
|
152
|
+
For example, add an interactive component next to your content:
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
// components/ImpactCounter.tsx
|
|
156
|
+
import { useState } from "react";
|
|
157
|
+
|
|
158
|
+
export function ImpactCounter({
|
|
159
|
+
label = "points",
|
|
160
|
+
accent = "blue",
|
|
161
|
+
featured = false,
|
|
162
|
+
}: {
|
|
163
|
+
label?: string;
|
|
164
|
+
accent?: "blue" | "green" | "purple";
|
|
165
|
+
featured?: boolean;
|
|
166
|
+
}) {
|
|
167
|
+
const [count, setCount] = useState(3);
|
|
168
|
+
const accentClass =
|
|
169
|
+
accent === "green"
|
|
170
|
+
? "border-green-300 bg-green-50"
|
|
171
|
+
: accent === "purple"
|
|
172
|
+
? "border-purple-300 bg-purple-50"
|
|
173
|
+
: "border-blue-300 bg-blue-50";
|
|
174
|
+
|
|
175
|
+
return (
|
|
176
|
+
<div className={`rounded-md border p-4 ${accentClass}`}>
|
|
177
|
+
<div className="text-sm text-muted-foreground">Launch impact</div>
|
|
178
|
+
<div className="mt-1 text-3xl font-semibold">
|
|
179
|
+
{count} {label}
|
|
180
|
+
</div>
|
|
181
|
+
{featured ? <div className="mt-1 text-sm">Featured metric</div> : null}
|
|
182
|
+
<button
|
|
183
|
+
type="button"
|
|
184
|
+
className="mt-3 rounded border px-3 py-1 text-sm"
|
|
185
|
+
onClick={() => setCount((value) => value + 1)}
|
|
186
|
+
>
|
|
187
|
+
Add point
|
|
188
|
+
</button>
|
|
189
|
+
</div>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export const ImpactCounterInputs = {
|
|
194
|
+
label: {
|
|
195
|
+
type: "string",
|
|
196
|
+
label: "Metric label",
|
|
197
|
+
default: "points",
|
|
198
|
+
},
|
|
199
|
+
accent: {
|
|
200
|
+
type: "select",
|
|
201
|
+
label: "Accent",
|
|
202
|
+
options: ["blue", "green", "purple"],
|
|
203
|
+
default: "blue",
|
|
204
|
+
},
|
|
205
|
+
featured: {
|
|
206
|
+
type: "boolean",
|
|
207
|
+
label: "Featured",
|
|
208
|
+
default: false,
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Then use it from any local MDX file:
|
|
214
|
+
|
|
215
|
+
```mdx
|
|
216
|
+
---
|
|
217
|
+
title: "Launch Notes"
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
# Launch Notes
|
|
221
|
+
|
|
222
|
+
<ImpactCounter label="wins" />
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
The Content dev server discovers PascalCase named exports and PascalCase default
|
|
226
|
+
exports from `.tsx`, `.jsx`, `.ts`, and `.js` files under `components/`. Those
|
|
227
|
+
components render inside the editor and appear in the slash menu under
|
|
228
|
+
**Local components**. Slash insertion creates a minimal tag such as
|
|
229
|
+
`<ImpactCounter />`; add props in the MDX source when needed.
|
|
230
|
+
|
|
231
|
+
If a component exports input metadata, selecting the component in the editor
|
|
232
|
+
shows an edit button in the component's top-right corner. Supported input types
|
|
233
|
+
are `string`, `textarea`, `number`, `boolean`, and `select`. The form writes
|
|
234
|
+
changes back to the MDX tag, so local files remain the source of truth. The
|
|
235
|
+
metadata can be exported as `ComponentNameInputs`, `ComponentNameConfig.inputs`,
|
|
236
|
+
`Component.inputs`, or `agentNative.inputs`.
|
|
237
|
+
|
|
238
|
+
Simple component tags with literal props can preview inline:
|
|
239
|
+
|
|
240
|
+
```mdx
|
|
241
|
+
<FrameworkTabs value="react" />
|
|
242
|
+
|
|
243
|
+
<Callout type="warning">This setting affects production deploys.</Callout>
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Complex JSX expressions are preserved in source. If the editor cannot safely
|
|
247
|
+
preview a component prop yet, it shows a warning placeholder rather than
|
|
248
|
+
silently dropping data.
|
|
249
|
+
|
|
250
|
+
## Sharing Local Files
|
|
251
|
+
|
|
252
|
+
Local files are not shared directly because other users cannot read a path on
|
|
253
|
+
your machine. The Content toolbar's Share button creates or refreshes a
|
|
254
|
+
database-backed copy of the selected file, navigates to that copy, and opens the
|
|
255
|
+
normal share popover. The original local file remains under Local files; the
|
|
256
|
+
database copy appears under Shared copies in Local File Mode and uses the
|
|
257
|
+
standard document sharing model.
|
|
258
|
+
|
|
259
|
+
## Local Extensions
|
|
260
|
+
|
|
261
|
+
Local File Mode can also load repo-backed extensions from the configured
|
|
262
|
+
`extensions` folder. Each extension is one directory with an `extension.json`
|
|
263
|
+
manifest and an HTML entry file:
|
|
264
|
+
|
|
265
|
+
```txt
|
|
266
|
+
extensions/
|
|
267
|
+
doc-status/
|
|
268
|
+
extension.json
|
|
269
|
+
index.html
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
```json
|
|
273
|
+
{
|
|
274
|
+
"id": "doc-status",
|
|
275
|
+
"name": "Doc Status",
|
|
276
|
+
"description": "Shows metadata for the selected Content file.",
|
|
277
|
+
"entry": "index.html",
|
|
278
|
+
"slots": ["content.sidebar.bottom"],
|
|
279
|
+
"permissions": {
|
|
280
|
+
"appActions": ["list-documents"],
|
|
281
|
+
"extensionData": true
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
`index.html` is the same Alpine/Tailwind extension body format used by normal
|
|
287
|
+
database-backed extensions. When the Content app sees a local extension that
|
|
288
|
+
declares `content.sidebar.bottom`, it renders that extension at the bottom of
|
|
289
|
+
the Content sidebar. The host passes `window.slotContext` with the selected
|
|
290
|
+
document id, title, source metadata, and whether Content is in Local File Mode.
|
|
291
|
+
|
|
292
|
+
Local extensions are previewed by the app but edited as files. The Extensions
|
|
293
|
+
list shows them with a Local File badge, and the full-page viewer points back to
|
|
294
|
+
the entry file. SQL-backed extension actions such as update, delete, share, and
|
|
295
|
+
history do not apply; use your editor, Codex, Claude Code, or Git history for
|
|
296
|
+
source changes.
|
|
297
|
+
|
|
298
|
+
For v1, local extensions are intentionally conservative:
|
|
299
|
+
|
|
300
|
+
- they can use `extensionData` for their own small runtime state
|
|
301
|
+
- they can call only the `appAction`s listed in `extension.json`
|
|
302
|
+
- raw SQL helpers and external `extensionFetch` are disabled
|
|
303
|
+
- slot targets are declared in `extension.json`, not installed through SQL
|
|
304
|
+
|
|
305
|
+
This gives local workspaces an Obsidian-like plugin surface without letting an
|
|
306
|
+
arbitrary repo file inherit every capability of a database-backed extension.
|
|
307
|
+
|
|
308
|
+
## How Apps Use It
|
|
309
|
+
|
|
310
|
+
Local File Mode is implemented through the framework's local artifact helpers.
|
|
311
|
+
An app declares roots for the artifact types it owns, then reads and writes
|
|
312
|
+
through the same action surface its UI and agent already use.
|
|
313
|
+
|
|
314
|
+
For Content, that means:
|
|
315
|
+
|
|
316
|
+
- `list-documents` lists configured `.md` and `.mdx` files.
|
|
317
|
+
- `get-document` reads a selected local file.
|
|
318
|
+
- `update-document` writes the selected local file.
|
|
319
|
+
- `create-document` creates a new local `.mdx` file in the selected folder.
|
|
320
|
+
- `delete-document` deletes the local file.
|
|
321
|
+
- search runs across the configured local files.
|
|
322
|
+
|
|
323
|
+
Moving, renaming, and reordering local-file pages from the Content UI is not
|
|
324
|
+
supported yet. Do those operations in the workspace or with a coding agent; the
|
|
325
|
+
Content sidebar will reflect the resulting file tree.
|
|
326
|
+
|
|
327
|
+
This keeps the agent contract simple: the agent can keep using Content actions,
|
|
328
|
+
and those actions decide whether the target is SQL-backed or file-backed.
|
|
329
|
+
|
|
330
|
+
Other apps can adopt the same pattern over time. A Slides app can map
|
|
331
|
+
`slides/*.mdx` to decks, a Plans app can map `plans/*` to plan documents, and a
|
|
332
|
+
Dashboards app can map `dashboards/*.mdx` to dashboards. Those app-specific
|
|
333
|
+
folders are conventions layered on top of the same local artifact contract.
|
|
334
|
+
|
|
335
|
+
## Local Files vs. Export/Import
|
|
336
|
+
|
|
337
|
+
Content has two different file workflows:
|
|
338
|
+
|
|
339
|
+
| Workflow | What happens |
|
|
340
|
+
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
341
|
+
| `/local-files` export/import | Database mode remains the source of truth. Files are an explicit sync surface you export, edit, preview, and import. |
|
|
342
|
+
| Local File Mode | Files are the source of truth. The Content sidebar and editor operate directly on local files. |
|
|
343
|
+
|
|
344
|
+
Use export/import when you want occasional file review around a hosted workspace.
|
|
345
|
+
Use Local File Mode when the repo itself is the workspace.
|
|
346
|
+
|
|
347
|
+
## History And Collaboration
|
|
348
|
+
|
|
349
|
+
Local File Mode leans on file-native history:
|
|
350
|
+
|
|
351
|
+
- commit important changes to Git
|
|
352
|
+
- use pull requests for review
|
|
353
|
+
- let coding agents edit the same files directly
|
|
354
|
+
- use normal file diffs to understand changes
|
|
355
|
+
|
|
356
|
+
Database mode remains the better fit for hosted collaboration features such as
|
|
357
|
+
sharing, comments, SQL-backed version history, and live multi-user editing.
|
|
358
|
+
|
|
359
|
+
Provider sync can be layered on top of either mode. For example, a docs repo can
|
|
360
|
+
add actions that pull content from a CMS into local MDX files or push selected
|
|
361
|
+
local files back to that CMS.
|
|
362
|
+
|
|
363
|
+
## Production Safety
|
|
364
|
+
|
|
365
|
+
Local File Mode gives app actions direct write access to configured workspace
|
|
366
|
+
files. That is appropriate for local development and trusted single-tenant file
|
|
367
|
+
bridges, but it is not the default production security model.
|
|
368
|
+
|
|
369
|
+
When `NODE_ENV=production`, the framework refuses `local-files` mode unless you
|
|
370
|
+
set:
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
AGENT_NATIVE_ALLOW_LOCAL_FILES_IN_PRODUCTION=true
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
Only set that for a trusted single-tenant deployment where everyone who can use
|
|
377
|
+
the app is allowed to read and write the configured files. For normal hosted,
|
|
378
|
+
multi-user apps, use database mode and SQL-backed sharing.
|
|
@@ -71,7 +71,10 @@ truth instead of SQL documents. Add `agent-native.json` to a repo, set
|
|
|
71
71
|
left sidebar from those local `.md`/`.mdx` files and writes edits back to the
|
|
72
72
|
selected file through the normal document actions. Use this for repo-first docs,
|
|
73
73
|
blogs, resource libraries, or Obsidian-style personal content; switch back to
|
|
74
|
-
database mode when you want hosted collaboration and SQL-backed sharing.
|
|
74
|
+
database mode when you want hosted collaboration and SQL-backed sharing. See
|
|
75
|
+
[Local File Mode](/docs/local-file-mode) for the standalone repo layout,
|
|
76
|
+
configuration, custom MDX components, local `extensions/` widgets, and
|
|
77
|
+
production safety guide.
|
|
75
78
|
|
|
76
79
|
## Why it's interesting
|
|
77
80
|
|
|
@@ -143,9 +146,18 @@ Sync state is tracked in the `document_sync_links` table (last synced time, conf
|
|
|
143
146
|
|
|
144
147
|
### Local file sync
|
|
145
148
|
|
|
146
|
-
The protected `/local-files` route uses the browser File System Access API
|
|
147
|
-
|
|
148
|
-
Markdown/MDX files from a user-chosen folder.
|
|
149
|
+
The protected `/local-files` route uses the browser File System Access API, or a
|
|
150
|
+
guarded native folder bridge inside Agent Native Desktop, to read and write
|
|
151
|
+
Markdown/MDX files from a user-chosen folder. After the folder is linked and
|
|
152
|
+
imported, the selected file is treated as the authority: opening the page reads
|
|
153
|
+
the file, and normal editor saves write the file first. SQL is then updated as a
|
|
154
|
+
cache/history layer for the existing document UI, search, and version panel, not
|
|
155
|
+
as the source of truth. The top-right page menu exposes the local source path:
|
|
156
|
+
relative path is always available, absolute path is available in true local-file
|
|
157
|
+
mode and Agent Native Desktop, and Reveal in Finder is available through the
|
|
158
|
+
desktop bridge or server-backed local-file mode.
|
|
159
|
+
|
|
160
|
+
The bulk sync route calls:
|
|
149
161
|
|
|
150
162
|
- `export-content-source` — reads the accessible document tree and returns a
|
|
151
163
|
deterministic `content/` file bundle.
|
|
@@ -156,6 +168,43 @@ Markdown/MDX files from a user-chosen folder. It calls:
|
|
|
156
168
|
The source format lives in `shared/content-source.ts`. Keep that file as the
|
|
157
169
|
single contract for filenames, frontmatter, parsing, and serialization.
|
|
158
170
|
|
|
171
|
+
Local file workspaces can also provide repo-local React components through the
|
|
172
|
+
configured `components` folder. The Content dev server imports PascalCase
|
|
173
|
+
exports from those files, renders matching MDX tags such as `<ImpactCounter />`
|
|
174
|
+
inside the editor, and exposes them in the slash menu under Local components.
|
|
175
|
+
This keeps custom MDX blocks local to the workspace without cloning the Content
|
|
176
|
+
app. A minimal workspace component can be:
|
|
177
|
+
|
|
178
|
+
```tsx
|
|
179
|
+
// components/ImpactCounter.tsx
|
|
180
|
+
import { useState } from "react";
|
|
181
|
+
|
|
182
|
+
export function ImpactCounter({
|
|
183
|
+
label = "points",
|
|
184
|
+
start = 3,
|
|
185
|
+
}: {
|
|
186
|
+
label?: string;
|
|
187
|
+
start?: number;
|
|
188
|
+
}) {
|
|
189
|
+
const [count, setCount] = useState(start);
|
|
190
|
+
return (
|
|
191
|
+
<button type="button" onClick={() => setCount(count + 1)}>
|
|
192
|
+
Impact: {count} {label}
|
|
193
|
+
</button>
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export const ImpactCounterInputs = {
|
|
198
|
+
label: { type: "string", label: "Label", default: "points" },
|
|
199
|
+
start: { type: "number", label: "Starting count", default: 3 },
|
|
200
|
+
};
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Use it in local MDX as `<ImpactCounter />`, or insert it from the editor slash
|
|
204
|
+
menu under Local components. When input metadata is exported, selecting the
|
|
205
|
+
component in the editor shows a corner edit button that rewrites the MDX props
|
|
206
|
+
in the local file.
|
|
207
|
+
|
|
159
208
|
### Comments
|
|
160
209
|
|
|
161
210
|
Threaded comments on documents with quoted-text anchors, replies, and resolve state. Backed by the `document_comments` table and `app/components/editor/CommentsSidebar.tsx`. Actions: `list-comments`, `add-comment`. Notion comments can sync both ways via `sync-notion-comments`.
|