fimo 0.12.0 → 0.13.0-staging.1
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/agent-templates/broken-link-sweeper/capabilities.yaml +0 -4
- package/assets/agent-templates/content-translator/capabilities.yaml +0 -2
- package/assets/agent-templates/seo-audit/capabilities.yaml +0 -1
- package/assets/content-templates/types-template.eta +13 -7
- package/assets/skills/fimo/SKILL.md +2 -2
- package/assets/skills/fimo-cli/SKILL.md +9 -9
- package/assets/skills/fimo-cli/references/agent-setup.md +1 -1
- package/assets/skills/fimo-cli/references/agents.md +5 -12
- package/assets/skills/fimo-cli/references/assets.md +2 -2
- package/assets/skills/fimo-cli/references/branches.md +1 -0
- package/assets/skills/fimo-cli/references/content.md +16 -30
- package/assets/skills/fimo-cli/references/deploy.md +5 -3
- package/assets/skills/fimo-cli/references/describe.md +1 -1
- package/assets/skills/fimo-cli/references/forms.md +8 -8
- package/assets/skills/fimo-cli/references/init.md +5 -4
- package/assets/skills/fimo-cli/references/labels.md +4 -4
- package/assets/skills/fimo-cli/references/locales.md +21 -6
- package/assets/skills/fimo-cli/references/project-vars-and-secrets.md +1 -1
- package/assets/skills/fimo-code/SKILL.md +40 -50
- package/assets/skills/fimo-code/references/assets.md +6 -4
- package/assets/skills/fimo-code/references/content/clients.md +130 -0
- package/assets/skills/fimo-code/references/content/primitives.md +5 -0
- package/assets/skills/fimo-code/references/content/richtext.md +48 -0
- package/assets/skills/fimo-code/references/content/schema.md +122 -0
- package/assets/skills/fimo-code/references/content.md +12 -597
- package/assets/skills/fimo-code/references/design.md +1 -1
- package/assets/skills/fimo-code/references/frameworks/next/app-router.md +116 -0
- package/assets/skills/fimo-code/references/frameworks/next/locales.md +59 -0
- package/assets/skills/fimo-code/references/frameworks/next/pages-router.md +99 -0
- package/assets/skills/fimo-code/references/frameworks/next.md +116 -0
- package/assets/skills/fimo-code/references/frameworks/react-router.md +295 -0
- package/assets/skills/fimo-code/references/frameworks/vite-react.md +225 -0
- package/assets/skills/fimo-code/references/labels.md +24 -83
- package/assets/skills/fimo-code/references/locales.md +22 -111
- package/assets/skills/fimo-code/references/setup-plain-vite.md +3 -227
- package/assets/skills/fimo-code/references/setup-react-router.md +3 -276
- package/assets/skills/fimo-code/references/ui.md +32 -78
- package/assets/skills/fimo-studio/references/billing-and-credits.md +10 -0
- package/dist/cli/bundle.json +2 -2
- package/dist/cli/index.js +102 -86
- package/dist/scripts/extract-translations.js +8 -1
- package/package.json +1 -1
- package/release.json +2 -2
- package/templates/react-router/AGENTS.md +10 -10
- package/templates/react-router/package.json +1 -1
- package/templates/react-router/react-router.config.ts +1 -1
|
@@ -1,67 +1,57 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: fimo-code
|
|
3
3
|
description: >-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
Write schema-first application code with the installed `fimo` package.
|
|
5
|
+
Load when declaring content schemas or forms, using generated content
|
|
6
|
+
clients, rendering Fimo primitives, reading labels, or integrating Fimo
|
|
7
|
+
with Next.js, React Router, Vite, or another application framework. CLI
|
|
8
|
+
commands and operational workflows live in the `fimo-cli` skill.
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
-
# Fimo
|
|
11
|
+
# Fimo code
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Use this skill for code that consumes the version-locked `fimo` package in the current project. Fimo connects content, labels, media, forms, editing metadata, and hosting to an application; the application continues to own routing, locale resolution, links, document language/direction, and SEO.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Use the project-installed CLI for local inspection, code generation, and validation (`pnpm exec fimo`, `npm exec fimo`, `yarn fimo`, or `bunx --no-install fimo`, matching the lockfile). If that runner tries to install packages even though dependencies already exist, invoke the local `node_modules/.bin/fimo` executable instead. Load the `fimo-cli` skill for remote operational workflows such as schema pushes, label writes, entry mutations, and deploys. If the skill is not already available locally, fetch it with `npx fimo@latest skills get fimo-cli`.
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
## Orient before writing
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
1. Run the project-installed `fimo describe --json` in a linked project and read `data.framework.slug`, schemas, locales, and tree. If the project is not linked yet, inspect `package.json` and the app directory instead.
|
|
20
|
+
2. Load only the references required by the task.
|
|
21
|
+
3. Load the framework reference before choosing imports, providers, or rendering APIs.
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
Framework routing:
|
|
22
24
|
|
|
23
|
-
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
- **Forms** → use the generated Zod schema + `submitX` helper from `@/forms/<name>`. Never hand-roll fetch or validation.
|
|
25
|
+
- `nextjs` or an `app/`, `src/app/`, `pages/`, or `src/pages/` tree → `references/frameworks/next.md`, then the matching App Router or Pages Router reference.
|
|
26
|
+
- React Router framework mode (`react-router.config.ts`, `src/routes.ts`) → `references/frameworks/react-router.md`.
|
|
27
|
+
- Vite + React without framework mode → `references/frameworks/vite-react.md`.
|
|
27
28
|
|
|
28
|
-
|
|
29
|
+
## Durable content contract
|
|
30
|
+
|
|
31
|
+
- Declare editor-managed content in `src/schemas/<Uid>.json`; the PascalCase filename must match `uid`.
|
|
32
|
+
- Apply every schema change with `fimo schemas push <Uid>`; it validates the JSON, generates framework-specific clients, and updates the linked environment.
|
|
33
|
+
- Import generated public modules; never edit generated `.ts`, `.client.ts`, `.types.ts`, or `index.ts` files.
|
|
34
|
+
- Render tracked values with the framework's Fimo primitives so Studio can identify and edit their source.
|
|
35
|
+
- Keep migration-only adapters (`Wrapped*`, private loaders, fallback stores) out of greenfield application code.
|
|
29
36
|
|
|
30
37
|
## Load only the references the task needs
|
|
31
38
|
|
|
32
39
|
Each reference defines one package contract. Fetch it when the task reaches that surface; do not batch-load unrelated references:
|
|
33
40
|
|
|
34
|
-
-
|
|
35
|
-
-
|
|
36
|
-
- `
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
- `references/
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
-
|
|
51
|
-
- ANY user-facing string in code → `references/labels.md`
|
|
52
|
-
- Locale-aware routes, links, or framework adapters → `references/locales.md`
|
|
53
|
-
- ANY JSX rendering schema content or `t()` output → `references/ui.md`
|
|
54
|
-
- Major visual / redesign / hero section / brand → `references/design.md`
|
|
55
|
-
|
|
56
|
-
## Anti-Patterns
|
|
57
|
-
|
|
58
|
-
- **Hardcoding content in JSX** — `<h1>My Blog</h1>` + an array of posts in code. Use schemas + entries + `t()`.
|
|
59
|
-
- **Raw HTML for schema content** — `<img src={post.coverImage.url}>` instead of `<Image value={post.coverImage}>`. The `fimo/ui` components carry metadata for inline editing in the admin.
|
|
60
|
-
- **Raw `<a href>` for internal navigation** — causes full page reloads. Use `<FimoLink>` for locale-aware internal links or React Router `<Link>` when intentionally bypassing locale helpers. Reserve `<a>` for external links.
|
|
61
|
-
- **Pulling stock photos from external URLs** — editors can't manage them. Use a Fimo media task such as `fimo image generate`.
|
|
62
|
-
- **Editing generated `.ts` files** under `src/schemas/` or `src/forms/` — regenerate them through `fimo validate` or the matching push command.
|
|
63
|
-
- **Writing raw HTML in `richtext` fields** — must be Tiptap JSONContent.
|
|
64
|
-
- **Calling `t()` with a dynamic first argument** — the key must be a string literal so the extractor finds it.
|
|
65
|
-
- **Decorating the disposable starter** — `src/pages/Index.tsx` is throwaway scaffolding. On first real generation, replace it entirely.
|
|
66
|
-
- **Skipping legal pages** — `Privacy.tsx` + `Terms.tsx` are required for public sites; the template ships them.
|
|
67
|
-
- **Showing Fimo branding** in the generated site unless the user explicitly asks for it.
|
|
41
|
+
- Schema JSON, field types, blocks, references, `showIf` → `references/content/schema.md`
|
|
42
|
+
- Richtext/Tiptap, entry payloads, slugs → `references/content/richtext.md`
|
|
43
|
+
- Generated clients: `list`, `getBySlug`, `useList`, `where`, `sort`, `fields`, `populate` → `references/content/clients.md`
|
|
44
|
+
- Tracked rendering: `Text`, `RichText`, `Image`, `FimoString`, `FimoMedia` → `references/ui.md`
|
|
45
|
+
- Forms: JSON spec, generated Zod schema, `submit*` helpers → `references/forms.md`
|
|
46
|
+
- Media values, `<Image>`, `<StaticImage>` → `references/assets.md`
|
|
47
|
+
- Static editable copy: `t()`, `useLabels`, `getLabels` → `references/labels.md`
|
|
48
|
+
- Locale ownership and framework handoff → `references/locales.md`
|
|
49
|
+
- Major visual work → `references/design.md`
|
|
50
|
+
|
|
51
|
+
## Non-negotiable boundaries
|
|
52
|
+
|
|
53
|
+
- Do not hardcode editor-owned collections, page content, labels, or media in JSX.
|
|
54
|
+
- Do not hand-roll content API fetches when a generated client covers the read.
|
|
55
|
+
- Do not hand-construct `FimoString`, `FimoMedia`, or other tracked values.
|
|
56
|
+
- Do not replace an application's router, locale library, URL policy, or SEO integration merely to add Fimo.
|
|
57
|
+
- Do not teach one framework's imports as universal package APIs.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> For the CLI commands (`fimo assets upload`, `fimo image generate`, folder management) and the "when to generate AI images" workflow rules, see **`fimo-cli/references/assets.md`**.
|
|
4
4
|
|
|
5
|
-
This file covers the
|
|
5
|
+
This file covers the package surface for working with assets in code: the `media` field value shape, rendering primitives, and URL format.
|
|
6
6
|
|
|
7
7
|
## `media` field value (stored/wire shape)
|
|
8
8
|
|
|
@@ -20,11 +20,11 @@ Asset values returned from `fimo assets upload` or Fimo media tasks, and stored
|
|
|
20
20
|
- `url`: stable HTTPS URL, no auth required, safe to embed.
|
|
21
21
|
- `alt`: optional alt text.
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Generated content reads wrap this stored value in `FimoMedia`, which exposes `url`, `alt`, `name`, `mime`, and optional `width`/`height`. It does not expose `source`; Fimo tracks that internally. Pass the whole entry value to `<Image>` / `<Video>`.
|
|
24
24
|
|
|
25
25
|
## Rendering in JSX
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Import the primitives from the active framework adapter: `fimo/next` on the Next server, `fimo/next/client` in Next Client Components, or `fimo/ui` in React Router/Vite.
|
|
28
28
|
|
|
29
29
|
| Asset source | Component | Pass via |
|
|
30
30
|
| --------------------------------------------------- | --------------------- | ------------------------- |
|
|
@@ -32,7 +32,7 @@ Always use the `fimo/ui` primitives — never raw HTML:
|
|
|
32
32
|
| Hard-coded URL or generated asset referenced inline | `<StaticImage>` | `src="https://..."` |
|
|
33
33
|
|
|
34
34
|
```tsx
|
|
35
|
-
import { Image, StaticImage, Video } from 'fimo/
|
|
35
|
+
import { Image, StaticImage, Video } from 'fimo/next';
|
|
36
36
|
|
|
37
37
|
// from a schema entry:
|
|
38
38
|
<Image value={post.coverImage} width={1200} height={630} fit="cover" />
|
|
@@ -41,6 +41,8 @@ import { Image, StaticImage, Video } from 'fimo/ui';
|
|
|
41
41
|
<StaticImage src="https://assets.fimo.ai/<project>/<id>.jpg" alt="Hero" width={1200} height={630} />
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
+
Fimo's `<Image>` is not Next's `next/image` component. Do not pass Next-only props such as `priority`, `fill`, `quality`, or `loader`; use only the props documented for the Fimo primitive. Preserve `next/image` for non-Fimo images when the application needs those Next-specific controls.
|
|
45
|
+
|
|
44
46
|
**Provide `width` and `height` when known** so Fimo can optimize the asset and reserve layout space (prevents CLS).
|
|
45
47
|
|
|
46
48
|
**Never hand-construct a `FimoMedia` object** to pass into `<Image>` — that bypasses inline-editing metadata. If you have a raw URL, use `<StaticImage>` instead.
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Generated content clients
|
|
2
|
+
|
|
3
|
+
Application code imports the public modules generated from `src/schemas/<Uid>.json`, not `.types.ts` directly.
|
|
4
|
+
|
|
5
|
+
The exact file split is framework-dependent. Load `references/frameworks/next.md`, `references/frameworks/react-router.md`, or `references/frameworks/vite-react.md` before choosing imports.
|
|
6
|
+
|
|
7
|
+
## Entry shape
|
|
8
|
+
|
|
9
|
+
Fields are top-level, never nested under `data`:
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
interface Article {
|
|
13
|
+
id: string;
|
|
14
|
+
entryId: string;
|
|
15
|
+
documentId: string;
|
|
16
|
+
slug: FimoString;
|
|
17
|
+
locale: string;
|
|
18
|
+
createdAt: string;
|
|
19
|
+
updatedAt: string;
|
|
20
|
+
__fimo: { contentType: string };
|
|
21
|
+
title: FimoString;
|
|
22
|
+
body?: FimoRichText | null;
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`id` is stable across locale variants. `entryId` identifies the returned variant. `documentId` is a compatibility alias for `id`. Reference inputs use `{ id: entry.id }`.
|
|
27
|
+
|
|
28
|
+
## Collection API
|
|
29
|
+
|
|
30
|
+
Generated collection modules expose promise methods:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
getById(id, { locale?, populate? })
|
|
34
|
+
getBySlug(slug, { locale?, populate? })
|
|
35
|
+
getByField(fieldName, value, { locale?, populate? })
|
|
36
|
+
list({ limit?, offset?, search?, sort?, where?, fields?, populate?, locale? })
|
|
37
|
+
get(query) // legacy bounded array helper
|
|
38
|
+
create(payload)
|
|
39
|
+
update(id, payload)
|
|
40
|
+
remove(id, { locale? })
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Generated React Query hooks
|
|
44
|
+
|
|
45
|
+
Client-capable generated modules also expose hooks:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
useGetById(...)
|
|
49
|
+
useGetBySlug(...)
|
|
50
|
+
useGetByField(...)
|
|
51
|
+
useList(query)
|
|
52
|
+
useInfiniteList(query)
|
|
53
|
+
useGet(query)
|
|
54
|
+
useCreate()
|
|
55
|
+
useUpdate()
|
|
56
|
+
useRemove()
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Promise reads and hooks share the same query shape. `list()`/`useList()` returns `{ items, pageInfo }`; `useInfiniteList()` accumulates pages and exposes `items`, `hasMore`, `loadMore`, and `isLoadingMore`.
|
|
60
|
+
|
|
61
|
+
Write inputs are plain JSON. Read values carry source metadata, so use the generated `ArticleInput` type for writes instead of sending an `Article` read model back.
|
|
62
|
+
|
|
63
|
+
## Singleton API
|
|
64
|
+
|
|
65
|
+
A schema with `isSingleton: true` generates:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
get({ locale?, populate? })
|
|
69
|
+
update(payload)
|
|
70
|
+
useGet(options)
|
|
71
|
+
useSuspenseGet(options)
|
|
72
|
+
useUpdate()
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
It does not expose create, remove, list, or identity lookup methods.
|
|
76
|
+
|
|
77
|
+
## Query selection
|
|
78
|
+
|
|
79
|
+
Supported query keys: `limit` (1–100), `offset`, `search`, `sort`, `where`, `fields`, `populate`, and `locale`.
|
|
80
|
+
|
|
81
|
+
Use explicit ordering whenever order matters:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
Article.list({ sort: ['position', 'id'], limit: 20 });
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Use scalar equality or operator objects in `where`:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
Article.list({
|
|
91
|
+
where: {
|
|
92
|
+
featured: true,
|
|
93
|
+
views: { $gte: 100 },
|
|
94
|
+
title: { $contains: 'Next' },
|
|
95
|
+
cover: { $null: false },
|
|
96
|
+
},
|
|
97
|
+
sort: ['-publishedAt', 'title'],
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Operators: `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`, `$contains`, `$startsWith`, and `$null`.
|
|
102
|
+
|
|
103
|
+
Reference filters use target ID strings. To-many `$eq`/`$contains` means membership; `$in` means any listed target; `$ne`/`$nin` means none; `$null: true` means empty. Reference fields cannot be sorted.
|
|
104
|
+
|
|
105
|
+
## Projection and population
|
|
106
|
+
|
|
107
|
+
Keep arrays `as const` so TypeScript narrows the result:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
const page = await Article.list({
|
|
111
|
+
fields: ['slug', 'title', 'author'] as const,
|
|
112
|
+
populate: ['author'] as const,
|
|
113
|
+
});
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Fimo always keeps `id`, `entryId`, `documentId`, and `locale`. Without `populate`, references are `{ id }`; with it, they become the target entry or `null`. Populate is depth-one and only accepts reference field names.
|
|
117
|
+
|
|
118
|
+
When a named type is needed, use the generated result type rather than typing populated data as the base entry:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
import type { ArticleResult } from '@/schemas/Article';
|
|
122
|
+
|
|
123
|
+
type ArticleWithAuthor = ArticleResult<undefined, 'author'>;
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Localized and shared reads
|
|
127
|
+
|
|
128
|
+
Localized types have one variant per locale. Framework providers or explicit query options supply the active locale. Shared types (`i18n.enabled: false`) are created once and returned in every locale context.
|
|
129
|
+
|
|
130
|
+
Localized reference targets remain strict by default. Pass `localeFallbacks: true` only when the product deliberately wants the best available target variant (project default first); do not implement cross-locale fallback manually.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Rich text and entry payloads
|
|
2
|
+
|
|
3
|
+
## Tiptap JSONContent
|
|
4
|
+
|
|
5
|
+
Richtext values use Tiptap JSONContent, never raw HTML:
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"type": "doc",
|
|
10
|
+
"content": [
|
|
11
|
+
{ "type": "heading", "attrs": { "level": 2 }, "content": [{ "type": "text", "text": "Title" }] },
|
|
12
|
+
{
|
|
13
|
+
"type": "paragraph",
|
|
14
|
+
"content": [
|
|
15
|
+
{ "type": "text", "text": "Hello " },
|
|
16
|
+
{ "type": "text", "marks": [{ "type": "bold" }], "text": "world" }
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Nodes: `doc`, `paragraph`, `heading`, `bulletList`, `orderedList`, `listItem`, `blockquote`, `codeBlock`, `horizontalRule`, `hardBreak`, `table`, `tableRow`, `tableHeader`, `tableCell`, `image`, and `iframe`.
|
|
24
|
+
|
|
25
|
+
Marks: `bold`, `italic`, `underline`, `strike`, `code`, and `link`.
|
|
26
|
+
|
|
27
|
+
Use semantic nodes instead of flattening long content into paragraphs. Render the returned value with the framework's `<RichText>` primitive so source metadata survives.
|
|
28
|
+
|
|
29
|
+
## Entry payload
|
|
30
|
+
|
|
31
|
+
CLI entry writes put every value, including the collection slug, under `data`:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"data": {
|
|
36
|
+
"slug": "my-first-post",
|
|
37
|
+
"title": "My First Post",
|
|
38
|
+
"body": { "type": "doc", "content": [] },
|
|
39
|
+
"cover": { "source": "local", "url": "https://...", "alt": "Cover" }
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Do not put `slug` at the top level; unsupported top-level keys are stripped.
|
|
45
|
+
|
|
46
|
+
Slugs should be lowercase, hyphenated, stable, meaningful, and unique per content type. Fimo slugifies the supplied candidate. If omitted, Fimo generates one, which is unsuitable for content with durable public URLs.
|
|
47
|
+
|
|
48
|
+
For media fields, prefer assets uploaded or generated through Fimo. Load `fimo-cli/references/assets.md` or `fimo-cli/references/media.md` for those commands.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Content schemas
|
|
2
|
+
|
|
3
|
+
Write one schema per `src/schemas/<Uid>.json`. The PascalCase filename must match `uid`.
|
|
4
|
+
|
|
5
|
+
```json
|
|
6
|
+
{
|
|
7
|
+
"uid": "Article",
|
|
8
|
+
"name": "Articles",
|
|
9
|
+
"i18n": { "enabled": true },
|
|
10
|
+
"fields": {
|
|
11
|
+
"title": { "type": "string", "required": true },
|
|
12
|
+
"summary": { "type": "text" },
|
|
13
|
+
"body": { "type": "richtext" },
|
|
14
|
+
"publishedAt": { "type": "date" },
|
|
15
|
+
"featured": { "type": "boolean" },
|
|
16
|
+
"cover": { "type": "media" },
|
|
17
|
+
"metadata": { "type": "json" },
|
|
18
|
+
"author": { "type": "reference", "target": "Author" },
|
|
19
|
+
"contributors": { "type": "reference", "target": "Author", "many": true }
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Required root keys: `uid`, `name`, and `fields`. Add `"isSingleton": true` for one document such as SiteSettings.
|
|
25
|
+
|
|
26
|
+
## Locale policy
|
|
27
|
+
|
|
28
|
+
- Omit `i18n` or use `{ "enabled": true }` for localized variants.
|
|
29
|
+
- Use `{ "enabled": false }` for one shared document/entry across locales.
|
|
30
|
+
- A top-level scalar or reference in a localized type may use `"i18n": false` for one shared field value, such as SKU or price.
|
|
31
|
+
- Fields inside blocks inherit the owning entry locale and cannot declare `i18n`.
|
|
32
|
+
|
|
33
|
+
## Reserved metadata
|
|
34
|
+
|
|
35
|
+
Never declare `id`, `entryId`, `documentId`, `slug`, `locale`, `createdAt`, `updatedAt`, or `__fimo` in `fields`. Collections receive `slug` automatically; supply it when creating an entry, not in the schema.
|
|
36
|
+
|
|
37
|
+
## Field types
|
|
38
|
+
|
|
39
|
+
| Type | Write shape | Use |
|
|
40
|
+
| ----------- | -------------------------- | ---------------------------------------- |
|
|
41
|
+
| `string` | string | one-line text; add `options` for an enum |
|
|
42
|
+
| `text` | string | multiline plain text |
|
|
43
|
+
| `richtext` | Tiptap JSONContent | formatted content |
|
|
44
|
+
| `number` | number | quantities and ordering fields |
|
|
45
|
+
| `boolean` | boolean | flags |
|
|
46
|
+
| `date` | ISO date string | dates/timestamps |
|
|
47
|
+
| `media` | media object or array | images, video, files |
|
|
48
|
+
| `json` | JSON | structured metadata |
|
|
49
|
+
| `reference` | `{ "id": "..." }` or array | links to another schema |
|
|
50
|
+
| `blocks` | ordered object array | nested/repeatable sections |
|
|
51
|
+
|
|
52
|
+
An enum string uses `options`; its optional `default` must be one of them:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
"layout": { "type": "string", "options": ["article", "video"], "default": "article" }
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Conditional fields
|
|
59
|
+
|
|
60
|
+
Use `showIf` when every clause must match and `showIfAny` when one may match:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"layout": { "type": "string", "options": ["article", "video"] },
|
|
65
|
+
"body": { "type": "richtext", "showIf": { "field": "layout", "equals": "article" } },
|
|
66
|
+
"videoUrl": { "type": "string", "required": true, "showIf": { "field": "layout", "equals": "video" } }
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Conditions reference sibling boolean, number, or enumerated string fields. Hidden fields keep stored values but are not validated; generated types therefore keep conditional fields optional. Conditions do not chain.
|
|
71
|
+
|
|
72
|
+
## Blocks
|
|
73
|
+
|
|
74
|
+
Use `schema.fields` for one repeated shape and `schema.oneOf` for selectable variants:
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
"sections": {
|
|
78
|
+
"type": "blocks",
|
|
79
|
+
"max": 20,
|
|
80
|
+
"schema": {
|
|
81
|
+
"oneOf": [
|
|
82
|
+
{
|
|
83
|
+
"uid": "hero",
|
|
84
|
+
"label": "Hero",
|
|
85
|
+
"fields": {
|
|
86
|
+
"heading": { "type": "string", "required": true },
|
|
87
|
+
"introduction": { "type": "text" }
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"uid": "quote",
|
|
92
|
+
"label": "Quote",
|
|
93
|
+
"fields": { "quote": { "type": "text", "required": true } }
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
- Blocks always read/write arrays; `max: 1` means `[]` or `[item]`.
|
|
101
|
+
- Fimo adds stable `_key` values; `oneOf` items also receive `_type`.
|
|
102
|
+
- Nest blocks up to seven levels. One `oneOf` supports up to 40 variants and one blocks field up to 200 items.
|
|
103
|
+
- Nested scalar values use the same source-tracked value type as top-level fields.
|
|
104
|
+
- Nested reference population and filtering are not supported.
|
|
105
|
+
|
|
106
|
+
## References
|
|
107
|
+
|
|
108
|
+
Use fixed `target` references whenever every value has one type. Use `many: true` for to-many fields. Values use stable document `id`, never `entryId`; use `null` or `[]` when empty. To-many array order is preserved.
|
|
109
|
+
|
|
110
|
+
Use `targets: ["Post", "Video"]` instead of `target` only for genuinely polymorphic slots. Populated polymorphic values expose `$type` for narrowing. They cannot currently be filtered.
|
|
111
|
+
|
|
112
|
+
## Safe transitions
|
|
113
|
+
|
|
114
|
+
After writing or changing `src/schemas/<Uid>.json`, run `fimo schemas push <Uid>` before building against that schema. The push validates the JSON, generates its public clients, and updates the linked environment.
|
|
115
|
+
|
|
116
|
+
- Optional additions and label changes preserve entries.
|
|
117
|
+
- Required additions need a valid default when existing objects require backfill.
|
|
118
|
+
- Removing a field or block variant removes only that value.
|
|
119
|
+
- String/text changes and safe primitive conversions preserve values.
|
|
120
|
+
- Fixed-target relation renames preserve links when the target remains the same; target changes clear them.
|
|
121
|
+
- Preserve explicit nested renames with `--rename old.path=new.path`.
|
|
122
|
+
- Failed migrations are atomic. There is no reset or data-loss flag.
|