fimo 0.13.0 → 0.14.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.
Files changed (44) hide show
  1. package/assets/content-templates/types-template.eta +3 -29
  2. package/assets/skills/fimo-cli/references/agents.md +1 -0
  3. package/assets/skills/fimo-cli/references/content.md +7 -0
  4. package/assets/skills/fimo-cli/references/deploy.md +11 -0
  5. package/assets/skills/fimo-cli/references/history.md +2 -0
  6. package/assets/skills/fimo-cli/references/locales.md +2 -0
  7. package/assets/skills/fimo-cli/references/project-vars-and-secrets.md +6 -2
  8. package/assets/skills/fimo-code/SKILL.md +7 -0
  9. package/assets/skills/fimo-code/references/content/clients.md +9 -1
  10. package/assets/skills/fimo-code/references/content/schema.md +14 -1
  11. package/assets/skills/fimo-code/references/frameworks/hosting.md +91 -0
  12. package/assets/skills/fimo-code/references/frameworks/next/app-router.md +1 -1
  13. package/assets/skills/fimo-code/references/frameworks/next.md +32 -3
  14. package/assets/skills/fimo-code/references/frameworks/react-router.md +7 -0
  15. package/assets/skills/fimo-code/references/frameworks/vite-react.md +8 -7
  16. package/assets/skills/fimo-code/references/ui.md +19 -0
  17. package/assets/skills/fimo-studio/references/cms.md +4 -1
  18. package/dist/build/next/config.d.ts +14 -0
  19. package/dist/build/next/config.js +34 -0
  20. package/dist/build/vite/plugins/server-config.js +15 -2
  21. package/dist/cli/bundle.json +1 -1
  22. package/dist/cli/index.js +92 -92
  23. package/dist/runtime/app/FimoScripts.js +2 -2
  24. package/dist/runtime/iframe/ScreenshotProvider.js +1 -1
  25. package/dist/runtime/next/labels.d.ts +1 -1
  26. package/dist/runtime/next/labels.js +1 -1
  27. package/dist/runtime/next/server-runtime.js +3 -3
  28. package/dist/runtime/primitives/lib/image-optimization.d.ts +3 -3
  29. package/dist/runtime/react-router/preset.d.ts +30 -0
  30. package/dist/runtime/react-router/preset.js +33 -0
  31. package/dist/runtime/seo/buildSeoForPath.d.ts +16 -16
  32. package/dist/runtime/shared/fimo-config.server.js +5 -0
  33. package/dist/runtime/shared/fimo-config.types.d.ts +20 -0
  34. package/dist/runtime/templates.d.ts +1 -1
  35. package/dist/scripts/validate-fimo-config.d.ts +5 -0
  36. package/dist/scripts/validate-fimo-config.js +29 -0
  37. package/dist/scripts/validate-route-metadata.js +1 -1
  38. package/package.json +11 -2
  39. package/release.json +2 -2
  40. package/templates/react-router/.fimo/config.json +1 -0
  41. package/templates/react-router/_gitignore +1 -0
  42. package/templates/react-router/package.json +5 -5
  43. package/templates/react-router/react-router.config.ts +2 -0
  44. package/templates/react-router/tsconfig.json +5 -6
@@ -144,34 +144,6 @@ function getInputTypeForField(field) {
144
144
  }
145
145
  }
146
146
 
147
- function getNestedFieldType(field, input) {
148
- switch(field.type) {
149
- case 'string':
150
- return getStringLiteralUnion(field) || 'string';
151
- case 'text':
152
- return 'string';
153
- case 'richtext':
154
- return 'FimoRichTextContent';
155
- case 'number':
156
- return 'number';
157
- case 'boolean':
158
- return 'boolean';
159
- case 'date':
160
- return 'string';
161
- case 'json':
162
- case 'media':
163
- return 'Record<string, unknown>';
164
- case 'reference': {
165
- const raw = Array.isArray(field.targets) && field.targets.length > 0 ? 'FimoPolymorphicReference' : 'FimoReference';
166
- return field.many ? `${raw}[]` : `${raw} | null`;
167
- }
168
- case 'blocks':
169
- return getBlocksType(field, input);
170
- default:
171
- return 'unknown';
172
- }
173
- }
174
-
175
147
  function getBlockObjectType(fields, input, metadata = {}) {
176
148
  const properties = [];
177
149
  if (metadata.key) {
@@ -181,7 +153,9 @@ function getBlockObjectType(fields, input, metadata = {}) {
181
153
  properties.push(`_type: "${metadata.type}"`);
182
154
  }
183
155
  for (const [key, field] of Object.entries(fields || {})) {
184
- properties.push(`${key}${isRequiredField(field) ? '' : '?'}: ${getNestedFieldType(field, input)}`);
156
+ properties.push(
157
+ `${key}${isRequiredField(field) ? '' : '?'}: ${input ? getInputTypeForField(field) : getTypeForField(field)}`
158
+ );
185
159
  }
186
160
  return `{ ${properties.join('; ')} }`;
187
161
  }
@@ -83,6 +83,7 @@ There is no all-capabilities wildcard; keeping the list explicit makes each agen
83
83
  | `fimo:logs:read` | Read production logs | Low |
84
84
  | `fimo:analytics:read` | Read analytics data | Low |
85
85
  | `fimo:preview:read` | Read a current preview URL | Low |
86
+ | `fimo:history:read` | Read project restore points | Low |
86
87
  | `fimo:deploy` | Trigger a production deploy | Critical |
87
88
  | `net:fetch` | Make outbound HTTP requests | Medium |
88
89
  | `agent:delegate` | Invoke declared sub-agents | Medium |
@@ -6,6 +6,13 @@
6
6
 
7
7
  This file covers the **CLI workflow** for content. Use it when the user wants to add a content type (blog, products, pages) or manage Singles and entries.
8
8
 
9
+ ## Choose the write path first
10
+
11
+ - Exactly one homepage, settings document, About page, or campaign page → declare `"isSingleton": true` and write it with `fimo singles update <TypeName>`.
12
+ - Repeated posts, products, team members, or reusable pages → keep a collection and create rows with `fimo entries create <TypeName>`.
13
+
14
+ Never remove `isSingleton: true` merely because `fimo entries create` rejects the type. `entries` and `singles` are separate command namespaces; inspect `fimo singles --help` when the content is one-off.
15
+
9
16
  ## Flow
10
17
 
11
18
  1. Write `src/schemas/{Uid}.json` — PascalCase filename (e.g. `BlogPost.json`). Run `npx fimo@latest skills get fimo-code --ref content/schema` for the JSON contract.
@@ -47,6 +47,17 @@ When reporting the result, present the raw values as named Markdown links. If no
47
47
 
48
48
  Public project variables managed with `fimo vars add` and `fimo vars update` are injected into preview/build/deploy environments. Project secrets are not injected into app builds; agents request secrets separately through their own config. See `references/project-vars-and-secrets.md`.
49
49
 
50
+ ## Framework hosting
51
+
52
+ Fimo preview resolves `runtime.commands` override → package script → detected
53
+ framework default. Production uses `.fimo/config.json#runtime.framework` and
54
+ the same bounded build/install overrides. Existing applications keep their
55
+ router and hosting behavior: do not replace the router or derive
56
+ deployment rewrites from `.fimo/config.json#routes`. When setup changes are
57
+ needed, load the `fimo-code` skill's `references/frameworks/hosting.md` recipe;
58
+ it covers the React Router `fimoPreset()` connector and the explicit catch-all
59
+ used only by plain Vite `BrowserRouter` SPAs.
60
+
50
61
  ## Warm the sandbox early in a session (optional)
51
62
 
52
63
  This is a **performance optimization, only worth doing when you already know a deploy is coming** (the developer asked to publish, or you're confident they'll want a hosted preview soon). If you're just iterating locally, skip it — don't deploy pre-emptively.
@@ -13,6 +13,8 @@ fimo history create "Before content migration"
13
13
  fimo history restore <version-id>
14
14
  ```
15
15
 
16
+ Studio chat can run `history list` and `history show`. Create and restore remain available through the standalone CLI and Studio's History page.
17
+
16
18
  Use the global `--env <name>` option to target a different environment. Use `--project <id>` when there is no local `.fimo/project.json`.
17
19
 
18
20
  ## Pagination and usage
@@ -15,6 +15,8 @@ fimo locales set-default es --yes --json
15
15
  fimo locales remove es --yes --json
16
16
  ```
17
17
 
18
+ Studio chat can run `locales list`. Manage the locale lifecycle through Studio Settings or the standalone CLI.
19
+
18
20
  These commands update the selected environment through the locale lifecycle API. The API commits `.fimo/config.json` to the Fimo branch, then the CLI synchronizes the **whole local branch** to that commit. They refuse a dirty config, a local-ahead branch, or a diverged branch before applying the remote change. `--yes` bypasses only the explanatory prompt.
19
21
 
20
22
  If a mutation exits with code `2` and `data.code` is `LOCALE_APPLIED_SYNC_REQUIRED`, the remote operation succeeded (`data.applied` is `true`) but the local fast-forward did not. **Do not retry the locale command.** Run the commands in `data.sync.recovery`, resolve the checkout, and confirm with `fimo status` or `fimo locales list`.
@@ -26,7 +26,8 @@ fimo vars pull .env.e2e
26
26
 
27
27
  Fimo only edits the block between `# fimo:vars:start` and `# fimo:vars:end`. User-authored lines in the file stay untouched.
28
28
 
29
- Variables are public by design. They may use browser-safe prefixes such as `VITE_`, `PUBLIC_`, or `NEXT_PUBLIC_`.
29
+ Variables are public by design. They may use browser-safe prefixes such as
30
+ `VITE_`, `PUBLIC_`, `NEXT_PUBLIC_`, or `NUXT_PUBLIC_`.
30
31
 
31
32
  ## Secrets
32
33
 
@@ -41,7 +42,10 @@ fimo secrets unset FIRECRAWL_API_KEY
41
42
  Secret values are hidden after write. Listing secrets shows the key and a masked value, never the plaintext.
42
43
  `fimo secrets add` refuses to replace an existing value. Use `fimo secrets update` for an intentional rotation.
43
44
 
44
- Secrets are not written to `.env.local`, preview app env files, browser bundles, or generated project files. Secrets cannot use public prefixes such as `VITE_`, `PUBLIC_`, or `NEXT_PUBLIC_`; those prefixes are for public variables.
45
+ Secrets are not written to `.env.local`, preview app env files, browser bundles,
46
+ or generated project files. Secrets cannot use public prefixes such as `VITE_`,
47
+ `PUBLIC_`, `NEXT_PUBLIC_`, or `NUXT_PUBLIC_`; those prefixes are for public
48
+ variables.
45
49
 
46
50
  ## Local Env Files
47
51
 
@@ -20,11 +20,17 @@ Use the project-installed CLI for local inspection, code generation, and validat
20
20
  2. Load only the references required by the task.
21
21
  3. Load the framework reference before choosing imports, providers, or rendering APIs.
22
22
 
23
+ For an existing application, preserve its project structure and add only the
24
+ connector required by the task. Complete example projects live in executable
25
+ fixtures and starters, not in this skill; `assets/` contains only files meant
26
+ to be copied verbatim.
27
+
23
28
  Framework routing:
24
29
 
25
30
  - `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
31
  - React Router framework mode (`react-router.config.ts`, `src/routes.ts`) → `references/frameworks/react-router.md`.
27
32
  - Vite + React without framework mode → `references/frameworks/vite-react.md`.
33
+ - Astro, Nuxt, Remix, SvelteKit, Vue, or another hosting-only setup → `references/frameworks/hosting.md`. The current content/primitives SDK is React-only; do not invent a framework adapter.
28
34
 
29
35
  ## Durable content contract
30
36
 
@@ -46,6 +52,7 @@ Each reference defines one package contract. Fetch it when the task reaches that
46
52
  - Media values, `<Image>`, `<StaticImage>` → `references/assets.md`
47
53
  - Static editable copy: `t()`, `useLabels`, `getLabels` → `references/labels.md`
48
54
  - Locale ownership and framework handoff → `references/locales.md`
55
+ - Framework detection, production routing, and hosting adapters → `references/frameworks/hosting.md`
49
56
  - Major visual work → `references/design.md`
50
57
 
51
58
  ## Non-negotiable boundaries
@@ -62,7 +62,15 @@ Write inputs are plain JSON. Read values carry source metadata, so use the gener
62
62
 
63
63
  ## Singleton API
64
64
 
65
- A schema with `isSingleton: true` generates:
65
+ A schema with `isSingleton: true` generates a default client:
66
+
67
+ ```tsx
68
+ import HomePage from '@/schemas/HomePage';
69
+
70
+ const { data: homePage } = HomePage.useGet();
71
+ ```
72
+
73
+ Its API is:
66
74
 
67
75
  ```ts
68
76
  get({ locale?, populate? })
@@ -21,7 +21,20 @@ Write one schema per `src/schemas/<Uid>.json`. The PascalCase filename must matc
21
21
  }
22
22
  ```
23
23
 
24
- Required root keys: `uid`, `name`, and `fields`. Add `"isSingleton": true` for one document such as SiteSettings.
24
+ Required root keys: `uid`, `name`, and `fields`.
25
+
26
+ Use `"isSingleton": true` whenever the site has exactly one logical document: a homepage, site settings, an About page, or one campaign landing page. Do not turn it into a one-entry collection just to seed content; keep the Single and load `fimo-cli/references/content.md` for the `fimo singles update` workflow.
27
+
28
+ ```json
29
+ {
30
+ "uid": "HomePage",
31
+ "name": "Homepage",
32
+ "isSingleton": true,
33
+ "fields": {
34
+ "title": { "type": "string", "required": true }
35
+ }
36
+ }
37
+ ```
25
38
 
26
39
  ## Locale policy
27
40
 
@@ -0,0 +1,91 @@
1
+ # Connect an application's hosting
2
+
3
+ Preserve the application's framework, router, routes, and 404 behavior. Fimo
4
+ detects supported frameworks for preview and translates only the
5
+ provider-neutral hosting settings the application explicitly owns.
6
+
7
+ ## Production framework profile
8
+
9
+ Fimo detects conventional projects for preview. Before publishing, commit the
10
+ matching profile in `.fimo/config.json`:
11
+
12
+ ```json
13
+ {
14
+ "runtime": { "framework": "nextjs" }
15
+ }
16
+ ```
17
+
18
+ Allowed values are `astro`, `nextjs`, `nuxtjs`, `react-router`, `remix`,
19
+ `sveltekit`, `vite`, and `vue`. The field remains optional for legacy Fimo
20
+ projects, which keep their existing static output contract.
21
+
22
+ Hosted preview and production inject the tenant API through these aliases:
23
+
24
+ | Application | Server | Public/build |
25
+ | ----------------------- | ---------------------- | -------------------------- |
26
+ | Next.js | `FIMO_CONTENT_API_URL` | `NEXT_PUBLIC_FIMO_API_URL` |
27
+ | Nuxt | `FIMO_CONTENT_API_URL` | `NUXT_PUBLIC_FIMO_API_URL` |
28
+ | Astro, Remix, SvelteKit | `FIMO_CONTENT_API_URL` | `PUBLIC_FIMO_API_URL` |
29
+ | React Router, Vite, Vue | `FIMO_CONTENT_API_URL` | `VITE_API_URL` |
30
+
31
+ Current `fimo init` and `fimo clone` write the Vite and Next aliases locally.
32
+ For another framework, preserve or add its normal local environment alias; do
33
+ not hardcode a tenant URL in application source.
34
+
35
+ ## React Router framework mode
36
+
37
+ For the supported client-rendered setup, keep `ssr: false` and add Fimo's
38
+ hosting preset. It hides the active hosting provider from application code:
39
+
40
+ ```ts
41
+ import type { Config } from '@react-router/dev/config';
42
+ import { fimoPreset } from 'fimo/react-router/preset';
43
+
44
+ export default {
45
+ ssr: false,
46
+ presets: [fimoPreset()],
47
+ } satisfies Config;
48
+ ```
49
+
50
+ Do not install or import a hosting-provider preset. Fimo's React Router SSR
51
+ adapter is not available yet; do not change an existing SSR project to
52
+ `ssr: false` merely to add Fimo.
53
+
54
+ ## Plain Vite SPA
55
+
56
+ A `BrowserRouter` SPA needs the host to serve its app shell for direct visits
57
+ to client routes. Declare that behavior once in `.fimo/config.json`:
58
+
59
+ ```json
60
+ {
61
+ "runtime": { "framework": "vite" },
62
+ "hosting": {
63
+ "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
64
+ }
65
+ }
66
+ ```
67
+
68
+ Do not add the rewrite to a `HashRouter` app or a Vite app that emits a real
69
+ file for every route. A catch-all preserves the browser router's not-found UI,
70
+ but the host initially returns the app shell with status 200.
71
+
72
+ ## Native frameworks
73
+
74
+ Next.js and the other supported native frameworks own their build and routing
75
+ output. Do not add a catch-all rewrite; the framework's hosting preset handles
76
+ routes, server functions, static output, and 404 responses.
77
+
78
+ `.fimo/config.json#routes` is the Studio page catalog, not deployment routing.
79
+ Never generate hosting rewrites from it. If a project already has a
80
+ provider-specific deployment file, preserve it; that file remains authoritative.
81
+
82
+ ## Non-standard commands
83
+
84
+ Use `runtime.commands.dev|build|install` only when normal package scripts and
85
+ framework defaults are insufficient. Do not add overrides to conventional
86
+ projects.
87
+
88
+ Vite defaults to `dist` and React Router defaults to `dist/client`. If an
89
+ existing project deliberately emits somewhere else, preserve that choice with
90
+ `runtime.outputDirectory`; do not rewrite the application's build merely to
91
+ match a Fimo default.
@@ -51,7 +51,7 @@ export default async function ArticlesPage() {
51
51
 
52
52
  `createFimo({ content, locale })` is a typed locale-bound facade over the generated registry. It does not own routing and does not force SSG.
53
53
 
54
- Static builds that read Fimo must receive the real build-time `FIMO_API_URL` (or `NEXT_PUBLIC_FIMO_API_URL`) and default locale environment. Do not switch a route to dynamic rendering merely to hide a missing build environment; choose SSG, ISR, or request-time rendering from the application's intended behavior.
54
+ Static builds that read Fimo must receive the real build-time `FIMO_CONTENT_API_URL` and default locale environment. Do not switch a route to dynamic rendering merely to hide a missing build environment; choose SSG, ISR, or request-time rendering from the application's intended behavior.
55
55
 
56
56
  ## Request-time rendering
57
57
 
@@ -14,6 +14,30 @@ When streaming a nested reference from the CLI, preserve its slashes: use `--ref
14
14
 
15
15
  Preserve the router already present. Do not add a second router or convert between App and Pages Router merely to integrate Fimo.
16
16
 
17
+ ## Production profile
18
+
19
+ Set `runtime.framework` to `nextjs` in `.fimo/config.json` before the first
20
+ hosted publish. Run `fimo validate`; load
21
+ `references/frameworks/hosting.md` for the shared profile contract and command
22
+ override rules.
23
+
24
+ ## Hosted preview config
25
+
26
+ Wrap the existing Next config once so Fimo can connect its hosted development
27
+ preview without exposing the active preview provider to the application:
28
+
29
+ ```ts
30
+ import type { NextConfig } from 'next';
31
+ import { withFimo } from 'fimo/next/config';
32
+
33
+ const nextConfig: NextConfig = {};
34
+ export default withFimo(nextConfig);
35
+ ```
36
+
37
+ Preserve all existing config fields or config-function logic. Do not hardcode a
38
+ preview domain in `allowedDevOrigins`; Fimo supplies it to the development
39
+ sandbox. The wrapper does not change production builds.
40
+
17
41
  ## Client dependency
18
42
 
19
43
  Server-only Fimo reads need no client data library. If the app uses `FimoProvider`,
@@ -26,12 +50,13 @@ do not install it automatically.
26
50
  Linked projects need the tenant content API in both Next runtimes:
27
51
 
28
52
  ```dotenv
29
- FIMO_API_URL=https://<tenant-api>
53
+ FIMO_CONTENT_API_URL=https://<tenant-api>
30
54
  NEXT_PUBLIC_FIMO_API_URL=https://<tenant-api>
31
55
  ```
32
56
 
33
57
  Current `fimo init` and `fimo clone` write these alongside `VITE_API_URL` while
34
- preserving user-owned values. Never point them at the management API. Keep the
58
+ preserving user-owned values. `FIMO_API_URL` remains reserved for CLI/control API
59
+ overrides. Keep the
35
60
  server variable private; only the public variable is compiled into Client
36
61
  Components.
37
62
 
@@ -113,4 +138,8 @@ Passing `locale` without `labels` is valid when only content hooks need context.
113
138
 
114
139
  Use normal schemas, generated clients, Fimo primitives, and labels. Do not use migration-only `Wrapped*` components, private `fetchEntries`, fallback stores, or adopted-site loaders. Migration code may temporarily adapt old source shapes, but those interfaces are not the Next SDK.
115
140
 
116
- Do not add `.fimo/config.json#routes` to a Next project yet. The current route-metadata validator still targets React Router and expects `src/routes.ts`; a first-class Next route catalog and preview bridge are separate product work. Fimo content, labels, locales, and hosting do not require that catalog.
141
+ `.fimo/config.json#routes` is an optional Studio page catalog, not Next routing.
142
+ Keep it aligned when the project uses Studio navigation or page metadata; Next's
143
+ file-system routes remain authoritative. `fimo validate` does not run the React
144
+ Router route-metadata validator on Next projects. Fimo content, labels, locales,
145
+ and hosting do not require the catalog.
@@ -70,10 +70,12 @@ Notes:
70
70
 
71
71
  ```ts
72
72
  import type { Config } from '@react-router/dev/config';
73
+ import { fimoPreset } from 'fimo/react-router/preset';
73
74
 
74
75
  export default {
75
76
  appDirectory: 'src',
76
77
  ssr: false,
78
+ presets: [fimoPreset()],
77
79
  // Static-site generation is opt-in. By default this template builds as an
78
80
  // SPA (single index.html shell, client-side routing). To prerender routes at
79
81
  // build time — required for crawler-visible per-route SEO — add this line:
@@ -88,6 +90,10 @@ export default {
88
90
  } satisfies Config;
89
91
  ```
90
92
 
93
+ `fimoPreset()` connects the client-rendered build to Fimo hosting without
94
+ exposing a provider package. See `references/frameworks/hosting.md`; do not
95
+ apply this SPA preset to an existing SSR project.
96
+
91
97
  **SSG is opt-in now.** Default = SPA (one HTML shell). Add `prerender`
92
98
  yourself if you want crawler-visible per-route HTML. The previous
93
99
  "prerender everything by default" behavior was a website-builder opinion
@@ -205,6 +211,7 @@ export default function HomePage() {
205
211
 
206
212
  ```json
207
213
  {
214
+ "runtime": { "framework": "react-router" },
208
215
  "version": "4",
209
216
  "seo": {
210
217
  "title": "__PROJECT_SLUG__",
@@ -142,7 +142,11 @@ export function App() {
142
142
 
143
143
  ```json
144
144
  {
145
- "version": "3",
145
+ "runtime": { "framework": "vite" },
146
+ "hosting": {
147
+ "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
148
+ },
149
+ "version": "4",
146
150
  "seo": {
147
151
  "title": "__PROJECT_SLUG__",
148
152
  "siteName": "__PROJECT_SLUG__"
@@ -156,12 +160,9 @@ export function App() {
156
160
  }
157
161
  ```
158
162
 
159
- Note: `"version": "3"` marks the legacy plain-Vite (no-RR-framework-mode)
160
- shape. `fimo()` is version-agnostic — it composes a fixed set of build-time
161
- plugins from the `seo`/`sitemap`/`robots` options you pass and never reads
162
- this version field. It also never injects the React Router plugin: in a
163
- framework-mode project that `reactRouter()` plugin is added by your own
164
- `vite.config.ts`, not by `fimo/vite`.
163
+ The rewrite is required for direct visits to `BrowserRouter` routes on Fimo
164
+ hosting. Omit it for `HashRouter` or real per-route static output. See
165
+ `references/frameworks/hosting.md`.
165
166
 
166
167
  ## File: `.fimo/project.json`
167
168
 
@@ -25,6 +25,25 @@ Use Fimo components for source-tracked schema and label values so Studio can ide
25
25
 
26
26
  Pass the tracked value directly. Do not replace `<Text>` with `<h1>{article.title}</h1>`, unwrap media into raw `<img>`, or hand-roll richtext rendering.
27
27
 
28
+ Blocks do not change this rule. Every visible nested scalar is source-tracked too, including fields inside repeated and nested blocks:
29
+
30
+ ```tsx
31
+ {
32
+ homePage.programs.map((program) => (
33
+ <article key={program._key}>
34
+ <Text value={program.level} />
35
+ <Text value={program.title} as="h3" />
36
+ <Text value={program.description} as="p" />
37
+ {program.highlights.map((highlight) => (
38
+ <Text key={highlight._key} value={highlight.label} />
39
+ ))}
40
+ </article>
41
+ ));
42
+ }
43
+ ```
44
+
45
+ Do not render those values as `{program.title}` or `{highlight.label}`. That displays text but bypasses the primitive that Studio uses to resolve the exact nested edit target.
46
+
28
47
  Use `<StaticImage>` only when the image is deliberately not editor-managed. Use `String(value)` for attributes/third-party APIs that cannot accept a `FimoString`; keep editable visible text in `<Text>`.
29
48
 
30
49
  Never construct `FimoString`, `FimoRichText`, `FimoBoolean`, or `FimoMedia` manually. Generated clients and label readers attach the correct source path.
@@ -60,7 +60,9 @@ Changes save automatically as you fill in each field (the save is debounced), so
60
60
  1. Click the entry you want to change.
61
61
  2. Update any fields you need.
62
62
 
63
- Your edits save automatically as you change each field (the save is debounced), so there is no Save button. Watch the top bar for the save status (Saving / Saved). The entry editor's only header actions are delete (trash icon) and copy link.
63
+ Your edits save automatically as you change each field (the save is debounced), so there is no Save button. Watch the top bar for the save status (Saving / Saved). The entry editor header lets you move to the previous or next entry, delete the current entry, or copy its link.
64
+
65
+ Press **Alt+J** to move to the next entry or **Alt+K** to move to the previous one (**Option+J** and **Option+K** on macOS). These shortcuts also work while your cursor is inside a rich-text field, and pending changes save before Fimo moves.
64
66
 
65
67
  If a field is invalid, the editor keeps the change unsaved and pins a status bar below the header. Choose **Review issues** to jump to the first invalid field, then **Next issue** to move through the remaining fields. Collapsed blocks open automatically. Once every issue is fixed, the editor confirms that all fields are valid and resumes saving.
66
68
 
@@ -71,6 +73,7 @@ A field labelled with a padlocked globe is shared across languages: it holds one
71
73
  - Short text such as titles, names, and slugs uses one compact line.
72
74
  - Plain multiline text such as summaries and descriptions starts taller and grows as you write.
73
75
  - Formatted content uses the rich-text editor for headings, links, lists, and media.
76
+ - In a rich-text field, paste or drop an image file to upload it to Assets and insert it. Type `/` and choose **Image** to reuse an existing image or upload a new one from the picker.
74
77
 
75
78
  ## Bulk Operations
76
79
 
@@ -0,0 +1,14 @@
1
+ export interface FimoNextConfigContext {
2
+ readonly defaultConfig?: object;
3
+ readonly [key: string]: unknown;
4
+ }
5
+ export type FimoNextConfigFactory<TConfig extends object = object> = (phase: string, context: FimoNextConfigContext) => TConfig | Promise<TConfig>;
6
+ export type FimoNextConfig<TConfig extends object = object> = TConfig | FimoNextConfigFactory<TConfig>;
7
+ /**
8
+ * Connect a Next development server to Fimo's hosted preview gateway.
9
+ *
10
+ * The platform supplies allowed preview origins at runtime, so applications do
11
+ * not need to know which preview provider Fimo currently uses.
12
+ */
13
+ export declare function withFimo<TConfig extends object>(applicationConfig: FimoNextConfig<TConfig>): FimoNextConfigFactory<TConfig>;
14
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1,34 @@
1
+ const NEXT_DEVELOPMENT_PHASE = 'phase-development-server';
2
+ const PREVIEW_ORIGINS_ENV = 'FIMO_PREVIEW_ALLOWED_ORIGINS';
3
+ function readPreviewOrigins() {
4
+ return (process.env[PREVIEW_ORIGINS_ENV] ?? '')
5
+ .split(',')
6
+ .map((origin) => origin.trim())
7
+ .filter(Boolean);
8
+ }
9
+ /**
10
+ * Connect a Next development server to Fimo's hosted preview gateway.
11
+ *
12
+ * The platform supplies allowed preview origins at runtime, so applications do
13
+ * not need to know which preview provider Fimo currently uses.
14
+ */
15
+ export function withFimo(applicationConfig) {
16
+ return async (phase, context) => {
17
+ const config = typeof applicationConfig === 'function'
18
+ ? await applicationConfig(phase, context)
19
+ : applicationConfig;
20
+ if (phase !== NEXT_DEVELOPMENT_PHASE) {
21
+ return config;
22
+ }
23
+ const previewOrigins = readPreviewOrigins();
24
+ if (previewOrigins.length === 0) {
25
+ return config;
26
+ }
27
+ const configuredOrigins = config.allowedDevOrigins;
28
+ const allowedDevOrigins = [
29
+ ...(Array.isArray(configuredOrigins) ? configuredOrigins : []),
30
+ ...previewOrigins,
31
+ ].filter((origin, index, origins) => origins.indexOf(origin) === index);
32
+ return { ...config, allowedDevOrigins };
33
+ };
34
+ }
@@ -1,10 +1,23 @@
1
+ const PREVIEW_ORIGINS_ENV = 'FIMO_PREVIEW_ALLOWED_ORIGINS';
2
+ function readPreviewHosts() {
3
+ return (process.env[PREVIEW_ORIGINS_ENV] ?? '')
4
+ .split(',')
5
+ .map((origin) => origin.trim())
6
+ .filter(Boolean)
7
+ .map((origin) => (origin.startsWith('**.') ? `.${origin.slice(3)}` : origin));
8
+ }
1
9
  export default function serverConfigPlugin() {
2
10
  return {
3
11
  name: 'fimo:server-config',
4
- config() {
12
+ config(config) {
13
+ const configuredHosts = config.server?.allowedHosts;
14
+ const previewHosts = readPreviewHosts();
15
+ const allowedHosts = configuredHosts === true
16
+ ? true
17
+ : [...(configuredHosts ?? []), ...previewHosts].filter((host, index, hosts) => hosts.indexOf(host) === index);
5
18
  return {
6
19
  server: {
7
- allowedHosts: true,
20
+ ...(allowedHosts === true || allowedHosts.length > 0 ? { allowedHosts } : {}),
8
21
  hmr: {
9
22
  overlay: false,
10
23
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "bundled": true,
3
3
  "bundler": "esbuild",
4
- "bundledAt": "2026-08-12T13:31:56.833Z",
4
+ "bundledAt": "2026-08-13T20:53:52.462Z",
5
5
  "cliVersion": "0.13.0",
6
6
  "external": [
7
7
  "oxc-parser",