fimo 0.8.0 → 0.9.0-experimental.10
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/content-translator/scripts/write-locale-files.ts +66 -0
- package/assets/agents-starter/claude/settings.json +19 -0
- package/assets/content-templates/hooks-template.eta +4 -2
- package/assets/content-templates/types-template.eta +67 -1
- package/assets/skills/fimo/SKILL.md +1 -1
- package/assets/skills/fimo/references/content.md +86 -15
- package/assets/skills/fimo/references/translations.md +75 -0
- package/assets/skills/fimo-cli/SKILL.md +6 -2
- package/assets/skills/fimo-cli/references/content.md +61 -2
- package/assets/skills/fimo-cli/references/integrations/firecrawl.md +20 -4
- package/assets/skills/fimo-cli/references/integrations.md +5 -1
- package/assets/skills/fimo-cli/references/webhooks.md +162 -0
- package/assets/skills/fimo-migration/SKILL.md +24 -2
- package/assets/skills/fimo-migration/references/content.md +24 -0
- package/assets/skills/fimo-migration/references/manifest.md +46 -0
- package/assets/skills/fimo-migration/references/pages.md +234 -0
- package/assets/skills/fimo-migration/references/qa.md +24 -2
- package/assets/skills/fimo-migration/references/workflow.md +12 -1
- package/assets/skills/fimo-migration/references/wrap.md +662 -0
- package/assets/skills/fimo-studio/SKILL.md +5 -3
- package/assets/skills/fimo-studio/references/cms.md +9 -1
- package/assets/skills/fimo-studio/references/visual-editing.md +5 -3
- package/assets/skills/fimo-studio/references/webhooks.md +42 -0
- package/dist/build/vite/plugins/translations.d.ts +2 -8
- package/dist/build/vite/plugins/translations.js +31 -131
- package/dist/cli/bundle.json +1 -1
- package/dist/cli/index.js +1337 -189
- package/dist/runtime/app/FimoProviders.d.ts +1 -11
- package/dist/runtime/app/FimoProviders.js +31 -30
- package/dist/runtime/astro/index.d.ts +2 -0
- package/dist/runtime/astro/index.js +3 -0
- package/dist/runtime/astro/server.d.ts +3 -0
- package/dist/runtime/astro/server.js +6 -0
- package/dist/runtime/content/client/internal.js +1 -0
- package/dist/runtime/content/client/types.d.ts +16 -0
- package/dist/runtime/core/BuiltWithBadge.d.ts +2 -0
- package/dist/runtime/core/BuiltWithBadge.js +68 -0
- package/dist/runtime/i18n/FimoLocaleContext.js +1 -0
- package/dist/runtime/next/FimoNextProviders.d.ts +24 -0
- package/dist/runtime/next/FimoNextProviders.js +20 -0
- package/dist/runtime/next/FimoNextScripts.d.ts +10 -0
- package/dist/runtime/next/FimoNextScripts.js +19 -0
- package/dist/runtime/next/index.d.ts +14 -0
- package/dist/runtime/next/index.js +14 -0
- package/dist/runtime/next/server.d.ts +2 -0
- package/dist/runtime/next/server.js +4 -0
- package/dist/runtime/nuxt/composables.d.ts +9 -0
- package/dist/runtime/nuxt/composables.js +57 -0
- package/dist/runtime/nuxt/index.d.ts +3 -0
- package/dist/runtime/nuxt/index.js +6 -0
- package/dist/runtime/nuxt/server.d.ts +3 -0
- package/dist/runtime/nuxt/server.js +6 -0
- package/dist/runtime/primitives/components/RichText.d.ts +5 -1
- package/dist/runtime/primitives/components/RichText.js +2 -2
- package/dist/runtime/primitives/labels-hook.d.ts +33 -0
- package/dist/runtime/primitives/labels-hook.js +41 -0
- package/dist/runtime/primitives/labels-store.d.ts +12 -0
- package/dist/runtime/primitives/labels-store.js +60 -0
- package/dist/runtime/primitives/lib/useFimoLiveValue.d.ts +5 -3
- package/dist/runtime/primitives/lib/useFimoLiveValue.js +11 -4
- package/dist/runtime/primitives/translations.d.ts +1 -27
- package/dist/runtime/primitives/translations.js +7 -85
- package/dist/runtime/react/FimoSpaProviders.d.ts +36 -0
- package/dist/runtime/react/FimoSpaProviders.js +122 -0
- package/dist/runtime/react/index.d.ts +35 -0
- package/dist/runtime/react/index.js +40 -0
- package/dist/runtime/react/spa-content-cache.d.ts +38 -0
- package/dist/runtime/react/spa-content-cache.js +64 -0
- package/dist/runtime/remix/FimoRemixProviders.d.ts +16 -0
- package/dist/runtime/remix/FimoRemixProviders.js +12 -0
- package/dist/runtime/remix/FimoRemixScripts.d.ts +10 -0
- package/dist/runtime/remix/FimoRemixScripts.js +19 -0
- package/dist/runtime/remix/index.d.ts +12 -0
- package/dist/runtime/remix/index.js +11 -0
- package/dist/runtime/remix/server.d.ts +2 -0
- package/dist/runtime/remix/server.js +2 -0
- package/dist/runtime/seo/neutral.d.ts +22 -0
- package/dist/runtime/seo/neutral.js +17 -0
- package/dist/runtime/shared/display-routes.d.ts +14 -0
- package/dist/runtime/shared/display-routes.js +25 -0
- package/dist/runtime/shared/fimo-config.server.d.ts +0 -1
- package/dist/runtime/shared/fimo-config.server.js +1 -13
- package/dist/runtime/shared/fimo-config.types.d.ts +2 -0
- package/dist/runtime/shared/i18n-messages.d.ts +29 -0
- package/dist/runtime/shared/i18n-messages.js +79 -0
- package/dist/runtime/shared/labels-fetch.pure.d.ts +17 -0
- package/dist/runtime/shared/labels-fetch.pure.js +71 -0
- package/dist/runtime/shared/labels-fetch.server.d.ts +7 -0
- package/dist/runtime/shared/labels-fetch.server.js +97 -0
- package/dist/runtime/shared/labels-t.pure.d.ts +2 -0
- package/dist/runtime/shared/labels-t.pure.js +10 -0
- package/dist/runtime/strapi/client.d.ts +30 -0
- package/dist/runtime/strapi/client.js +132 -0
- package/dist/runtime/strapi/index.d.ts +5 -0
- package/dist/runtime/strapi/index.js +6 -0
- package/dist/runtime/strapi/reshape.d.ts +50 -0
- package/dist/runtime/strapi/reshape.js +121 -0
- package/dist/runtime/svelte/index.d.ts +3 -0
- package/dist/runtime/svelte/index.js +7 -0
- package/dist/runtime/svelte/server.d.ts +3 -0
- package/dist/runtime/svelte/server.js +6 -0
- package/dist/runtime/vue/index.d.ts +3 -0
- package/dist/runtime/vue/index.js +5 -0
- package/dist/runtime/vue/server.d.ts +3 -0
- package/dist/runtime/vue/server.js +6 -0
- package/dist/runtime/wrapped/FimoFileLink.d.ts +17 -0
- package/dist/runtime/wrapped/FimoFileLink.js +19 -0
- package/dist/runtime/wrapped/FimoMediaImage.d.ts +14 -0
- package/dist/runtime/wrapped/FimoMediaImage.js +20 -0
- package/dist/runtime/wrapped/FimoMediaVideo.d.ts +14 -0
- package/dist/runtime/wrapped/FimoMediaVideo.js +20 -0
- package/dist/runtime/wrapped/FimoRichTextBlock.d.ts +26 -0
- package/dist/runtime/wrapped/FimoRichTextBlock.js +22 -0
- package/dist/runtime/wrapped/FimoText.d.ts +22 -0
- package/dist/runtime/wrapped/FimoText.js +20 -0
- package/dist/runtime/wrapped/WrappedContentContext.d.ts +28 -0
- package/dist/runtime/wrapped/WrappedContentContext.js +30 -0
- package/dist/runtime/wrapped/WrappedProviders.d.ts +33 -0
- package/dist/runtime/wrapped/WrappedProviders.js +101 -0
- package/dist/runtime/wrapped/content-fetch.pure.d.ts +20 -0
- package/dist/runtime/wrapped/content-fetch.pure.js +106 -0
- package/dist/runtime/wrapped/dom.d.ts +4 -0
- package/dist/runtime/wrapped/dom.js +23 -0
- package/dist/runtime/wrapped/server.d.ts +80 -0
- package/dist/runtime/wrapped/server.js +207 -0
- package/dist/scripts/apply-wrap-templates.d.ts +61 -0
- package/dist/scripts/apply-wrap-templates.js +137 -0
- package/dist/scripts/apply-wrap.d.ts +73 -0
- package/dist/scripts/apply-wrap.js +340 -0
- package/dist/scripts/cms/discover.d.ts +2 -0
- package/dist/scripts/cms/discover.js +17 -0
- package/dist/scripts/cms/example-content.d.ts +33 -0
- package/dist/scripts/cms/example-content.js +165 -0
- package/dist/scripts/cms/strapi/detect.d.ts +2 -0
- package/dist/scripts/cms/strapi/detect.js +186 -0
- package/dist/scripts/cms/strapi/index.d.ts +3 -0
- package/dist/scripts/cms/strapi/index.js +25 -0
- package/dist/scripts/cms/strapi/list-source.d.ts +17 -0
- package/dist/scripts/cms/strapi/list-source.js +90 -0
- package/dist/scripts/cms/strapi/schema-map.d.ts +9 -0
- package/dist/scripts/cms/strapi/schema-map.js +289 -0
- package/dist/scripts/cms/strapi/shapes.d.ts +25 -0
- package/dist/scripts/cms/strapi/shapes.js +48 -0
- package/dist/scripts/cms/strapi/touchpoints.d.ts +31 -0
- package/dist/scripts/cms/strapi/touchpoints.js +145 -0
- package/dist/scripts/cms/strapi/wire-client.d.ts +15 -0
- package/dist/scripts/cms/strapi/wire-client.js +107 -0
- package/dist/scripts/cms/strapi/wiring.d.ts +17 -0
- package/dist/scripts/cms/strapi/wiring.js +46 -0
- package/dist/scripts/cms/types.d.ts +145 -0
- package/dist/scripts/cms/types.js +11 -0
- package/dist/scripts/detect-framework.d.ts +39 -0
- package/dist/scripts/detect-framework.js +139 -0
- package/dist/scripts/draft-rows.d.ts +19 -0
- package/dist/scripts/draft-rows.js +178 -0
- package/dist/scripts/draft-schemas.d.ts +27 -0
- package/dist/scripts/draft-schemas.js +247 -0
- package/dist/scripts/extract-translations.js +16 -11
- package/dist/scripts/frameworks/astro/routes.d.ts +3 -0
- package/dist/scripts/frameworks/astro/routes.js +44 -0
- package/dist/scripts/frameworks/astro/template-style.d.ts +7 -0
- package/dist/scripts/frameworks/astro/template-style.js +19 -0
- package/dist/scripts/frameworks/discover.d.ts +83 -0
- package/dist/scripts/frameworks/discover.js +288 -0
- package/dist/scripts/frameworks/discovered-route.d.ts +9 -0
- package/dist/scripts/frameworks/discovered-route.js +17 -0
- package/dist/scripts/frameworks/next/rewire.d.ts +43 -0
- package/dist/scripts/frameworks/next/rewire.js +282 -0
- package/dist/scripts/frameworks/next/routes.d.ts +30 -0
- package/dist/scripts/frameworks/next/routes.js +176 -0
- package/dist/scripts/frameworks/next/wiring.d.ts +33 -0
- package/dist/scripts/frameworks/next/wiring.js +186 -0
- package/dist/scripts/frameworks/nuxt/routes.d.ts +3 -0
- package/dist/scripts/frameworks/nuxt/routes.js +38 -0
- package/dist/scripts/frameworks/nuxt/template-style.d.ts +9 -0
- package/dist/scripts/frameworks/nuxt/template-style.js +27 -0
- package/dist/scripts/frameworks/remix/routes.d.ts +3 -0
- package/dist/scripts/frameworks/remix/routes.js +36 -0
- package/dist/scripts/frameworks/support.d.ts +75 -0
- package/dist/scripts/frameworks/support.js +165 -0
- package/dist/scripts/frameworks/sveltekit/routes.d.ts +3 -0
- package/dist/scripts/frameworks/sveltekit/routes.js +35 -0
- package/dist/scripts/frameworks/sveltekit/template-style.d.ts +9 -0
- package/dist/scripts/frameworks/sveltekit/template-style.js +54 -0
- package/dist/scripts/frameworks/vite/routes.d.ts +20 -0
- package/dist/scripts/frameworks/vite/routes.js +143 -0
- package/dist/scripts/frameworks/vite/wiring.d.ts +22 -0
- package/dist/scripts/frameworks/vite/wiring.js +144 -0
- package/dist/scripts/i18n-namespace.d.ts +27 -0
- package/dist/scripts/i18n-namespace.js +155 -0
- package/dist/scripts/lib/humanize.d.ts +14 -0
- package/dist/scripts/lib/humanize.js +54 -0
- package/dist/scripts/lib/validation-report.d.ts +1 -3
- package/dist/scripts/lib/validation-report.js +3 -9
- package/dist/scripts/render-parity/capture.d.ts +64 -0
- package/dist/scripts/render-parity/capture.js +436 -0
- package/dist/scripts/render-parity/compare.d.ts +59 -0
- package/dist/scripts/render-parity/compare.js +0 -0
- package/dist/scripts/render-parity/normalize-html.d.ts +13 -0
- package/dist/scripts/render-parity/normalize-html.js +223 -0
- package/dist/scripts/render-parity/types.d.ts +41 -0
- package/dist/scripts/render-parity/types.js +1 -0
- package/dist/scripts/routes/bindings.d.ts +93 -0
- package/dist/scripts/routes/bindings.js +117 -0
- package/dist/scripts/routes/label-prefixes.d.ts +49 -0
- package/dist/scripts/routes/label-prefixes.js +136 -0
- package/dist/scripts/routes/module-resolve.d.ts +20 -0
- package/dist/scripts/routes/module-resolve.js +78 -0
- package/dist/scripts/routes/page-structure.d.ts +72 -0
- package/dist/scripts/routes/page-structure.js +234 -0
- package/dist/scripts/scan-wrappable.d.ts +200 -0
- package/dist/scripts/scan-wrappable.js +1355 -0
- package/dist/scripts/validate-route-metadata.js +11 -0
- package/dist/scripts/validate-schemas.js +42 -1
- package/package.json +88 -4
- package/release.json +2 -2
- package/templates/react-router/package.json +1 -1
- package/templates/react-router/translations/en.json +1 -0
|
@@ -67,7 +67,7 @@ Use `connect` for provider accounts, workspaces, OAuth installs, and API-key acc
|
|
|
67
67
|
fimo integrations run firecrawl scrape --url https://example.com
|
|
68
68
|
fimo integrations run firecrawl scrape --url https://example.com --formats markdown,summary,links
|
|
69
69
|
fimo integrations run firecrawl scrape --url https://example.com --connection client-b
|
|
70
|
-
fimo integrations run firecrawl search --query "Example Domain" --max-results 3
|
|
70
|
+
fimo integrations run firecrawl search --query "Example Domain" --max-results 3 --include-domains example.com
|
|
71
71
|
fimo integrations run firecrawl map --url https://example.com --limit 20
|
|
72
72
|
fimo integrations run firecrawl crawl --url https://example.com --limit 3 --formats markdown
|
|
73
73
|
fimo integrations run firecrawl monitor.create --name pricing --url https://example.com/pricing --schedule hourly
|
|
@@ -76,6 +76,10 @@ fimo integrations run firecrawl monitor.list
|
|
|
76
76
|
|
|
77
77
|
Firecrawl execution supports `search`, `scrape`, `map`, `crawl`, and `monitor.*` lifecycle tools. The default scrape/crawl output format is `markdown`; supported formats are `markdown`, `summary`, `links`, `images`, `html`, and `raw-html`.
|
|
78
78
|
|
|
79
|
+
Firecrawl search returns query-relevant excerpts by default. Use them for direct, sourced answers and scrape only when
|
|
80
|
+
full context or exact wording is needed. Search can be narrowed with source, category, domain, freshness, location,
|
|
81
|
+
and country options; see the Firecrawl reference for the full command shape.
|
|
82
|
+
|
|
79
83
|
Use `--connection <alias>` only for one run when a named connection already exists. It does not change the project default
|
|
80
84
|
integration setup.
|
|
81
85
|
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Outbound webhooks
|
|
2
|
+
|
|
3
|
+
> **Run via `npx fimo@latest <command>`** so the event catalog and delivery commands match the platform.
|
|
4
|
+
|
|
5
|
+
> **Beta:** Test each destination and inspect its delivery history before depending on it in production.
|
|
6
|
+
|
|
7
|
+
Use `fimo webhooks` to send project events to external HTTPS endpoints. The CLI and Studio edit the same project-wide configurations and delivery history. The CLI has no provider presets: inspect the destination's API documentation, then pass its URL, headers, and JSON body explicitly.
|
|
8
|
+
|
|
9
|
+
Webhook commands require Full Access to the project. Do not attempt them when the current CLI identity has Edit, Comment, View, or agent access; the API enforces the same permission boundary as Studio.
|
|
10
|
+
|
|
11
|
+
## Start from the live event catalog
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
fimo webhooks events
|
|
15
|
+
fimo webhooks events form.submitted
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Run this before writing a custom payload. The list shows supported event types, descriptions, and valid
|
|
19
|
+
`event.data...` template variables. Pass one event name to get its example payload too. The initial families are:
|
|
20
|
+
|
|
21
|
+
- Forms: `form.submitted`
|
|
22
|
+
- Publish: `publish.started`, `publish.succeeded`, `publish.failed`, `publish.unpublished`
|
|
23
|
+
- Agents: run started/completed/failed/cancelled and review requested/resolved
|
|
24
|
+
- Analytics: `analytics.report_ready`
|
|
25
|
+
- Media: uploaded/updated/deleted/generated/processing_failed
|
|
26
|
+
- Entries: `entry.changed`
|
|
27
|
+
|
|
28
|
+
Do not guess variable paths. The common envelope is:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"id": "event-id",
|
|
33
|
+
"type": "form.submitted",
|
|
34
|
+
"version": 1,
|
|
35
|
+
"test": false,
|
|
36
|
+
"createdAt": "2026-07-17T10:00:00.000Z",
|
|
37
|
+
"project": { "id": "project-id" },
|
|
38
|
+
"env": { "name": "main" },
|
|
39
|
+
"data": {}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Omit `--body` to send this full envelope. Prefer that default when the receiver can accept Fimo's shape.
|
|
44
|
+
|
|
45
|
+
## Create a provider-specific request
|
|
46
|
+
|
|
47
|
+
Store credentials as project secrets, never literal header flags:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
printf '%s' "$RESEND_API_KEY" | fimo secrets set RESEND_API_KEY --stdin
|
|
51
|
+
|
|
52
|
+
fimo webhooks create waitlist-resend \
|
|
53
|
+
--event form.submitted \
|
|
54
|
+
--form waitlist \
|
|
55
|
+
--url https://api.resend.com/contacts \
|
|
56
|
+
--header "Authorization=bearer:RESEND_API_KEY" \
|
|
57
|
+
--body '{"email":"{{ event.data.submission.data.email }}"}'
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Header sources:
|
|
61
|
+
|
|
62
|
+
- `Name=secret:KEY`: secret is the complete value
|
|
63
|
+
- `Name=bearer:KEY`: `Bearer ` plus the secret
|
|
64
|
+
- `Name=token:KEY`: `token ` plus the secret
|
|
65
|
+
- `Name=literal:value`: non-secret fixed value
|
|
66
|
+
|
|
67
|
+
Secret-backed values resolve when a delivery runs, so rotating a project secret updates later deliveries without editing the webhook. Fimo masks destination URLs, credentials, payload secrets, and response excerpts in CLI and Studio output.
|
|
68
|
+
|
|
69
|
+
## Shape custom JSON safely
|
|
70
|
+
|
|
71
|
+
`--body` accepts JSON with exact `{{ event... }}` substitutions in values:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
fimo webhooks create publish-slack \
|
|
75
|
+
--event publish.succeeded \
|
|
76
|
+
--url https://hooks.slack.com/services/... \
|
|
77
|
+
--body '{"text":"Published {{ event.data.publication.url }}"}'
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Use `--body @path/to/payload.json` for a file or `--body -` for stdin. Paths resolve from `-C` or the current
|
|
81
|
+
project directory.
|
|
82
|
+
|
|
83
|
+
When a variable occupies the entire JSON value, objects and arrays retain their JSON type:
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"submission": "{{ event.data.submission }}",
|
|
88
|
+
"email": "{{ event.data.submission.data.email }}"
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Do not add executable transform scripts or workers to a project just to reshape a payload. Use the JSON template for deterministic mappings; use an external workflow endpoint only when the integration genuinely needs branching or code.
|
|
93
|
+
|
|
94
|
+
Available filters are event-specific:
|
|
95
|
+
|
|
96
|
+
- `--environments <main|all>` for the event origin; the default is `main`
|
|
97
|
+
- `--form <id>` for `form.submitted`
|
|
98
|
+
- `--agent <name>` for agent events
|
|
99
|
+
- `--media-type <image|video|audio|document|other>` for media events
|
|
100
|
+
- `--action <created|updated|deleted>`, `--content-type <name>`, and `--locale <locale>` for `entry.changed`
|
|
101
|
+
- `--debounce-changes <immediate|5s|30s|1m>` for direct `entry.changed` delivery grouping
|
|
102
|
+
|
|
103
|
+
`entry.changed` represents content accepted in the selected environments. New entry webhooks wait 5 seconds after the last direct edit by default, then send one delivery with the combined `data.changes`. Exact repeated autosave changes appear once. Use `--debounce-changes immediate` to disable grouping. Accepted agent edits and environment merges already carry compact batches and send immediately. Operations above the delivery batch size share an `operationId` and include `{ index, total }` batch metadata. Every event includes its origin at `event.env.name`.
|
|
104
|
+
|
|
105
|
+
## Inspect before depending on it
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
fimo webhooks list
|
|
109
|
+
fimo webhooks get <webhook-id>
|
|
110
|
+
fimo webhooks test <webhook-id> --wait
|
|
111
|
+
fimo webhooks deliveries <webhook-id> --limit 20
|
|
112
|
+
fimo webhooks delivery <webhook-id> <delivery-id>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
`test` uses the selected event's documented example data and adds `X-Fimo-Test: true`. `--wait` waits up to 60
|
|
116
|
+
seconds for success or failure. Pass `--data '{...}'` only when a specific shape needs testing.
|
|
117
|
+
|
|
118
|
+
Fimo automatically retries temporary failures with backoff. After retries are exhausted:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
fimo webhooks retry <webhook-id> <delivery-id>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Use the delivery error code and attempt history to distinguish destination errors, timeouts, missing secrets, invalid templates, and blocked unsafe URLs. A delivery accepts up to five manual retries.
|
|
125
|
+
|
|
126
|
+
## Manage configurations
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
fimo webhooks update <webhook-id> --enabled off
|
|
130
|
+
fimo webhooks update <webhook-id> --url https://example.com/hooks/fimo
|
|
131
|
+
fimo webhooks update <webhook-id> --default-body
|
|
132
|
+
fimo webhooks delete <webhook-id>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Webhooks belong to the project, with up to 20 configurations per project. The same configuration is visible from every environment. Delivery listens to `main` by default. Use `--environments all` to include branch activity, or `--environments main` to return to main-only delivery.
|
|
136
|
+
|
|
137
|
+
## Verify Fimo signatures
|
|
138
|
+
|
|
139
|
+
Signing is on by default. Save the signing secret shown once at creation. Fimo sends:
|
|
140
|
+
|
|
141
|
+
- `X-Fimo-Delivery`: stable delivery ID
|
|
142
|
+
- `X-Fimo-Event`: event type
|
|
143
|
+
- `X-Fimo-Event-Id`: stable event ID for receiver deduplication
|
|
144
|
+
- `X-Fimo-Test`: `true` for synthetic test deliveries
|
|
145
|
+
- `X-Fimo-Timestamp`: Unix timestamp for the attempt
|
|
146
|
+
- `X-Fimo-Signature`: `v1=` plus HMAC-SHA256 of `<timestamp>.<raw-request-body>`
|
|
147
|
+
|
|
148
|
+
At the receiver, reject stale timestamps and compare the computed signature with a timing-safe comparison before parsing or acting on the payload. Rotate an exposed signing secret with:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
fimo webhooks rotate-secret <webhook-id>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Save the returned value immediately; it is not shown again.
|
|
155
|
+
|
|
156
|
+
## Guardrails
|
|
157
|
+
|
|
158
|
+
- Destinations must use public HTTPS URLs in production. Local/private/link-local addresses and redirects are blocked.
|
|
159
|
+
- Do not place access tokens in URLs, literal headers, payload templates, logs, or committed files.
|
|
160
|
+
- Do not retry a pending or actively retrying delivery manually.
|
|
161
|
+
- Do not assume a successful queue operation means the destination accepted the request; inspect the delivery result.
|
|
162
|
+
- Use `--json` when another agent or script needs stable, parseable output.
|
|
@@ -17,7 +17,10 @@ exports, source repositories, CMS exports, media folders, or any hybrid of those
|
|
|
17
17
|
It owns intake, source inventory, URL crawl bootstrapping, ledger normalization,
|
|
18
18
|
imports, and QA so any LLM can run the work without silently dropping content.
|
|
19
19
|
|
|
20
|
-
> Run every `fimo` command as `npx fimo
|
|
20
|
+
> Run every `fimo` command as `npx fimo <command>` when the project declares a
|
|
21
|
+
> `fimo` dependency (adopted/wrapped projects pin an exact version tied to their
|
|
22
|
+
> backend — never override it with `@latest`). Only fall back to
|
|
23
|
+
> `npx fimo@latest` when the project has no `fimo` dependency.
|
|
21
24
|
|
|
22
25
|
## Non-Negotiables
|
|
23
26
|
|
|
@@ -30,6 +33,13 @@ imports, and QA so any LLM can run the work without silently dropping content.
|
|
|
30
33
|
ledger.
|
|
31
34
|
- Source exports beat inferred crawls. If CSV/XML/JSON exports, media folders, or
|
|
32
35
|
source code exist, treat the public URL as visual/SEO reference only.
|
|
36
|
+
- A working JS codebase is wrapped, not rewritten. Wrap mode
|
|
37
|
+
(`references/wrap.md`) keeps the user's routing, styling, and components
|
|
38
|
+
untouched; the diff is wiring + wrappers + config only. As the coding
|
|
39
|
+
agent you own the whole wrap loop — run `npx fimo migrate` yourself and
|
|
40
|
+
follow `references/wrap.md` § W0 (relay the recorded data-source
|
|
41
|
+
decisions to the user, then loop `npx fimo migrate wrap --check` to
|
|
42
|
+
exit 0).
|
|
33
43
|
- Builder HTML is evidence, not the final runtime. Rebuild with Fimo conventions,
|
|
34
44
|
schemas, forms, media primitives, translations, and routes.
|
|
35
45
|
- Do not report completion until the QA gate passes or every failed check is
|
|
@@ -59,7 +69,15 @@ imports, and QA so any LLM can run the work without silently dropping content.
|
|
|
59
69
|
pack.
|
|
60
70
|
- **hybrid**: source files plus public URL. Use source-backed as truth and URL
|
|
61
71
|
for route, SEO, visual, and behavior comparison.
|
|
62
|
-
4.
|
|
72
|
+
4. Pick the mode:
|
|
73
|
+
- **wrap** (default for a source-backed, working JS codebase — Next.js,
|
|
74
|
+
Vite/React, React Router): keep the user's stack, adopt the repo with
|
|
75
|
+
`fimo init`, and make content editable by wrapping it in place. Never
|
|
76
|
+
rewrite routing, styling, or components. Follow `references/wrap.md`.
|
|
77
|
+
- **rebuild**: url-only sources, builder exports/HTML dumps, non-JS
|
|
78
|
+
backends, or codebases that do not build. Follow the standard workflow
|
|
79
|
+
phases.
|
|
80
|
+
5. Create or update the canonical ledger described in
|
|
63
81
|
`references/manifest.md`.
|
|
64
82
|
|
|
65
83
|
## Workflow
|
|
@@ -96,7 +114,11 @@ node <this-skill>/scripts/write-migration-report.mjs <project-root>
|
|
|
96
114
|
## References
|
|
97
115
|
|
|
98
116
|
- `references/workflow.md` - full decision tree and phase order.
|
|
117
|
+
- `references/wrap.md` - wrap mode: adopt a working JS codebase and wrap its
|
|
118
|
+
content in place (default for source-backed JS sites).
|
|
99
119
|
- `references/manifest.md` - canonical migration ledger schema.
|
|
120
|
+
- `references/pages.md` - the page registry (templates, schema bindings,
|
|
121
|
+
instances), Studio preview navigation, and the opt-in per-page SEO recipes.
|
|
100
122
|
- `references/content.md` - CMS, entries, references, and source value rules.
|
|
101
123
|
- `references/media.md` - media inventory, upload, dedupe, and replacement rules.
|
|
102
124
|
- `references/forms.md` - form classification and Fimo replacement rules.
|
|
@@ -18,6 +18,14 @@ ways:
|
|
|
18
18
|
news teasers, and feature lists are almost always collections even when the
|
|
19
19
|
source renders them inside one page.
|
|
20
20
|
|
|
21
|
+
> **Rebuild path only.** These rules apply when Fimo re-authors the site
|
|
22
|
+
> (URL/export migrations): the rebuilt code is disposable, so content belongs
|
|
23
|
+
> in collections aggressively. **Wrap mode is deliberately stricter** — the
|
|
24
|
+
> user's code stays primary, page furniture and nav stay in code with `t()`
|
|
25
|
+
> labels, and every collection candidate is confirmed with the user first.
|
|
26
|
+
> See `wrap.md` (W0 and the generated agent-prompt) — in wrap mode that
|
|
27
|
+
> guidance overrides this section.
|
|
28
|
+
|
|
21
29
|
After the source-faithful rebuild, treat **any hardcoded array of 3+ items with
|
|
22
30
|
the same shape** as a collection candidate. Do not leave it hardcoded.
|
|
23
31
|
|
|
@@ -97,3 +105,19 @@ Skipped fields or entries require a manifest note with:
|
|
|
97
105
|
- reason
|
|
98
106
|
- owner impact
|
|
99
107
|
- suggested action
|
|
108
|
+
|
|
109
|
+
## Scaffolded CMS — verify pages render
|
|
110
|
+
|
|
111
|
+
When `fimo migrate --scaffold-cms` wires the site to Fimo, the machine does the
|
|
112
|
+
deterministic work: it maps the CMS's components and dynamic zones to editable
|
|
113
|
+
Fimo blocks, seeds every block with generic example content in the shape the
|
|
114
|
+
components expect, and swaps the client's fetch for the generated Fimo adapter —
|
|
115
|
+
so the whole site reads from Fimo with no per-view wiring.
|
|
116
|
+
|
|
117
|
+
The last mile is yours and it is per-site. Open the main pages in `pnpm dev` (a
|
|
118
|
+
list, a detail, the page-builder home) and confirm each renders. Every renderer is
|
|
119
|
+
the site's own code, so a component may read a field the generic content did not
|
|
120
|
+
fill, or expect a slightly different shape. Where a section renders blank or
|
|
121
|
+
throws, fix it at that component — a defensive default, or the field it truly
|
|
122
|
+
needs — and re-check. Record anything you cannot resolve as a caveat. Do not
|
|
123
|
+
re-scaffold, re-wire, or hand-wrap content; the machine owns those.
|
|
@@ -34,6 +34,7 @@ follow-up agents, and import/QA checks.
|
|
|
34
34
|
"seo": [],
|
|
35
35
|
"unsupported": [],
|
|
36
36
|
"unresolved": [],
|
|
37
|
+
"wrap": null,
|
|
37
38
|
"qa": {
|
|
38
39
|
"status": "not-run|passed|failed|passed-with-unresolved",
|
|
39
40
|
"checks": []
|
|
@@ -41,6 +42,51 @@ follow-up agents, and import/QA checks.
|
|
|
41
42
|
}
|
|
42
43
|
```
|
|
43
44
|
|
|
45
|
+
## Wrap Block (wrap mode only)
|
|
46
|
+
|
|
47
|
+
When the migration is a wrap (see `references/wrap.md`), set
|
|
48
|
+
`source.mode: "source-backed"` and fill the `wrap` block; leave it `null` for
|
|
49
|
+
rebuild migrations:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"wrap": {
|
|
54
|
+
"mode": "wrap",
|
|
55
|
+
"framework": "next|react-router|vite",
|
|
56
|
+
"adopted": true,
|
|
57
|
+
"wired": true,
|
|
58
|
+
"coverage": {
|
|
59
|
+
"wrappable": 0,
|
|
60
|
+
"wrapped": 25,
|
|
61
|
+
"ignored": 0,
|
|
62
|
+
"unresolvedItems": 0
|
|
63
|
+
},
|
|
64
|
+
"seeded": {
|
|
65
|
+
"labels": 21,
|
|
66
|
+
"wrappedMedia": 3,
|
|
67
|
+
"wrappedRichText": 1
|
|
68
|
+
},
|
|
69
|
+
"seo": { "decision": "external", "decidedBy": "default" },
|
|
70
|
+
"planPath": ".fimo/migration/plan.json"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`wrap.seo` records who owns the site's SEO metadata — a USER decision, like
|
|
76
|
+
`wrap.dataSources`: `decision` is `"fimo"` (Fimo manages per-page SEO,
|
|
77
|
+
editable in the Studio) or `"external"` (the code / an external SEO tool
|
|
78
|
+
keeps ownership — the DEFAULT, nothing is ever wired on it). `decidedBy` is
|
|
79
|
+
`"default"` until the user actually answered; relay defaulted records and
|
|
80
|
+
rewrite them with `decidedBy: "user"`. Page bindings themselves live in the
|
|
81
|
+
page registry (`fimo-config.json#routes` →
|
|
82
|
+
`params: { "<param>": { "schema", "queryField", "displayField" } }`), not in
|
|
83
|
+
the manifest — see `references/pages.md`.
|
|
84
|
+
|
|
85
|
+
`coverage` mirrors the final `fimo migrate wrap --check` output: `wrappable`
|
|
86
|
+
must be 0 (or fully accounted for by `ignored` + `unresolvedItems`, each with a
|
|
87
|
+
ledger entry). `seeded` counts must match what `fimo labels list` /
|
|
88
|
+
`fimo entries list` report — fallback-only content is not seeded.
|
|
89
|
+
|
|
44
90
|
## Required Item Fields
|
|
45
91
|
|
|
46
92
|
Every route, content type, entry batch, media asset, form, redirect, locale, SEO
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# Pages — the page registry, Preview navigation, and opt-in SEO
|
|
2
|
+
|
|
3
|
+
A **Page** is a navigable URL surface of the site, in two forms:
|
|
4
|
+
|
|
5
|
+
- **Page template** — what the app's routing declares: `/pricing` (static),
|
|
6
|
+
`/blog/:slug` (dynamic). The app's CODE is the source of truth for page
|
|
7
|
+
structure; `fimo migrate` discovers templates per framework and reconciles
|
|
8
|
+
them into the registry, `fimo-config.json#routes` (manual entries are
|
|
9
|
+
preserved). Param syntax is ALWAYS `:param` / catch-all `:param*` — never
|
|
10
|
+
`[param]`.
|
|
11
|
+
- **Page instance** — a concrete page: template × content entry
|
|
12
|
+
(`/blog/:slug` × `hello-world`). Instances are NEVER stored; they derive
|
|
13
|
+
from entries through the template's binding, so they cannot drift.
|
|
14
|
+
|
|
15
|
+
The registry entry shape:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
"blog-post": {
|
|
19
|
+
"label": "Blog post",
|
|
20
|
+
"path": "/blog/:slug",
|
|
21
|
+
"params": { "slug": { "schema": "BlogPost", "queryField": "slug", "displayField": "title" } },
|
|
22
|
+
"seo": { "title": "{{blog-post.title}} — {{siteName}}" }
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
- `params[<param>]` is the **binding**: the schema whose entries materialize
|
|
27
|
+
the instances. `queryField` = the entry field substituted into the URL
|
|
28
|
+
(entry `slug` metadata always qualifies); `displayField` = the label the
|
|
29
|
+
Studio's page picker shows.
|
|
30
|
+
- The Studio preview navigates ONLY what the registry describes: static pages
|
|
31
|
+
as-is, dynamic pages once bound. An unbound dynamic page navigates to a
|
|
32
|
+
literal `/blog/:slug` URL — broken by definition.
|
|
33
|
+
- Locale params (`:locale`, `:lang`) are never schema-bound; tooling
|
|
34
|
+
substitutes the project's default locale. (Studio locale switching for
|
|
35
|
+
dynamic pages is a platform follow-up, not your problem.)
|
|
36
|
+
|
|
37
|
+
## Completing the bindings (agent workflow)
|
|
38
|
+
|
|
39
|
+
`fimo migrate` writes strong-evidence bindings itself (a rewired parent list
|
|
40
|
+
page; a wired CMS with a single page-builder type) and lists candidates +
|
|
41
|
+
unbound pages in the generated prompt. Your job:
|
|
42
|
+
|
|
43
|
+
1. `npx fimo pages list` — see every template and its status
|
|
44
|
+
(`static | dynamic:bound | dynamic:unbound`).
|
|
45
|
+
2. For each candidate/unbound page, find the schema whose entries the page
|
|
46
|
+
renders (read the page component's fetch). Apply with
|
|
47
|
+
`npx fimo pages set <id> --params '{"<param>":{"schema":"<Type>","queryField":"slug","displayField":"<field>"}}'`
|
|
48
|
+
— it validates the schema and both fields against the server. Never
|
|
49
|
+
hand-edit the JSON. If drafts are not adopted yet, run
|
|
50
|
+
`schemas adopt-drafts` FIRST and bind with the FINAL names.
|
|
51
|
+
3. Add pages the scanner missed (SPA relative/wildcard routes):
|
|
52
|
+
`npx fimo pages set <id> --path /the/path --label "Label"`.
|
|
53
|
+
Never repeat the folder/category in the label: the `/features/agents` page
|
|
54
|
+
is labeled "Agents", NOT "Feature: Agents" — the Studio tree already nests
|
|
55
|
+
it under Features.
|
|
56
|
+
Labels must read like a human wrote them: acronyms uppercase ("Agentic
|
|
57
|
+
CMS", "AI Stack", "SEO GEO" — never "Agentic Cms"), no two sibling pages
|
|
58
|
+
with the same name (a bound template is named after its schema — "Blog
|
|
59
|
+
Post" next to the "Blog" index; the machine does this when it binds, fix
|
|
60
|
+
any leftover with `--label`).
|
|
61
|
+
When the site's NAV groups flat pages editorially (a "Resources" menu over
|
|
62
|
+
/for-developers, /for-founders…), mirror it with
|
|
63
|
+
`npx fimo pages set <id> --group "Resources"` — the Studio Pages tree
|
|
64
|
+
folds them under that group even without a shared URL segment.
|
|
65
|
+
4. Map each page to its label keys when they diverge. The Studio shows a
|
|
66
|
+
page's labels by key prefix, defaulting to `<pageId>.` — but wrapped keys
|
|
67
|
+
derive from FILE names (`AiCms.tsx` → `ai-cms.*`) or data files
|
|
68
|
+
(`personas.*`), which can differ from the URL-derived page id
|
|
69
|
+
(`agentic-cms`). A page whose Studio view is EMPTY almost always means
|
|
70
|
+
this mismatch. `fimo migrate` PREFILLS `labelPrefixes` wherever it can
|
|
71
|
+
prove the join (a staged key appears verbatim in the route's component
|
|
72
|
+
file) and the prompt § Routes & pages lists every UNCLAIMED prefix left.
|
|
73
|
+
Your job: place each unclaimed prefix — claim it with
|
|
74
|
+
`npx fimo pages set <id> --label-prefix "<prefix>"` (comma-separated for
|
|
75
|
+
several; claims MERGE into the existing list so machine-prefilled
|
|
76
|
+
prefixes survive, `""` clears the whole list) when one page renders those keys, or leave it
|
|
77
|
+
deliberately when it is shared (chrome, multi-page data files) and say so
|
|
78
|
+
in your report. No prefix may end up merely forgotten.
|
|
79
|
+
5. Give each page the Lucide icon that best matches its CONTENT:
|
|
80
|
+
`npx fimo pages set <id> --icon <kebab-name>` (pricing → `tag`, blog →
|
|
81
|
+
`newspaper`, contact → `mail`, legal pages → `scale`, team/about →
|
|
82
|
+
`users`, docs → `book-open`). Read the page component to judge. Use
|
|
83
|
+
well-known Lucide names only — an unknown name silently falls back to
|
|
84
|
+
the default file icon in the Studio. Skip the flag when nothing clearly
|
|
85
|
+
fits.
|
|
86
|
+
6. Verify: `npx fimo pages list --expand` materializes every instance —
|
|
87
|
+
each page the site's nav links to must appear as a real URL.
|
|
88
|
+
|
|
89
|
+
## Shared chrome → Single Types (the content-model rule)
|
|
90
|
+
|
|
91
|
+
A site's content model must read like a CMS, not like an implementation:
|
|
92
|
+
|
|
93
|
+
- **Chrome** (header, footer, nav, menus, banners) is edited as ONE thing →
|
|
94
|
+
a SINGLE TYPE per piece (`src/schemas/<Name>.json` with
|
|
95
|
+
`"isSingleton": true`, real fields mirroring the source: nav items as an
|
|
96
|
+
array/blocks field, logo as media), pushed with `npx fimo schemas push`,
|
|
97
|
+
its ONE document written from the source values with
|
|
98
|
+
`npx fimo documents set <Name> --body '<json>'` (singletons REJECT the
|
|
99
|
+
entries endpoints), component rewired to read it. Never a loose label
|
|
100
|
+
pile, never a collection.
|
|
101
|
+
- **Page-scoped structure** (a pricing page's FAQ list) → a component array
|
|
102
|
+
on that page's Single, or a collection + reference when genuinely reused
|
|
103
|
+
across pages. Never an orphan collection nobody can situate. CLAIM the
|
|
104
|
+
single on its page (`npx fimo pages set pricing --single Pricing`) — it
|
|
105
|
+
then edits inline in the page's Studio view and leaves the Singles tab.
|
|
106
|
+
- **Real repeating content** (blog posts, team members) → a collection, with
|
|
107
|
+
HUMAN slugs derived from the display field (never `faq-item-<hash>`), and
|
|
108
|
+
schema field order matching reading order (question before answer).
|
|
109
|
+
- **A page's SECTIONS are its Single's nested blocks.** A marketing page is
|
|
110
|
+
a sequence of sections (hero, logo strip, features grid with grouped
|
|
111
|
+
cards, testimonials, integrations, stats, FAQ) — model the page as ONE
|
|
112
|
+
Single whose fields are nested block components mirroring that structure
|
|
113
|
+
(blocks nest: a `features` field holds groups, each group holds cards).
|
|
114
|
+
Section card lists are NEVER "page furniture" exemptions when they carry
|
|
115
|
+
real copy — an exemption hides marketing content from the editor, which
|
|
116
|
+
is a failed migration for that section. Claim the Single on its page.
|
|
117
|
+
**The machine BUILDS this model for you**: `fimo migrate` writes, per
|
|
118
|
+
multi-section page, an analysis draft (`.fimo/migration/page-drafts/`,
|
|
119
|
+
regenerate with `npx fimo pages draft`) AND a ready page Single
|
|
120
|
+
(`.fimo/migration/page-singles/<Uid>.json` — singleton schema + document
|
|
121
|
+
filled with the staged label values and the source block rows). Sections
|
|
122
|
+
flagged `"shared": true` render on several pages — that is chrome: model
|
|
123
|
+
each once as a Single Type, never as a per-page block. The `wrap --check`
|
|
124
|
+
Content-model gate fails while a built Single is neither claimed
|
|
125
|
+
(`pages set <id> --single <Uid>`) nor recorded under
|
|
126
|
+
`wrap.modelDeviations` (`{"page": "<id>", "reason": "…"}`) — a reason the
|
|
127
|
+
user would accept; "faster as labels" is not one. Your work per page:
|
|
128
|
+
rename machine field keys to editorial names, push, `documents set`,
|
|
129
|
+
rewire the reads with source fallback, claim.
|
|
130
|
+
|
|
131
|
+
**Worked real example** (the Fimo homepage, the model the user ratified):
|
|
132
|
+
the page renders hero → logo strip → features grid (3 groups, each with
|
|
133
|
+
cards) → testimonials → integrations → stats bar → FAQ. Its Single:
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"uid": "Home",
|
|
138
|
+
"isSingleton": true,
|
|
139
|
+
"fields": {
|
|
140
|
+
"builtOnTheBest": {
|
|
141
|
+
"type": "blocks",
|
|
142
|
+
"schema": { "fields": { "name": { "type": "string" }, "domain": { "type": "string" } } }
|
|
143
|
+
},
|
|
144
|
+
"features": {
|
|
145
|
+
"type": "blocks",
|
|
146
|
+
"schema": {
|
|
147
|
+
"fields": {
|
|
148
|
+
"title": { "type": "string" },
|
|
149
|
+
"subtitle": { "type": "string" },
|
|
150
|
+
"cards": {
|
|
151
|
+
"type": "blocks",
|
|
152
|
+
"schema": { "fields": { "title": { "type": "string" }, "description": { "type": "text" } } }
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
"testimonials": {
|
|
158
|
+
"type": "blocks",
|
|
159
|
+
"schema": {
|
|
160
|
+
"fields": {
|
|
161
|
+
"quote": { "type": "text" },
|
|
162
|
+
"metricValue": { "type": "string" },
|
|
163
|
+
"metricLabel": { "type": "string" },
|
|
164
|
+
"author": { "type": "string" },
|
|
165
|
+
"role": { "type": "string" }
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
"ecosystem": {
|
|
170
|
+
"type": "blocks",
|
|
171
|
+
"max": 1,
|
|
172
|
+
"schema": {
|
|
173
|
+
"fields": {
|
|
174
|
+
"title": { "type": "string" },
|
|
175
|
+
"stats": { "type": "blocks", "schema": { "fields": { "label": { "type": "string" } } } }
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
"faqs": { "type": "blocks", "schema": { "fields": { "q": { "type": "string" }, "a": { "type": "text" } } } }
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Note what made it right: block names are the on-page section titles
|
|
185
|
+
("Built on top of the best" → `builtOnTheBest`), field names are ROLES
|
|
186
|
+
(`title`, `quote`, `author`) never copy slugs, a logo strip carries its
|
|
187
|
+
ITEMS (not just its heading), computed live values (stat numbers) stay in
|
|
188
|
+
code, and the whole thing was claimed on the page. Smart deviations were
|
|
189
|
+
reported, not silent.
|
|
190
|
+
|
|
191
|
+
- **Plumbing** (`WrappedRichText`, `WrappedMedia`) is storage — the Studio
|
|
192
|
+
hides it from Collections and shows the entries under their pages; never
|
|
193
|
+
present it as content in your report.
|
|
194
|
+
|
|
195
|
+
## SEO — a USER decision, never wired by default
|
|
196
|
+
|
|
197
|
+
Who owns SEO metadata is recorded in `.fimo/migration/manifest.json` →
|
|
198
|
+
`wrap.seo` (`{ "decision": "fimo" | "external", "decidedBy": "user" | "default" }`).
|
|
199
|
+
The default is ALWAYS `external` (nothing touched — the site's code or an
|
|
200
|
+
external SEO tool keeps ownership). When the prompt shows the decision as
|
|
201
|
+
DEFAULTED, relay it to the user once; only an explicit user "fimo" unlocks
|
|
202
|
+
wiring. Never migrate, edit, or inject metadata on the default.
|
|
203
|
+
|
|
204
|
+
When the user opted into Fimo-managed SEO, the engine is the neutral
|
|
205
|
+
`fimo/seo` export — pure resolution over the registry, no framework coupling:
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
import { getFimoSeoForPath } from 'fimo/seo';
|
|
209
|
+
const seo = getFimoSeoForPath(pathname, { routeData: { 'blog-post': entry } });
|
|
210
|
+
// seo.title / seo.description / seo.image / seo.robots …
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Per-framework injection (map the resolved values to the framework's head API):
|
|
214
|
+
|
|
215
|
+
- **Next (app router)** — in the layout or page, `generateMetadata()` calls
|
|
216
|
+
`getFimoSeoForPath` with the resolved pathname (+ the entry as `routeData`
|
|
217
|
+
on dynamic pages) and returns `{ title, description, openGraph: {...} }`.
|
|
218
|
+
- **React Router** — already shipped: `loadFimoMetaData` / `buildFimoMeta` /
|
|
219
|
+
`fimoHtmlProps` from `fimo/react-router`.
|
|
220
|
+
- **Astro** — a head partial calling `getFimoSeoForPath(Astro.url.pathname)`
|
|
221
|
+
server-side and rendering the `<meta>` tags.
|
|
222
|
+
- **Nuxt** — `useSeoMeta()` fed from a server util wrapping `getFimoSeoForPath`.
|
|
223
|
+
- **SvelteKit** — resolve in `+layout.server` load, render in the root
|
|
224
|
+
layout's `<svelte:head>`.
|
|
225
|
+
|
|
226
|
+
Route-level `seo` blocks support `{{variables}}` resolved against
|
|
227
|
+
`routeData` — per-INSTANCE metadata from one template.
|
|
228
|
+
|
|
229
|
+
## Sitemap / robots
|
|
230
|
+
|
|
231
|
+
Once bindings exist, `getFimoPaths` (from `fimo/paths`) materializes the full
|
|
232
|
+
instance list for prerender/sitemap use. It reads the API base URL from
|
|
233
|
+
`VITE_API_URL` (a plain env var or `.env` line works outside Vite). The
|
|
234
|
+
`fimo pages list --expand` output is the same list, CLI-side.
|
|
@@ -18,8 +18,11 @@ Run this gate before reporting completion.
|
|
|
18
18
|
## Behavior
|
|
19
19
|
|
|
20
20
|
- Dependencies are installed in the target project.
|
|
21
|
-
- The project builds successfully
|
|
22
|
-
|
|
21
|
+
- The project builds successfully **with its own toolchain** (`next build`,
|
|
22
|
+
`vite build`, …) — wrapped sites are not Vite/React-Router projects; never
|
|
23
|
+
assume Fimo-template tooling.
|
|
24
|
+
- Local dev starts without loader/schema/form generation errors (Vite errors
|
|
25
|
+
apply to rebuild-mode projects only).
|
|
23
26
|
- Primary routes render without console/runtime errors.
|
|
24
27
|
- Collection listing/detail pages work with imported data, seed data, or explicit
|
|
25
28
|
empty states.
|
|
@@ -33,6 +36,25 @@ Run this gate before reporting completion.
|
|
|
33
36
|
- Remove generated placeholder copy from visible UI.
|
|
34
37
|
- Verify media aspect ratios and no broken images on primary routes.
|
|
35
38
|
|
|
39
|
+
## Wrap Mode (additional blocking checks)
|
|
40
|
+
|
|
41
|
+
When the manifest says `mode: "wrap"`:
|
|
42
|
+
|
|
43
|
+
- `fimo migrate wrap --check` exits zero — it enforces coverage (zero
|
|
44
|
+
unwrapped items), render parity (rendered text/marks/media/links identical
|
|
45
|
+
to the pre-wrap baseline), and seeding (every wrapped key exists in the
|
|
46
|
+
database) — or every remaining item is an explicit ignored/unresolved
|
|
47
|
+
ledger entry with a reason.
|
|
48
|
+
- Labels are seeded: every `FimoText`/`t()` key exists in `fimo labels list`
|
|
49
|
+
with the original string. Fallback-only content fails the gate.
|
|
50
|
+
- Wrapped media/rich text have their `WrappedMedia`/`WrappedRichText` entries
|
|
51
|
+
created and assets uploaded.
|
|
52
|
+
- Render parity: pages render identically to pre-migration — same text, same
|
|
53
|
+
formatting marks (bold/italic/underline/links), same media.
|
|
54
|
+
- Diff audit: the migration diff contains only wiring, wrappers, label calls,
|
|
55
|
+
config, and dependency changes. Any routing/styling/component rewrite fails
|
|
56
|
+
the gate.
|
|
57
|
+
|
|
36
58
|
## Import Verification
|
|
37
59
|
|
|
38
60
|
Record:
|
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Use this as the phase contract for complete migrations.
|
|
4
4
|
|
|
5
|
+
> **Mode fork.** For a source-backed, WORKING JS codebase (Next.js, Vite/React,
|
|
6
|
+
> React Router), wrap mode is the default: skip Phases 0 and 6 below and follow
|
|
7
|
+
> `references/wrap.md` (adopt via `fimo init`, scan via `fimo migrate wrap`,
|
|
8
|
+
> wrap in place, seed, verify). Phases 3–5 (content model, media/forms, import)
|
|
9
|
+
> and Phase 8 (QA + report) still apply — wrap changes how content becomes
|
|
10
|
+
> editable, not the accounting obligations. Everything else here is the rebuild
|
|
11
|
+
> path.
|
|
12
|
+
|
|
5
13
|
## Phase 0: Target Safety
|
|
6
14
|
|
|
7
15
|
1. Confirm the target path.
|
|
@@ -119,7 +127,10 @@ Required order:
|
|
|
119
127
|
Record target IDs, import counts, failures, and unresolved items in the
|
|
120
128
|
canonical ledger. Generated JSON without import counts is still draft state.
|
|
121
129
|
|
|
122
|
-
## Phase 6: Fimo Implementation
|
|
130
|
+
## Phase 6: Fimo Implementation (rebuild mode)
|
|
131
|
+
|
|
132
|
+
In wrap mode this phase is replaced by `references/wrap.md` phases W3–W5
|
|
133
|
+
(wire, wrap, seed); do not rebuild pages for a wrapped site.
|
|
123
134
|
|
|
124
135
|
Implement routes, schemas, forms, entries, media, redirects, translations, and
|
|
125
136
|
React pages with Fimo conventions.
|