fimo 0.10.1-staging.4 → 0.11.0-staging.2
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/assets/skills/fimo/SKILL.md +4 -0
- package/assets/skills/fimo-code/references/content.md +19 -15
- package/assets/skills/fimo-code/references/ui.md +3 -0
- package/assets/skills/fimo-studio/references/ai-chat.md +8 -0
- package/assets/skills/fimo-studio/references/publish-and-deploy.md +6 -0
- package/dist/cli/bundle.json +1 -1
- package/dist/cli/index.js +3 -3
- package/dist/runtime/content/client/createContentClient.d.ts +15 -0
- package/dist/runtime/content/client/createContentClient.js +23 -0
- package/dist/runtime/content/client/createSingletonClient.js +3 -0
- package/dist/runtime/content/client/internal.js +63 -2
- package/dist/runtime/content/utils/retrieve-data-sources.d.ts +13 -0
- package/dist/runtime/content/utils/retrieve-data-sources.js +45 -31
- package/dist/runtime/primitives/components/Json.d.ts +25 -0
- package/dist/runtime/primitives/components/Json.js +29 -0
- package/dist/runtime/primitives/index.d.ts +1 -0
- package/dist/runtime/primitives/index.js +1 -0
- package/package.json +4 -4
- package/templates/react-router/package.json +6 -6
|
@@ -17,6 +17,10 @@ When you are about to do Fimo work:
|
|
|
17
17
|
1. List what's available: `npx fimo@latest skills list`
|
|
18
18
|
2. Load the relevant skill: `npx fimo@latest skills get <name>` (add `--ref <doc>` for a reference doc)
|
|
19
19
|
|
|
20
|
+
Reference paths mentioned in streamed skill output, such as `references/media.md`, are identifiers,
|
|
21
|
+
not files in the project. Load them through the CLI, for example
|
|
22
|
+
`npx fimo@latest skills get fimo-cli --ref media`. Do not use a filesystem read tool for them.
|
|
23
|
+
|
|
20
24
|
Pick by task:
|
|
21
25
|
|
|
22
26
|
- Writing code — schema-driven JSX, schemas/forms JSON, `t()` labels, `fimo/ui` media → `fimo-code`
|
|
@@ -73,7 +73,7 @@ something else (e.g. `handle`, `permalink`).
|
|
|
73
73
|
| `reference` | `{ "id": "..." }`, `null`, or an array of reference objects when `many: true` | References to another schema |
|
|
74
74
|
| `blocks` | ordered array of objects | Fixed groups, repeated sections, or selectable page blocks |
|
|
75
75
|
|
|
76
|
-
A `date` field
|
|
76
|
+
A `date` field generates as `string` in the TS client and wraps in `FimoString` at read time — the same source-tracked shape as `string`/`text` — so `<Date value={post.someDate} />` and plain string methods (`.slice()`, template literals, …) both work directly.
|
|
77
77
|
|
|
78
78
|
## Enumerated strings
|
|
79
79
|
|
|
@@ -167,6 +167,7 @@ A field may declare `showIf` (every clause must match) or `showIfAny` (one claus
|
|
|
167
167
|
- `min` and `max` constrain the total number of blocks. Use `min: 1` to require at least one block; `required: true` has the same minimum-one behavior.
|
|
168
168
|
- Fimo creates a stable `_key` for each item. A `oneOf` item also carries `_type`, matching the variant `uid`.
|
|
169
169
|
- Nested fields support the same defaults and validators as top-level fields.
|
|
170
|
+
- **Each block item's own scalar fields wrap the same way their field type wraps at the top level** — a nested `string`/`text` field is a `FimoString`, a nested `richtext` field is a `FimoRichText`, a nested `media` field is a `FimoMedia`, a nested `boolean` is a `FimoBoolean`, a nested `date` is a `FimoString`, a nested `json` field is a shallow-cloned, source-tagged object, a nested `number` stays a plain `number`, and a nested `blocks` field recurses the same way. Pass those nested values to the matching `fimo/ui` component exactly like a top-level field — `<Text value={section.heading} />` or `<Json value={section.metadata} />` inside a `.map()` over `page.sections` stays inline-editable.
|
|
170
171
|
- Blocks inherit the owning entry's locale.
|
|
171
172
|
- Nested references use one fixed `target`. Unpopulated reads return `{ id, documentId }`, like top-level references.
|
|
172
173
|
- Nested population and filtering are not supported yet.
|
|
@@ -516,22 +517,25 @@ Populate is depth-one. It only works for reference fields; trying to populate a
|
|
|
516
517
|
|
|
517
518
|
The entry objects a hook returns are **not** plain JS values. The generated client wraps each _trackable_ field in a `fimo/ui` primitive that carries source metadata for inline editing. Which fields wrap, and which stay plain:
|
|
518
519
|
|
|
519
|
-
| Schema field type | Field value you get | Notes
|
|
520
|
-
| ----------------- | ----------------------------------- |
|
|
521
|
-
| `string` | `FimoString` | `extends String` — **not** a primitive `string`
|
|
522
|
-
| `text` | `FimoString` | Multiline plain text with the same source tracking as `string`
|
|
523
|
-
| `richtext` | `FimoRichText` | Tiptap JSONContent + source metadata
|
|
524
|
-
| `boolean` | `FimoBoolean` | class; `.valueOf()` → `boolean`
|
|
525
|
-
| `media` | `FimoMedia` / `FimoMedia[]` | shape + rendering in `references/assets.md`
|
|
526
|
-
| `number` | `number` | plain — not wrapped
|
|
527
|
-
| `json` | `Record<string, any>` |
|
|
528
|
-
| `date` | `
|
|
529
|
-
| `
|
|
520
|
+
| Schema field type | Field value you get | Notes |
|
|
521
|
+
| ----------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
522
|
+
| `string` | `FimoString` | `extends String` — **not** a primitive `string` |
|
|
523
|
+
| `text` | `FimoString` | Multiline plain text with the same source tracking as `string` |
|
|
524
|
+
| `richtext` | `FimoRichText` | Tiptap JSONContent + source metadata |
|
|
525
|
+
| `boolean` | `FimoBoolean` | class; `.valueOf()` → `boolean` |
|
|
526
|
+
| `media` | `FimoMedia` / `FimoMedia[]` | shape + rendering in `references/assets.md` |
|
|
527
|
+
| `number` | `number` | plain — not wrapped. A wrapper would break `<span>{post.views}</span>` (React renders a boxed `String` directly but throws on a boxed `Number`), so it stays untracked and unclickable in the editing surfaces |
|
|
528
|
+
| `json` | `Record<string, any>` | the same shape you wrote, plus a hidden (non-enumerable, symbol-keyed) source tag — render with `<Json>`, see below |
|
|
529
|
+
| `date` | `FimoString` | same wrapper as `string`/`text`, **not** `FimoDate` — see below |
|
|
530
|
+
| `blocks` | array of plain objects | the array/objects themselves are plain; each item's own scalar fields are wrapped by their own field type (a nested `string` is still `FimoString`, a nested `number` stays a plain `number`, …) — see "Blocks" above |
|
|
531
|
+
| `reference` | `FimoReference` / `FimoReference[]` | reference object(s) with target `id`; use `populate` when embedded targets are needed |
|
|
530
532
|
|
|
531
533
|
Rules of thumb:
|
|
532
534
|
|
|
533
|
-
- **Pass the whole primitive to the matching `fimo/ui` component** — `<Text value={post.title} />`, `<Image value={post.cover} />`, `<RichText value={post.body} />`, `<Boolean value={p.inStock} />`. Don't unwrap first; the component reads the source metadata so the field stays inline-editable in the dashboard.
|
|
535
|
+
- **Pass the whole primitive to the matching `fimo/ui` component** — `<Text value={post.title} />`, `<Image value={post.cover} />`, `<RichText value={post.body} />`, `<Boolean value={p.inStock} />`, `<Date value={post.publishDate} />`, `<Json value={post.metadata} />`. Don't unwrap first; the component reads the source metadata so the field stays inline-editable in the dashboard.
|
|
534
536
|
- **`FimoString extends String`**, so `typeof post.title === 'object'` and `post.title === 'Hi'` is `false`. It stringifies fine inside JSX and template literals; call `.toString()` only when something genuinely needs a primitive `string`.
|
|
537
|
+
- **`number` fields are the one scalar type left unwrapped** — `post.views` is a plain `number`, so `{post.views}` renders directly in JSX, `typeof`/`===`/arithmetic all behave normally, and there is no `<Number>` component. This is deliberate, not a gap: wrapping it would break direct JSX rendering in every existing site.
|
|
538
|
+
- **`json` fields are a shallow clone of what you wrote**, tagged with a hidden source symbol — not the original object, and not a class instance. Reading it behaves exactly like plain JSON (`JSON.stringify` round-trips it unchanged; `for...in`/`Object.keys` see only your own keys). Render it with `<Json value={post.metadata} />` (default renders as a `<span>`; pass `as="pre"` for a formatted block, or a children render function for specific keys) so it stays inline-editable and live-updates in the dashboard preview like every other field.
|
|
535
539
|
- **Never hand-construct** a `FimoString` / `FimoMedia` / etc. — that bypasses source tracking. For a literal string use `t()`; for a literal image use `<StaticImage>`.
|
|
536
540
|
- `t()` also returns a `FimoString` (see `references/labels.md`).
|
|
537
541
|
|
|
@@ -553,7 +557,7 @@ class FimoBoolean {
|
|
|
553
557
|
}
|
|
554
558
|
```
|
|
555
559
|
|
|
556
|
-
> **`FimoDate`:** exported from `fimo/ui` (it's the `<Date>` component's value
|
|
560
|
+
> **`FimoDate`:** exported from `fimo/ui` (it's one of the `<Date>` component's accepted value types), but the generated schema client does **not** wrap `date` fields in it — a `date` field wraps as `FimoString` instead (see the table above), because the generated TypeScript type for a `date` field is `string`, and `FimoString` is what keeps that contract's string methods (`.slice()`, `.includes()`, …) working. `<Date value={post.someDate} />` accepts a `FimoString`, a `FimoDate`, a raw `Date`, or a raw string — all four render correctly.
|
|
557
561
|
|
|
558
562
|
## UI code pattern
|
|
559
563
|
|
|
@@ -579,7 +583,7 @@ export function BlogList() {
|
|
|
579
583
|
}
|
|
580
584
|
```
|
|
581
585
|
|
|
582
|
-
For the `<Text>` / `<RichText>` / `<Image>` / `<Date>` components and the rules of thumb, see `references/ui.md`.
|
|
586
|
+
For the `<Text>` / `<RichText>` / `<Image>` / `<Date>` / `<Json>` components and the rules of thumb, see `references/ui.md`.
|
|
583
587
|
|
|
584
588
|
## Read path (published app, no auth)
|
|
585
589
|
|
|
@@ -17,6 +17,7 @@ Use these to render content-type field values consistently. They carry source me
|
|
|
17
17
|
| `<Video>` | Schema `media` video fields | `<Video value={post.heroVideo} />` |
|
|
18
18
|
| `<Date>` | Schema date fields | `<Date value={post.publishDate} />` |
|
|
19
19
|
| `<Boolean>` | Schema boolean fields | `<Boolean value={product.inStock} />` |
|
|
20
|
+
| `<Json>` | Schema `json` fields | `<Json value={post.metadata} as="pre" />` |
|
|
20
21
|
| `` fimo`...` `` | Compose tracked values (mix `t()` + schema text) | ``<Text value={fimo`${t('by')} ${post.author}`} />`` |
|
|
21
22
|
| `useLabels()` | `t('key')` hook | see `references/labels.md` |
|
|
22
23
|
| `useLocale()` | Active locale and route locale metadata | see `references/locales.md` |
|
|
@@ -29,6 +30,7 @@ Use these to render content-type field values consistently. They carry source me
|
|
|
29
30
|
4. **Label text → `<Text value={t('key')} />`**, not `<h1>{t(...)}</h1>`. Label values live in the DB for `i18n.defaultLocale` from `fimo-config.json` unless a non-default locale is explicitly targeted. See `references/labels.md`.
|
|
30
31
|
5. **Mixed schema + translated text** → the `` fimo`...` `` template literal inside `<Text>`.
|
|
31
32
|
6. **Never hand-roll richtext rendering** — always `<RichText>`. To restyle a node, pass `components={{ heading: ..., link: ..., ... }}`.
|
|
33
|
+
7. **Schema `json` → `<Json>`**, not a hand-rolled `<pre data-fimo-source={getFimoSource(post.metadata)}>{JSON.stringify(post.metadata)}</pre>`. Default renders as a `<span>`; pass `as="pre"` (with a `whitespace-pre-wrap` class) for a formatted block, or a children render function for custom display of specific keys.
|
|
32
34
|
|
|
33
35
|
## App code conventions
|
|
34
36
|
|
|
@@ -78,6 +80,7 @@ The template uses **Vite + React 19 + TypeScript + Tailwind v4 + shadcn/ui + rea
|
|
|
78
80
|
|
|
79
81
|
- Raw `<a href>` for internal nav → use `<FimoLink>` for locale-aware paths or React Router `<Link>` / `<NavLink>` only when intentionally bypassing Fimo locale helpers.
|
|
80
82
|
- Raw `<img>` for schema media → use `<Image>` (with width/height).
|
|
83
|
+
- Raw `<pre data-fimo-source={getFimoSource(...)}>` for schema `json` fields → use `<Json>`.
|
|
81
84
|
- Hardcoded strings in JSX → wrap in `t('key')` and add the DB value with `fimo labels set`.
|
|
82
85
|
- Calling `t()` with a dynamic first argument → key must be a string literal.
|
|
83
86
|
- Editing generated `.ts` files under `src/schemas/` or `src/forms/` → regenerate them through `fimo validate` or the matching push command.
|
|
@@ -33,6 +33,14 @@ To halt the AI mid-generation, use the **Stop button** in the input bar — whil
|
|
|
33
33
|
|
|
34
34
|
While the AI works, you see small badges in the chat showing what it is doing. Each badge displays a tool name and its current status. Examples include reading files, writing code, searching your project, or generating images. These badges help you follow along without needing to understand the technical details.
|
|
35
35
|
|
|
36
|
+
## Reviewing Changes That Could Not Merge
|
|
37
|
+
|
|
38
|
+
Chat changes are prepared separately and then applied to the environment you are viewing. Most changes merge automatically.
|
|
39
|
+
|
|
40
|
+
If the project changed in the same place while the AI was working, the response shows a **Review changes** card instead. Open it to inspect the proposal, resolve any conflicts, and merge when it is ready. Until you merge it, the proposal is not part of the environment and later chat messages will not see it.
|
|
41
|
+
|
|
42
|
+
Discarding the merge leaves the current environment unchanged and keeps the proposal separate.
|
|
43
|
+
|
|
36
44
|
## Tips for Better Results
|
|
37
45
|
|
|
38
46
|
- **Be specific**: Mention colors, layout, text content, and spacing when you can.
|
|
@@ -16,6 +16,12 @@ To push your latest changes live, open the publish panel from the header **Publi
|
|
|
16
16
|
|
|
17
17
|
> **Tip:** Before your site has ever been published, the chat shows a one-click **Publish** button that deploys immediately without opening the panel.
|
|
18
18
|
|
|
19
|
+
## Publishing Changes That Need Review
|
|
20
|
+
|
|
21
|
+
If an AI chat change cannot merge automatically, use the response's **Review changes** card first. Resolve the conflicts and merge the proposal into `main`.
|
|
22
|
+
|
|
23
|
+
When the AI requested publication, the review dialog offers **Merge and publish** after the conflicts are resolved. Publishing starts only after the merge succeeds, so unresolved or discarded proposals never reach the live site.
|
|
24
|
+
|
|
19
25
|
## What You See When You Click Publish
|
|
20
26
|
|
|
21
27
|
The header **Publish** button itself only shows the label "Publish" (or a spinner while a deploy is running). Open the panel to see the current state:
|