fimo 2.6.0 → 2.7.0-experimental.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/skills/fimo-cli/SKILL.md +1 -1
- package/assets/skills/fimo-cli/references/analytics.md +29 -1
- package/assets/skills/fimo-cli/references/content.md +2 -2
- package/assets/skills/fimo-cli/references/hosting.md +11 -0
- package/assets/skills/fimo-cli/references/locales.md +2 -2
- package/assets/skills/fimo-cli/references/pages.md +14 -2
- package/assets/skills/fimo-code/SKILL.md +8 -0
- package/assets/skills/fimo-code/references/analytics.md +104 -0
- package/assets/skills/fimo-code/references/frameworks/astro.md +2 -0
- package/assets/skills/fimo-code/references/frameworks/next.md +12 -9
- package/assets/skills/fimo-code/references/ui.md +6 -1
- package/assets/skills/fimo-migration/SKILL.md +9 -6
- package/assets/skills/fimo-migration/references/frameworks/nextjs.md +24 -27
- package/assets/skills/fimo-migration/references/media.md +98 -62
- package/assets/skills/fimo-migration/references/qa.md +111 -11
- package/assets/skills/fimo-migration/references/workers/content-execution.md +2 -1
- package/assets/skills/fimo-migration/references/workers/validator.md +22 -6
- package/assets/skills/fimo-migration/references/workers.md +5 -3
- package/assets/skills/fimo-migration/scripts/check-rendered-guardrails.mjs +500 -0
- package/assets/skills/fimo-studio/SKILL.md +1 -0
- package/assets/skills/fimo-studio/references/analytics.md +28 -0
- package/assets/skills/fimo-studio/references/publish-and-deploy.md +1 -0
- package/dist/cli/bundle.json +1 -1
- package/dist/cli/index.js +27 -27
- package/dist/runtime/paths/get-fimo-paths.d.ts +3 -1
- package/dist/runtime/paths/get-fimo-paths.js +59 -5
- package/dist/runtime/primitives/lib/primitives.d.ts +20 -1
- package/dist/runtime/primitives/lib/primitives.js +24 -1
- package/dist/runtime/routes/index.d.ts +19 -3
- package/dist/runtime/routes/index.js +27 -2
- package/dist/runtime/templates.d.ts +1 -1
- package/dist/runtime/templates.js +1 -0
- package/dist/scripts/validate-page-registry.js +14 -3
- package/package.json +10 -9
- package/release.json +2 -2
- package/templates/astro/package.json +2 -2
- package/templates/nextjs/package.json +3 -3
- package/templates/react-router/package.json +4 -4
- package/templates/sveltekit/package.json +2 -2
- package/templates/vite/package.json +4 -4
|
@@ -44,7 +44,7 @@ A Fimo project is identified by `.fimo/project.json`, written by `fimo init`. Th
|
|
|
44
44
|
|
|
45
45
|
## Critical: commands target the Branch matching the current git branch
|
|
46
46
|
|
|
47
|
-
A project can have multiple **Branches** — each is a git branch _plus_ its own DB, sandbox, preview, and assets. Project-scoped commands (`deploy`, `status`, `entries`, `diff`, …) operate on the Branch matching the **current git branch**, and print a one-line banner saying which one. New projects start on `main`. Override for a single command with the canonical `--branch <name>` flag; the removed `--env <name>` spelling is rejected. Never edit the link file to switch. The full git-shaped workflow (`branch` / `checkout` / `switch` / `pull` / `diff` / `merge` / `status` / `publish`) lives in `references/branches.md`.
|
|
47
|
+
A project can have multiple **Branches** — each is a git branch _plus_ its own DB, sandbox, preview, and assets. Project-scoped commands (`deploy`, `status`, `entries`, `diff`, …) operate on the Branch matching the **current git branch**, and print a one-line banner saying which one. Analytics reads are the exception: they default to canonical `prod`, independent of the checkout; see `references/analytics.md`. Annotation writes keep the current or explicit Branch. New projects start on `main`. Override for a single command with the canonical `--branch <name>` flag; the removed `--env <name>` spelling is rejected. Never edit the link file to switch. The full git-shaped workflow (`branch` / `checkout` / `switch` / `pull` / `diff` / `merge` / `status` / `publish`) lives in `references/branches.md`.
|
|
48
48
|
|
|
49
49
|
## Quick Start
|
|
50
50
|
|
|
@@ -1,9 +1,36 @@
|
|
|
1
1
|
# Analytics workflow
|
|
2
2
|
|
|
3
|
-
Pageview aggregates for the **published** site are stored in Fimo's analytics pipeline.
|
|
3
|
+
Pageview aggregates for the **published** site are stored in Fimo's analytics pipeline.
|
|
4
|
+
Ingestion accepts any resolved branch, so do not assume that every possible preview
|
|
5
|
+
sender is excluded; a preview visit is stored under its own branch rather than dropped.
|
|
6
|
+
|
|
7
|
+
For tracking setup, load `fimo-code`. Reading analytics does not install a tracker.
|
|
8
|
+
If counts are zero, check the selected branch, built scripts, enabled setting,
|
|
9
|
+
browser requests and stored results before diagnosing a missing implementation.
|
|
10
|
+
A successful HTTP response alone does not establish that a row was stored.
|
|
11
|
+
Use `fimo-code` analytics setup for the standalone `fimo-analytics` APIs.
|
|
12
|
+
Confirm that the selected package release contains them before generating imports;
|
|
13
|
+
older Fimo releases and existing published sites do not acquire a tracker automatically.
|
|
14
|
+
|
|
15
|
+
For Studio tracking verification, load `fimo-studio` and its analytics reference.
|
|
16
|
+
Its tracking status is independent of the chart range and device filter; a failed
|
|
17
|
+
status check is not evidence of missing tracking.
|
|
4
18
|
|
|
5
19
|
Analytics has a **retained preview for every org** — free included. The free default is a 7-day retention window, so short ranges (`today`, `yesterday`, `this_week`, `last_week`, `last_7_days`) work for everyone. **Extended date ranges and longer retention are paid** — `last_30_days`, `last_90_days`, `this_month`, `last_month`, `last_quarter`, `last_year`, and `custom` require the `canUseExtendedDateRanges` privilege, which only paid orgs have. Asking for an extended range as a free user returns a 403 with an upgrade hint.
|
|
6
20
|
|
|
21
|
+
## Select published traffic
|
|
22
|
+
|
|
23
|
+
For traffic, growth, or site-performance questions, read **`prod`**, regardless of the current Git branch, `FIMO_ENV`, or the source branch published to Production. Analytics reads (`pageviews`, `top`, `annotations list`) default to this canonical published target. On older CLI versions, select it explicitly:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
fimo --branch prod analytics pageviews --days 7 --json
|
|
27
|
+
fimo --branch prod analytics top countries --json
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Structured read results include `branch` (`data.branch` in the CLI JSON envelope). Check it before interpreting metrics. An intentional `--branch <name>` overrides the default; zero traffic on `main` or a preview branch does **not** mean the published site has no traffic. Preview visits do not appear in published traffic. If publication or access is unavailable, report that limitation; do not fall back to another branch or present the failure as zero traffic.
|
|
31
|
+
|
|
32
|
+
SDK and hosted MCP reads also default omitted `branch` to `prod` and return the selected `branch`. Annotation **writes** keep the current/explicit Branch and its existing permissions; the read default does not grant permission to write to `prod`.
|
|
33
|
+
|
|
7
34
|
## Bot traffic is excluded
|
|
8
35
|
|
|
9
36
|
Every number below is **humans only**. Bot hits — AI crawlers and headless browsers — are tagged
|
|
@@ -37,6 +64,7 @@ The headline command returns everything in one payload — KPIs, the visitors se
|
|
|
37
64
|
|
|
38
65
|
```json
|
|
39
66
|
{
|
|
67
|
+
"branch": "prod",
|
|
40
68
|
"range": { "preset": "last_30_days", "effectiveFrom": "...", "effectiveTo": "...", "groupBy": "day", ... },
|
|
41
69
|
"deviceFilter": null,
|
|
42
70
|
"visitors": 1240, "pageviews": 3870, "bounceRate": 42.5, "viewsPerVisit": 3.12, "averageVisitDurationSeconds": 95.4,
|
|
@@ -71,7 +71,7 @@ fimo entries create <TypeName> --body '<json>'
|
|
|
71
71
|
fimo entries create <TypeName> --locale es --document-id <documentId> --body '<json>'
|
|
72
72
|
fimo entries list <TypeName> [--limit N] [--cursor CURSOR] [--all-pages] [--search Q] [--where JSON] [--sort F] [--fields FIELDS] [--populate FIELDS]
|
|
73
73
|
fimo entries list <TypeName> --locale es
|
|
74
|
-
fimo entries get <TypeName> <id> [--locale es]
|
|
74
|
+
fimo entries get <TypeName> <id> [--locale es] [--populate FIELDS]
|
|
75
75
|
fimo entries update <TypeName> <id> [--locale es] --body '<json>'
|
|
76
76
|
fimo entries delete <TypeName> <id> [--locale es]
|
|
77
77
|
fimo entries query (--sql '<select>' | --file <path> | --stdin)
|
|
@@ -101,7 +101,7 @@ Use the canonical read query flags: `--search`, `--sort`, `--where`, `--limit`,
|
|
|
101
101
|
Reference filters take the target `id` string (`{"author":"750e..."}`). On a to-many field, `$eq` and `$contains` mean membership, `$in` means any listed target is present, `$ne` and `$nin` mean none are present, and `$null: true` means empty or missing. Reference fields cannot be sorted; use `--sort field` / `--sort -field` on scalar fields.
|
|
102
102
|
`--fields` is a comma-separated projection for list payloads. The API always keeps `id`, `entryId`, `documentId`, and `locale`; pass only the other fields your view needs, such as `slug,title,excerpt,coverImage`.
|
|
103
103
|
|
|
104
|
-
`--populate` is a comma-separated list of
|
|
104
|
+
`--populate` is a comma-separated list of top-level fields to embed, on `entries list`, `entries get`, and `singles get`. It accepts reference fields, media fields, and blocks fields that contain media; naming a blocks field populates every media value inside it. Nested paths such as `sections.image` are not supported, and other field types return 400. Run `fimo schemas get <TypeName> --json` to inspect field names and types. Without it, reference fields return `{ "id": "..." }` and media fields return the stored `{ "source", "id", "url", "alt" }`; with `--populate author,cover`, `author` returns the target entry for the requested locale and `cover` adds the asset's current `name`, `mime`, `width`, and `height`. Populate never selects which target fields come back. A populated target missing in the requested locale resolves to null unless you pass `localeFallbacks=true`, which falls back to the best available locale variant, marked by its `locale` field. Limits: 200 references per to-many write, 500 distinct populated documents per field per request (400 past either).
|
|
105
105
|
|
|
106
106
|
Polymorphic references declare `targets: ["Post", "Product"]` instead of `target` (never both) and their values carry both parts: `{ "contentType": "Post", "id": "..." }`. Populate returns mixed full entries, and generated hooks expose `$type` on each populated value to branch on. `--where` on polymorphic fields is not supported yet and fails with a clear error. Fixed and polymorphic references also work inside blocks with these same write shapes (`id`, `documentId`, or `slug` selectors), but nested fields cannot be populated or filtered.
|
|
107
107
|
|
|
@@ -33,6 +33,17 @@ Declare redirects, headers, rewrites, and URL shape in
|
|
|
33
33
|
|
|
34
34
|
Every field is optional. Only what you declare is emitted.
|
|
35
35
|
|
|
36
|
+
## Preview and security headers
|
|
37
|
+
|
|
38
|
+
A restrictive application-owned CSP or `X-Frame-Options` policy can block Studio
|
|
39
|
+
Preview. Do not assume automatic header rewriting; Next.js `withFimo` does not
|
|
40
|
+
provide it. Inspect the served policy and scope any manual adaptation to Preview,
|
|
41
|
+
preserving production protections and unrelated headers. `frame-ancestors`
|
|
42
|
+
permits the Studio parent, not the framed app's preview origin. Never derive
|
|
43
|
+
ancestor sources from a preview-origin variable. For `script-src`, `connect-src`,
|
|
44
|
+
`frame-src`, and `form-action`, use resolved/observed Fimo resources and endpoints
|
|
45
|
+
actually used by the iframe. Studio-parent WebSockets do not belong in app CSP.
|
|
46
|
+
|
|
36
47
|
## Matching
|
|
37
48
|
|
|
38
49
|
`source` matches the pathname only, never the query string.
|
|
@@ -90,7 +90,7 @@ Write the locale into a route's path with the reserved `:locale` segment, never
|
|
|
90
90
|
| `/:locale/blog/:slug` | `{ "type": "locale", "optional": false }` | `/en/blog/hello` and `/fr/blog/bonjour` |
|
|
91
91
|
| `/:locale/pricing` | omitted | `/pricing` for `en`, `/fr/pricing` for `fr` |
|
|
92
92
|
|
|
93
|
-
- `locale` is reserved. It is read from the URL, so it never takes `schema` or `queryField` and never becomes a CMS query. Every other param is
|
|
93
|
+
- `locale` is reserved. It is read from the URL, so it never takes `schema` or `queryField` and never becomes a CMS query. Every other param is an `entry` param that needs both, unless it declares `"type": "external"`: an external param takes no other keys, and the application owns its values.
|
|
94
94
|
- `optional: true` means omit the configured default locale from the URL. With `i18n.defaultLocale: "en"`, `/pricing` is English and `/fr/pricing` is French.
|
|
95
95
|
- `optional: false` prefixes every locale, including the default (`/en/pricing` and `/fr/pricing`). Changing `i18n.defaultLocale` chooses the fallback locale; it does not by itself change this prefix policy.
|
|
96
96
|
- A route with no `:locale` segment stays application-owned. Studio shows it once and neither adds nor interprets a locale segment.
|
|
@@ -102,7 +102,7 @@ Register the same shape in the router. React Router spells the omittable segment
|
|
|
102
102
|
route(':locale?/blog/:slug', './pages/BlogPost.tsx');
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
-
These canonical entries are also the optional metadata used by Studio Pages. See `references/pages.md` for
|
|
105
|
+
These canonical entries are also the optional metadata used by Studio Pages. See `references/pages.md` for the three `params` types and declared `sources`.
|
|
106
106
|
|
|
107
107
|
For every framework, the application owns its URL scheme, resolves the locale, and passes it into Fimo. Studio stores the locale the app reports for the current location — including when only the locale changed — and reads content in it. Route metadata is optional unless the project wants Fimo Studio route selection/navigation.
|
|
108
108
|
|
|
@@ -7,15 +7,27 @@ Pages can mirror the application's routes in Fimo Studio. It gives editors a rou
|
|
|
7
7
|
A route has three separate parts:
|
|
8
8
|
|
|
9
9
|
- `path` is the URL pattern, such as `/blog/:slug`.
|
|
10
|
-
- `params` optionally
|
|
10
|
+
- `params` optionally describes each path placeholder: an entry bound to a Collection so Studio can select a concrete route in the page header, the reserved `locale` segment, or a value the application owns.
|
|
11
11
|
- `sources` optionally names the Labels, Single, and Collection results editors manage after selecting a route.
|
|
12
12
|
|
|
13
|
-
Each param key matches a `:placeholder` in `path`. `schema` selects the Collection, `queryField` is the entry field stored in the URL, and `displayField` is the field Studio shows to editors. Use `id` or the built-in `slug` for `queryField`; a custom URL field must set both `"required": true` and `"unique": true` in its schema. Params resolve in path order, so a later param query may use an earlier selection:
|
|
13
|
+
Each param key matches a `:placeholder` in `path`. For an entry param, `schema` selects the Collection, `queryField` is the entry field stored in the URL, and `displayField` is the field Studio shows to editors. Use `id` or the built-in `slug` for `queryField`; a custom URL field must set both `"required": true` and `"unique": true` in its schema. Params resolve in path order, so a later param query may use an earlier selection:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
16
|
fimo pages set <id> --path '/shop/:category/:product' --params '{"category":{"schema":"Category","queryField":"slug","displayField":"name"},"product":{"schema":"Product","queryField":"slug","displayField":"name","query":{"where":{"category":"$params.category.id"},"sort":"name"}}}'
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
A descriptor's `type` is optional and selects one of three param kinds:
|
|
20
|
+
|
|
21
|
+
- `entry` (the default) binds the placeholder to a Collection with `schema`, `queryField`, `displayField`, and an optional `query`.
|
|
22
|
+
- `locale` is the reserved `:locale` segment with an optional `optional` boolean. See `references/locales.md`.
|
|
23
|
+
- `external` takes no other keys. The application owns the values: Fimo matches the segment from the URL and never looks it up in the CMS.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
fimo pages set <id> --path '/cartes/:slug' --params '{"slug":{"type":"external"}}'
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Declare a placeholder `external` when its values are not Fimo content — a catalogue synced from an upstream source and stored as a media asset, ids that exist only in the visitor's browser, computed archive or pagination segments, third-party ids. Never bind a placeholder to an unrelated Collection to make `fimo validate` pass. `fimo pages list` reports `dynamic:external` and `fimo pages list --expand` skips the route; `fimo/paths` and the generated sitemap emit nothing for it, so the application enumerates those URLs itself. A `$params.<name>.<field>` expression in a param query or a source may reference entry params only. A route may mix kinds: entry params keep their selectors in Studio, and an external param takes a typed value in the preview header.
|
|
30
|
+
|
|
19
31
|
`sources` is a named object under `routes.<id>.sources`. It is not an array or a route definition. Keep its keys stable and descriptive:
|
|
20
32
|
|
|
21
33
|
```json
|
|
@@ -76,6 +76,14 @@ Each reference defines one package contract. Fetch it when the task reaches that
|
|
|
76
76
|
- Framework detection, production routing, and hosting adapters → `references/frameworks/hosting.md`
|
|
77
77
|
- Major visual work → `references/design.md`
|
|
78
78
|
|
|
79
|
+
## Analytics
|
|
80
|
+
|
|
81
|
+
For pageview installation, read [references/analytics.md](references/analytics.md).
|
|
82
|
+
`FimoProviders` from `fimo-react-router` already tracks when `VITE_API_URL` and
|
|
83
|
+
`VITE_ENABLE_ANALYTICS=true` are configured. Inspect the installed version and
|
|
84
|
+
browser requests before adding a sender. Hosting or the neutral Vite plugin alone
|
|
85
|
+
does not install a tracker. Older releases do not acquire new package exports.
|
|
86
|
+
|
|
79
87
|
## Non-negotiable boundaries
|
|
80
88
|
|
|
81
89
|
- Do not hardcode editor-owned collections, page content, labels, or media in JSX.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Pageview tracking
|
|
2
|
+
|
|
3
|
+
First inspect the installed package and the built page. React Router's
|
|
4
|
+
`FimoProviders` already tracks when `VITE_API_URL` and
|
|
5
|
+
`VITE_ENABLE_ANALYTICS=true` are present. Do not mount another sender beside an
|
|
6
|
+
unmodified legacy tracker. The neutral Vite plugin and hosting alone do not
|
|
7
|
+
install tracking.
|
|
8
|
+
|
|
9
|
+
## Standalone setup
|
|
10
|
+
|
|
11
|
+
Install a released version of `fimo-analytics` that exposes the adapter you need.
|
|
12
|
+
Keep any version/channel selector the user already chose. An older `fimo`
|
|
13
|
+
release does not imply these standalone APIs exist, and existing published
|
|
14
|
+
sites need a code update to gain missing instrumentation.
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
pnpm add fimo-analytics
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Obtain the tenant API base URL from the project's configured Fimo connection,
|
|
21
|
+
and append `/e/p`. Pass that complete URL as `endpoint`. Never infer it from the
|
|
22
|
+
site's public URL, guess a project hostname, or invent a discovery command. If
|
|
23
|
+
the connection does not supply a tenant endpoint, obtain it before enabling
|
|
24
|
+
tracking. A configured origin-relative proxy is also accepted.
|
|
25
|
+
|
|
26
|
+
| Framework | Import | Placement |
|
|
27
|
+
| -------------- | --------------------------------------------------- | -------------------------------------------- |
|
|
28
|
+
| React | `{ Analytics }` from `fimo-analytics/react` | Application root |
|
|
29
|
+
| React Router | `{ Analytics }` from `fimo-analytics/react-router` | Inside root router |
|
|
30
|
+
| Next App/Pages | `{ Analytics }` from `fimo-analytics/next` | Root layout or `_app` |
|
|
31
|
+
| Astro | default `Analytics` from `fimo-analytics/astro` | Shared layout, no `client:*` |
|
|
32
|
+
| Svelte | default `Analytics` from `fimo-analytics/svelte` | Root component |
|
|
33
|
+
| SvelteKit | default `Analytics` from `fimo-analytics/sveltekit` | Root `+layout.svelte` |
|
|
34
|
+
| Vue | `{ Analytics }` from `fimo-analytics/vue` | Root component, history routing |
|
|
35
|
+
| Nuxt | `modules: ['fimo-analytics/nuxt']` | `analytics: { endpoint, enabled }` in config |
|
|
36
|
+
|
|
37
|
+
Components accept `endpoint` and `enabled`. React example:
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import { Analytics } from 'fimo-analytics/next';
|
|
41
|
+
<Analytics endpoint={endpoint} enabled={isProduction} />;
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
For Nuxt, also install the optional build peer with `pnpm add -D @nuxt/kit`.
|
|
45
|
+
Next owns its client and Suspense boundaries. SvelteKit uses committed
|
|
46
|
+
navigation; Nuxt covers reused pages and query changes. Generic React, Vue and
|
|
47
|
+
Svelte observe history. For a router that changes the URL before committing,
|
|
48
|
+
use the manual core. For Vue Router, initialize in `onMounted` after initial
|
|
49
|
+
router readiness, send once, subscribe to `router.afterEach`, send only when
|
|
50
|
+
`failure` is falsy, and remove the subscription and destroy on unmount.
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { init } from 'fimo-analytics';
|
|
54
|
+
const analytics = init({ endpoint, enabled: isProduction, routing: 'manual' });
|
|
55
|
+
// In the router's successful-navigation callback:
|
|
56
|
+
analytics.pageview();
|
|
57
|
+
// During cleanup:
|
|
58
|
+
analytics.destroy();
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Vanilla apps can omit `routing` to track the initial page and browser history.
|
|
62
|
+
Hash routers can pass `{ path: resolvedVirtualPath, pageName }` to `pageview`;
|
|
63
|
+
the React Router adapter already reads its router's virtual location.
|
|
64
|
+
|
|
65
|
+
For plain HTML, copy the installed `dist/browser.js` into static assets:
|
|
66
|
+
|
|
67
|
+
```html
|
|
68
|
+
<script defer src="/fimo-analytics.js" data-endpoint="https://YOUR-TENANT-API-HOST/e/p" data-enabled="true"></script>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Use a classic script, not `type="module"`. Set `data-enabled="false"` in preview
|
|
72
|
+
builds. No framework peer is required for core or HTML. Framework peers are
|
|
73
|
+
optional and only the chosen adapter's framework is needed.
|
|
74
|
+
|
|
75
|
+
## Choose the enabled guard
|
|
76
|
+
|
|
77
|
+
Tracking defaults to enabled, so always pass `enabled`. Never use `NODE_ENV`:
|
|
78
|
+
a Fimo hosted preview is a production build, so that guard leaves previews
|
|
79
|
+
reporting. Read the build variable Fimo already sets:
|
|
80
|
+
|
|
81
|
+
| Framework | Guard |
|
|
82
|
+
| ------------------------- | -------------------------------------------------- |
|
|
83
|
+
| React Router and any Vite | `import.meta.env.VITE_ENABLE_ANALYTICS === 'true'` |
|
|
84
|
+
| Next.js | `process.env.NEXT_PUBLIC_FIMO_ENV === 'prod'` |
|
|
85
|
+
| Build-time server env | `process.env.FIMO_ENV === 'prod'` |
|
|
86
|
+
|
|
87
|
+
Astro, SvelteKit, Svelte and Vue have no browser-visible environment name from
|
|
88
|
+
Fimo. Read `FIMO_ENV` at build time and pass the boolean into the bundle through
|
|
89
|
+
the framework's own public-variable mechanism. Do not invent a `PUBLIC_FIMO_ENV`
|
|
90
|
+
and do not expose the whole environment name when a boolean is enough.
|
|
91
|
+
|
|
92
|
+
## Verify the installed integration
|
|
93
|
+
|
|
94
|
+
Standalone tracking defaults to enabled. Supply an explicit production guard;
|
|
95
|
+
`bl_preview_token` also suppresses sends. SSR and disabled calls are inert.
|
|
96
|
+
Do not add browser secrets, project IDs or branch claims to payloads.
|
|
97
|
+
|
|
98
|
+
Verify one initial POST, navigation, query-only changes, back/forward and a
|
|
99
|
+
route revisit. Check duplicate mounts and cleanup. Existing visitor/session
|
|
100
|
+
storage keys are retained; blocked storage uses per-document IDs. Delivery is
|
|
101
|
+
best effort and has no retries. A 202 response alone does not prove persistence;
|
|
102
|
+
check recorded analytics separately. Framework peer ranges are not proof that
|
|
103
|
+
every older framework release was tested. Use the installed package's version
|
|
104
|
+
qualification and preserve existing supported integrations when upgrading.
|
|
@@ -170,6 +170,8 @@ The new-project shell pairs unprefixed default-locale pages with a parallel `[lo
|
|
|
170
170
|
}
|
|
171
171
|
```
|
|
172
172
|
|
|
173
|
+
A dynamic segment whose values are not Fimo content takes `{ "type": "external" }` instead of a Collection binding; Fimo matches it from the URL, and the page's own `getStaticPaths` (or on-demand rendering) supplies those values.
|
|
174
|
+
|
|
173
175
|
## Client islands
|
|
174
176
|
|
|
175
177
|
Generated content reads remain server-only. Preserve existing islands and do not add React or a client SDK to work around this boundary.
|
|
@@ -46,11 +46,8 @@ own tenant URL.
|
|
|
46
46
|
|
|
47
47
|
## Hosted preview config
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
the application does not set Next's `devIndicators`, the wrapper hides it in
|
|
52
|
-
hosted Preview while local `next dev` keeps Next's default. Any explicit
|
|
53
|
-
`devIndicators` setting is preserved:
|
|
49
|
+
Keep the generated `FimoProvider` and `withFimo` integration to render Fimo
|
|
50
|
+
Preview in Fimo Studio and enable Edit Mode. Wrap the existing Next config once:
|
|
54
51
|
|
|
55
52
|
```ts
|
|
56
53
|
import type { NextConfig } from 'next';
|
|
@@ -60,10 +57,16 @@ const nextConfig: NextConfig = {};
|
|
|
60
57
|
export default withFimo(nextConfig);
|
|
61
58
|
```
|
|
62
59
|
|
|
63
|
-
Preserve
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
Preserve existing config fields and config-function logic. `withFimo` currently
|
|
61
|
+
does not rewrite response headers or adapt application-owned CSP. A restrictive
|
|
62
|
+
policy may need a manual Preview adaptation; inspect actual framing and blocked
|
|
63
|
+
requests, preserve production protections, and verify the result in a browser.
|
|
64
|
+
`frame-ancestors` permits the Studio parent, not the app's preview origin or a
|
|
65
|
+
value derived from a preview-origin variable. `script-src`, `connect-src`,
|
|
66
|
+
`frame-src`, and `form-action` concern resources/endpoints used by the iframe;
|
|
67
|
+
use the resolved connection and observed requests. Never add a Studio-parent
|
|
68
|
+
WebSocket to application CSP. Scope exceptions to Preview and keep unrelated
|
|
69
|
+
security headers unchanged.
|
|
67
70
|
|
|
68
71
|
## Client dependency
|
|
69
72
|
|
|
@@ -53,7 +53,7 @@ Use `<StaticImage>` only when the image is deliberately not editor-managed.
|
|
|
53
53
|
`FimoString`, `FimoBoolean`, and the other tracked values are objects, not primitives: a plain string or boolean cannot carry the source field, locale, and edit-target metadata Fimo editing needs. That gives one two-sided rule:
|
|
54
54
|
|
|
55
55
|
- **MUST** pass the wrapper directly to Fimo rendering primitives (`Text`, `Boolean`, …). Unwrapping first removes the edit target.
|
|
56
|
-
- **MUST** normalize the wrapper before any JavaScript comparison, condition, attribute, or third-party API: `String(value)` for strings, `value.value`
|
|
56
|
+
- **MUST** normalize the wrapper before any JavaScript comparison, condition, attribute, or third-party API: `String(value)` for strings, `value.value` for booleans.
|
|
57
57
|
|
|
58
58
|
```ts
|
|
59
59
|
fimoValue === 'build'; // false — an object never strict-equals a primitive
|
|
@@ -63,6 +63,11 @@ if (fimoFlag) { … } // always runs — an object is truthy even whe
|
|
|
63
63
|
if (fimoFlag.value) { … } // correct
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
Nothing catches `if (fimoFlag)` for you: an object is unconditionally truthy in
|
|
67
|
+
JavaScript, and TypeScript reports no error. Read `.value` every time. A boolean
|
|
68
|
+
field without `required: true` generates `flag?: FimoBoolean`, so read
|
|
69
|
+
`flag?.value`.
|
|
70
|
+
|
|
66
71
|
Keep editable visible text in `<Text>`; normalized primitives are for logic and APIs only, never a substitute for rendering through the primitive.
|
|
67
72
|
|
|
68
73
|
Numeric fields stay plain JavaScript numbers, so they do not carry Studio source metadata. SvelteKit's `Number` component is an optional display/formatting helper; it is not source-editable. Other framework surfaces should render numeric fields normally until a shared tracked-number contract exists.
|
|
@@ -174,18 +174,18 @@ report the exact failed command and setup requirement.
|
|
|
174
174
|
reason. Better modeling never redesigns the site: preserve the source's
|
|
175
175
|
content shape and behavior, and record the source-to-Fimo mapping
|
|
176
176
|
(`references/content.md`).
|
|
177
|
-
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
command cannot carry it (`references/media.md`).
|
|
177
|
+
- Before writing media or wiring `<Image>`, load
|
|
178
|
+
`fimo skills get fimo-migration --ref media` for the stored value, explicit
|
|
179
|
+
`populate`, and responsive-image checks (`references/media.md`).
|
|
181
180
|
- Every write is create-or-update, so any step can be rerun without duplicating
|
|
182
181
|
a schema, entry, asset, single, or label.
|
|
183
182
|
- Every decision cites the source file (and line when it matters) that proves
|
|
184
183
|
it. What no worker could prove stays unresolved with an owner action.
|
|
185
184
|
- Keep coordination evidence in the plain-text files
|
|
186
185
|
`.fimo/migration/migration-plan.md` and
|
|
187
|
-
`.fimo/migration/migration-report.md`. Use JSON
|
|
188
|
-
schema/content payloads
|
|
186
|
+
`.fimo/migration/migration-report.md`. Use JSON for actual Fimo
|
|
187
|
+
schema/content import payloads and the rendered guardrail inventory and
|
|
188
|
+
capture response metadata required by `references/qa.md`. Do not
|
|
189
189
|
create a target description, worker plan, decision registry, or JSON receipt
|
|
190
190
|
just to describe the filesystem or agent work.
|
|
191
191
|
- Do not report completion until the QA gate passes or every failed check is
|
|
@@ -378,6 +378,9 @@ writes go through the normal commands against the linked target:
|
|
|
378
378
|
- `references/workers/content-execution.md` - data import and code-wiring
|
|
379
379
|
contracts.
|
|
380
380
|
- `references/workers/validator.md` - independent fan-in validation.
|
|
381
|
+
- `scripts/check-rendered-guardrails.mjs` evaluates the cited guardrail
|
|
382
|
+
inventory against rendered HTML or a local server and fails closed on empty,
|
|
383
|
+
missing, redirected, or vacuous evidence.
|
|
381
384
|
- `scripts/apply-decision.mjs` and `scripts/write-migration-report.mjs` replay
|
|
382
385
|
an older JSON-ledger migration. A new migration writes the plain-text plan
|
|
383
386
|
and report instead; do not invoke them unless the user asks for that replay.
|
|
@@ -99,8 +99,7 @@ Follow the target project's `fimo-code` Next.js reference and render its
|
|
|
99
99
|
`FimoProvider` once at the application root. The provider uses an explicit
|
|
100
100
|
host connection when one exists; otherwise it resolves the linked project and
|
|
101
101
|
active git branch on the server and passes only the public connection to the
|
|
102
|
-
browser.
|
|
103
|
-
connection.
|
|
102
|
+
browser.
|
|
104
103
|
|
|
105
104
|
Do not create or edit `.env` / `.env.local` for a linked project's Fimo
|
|
106
105
|
connection. Run the project's normal `next dev`, `next build`, and `next start`
|
|
@@ -108,31 +107,29 @@ commands, then exercise at least one server read and one client-side data read.
|
|
|
108
107
|
|
|
109
108
|
## Preview embedding and response headers
|
|
110
109
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
headers carry no unconditional framing block, then mark visual proof
|
|
135
|
-
unavailable in the QA report.
|
|
110
|
+
Keep the generated `FimoProvider` and `withFimo` integration. It supports
|
|
111
|
+
rendering Fimo Preview in Fimo Studio and enabling Edit Mode.
|
|
112
|
+
|
|
113
|
+
The application owns response and security headers; `withFimo` currently does
|
|
114
|
+
not rewrite them or adapt CSP automatically. A restrictive policy may still
|
|
115
|
+
need a manual Preview adaptation. Inspect framing behavior and response headers
|
|
116
|
+
first. Scope changes to Preview, preserve production protections and unrelated
|
|
117
|
+
security headers, and record them in the runtime report's Hosting section.
|
|
118
|
+
When the existing policy sends `X-Frame-Options` or an unconditional
|
|
119
|
+
`frame-ancestors` block, condition or relax that framing control only for the
|
|
120
|
+
verified Preview embedding context; retain it for non-Preview and production
|
|
121
|
+
responses.
|
|
122
|
+
|
|
123
|
+
- `frame-ancestors` controls which Fimo Studio parent may embed the app. The
|
|
124
|
+
incident's manual fix used the current Studio sources `https://fimo.ai` and
|
|
125
|
+
`https://*.fimo.ai`. Verify the Studio parent for the target environment;
|
|
126
|
+
these sources are not a universal resource allowlist. Never derive them from
|
|
127
|
+
a preview-origin variable. The sandbox or hosted preview origin identifies
|
|
128
|
+
the app being framed, not its ancestor.
|
|
129
|
+
- `script-src` controls scripts, `connect-src` API and WebSocket connections,
|
|
130
|
+
`frame-src` frames embedded by the app, and `form-action` form submission
|
|
131
|
+
destinations. Base Fimo sources on the resolved connection and observed
|
|
132
|
+
requests made by the preview iframe, only for resources/endpoints it uses.
|
|
136
133
|
|
|
137
134
|
## Locales
|
|
138
135
|
|