fimo 0.17.0 → 0.18.0

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 (159) hide show
  1. package/assets/astro/components/DateTime.astro +22 -0
  2. package/assets/astro/components/index.d.ts +1 -0
  3. package/assets/astro/components/index.js +1 -0
  4. package/assets/content-templates/shared/types.eta +2 -0
  5. package/assets/skills/fimo-cli/SKILL.md +3 -2
  6. package/assets/skills/fimo-cli/references/content.md +2 -2
  7. package/assets/skills/fimo-cli/references/deploy.md +2 -0
  8. package/assets/skills/fimo-cli/references/init.md +11 -4
  9. package/assets/skills/fimo-cli/references/locales.md +38 -14
  10. package/assets/skills/fimo-cli/references/pages.md +70 -0
  11. package/assets/skills/fimo-cli/references/webhooks.md +1 -1
  12. package/assets/skills/fimo-code/SKILL.md +11 -0
  13. package/assets/skills/fimo-code/assets/react-router-locales/LocaleLayout.tsx +12 -0
  14. package/assets/skills/fimo-code/assets/react-router-locales/routes.ts +7 -6
  15. package/assets/skills/fimo-code/references/best-practices/astro.md +47 -0
  16. package/assets/skills/fimo-code/references/best-practices/next.md +42 -0
  17. package/assets/skills/fimo-code/references/best-practices/sveltekit.md +17 -0
  18. package/assets/skills/fimo-code/references/content/richtext.md +5 -0
  19. package/assets/skills/fimo-code/references/content/schema.md +4 -1
  20. package/assets/skills/fimo-code/references/frameworks/astro.md +5 -3
  21. package/assets/skills/fimo-code/references/frameworks/hosting.md +5 -2
  22. package/assets/skills/fimo-code/references/frameworks/next/app-router.md +6 -0
  23. package/assets/skills/fimo-code/references/frameworks/next/locales.md +12 -2
  24. package/assets/skills/fimo-code/references/frameworks/next.md +7 -0
  25. package/assets/skills/fimo-code/references/frameworks/react-router.md +15 -7
  26. package/assets/skills/fimo-code/references/frameworks/sveltekit.md +15 -8
  27. package/assets/skills/fimo-code/references/labels.md +9 -1
  28. package/assets/skills/fimo-code/references/locales.md +8 -2
  29. package/assets/skills/fimo-code/references/migrations/react-router-route-ownership.md +93 -0
  30. package/assets/skills/fimo-code/references/ui.md +21 -2
  31. package/assets/skills/fimo-migration/SKILL.md +276 -51
  32. package/assets/skills/fimo-migration/references/content.md +119 -35
  33. package/assets/skills/fimo-migration/references/decision.md +72 -0
  34. package/assets/skills/fimo-migration/references/forms.md +38 -6
  35. package/assets/skills/fimo-migration/references/frameworks/nextjs.md +179 -23
  36. package/assets/skills/fimo-migration/references/import-contract.md +71 -19
  37. package/assets/skills/fimo-migration/references/manifest.md +11 -161
  38. package/assets/skills/fimo-migration/references/media.md +33 -1
  39. package/assets/skills/fimo-migration/references/platforms.md +26 -2
  40. package/assets/skills/fimo-migration/references/qa.md +167 -13
  41. package/assets/skills/fimo-migration/references/workers/content-execution.md +39 -0
  42. package/assets/skills/fimo-migration/references/workers/content-planner.md +64 -0
  43. package/assets/skills/fimo-migration/references/workers/framework.md +37 -0
  44. package/assets/skills/fimo-migration/references/workers/validator.md +25 -0
  45. package/assets/skills/fimo-migration/references/workers.md +82 -0
  46. package/assets/skills/fimo-migration/references/workflow.md +140 -192
  47. package/assets/skills/fimo-migration/scripts/apply-decision.mjs +534 -0
  48. package/assets/skills/fimo-migration/scripts/build-canonical-manifest.mjs +7 -4
  49. package/assets/skills/fimo-migration/scripts/write-migration-report.mjs +191 -4
  50. package/assets/skills/fimo-studio/references/cms.md +25 -7
  51. package/assets/skills/fimo-studio/references/webhooks.md +1 -1
  52. package/assets/sveltekit/components/DateTime.svelte +35 -0
  53. package/assets/sveltekit/components/FimoProvider.svelte +2 -2
  54. package/assets/sveltekit/components/index.d.ts +1 -0
  55. package/assets/sveltekit/components/index.js +1 -0
  56. package/dist/build/next/config.d.ts +4 -1
  57. package/dist/build/next/config.js +21 -5
  58. package/dist/build/sveltekit/vite.d.ts +3 -4
  59. package/dist/build/sveltekit/vite.js +3 -4
  60. package/dist/build/vite/plugins/runtime-env.d.ts +2 -1
  61. package/dist/build/vite/plugins/runtime-env.js +14 -10
  62. package/dist/cli/bundle.json +2 -2
  63. package/dist/cli/index.js +76 -78
  64. package/dist/runtime/app/FimoProviders.js +25 -14
  65. package/dist/runtime/app/prefetch.d.ts +3 -1
  66. package/dist/runtime/app/prefetch.js +11 -55
  67. package/dist/runtime/astro/preview.js +7 -9
  68. package/dist/runtime/content/client/internal.js +1 -0
  69. package/dist/runtime/i18n/locale.d.ts +4 -0
  70. package/dist/runtime/i18n/locale.js +14 -14
  71. package/dist/runtime/next/client-runtime.js +5 -1
  72. package/dist/runtime/next/client.d.ts +3 -2
  73. package/dist/runtime/next/client.js +2 -1
  74. package/dist/runtime/next/labels.d.ts +2 -2
  75. package/dist/runtime/next/labels.js +2 -2
  76. package/dist/runtime/next/preview.d.ts +13 -0
  77. package/dist/runtime/next/preview.js +34 -0
  78. package/dist/runtime/next/primitives/server.d.ts +2 -0
  79. package/dist/runtime/next/primitives/server.js +8 -0
  80. package/dist/runtime/next/provider.d.ts +5 -0
  81. package/dist/runtime/next/provider.js +17 -3
  82. package/dist/runtime/next/server-runtime.js +4 -1
  83. package/dist/runtime/next/server.d.ts +1 -1
  84. package/dist/runtime/next/server.js +1 -1
  85. package/dist/runtime/paths/get-fimo-paths.d.ts +6 -5
  86. package/dist/runtime/paths/get-fimo-paths.js +43 -42
  87. package/dist/runtime/preview/location.d.ts +19 -2
  88. package/dist/runtime/preview/location.js +16 -2
  89. package/dist/runtime/primitives/index.d.ts +1 -0
  90. package/dist/runtime/primitives/index.js +1 -0
  91. package/dist/runtime/react/primitives/editable/DateTime.d.ts +4 -0
  92. package/dist/runtime/react/primitives/editable/DateTime.js +13 -0
  93. package/dist/runtime/react/primitives/renderers/DateRenderer.d.ts +7 -1
  94. package/dist/runtime/react/primitives/renderers/DateRenderer.js +11 -8
  95. package/dist/runtime/react-router/{routes.d.ts → legacy/routes.d.ts} +6 -1
  96. package/dist/runtime/react-router/{routes.js → legacy/routes.js} +22 -7
  97. package/dist/runtime/routes/contract.d.ts +116 -0
  98. package/dist/runtime/routes/contract.js +377 -0
  99. package/dist/runtime/routes/index.d.ts +3 -0
  100. package/dist/runtime/routes/index.js +3 -0
  101. package/dist/runtime/routing/AppRoutesProvider.js +4 -3
  102. package/dist/runtime/seo/resolver.d.ts +5 -0
  103. package/dist/runtime/seo/resolver.js +10 -42
  104. package/dist/runtime/shared/fimo-config.types.d.ts +34 -8
  105. package/dist/runtime/shared/preview-location.d.ts +1 -22
  106. package/dist/runtime/shared/preview-location.js +5 -93
  107. package/dist/runtime/sveltekit/preview.d.ts +12 -3
  108. package/dist/runtime/sveltekit/preview.js +13 -8
  109. package/dist/scripts/sync-forms.js +1 -1
  110. package/dist/scripts/sync-schemas.js +1 -4
  111. package/dist/scripts/validate-fimo-config.js +5 -1
  112. package/dist/scripts/validate-page-registry.d.ts +2 -0
  113. package/dist/scripts/validate-page-registry.js +167 -0
  114. package/dist/scripts/validate-route-metadata.js +132 -41
  115. package/package.json +7 -3
  116. package/templates/astro/.fimo/config.json +13 -5
  117. package/templates/astro/AGENTS.md +5 -1
  118. package/templates/astro/astro.config.mjs +7 -0
  119. package/templates/astro/pnpm-workspace.yaml +0 -3
  120. package/templates/astro/src/components/ProjectOverview.astro +9 -6
  121. package/templates/astro/src/layouts/Base.astro +1 -1
  122. package/templates/astro/src/locales.ts +4 -0
  123. package/templates/astro/src/pages/[locale]/index.astro +19 -0
  124. package/templates/astro/src/pages/[locale]/projects/[slug].astro +35 -0
  125. package/templates/astro/src/pages/[locale]/projects/index.astro +19 -0
  126. package/templates/astro/src/pages/index.astro +5 -2
  127. package/templates/astro/src/pages/projects/[slug].astro +4 -2
  128. package/templates/astro/src/pages/projects/index.astro +5 -2
  129. package/templates/nextjs/.fimo/config.json +2 -1
  130. package/templates/nextjs/AGENTS.md +5 -0
  131. package/templates/nextjs/src/app/(default)/layout.tsx +10 -0
  132. package/templates/nextjs/src/app/[locale]/layout.tsx +22 -0
  133. package/templates/nextjs/src/app/[locale]/page.tsx +1 -0
  134. package/templates/nextjs/src/components/Document.tsx +26 -0
  135. package/templates/nextjs/src/components/FimoPreviewBridge.tsx +13 -0
  136. package/templates/nextjs/src/locales.ts +13 -0
  137. package/templates/react-router/.fimo/config.json +3 -6
  138. package/templates/react-router/AGENTS.md +4 -0
  139. package/templates/react-router/package.json +1 -1
  140. package/templates/react-router/pnpm-workspace.yaml +1 -3
  141. package/templates/react-router/react-router.config.ts +4 -10
  142. package/templates/react-router/src/pages/LocaleLayout.tsx +12 -0
  143. package/templates/react-router/src/root.tsx +2 -4
  144. package/templates/react-router/src/routes.ts +5 -3
  145. package/templates/sveltekit/.fimo/config.json +2 -1
  146. package/templates/sveltekit/AGENTS.md +5 -0
  147. package/templates/sveltekit/src/app.html +1 -1
  148. package/templates/sveltekit/src/hooks.server.ts +11 -0
  149. package/templates/sveltekit/src/locales.ts +8 -0
  150. package/templates/sveltekit/src/params/locale.ts +5 -0
  151. package/templates/sveltekit/src/routes/+layout.server.ts +6 -1
  152. package/templates/sveltekit/src/routes/+layout.svelte +5 -0
  153. package/assets/skills/fimo-migration/references/inventory/coordinator.md +0 -40
  154. package/assets/skills/fimo-migration/references/inventory/locales/next-intl.md +0 -39
  155. package/assets/skills/fimo-migration/references/inventory/locales.md +0 -41
  156. package/assets/skills/fimo-migration/scripts/inventory/locales/next-intl.mjs +0 -459
  157. package/templates/nextjs/src/app/layout.tsx +0 -17
  158. /package/templates/nextjs/src/app/{page.tsx → (default)/page.tsx} +0 -0
  159. /package/templates/sveltekit/src/routes/{+page.svelte → [[locale=locale]]/+page.svelte} +0 -0
@@ -0,0 +1,72 @@
1
+ # Migration decisions
2
+
3
+ Migration decisions are plain text. Put them in
4
+ `.fimo/migration/migration-plan.md` and the relevant worker report. Do not
5
+ create `.fimo/migration/decision.json`, a target metadata file, or a second
6
+ decision registry.
7
+
8
+ The decision must say, in ordinary language:
9
+
10
+ - what the source construct is;
11
+ - where it is proven in the source;
12
+ - whether it becomes collection content, a single, a label, or
13
+ application-owned code;
14
+ - which schema/payload and consuming files are involved;
15
+ - what was preserved, replaced, or left unresolved; and
16
+ - who or what must do the next action.
17
+
18
+ The owning worker may write schemas, content payloads, entries, assets, singles,
19
+ and labels directly through the normal Fimo CLI/API contracts. The text plan is
20
+ the handoff; it is not an approval queue and it is not required to replay a
21
+ completed migration.
22
+
23
+ ## Labels
24
+
25
+ A label is UI-visible copy presented to a visitor or user: navigation text,
26
+ headings, buttons, form labels, validation and error text, calls to action,
27
+ visible empty states, and visible translated copy.
28
+
29
+ Do not classify every string as a label. Object keys, route segments, CSS
30
+ tokens, analytics event names, internal identifiers, prices and other data
31
+ values, application settings, and assistive-only attribute text remain in
32
+ application code unless the source proves they are editor-managed content.
33
+ Record the source file and consuming UI for each label.
34
+
35
+ ## Schema decisions
36
+
37
+ Write the complete valid Fimo schema that the source justifies. For every field,
38
+ decide its Fimo type, requiredness, default, string options, uniqueness,
39
+ locale-sharing behavior, media multiplicity/MIME constraints, and reference
40
+ target/cardinality when the source proves them. The schema JSON is an actual
41
+ Fimo artifact and may be pushed by the content planner; it is not a report
42
+ about the agent's reasoning.
43
+
44
+ Choose field types from source semantics and editor experience, following
45
+ `references/content.md`: use richtext for portable editorial prose, blocks for
46
+ structured or repeatable editorial sections, media for assets, and references
47
+ for independently managed records proven by the source. Use JSON only for
48
+ opaque or application-owned data that has no Fimo-native model, and record why.
49
+
50
+ Requiredness and defaults come from the source contract, such as a CMS schema,
51
+ collection configuration, validation contract, or type declaration. A field is
52
+ not required merely because the sampled files fill it. Use only source-declared
53
+ or safe technical defaults such as an empty list, `false`, or absent. Never
54
+ invent human-readable copy as a default.
55
+
56
+ Preserve the raw value and explain the uncertainty in the text plan when a
57
+ mapping is unclear. Validate every schema against the actual Fimo CLI/content
58
+ schema contract and use its generated clients, renderers, and primitives.
59
+
60
+ ## Mapping rules
61
+
62
+ - Markdown collections become one content type plus one document per slug.
63
+ - Localized documents become one document with one payload per locale.
64
+ - Local assets referenced by content become media-library uploads, and the
65
+ content payload references the uploaded asset. Media owns its alt text; do
66
+ not add a parallel alt field to the content schema.
67
+ - Routes map source route modules to target route modules.
68
+ - References are created only from stable source identity or a confirmed
69
+ mapping.
70
+ - A custom or executable construct is unresolved only when it genuinely cannot
71
+ be carried over. Record its exact source location, why it is not portable,
72
+ and a suggested action. Never silently remove it.
@@ -1,15 +1,21 @@
1
1
  # Forms
2
2
 
3
- Builder form backends rarely migrate directly. Replace simple forms with Fimo
4
- forms and document complex behavior.
3
+ Preserve the behavior a visitor sees. Replace a form with a Fimo form only when
4
+ Fimo reproduces the source form's user-visible behavior end to end; otherwise
5
+ keep the original integration wired and record what it needs.
5
6
 
6
7
  ## Classify
7
8
 
8
- Use `fimo-native` when the form is a simple contact, newsletter, lead capture,
9
- RSVP, quote request, or similar data collection form.
9
+ Use `fimo-native` only when Fimo genuinely reproduces the source form's
10
+ user-visible behavior end to end: a simple contact, newsletter, lead capture,
11
+ RSVP, or quote request form whose submit, validation, and success/error flow a
12
+ Fimo form matches 1:1.
10
13
 
11
- Use `third-party` when the form posts to Mailchimp, HubSpot, Typeform, Formspree,
12
- Zapier, Airtable, payment providers, or another external backend.
14
+ Use `third-party` when the form posts to Brevo, Mailchimp, HubSpot, Typeform,
15
+ Formspree, Zapier, Airtable, payment providers, or another external backend.
16
+ When the external behavior is not 1:1 reproducible - a Brevo double-opt-in
17
+ newsletter flow, for example - keeping the original integration wired is the
18
+ correct terminal state, not a migration failure.
13
19
 
14
20
  Use `unsupported` when the form depends on auth, checkout, dynamic pricing,
15
21
  multi-step state, file workflows not supported by the current project, custom JS,
@@ -43,6 +49,32 @@ For `fimo-native` forms:
43
49
  Do not claim live submission parity until the form has been pushed/imported and
44
50
  rendered by the site.
45
51
 
52
+ ## Definition Versus Wiring
53
+
54
+ Importing the Fimo form definition and wiring the source form UI are two
55
+ different obligations; report them separately.
56
+
57
+ - The definition (`src/forms/*.json`, pushed to Fimo) covers what the form
58
+ collects: fields, options, required flags.
59
+ - The wiring covers the behavior the visitor sees around the form: the source
60
+ page's markup, conditional pricing, availability rules, client-side
61
+ validation, and the submit/success/error flow. Preserve that local behavior
62
+ in the application code where possible; pushing the definition does not
63
+ migrate it.
64
+ - A third-party integration may be explicitly deferred as an unresolved item
65
+ with the source action and an owner decision, but a form is never reported
66
+ as migrated while its local behavior is missing or its integration was
67
+ silently dropped.
68
+
69
+ ## Credentials And Secrets
70
+
71
+ Record the credential environment keys a preserved integration needs by name
72
+ (`BREVO_API_KEY`, not its value). Never read secret values or copy them into
73
+ migration artifacts. A missing secret is a user follow-up in the report: the
74
+ integration stays wired, local build, evaluation, and QA checks still run with
75
+ the integration inert, and the behavior is never deleted because its secret is
76
+ unavailable.
77
+
46
78
  ## Unsupported Or Third-Party Forms
47
79
 
48
80
  Create an unresolved item with:
@@ -1,26 +1,182 @@
1
- # Next.js source inventory
1
+ # Next.js source
2
2
 
3
- Load this reference when the migration source is a Next.js application. This
4
- reference selects evidence strategies; use the target project's `fimo-code`
3
+ Load this reference when the migration source is a Next.js application or the
4
+ user explicitly chose Next.js as a conversion target. It describes what each
5
+ worker must read in that source; use the target project's `fimo-code`
5
6
  framework guidance when implementing the migrated application.
6
7
 
7
- ## Inventory
8
-
9
- 1. Record the installed Next.js and internationalization package declarations.
10
- 2. Identify App Router, Pages Router, or a mixed tree without changing it.
11
- 3. Inspect `next.config.*`, request configuration, middleware or proxy files,
12
- navigation helpers, route segments, and message dictionaries.
13
- 4. Keep these claims separate:
14
- - dictionary locale candidates;
15
- - configured locales;
16
- - default locale;
17
- - publicly routable locales;
18
- - localized pathnames.
19
- 5. When next-intl is declared, load
20
- `references/inventory/locales/next-intl.md` and run its bounded strategy.
21
- 6. Record dynamic, imported, remote, or otherwise unproven configuration as
22
- unresolved for the locale inventory fan-in.
23
-
24
- Use package versions to prioritize likely strategies, not as proof of the
25
- source shape. Projects backport, customize, and combine conventions across
26
- versions; accept a claim only when its source evidence supports it.
8
+ A Next.js source stays a Next.js target. Keep the detected router flavor,
9
+ `next.config.*`, middleware, and runtime configuration; do not convert the app
10
+ to React Router or another framework to simplify the migration. When framework
11
+ detection is ambiguous, stop and ask. A non-Next.js source converts to Next.js
12
+ only when the user explicitly chooses it.
13
+
14
+ ## Next.js as a conversion target
15
+
16
+ When the user explicitly chose converting another framework (for example React
17
+ Router/Vite) to Next.js, the framework conversion worker in
18
+ `references/workers.md` owns the target. It inspects the app tree that
19
+ `fimo migrate init` actually created, keeps that single tree, and rebuilds the
20
+ source routes, 404, redirects, headers, middleware, sitemap/robots/OG
21
+ structure, and locale routing structure inside it. It ports the source's own
22
+ loaders, APIs, hardcoded content, and integrations unchanged; Fimo wiring
23
+ happens later through the content workers. The conversion must pass the
24
+ framework gate before content data and code workers start.
25
+
26
+ Use package versions to prioritize likely shapes, not as proof of the source.
27
+ Projects backport, customize, and combine conventions across versions; accept a
28
+ claim only when its source evidence supports it.
29
+
30
+ ## Runtime and routes
31
+
32
+ 1. Record the installed Next.js, content, and internationalization package
33
+ declarations. A data-source package is a retrieval clue for the content
34
+ worker, nothing more.
35
+ 2. Identify App Router, Pages Router, or a mixed tree.
36
+ 3. Read `next.config.*`, request configuration, middleware or proxy files,
37
+ navigation helpers, and route segments before changing them. Map every
38
+ source route to a target route module, a redirect, or an unresolved item.
39
+ 4. Inventory `redirects()`, `rewrites()`, `headers()`, route handlers,
40
+ middleware, cache/revalidation calls, and provider adapters separately.
41
+ Preserve each rule until its behavior is replaced and verified. Record the
42
+ disposition of every rule; do not delete a whole provider file because some
43
+ rules became redundant.
44
+
45
+ ## Equivalents and hosting boundary
46
+
47
+ Load the target project's `fimo-code` `frameworks/next` and
48
+ `frameworks/hosting` references before implementing. Use normal Next.js
49
+ equivalents when they fit the accepted contract:
50
+
51
+ - route modules and route handlers for routes, feeds, negotiated responses, and
52
+ special text/XML files;
53
+ - `not-found` and `notFound()` for framework-owned 404 behavior;
54
+ - metadata APIs and OG/Twitter image routes for SEO and social output;
55
+ - `redirects()`, `rewrites()`, `headers()`, middleware, or response headers for
56
+ rules that the chosen runtime actually executes; and
57
+ - Next.js fetch/cache/revalidation APIs only when freshness is an observable
58
+ requirement rather than copied provider machinery.
59
+
60
+ These are application-level options, not guarantees that Fimo hosting supports
61
+ every header, redirect, route handler, cache mode, edge API, or middleware
62
+ behavior. Verify the chosen host/runtime. If support cannot be established,
63
+ preserve the existing deployment path or record the behavior unresolved and ask
64
+ the user; do not promise equivalence from code shape alone.
65
+
66
+ ### Port Cloudflare behavior
67
+
68
+ Do not mark a rule unresolved merely because it came from a Cloudflare Worker:
69
+ port static redirects, rewrites, headers, and asset cache headers to the real
70
+ `next.config.*`, then verify each with a request. Put dynamic behavior in
71
+ middleware or route handlers, and use Next.js cache/revalidation APIs when they
72
+ replace observable freshness. Cloudflare-only Cache API, bindings, `waitUntil`,
73
+ and purge calls need a verified host equivalent or remain explicitly unresolved.
74
+
75
+ Give every worker rule a `preserved`, `replaced`,
76
+ `safely-unnecessary-implementation-detail`, or `unresolved` disposition with
77
+ its target file and request-level proof.
78
+
79
+ ## SEO, OG, and social
80
+
81
+ The routes/SEO worker owns the source's existing SEO and social surface:
82
+ `metadata` exports, `generateMetadata`, `opengraph-image.*` and
83
+ `twitter-image.*` route files, dynamic OG image routes built on
84
+ `ImageResponse`, canonical URLs, robots, and sitemap generation. Preserve each
85
+ behavior in place; when one cannot be preserved, record an explicit gap with
86
+ the affected routes instead of shipping pages that silently lost their share
87
+ metadata.
88
+
89
+ ## Build-time and browser runtime
90
+
91
+ The Next server runtime reads `FIMO_CONTENT_API_URL`; client components and
92
+ generated client hooks read `NEXT_PUBLIC_FIMO_API_URL`. For a local production
93
+ build or migration acceptance run, expose both names and point them at the
94
+ same tenant content URL. `FIMO_API_URL` is the management/CLI API and is not a
95
+ substitute for either content API variable.
96
+
97
+ `withFimo` derives these aliases during `next dev` when the project is linked,
98
+ so local development does not need hand-written values. A production build,
99
+ however, compiles `NEXT_PUBLIC_*` values into the browser bundle and the
100
+ adapter intentionally does not inject them outside the development phase.
101
+ For `next build`/`next start`, set temporary values in the shell or an ignored
102
+ `.env.local`; never commit secret values. In either mode, exercise at least one
103
+ client-side data read after startup.
104
+
105
+ ## Preview embedding and response headers
106
+
107
+ Fimo Preview loads the app in an iframe and drives it over the postMessage
108
+ preview bridge, so development/preview responses must let the preview origin
109
+ frame the app.
110
+
111
+ - `withFimo` consumes `FIMO_PREVIEW_ALLOWED_ORIGINS` (platform-supplied,
112
+ comma-separated `**.<domain>` patterns) only to extend `allowedDevOrigins`
113
+ during `next dev`. It does not add, remove, or rewrite response headers;
114
+ wrapping the config never fixes a framing block by itself.
115
+ - When the source `headers()` sends `X-Frame-Options` or a CSP
116
+ `frame-ancestors` directive, keep `X-Content-Type-Options`,
117
+ `Strict-Transport-Security`, and `Referrer-Policy` unchanged, and translate
118
+ the framing block in the migrated config. For a hosted/remote preview, while
119
+ `FIMO_PREVIEW_ALLOWED_ORIGINS` is set, omit `X-Frame-Options` and send
120
+ `Content-Security-Policy: frame-ancestors 'self' https://*.<domain>` derived
121
+ from each `**.<domain>` entry. For local `next dev`, when the platform
122
+ variable is absent, omit the framing block only while
123
+ `process.env.NODE_ENV !== 'production'`; keep the source framing policy in
124
+ production. Never hardcode a preview provider domain.
125
+ - Record every translated or dropped header in the runtime report's Hosting
126
+ section.
127
+
128
+ Without a browser, verify embeddability deterministically: with the variable
129
+ set, request a route from the running dev server and assert the response
130
+ headers carry no unconditional framing block, then mark visual proof
131
+ unavailable in the QA report.
132
+
133
+ ## Locales
134
+
135
+ Keep these claims separate, and treat any one of them as unproven until its
136
+ source says so: dictionary locale candidates, configured locales, the default
137
+ locale, publicly routable locales, and localized pathnames. A dictionary file
138
+ never proves route reachability.
139
+
140
+ When `package.json` declares next-intl, the locales worker reads the actual
141
+ message files, `defineRouting` values, middleware, request helpers, and call
142
+ sites directly. A dictionary filename is evidence for a message locale, not
143
+ proof that the locale is routable. If the source uses another library or a
144
+ custom store, follow its imports and reads in the same worker. The worker may
145
+ write a short bounded temporary extractor when that is faster, but it owns the
146
+ interpretation and must record the source evidence and any unresolved claim.
147
+
148
+ ## Markdown, MDX, and inline content
149
+
150
+ The content planner reads the content itself: file locations and formats,
151
+ frontmatter keys and values, locale-shaped filenames or directories, route and
152
+ component modules that consume them, hardcoded arrays and object literals, and
153
+ local asset references under `public/`. It records every consuming source and
154
+ target module in `affectedFiles` before code workers start. Nested frontmatter,
155
+ mixed locale conventions, missing local assets, and unproven route references
156
+ need a decision from the source, not a guess.
157
+
158
+ Map what the source proves: a directory of Markdown files with several slugs may
159
+ be one collection, locale-suffixed files may be locale payloads of one
160
+ document, and a `public/` reference may become a media upload. The content
161
+ planner decides the destination from the consuming route and data shape, rather
162
+ than using a filename or extension as an automatic classification.
163
+
164
+ Create one source item per Markdown/MDX document and per independently handled
165
+ construct inside it. Portable prose and an executable MDX component are
166
+ different items even when they share one file. Read the custom component, its
167
+ import, and its data path; assign it to a code batch when it can be rebuilt with
168
+ native Fimo content, otherwise record it unresolved before data import begins.
169
+ Never remove JSX from the richtext payload without representing that JSX as its
170
+ own migrated or unresolved source item.
171
+
172
+ For a hardcoded content array, create one source item per object and preserve
173
+ observable order explicitly. The matching data batch count must equal the
174
+ source item count. A schema and query with zero planned entry items is an
175
+ incomplete handoff.
176
+
177
+ Use a temporary read-only extractor only when it reduces repeated work. Parsing
178
+ frontmatter or a large literal array can be useful; a general Next.js AST parser
179
+ is not required. Record the mapping in the text content plan and worker report.
180
+
181
+ Content that is not file-backed follows the content planner's discovery branches
182
+ in `references/workers.md`; preserve every provider gap as unresolved evidence.
@@ -8,6 +8,13 @@ but it is not complete until the relevant Fimo project contains the imported
8
8
  assets, schemas, entries, and forms, or the gaps are owner-visible unresolved
9
9
  items.
10
10
 
11
+ Every data-plane write in this contract targets the linked project from
12
+ workflow Phase 0. Local artifacts never require the link — `fimo migrate
13
+ import` only prints the import plan (it writes no data) and warns in an
14
+ unlinked directory — running the printed commands is what needs the link.
15
+ When no owner-supplied target exists, the writes stay unresolved owner
16
+ actions; do not fake a link to make them pass.
17
+
11
18
  ## Media Files
12
19
 
13
20
  Discovery must include:
@@ -17,13 +24,17 @@ Discovery must include:
17
24
  - CMS media fields
18
25
  - SEO/share images
19
26
  - downloadable files linked from pages or entries
27
+ - every schema media field, including empty or unresolved source values
28
+ - image nodes nested anywhere in richtext or Tiptap payloads
20
29
 
21
30
  Import requirements:
22
31
 
23
- - every imported asset records a Fimo target asset ID or URL in
24
- `.fimo/migration/manifest.json`
32
+ - every imported asset records a Fimo target asset ID or URL in the worker and
33
+ migration reports
25
34
  - every failed asset has an unresolved item with references to the affected
26
35
  route or entry
36
+ - every planner media obligation has an uploaded mapping, an explicit
37
+ unresolved/unsupported disposition, or a proven duplicate mapping
27
38
  - CMS media fields are rewritten after upload; source URLs are not left in
28
39
  editable entry payloads unless explicitly unresolved
29
40
 
@@ -46,10 +57,14 @@ Discovery must include:
46
57
 
47
58
  Import requirements:
48
59
 
49
- - schemas are pushed before entries
60
+ - schemas are validated and pushed before media or content writes
61
+ - `fimo schemas push` reconciles an ambiguous 504 by reading every requested
62
+ schema back. A complete match counts as committed; when all are absent it
63
+ retries once; mixed, mismatched, or still-absent state stops for review
64
+ instead of replaying another blind write.
50
65
  - entries are created or updated in Fimo, not only written as seed JSON
51
66
  - source count, generated count, imported count, skipped count, and unresolved
52
- count are recorded per content type
67
+ count are recorded per content type in the text plan/report
53
68
  - references are resolved in a second pass only when stable IDs or confirmed
54
69
  mappings exist
55
70
 
@@ -72,32 +87,69 @@ Discovery must include:
72
87
 
73
88
  Import requirements:
74
89
 
75
- - simple contact/newsletter/lead forms become `src/forms/*.json` and are pushed
76
- to Fimo
77
- - third-party or unsupported forms are recorded with source action, reason, and
78
- owner action
90
+ - a form becomes `src/forms/*.json` and is pushed to Fimo only when the Fimo
91
+ form reproduces the source form's user-visible behavior end to end
92
+ - a third-party form whose behavior is not 1:1 reproducible keeps its original
93
+ integration wired, with the required credential environment keys recorded by
94
+ name (never their values) and any missing secret reported as a user
95
+ follow-up
96
+ - unsupported forms are recorded with source action, reason, and owner action
79
97
  - the report records form count, Fimo-native count, third-party count, and
80
98
  unsupported/unresolved count
81
99
 
82
100
  Acceptance:
83
101
 
84
- - every visible source form is represented by a Fimo form, third-party plan, or
85
- unsupported/unresolved item
102
+ - every visible source form is represented by a Fimo form, a preserved
103
+ third-party integration, or an unsupported/unresolved item
86
104
  - no page keeps a broken form UI that appears live
87
105
 
106
+ Historical form submissions do not have a write contract. The current
107
+ form-submissions CLI is read-only, so never claim that old submissions were
108
+ imported. Preserve the source export and record historical submission import as
109
+ unsupported with an owner action until a dedicated import contract exists.
110
+
111
+ ## Pagination And Batching
112
+
113
+ The data-plane commands are paginated and capped. Read the limits instead of
114
+ assuming one request covers everything:
115
+
116
+ - `fimo entries list` and `fimo assets list` return 20 items by default and at
117
+ most 100 per request (`--limit`, `--offset`). The response carries `total`
118
+ and `hasMore`; page until `hasMore` is false before treating a listing as
119
+ complete.
120
+ - `fimo entries bulk-create` chunks at 100 entries by default. Migration data
121
+ workers use `--upsert-by slug`; the identity includes locale, the command
122
+ rereads after an ambiguous 504 before retrying absent entries, and its
123
+ receipt aggregates per-chunk created/updated/conflict counts. Use
124
+ `--chunk-size` only when the transport supports a different bounded size
125
+ (maximum 1,000). `bulk-update` and `bulk-delete` remain capped at 1,000.
126
+ - `fimo labels set-many` sends its whole `--file`/`--data` payload in one
127
+ request; keep one payload per worker batch so a retry replays a bounded set.
128
+
129
+ Listing existing Fimo entries or assets serves idempotency, retry, and fan-in
130
+ reconciliation only - confirming what a rerun must update instead of create.
131
+ The source of the content is always the source tree or export, never a listing
132
+ of what already exists in Fimo.
133
+
88
134
  ## Minimum Import Loop
89
135
 
90
136
  For each migration, agents should run this loop:
91
137
 
92
- 1. Build or refresh the canonical manifest.
93
- 2. Fill missing media, CMS, and form discovery data.
94
- 3. Generate reviewed schemas/forms/import payloads.
95
- 4. Import media first.
96
- 5. Push schemas.
97
- 6. Import entries with media references resolved.
98
- 7. Push forms.
99
- 8. Refresh the canonical manifest with target IDs and counts.
100
- 9. Write the migration report.
138
+ 1. Read the text migration plan and the initialized target.
139
+ 2. Have the owning workers define complete schemas/forms and write them through
140
+ the normal Fimo contracts.
141
+ 3. Validate and push schemas before dependent content writes.
142
+ 4. Upload media.
143
+ 5. Import entries, then resolve proven references against stable target IDs.
144
+ 6. Update singles and apply labels.
145
+ 7. Handle form definitions through their separate supported contract; do not
146
+ import historical submissions.
147
+ 8. Write target IDs, counts, failures, and unresolved items into worker and
148
+ migration reports.
149
+
150
+ The data-plane dependency order remains `schemas`, `media`,
151
+ `entries/references`, `singles`, and `labels`. It is a simple execution order,
152
+ not a reason to add another orchestrator.
101
153
 
102
154
  If any step cannot be completed, write an unresolved item immediately with the
103
155
  source evidence and owner action needed.
@@ -1,164 +1,14 @@
1
- # Canonical Migration Manifest
1
+ # Legacy migration manifest
2
2
 
3
- Write `.fimo/migration/manifest.json`. It is the source of truth for humans,
4
- follow-up agents, and import/QA checks.
3
+ New migrations do not create a canonical `manifest.json`. The coordinator uses
4
+ the readable `.fimo/migration/migration-plan.md` and
5
+ `.fimo/migration/migration-report.md` instead.
5
6
 
6
- ## Shape
7
+ Older URL-only migrations may contain `.fimo/migrations/current/manifest.json`.
8
+ Read it as source evidence when useful, but do not copy it into another
9
+ registry or ask workers to keep it synchronized.
7
10
 
8
- ```json
9
- {
10
- "version": 1,
11
- "source": {
12
- "mode": "url-only|source-backed|hybrid",
13
- "platform": "webflow|framer|squarespace|wix|wordpress|carrd|custom|unknown",
14
- "publicUrl": "https://example.com",
15
- "rootPath": "../source",
16
- "inventoryPath": ".fimo/migration/inventory.json",
17
- "sourceLedgers": []
18
- },
19
- "artifacts": {
20
- "code": [],
21
- "cms": [],
22
- "media": [],
23
- "forms": [],
24
- "screenshots": [],
25
- "other": []
26
- },
27
- "routes": [],
28
- "contentTypes": [],
29
- "entries": [],
30
- "media": [],
31
- "forms": [],
32
- "redirects": [],
33
- "locales": [],
34
- "seo": [],
35
- "unsupported": [],
36
- "unresolved": [],
37
- "qa": {
38
- "status": "not-run|passed|failed|passed-with-unresolved",
39
- "checks": []
40
- }
41
- }
42
- ```
43
-
44
- ## Required Item Fields
45
-
46
- Every route, content type, entry batch, media asset, form, redirect, locale, SEO
47
- item, unsupported item, and unresolved item should include:
48
-
49
- ```json
50
- {
51
- "id": "stable-human-readable-id",
52
- "status": "discovered|planned|generated|imported|verified|ignored|unsupported|unresolved",
53
- "sourceFiles": [],
54
- "sourceUrls": [],
55
- "targetFiles": [],
56
- "confidence": 1,
57
- "notes": []
58
- }
59
- ```
60
-
61
- Use honest confidence. Inferred content from crawled pages is lower confidence
62
- than first-party CSV/XML/JSON exports.
63
-
64
- ## Content Type Item
65
-
66
- ```json
67
- {
68
- "id": "blog-post",
69
- "uid": "BlogPost",
70
- "name": "Blog Posts",
71
- "status": "planned",
72
- "sourceFiles": ["exports/blog.csv"],
73
- "targetFiles": ["src/schemas/BlogPost.json"],
74
- "sourceCount": 42,
75
- "plannedCount": 42,
76
- "importedCount": 0,
77
- "fields": {
78
- "title": { "type": "string", "source": "Name" },
79
- "body": { "type": "richtext", "source": "Post Body" },
80
- "coverImage": { "type": "media", "source": "Main Image" },
81
- "publishedAt": { "type": "datetime", "source": "Published On" }
82
- },
83
- "references": []
84
- }
85
- ```
86
-
87
- > **Do not put reserved names in `fields`.** `id`, `documentId`, `slug`, `locale`,
88
- > `createdAt`, `updatedAt`, and `__fimo` are built-in entry metadata — declaring them as
89
- > schema fields makes `fimo schemas push` fail with a 400. Map a source "Slug" column onto
90
- > the entry's built-in `slug` (inside `data`) at import time, not onto a schema field.
91
-
92
- ## Entry Batch Item
93
-
94
- ```json
95
- {
96
- "id": "blog-post-entries",
97
- "contentType": "BlogPost",
98
- "status": "generated",
99
- "sourceFiles": ["exports/blog.csv"],
100
- "targetFiles": [".fimo/migration/entries/BlogPost.json"],
101
- "sourceCount": 42,
102
- "generatedCount": 42,
103
- "importedCount": 0,
104
- "skipped": []
105
- }
106
- ```
107
-
108
- ## Media Item
109
-
110
- ```json
111
- {
112
- "id": "media-hero-jpg",
113
- "status": "imported",
114
- "sourceUrl": "https://example.com/hero.jpg",
115
- "sourcePath": "assets/hero.jpg",
116
- "targetAssetId": "asset_123",
117
- "targetUrl": "https://...",
118
- "sha256": "optional",
119
- "contentType": "image/jpeg",
120
- "bytes": 123456,
121
- "width": 1600,
122
- "height": 900,
123
- "alt": "Hero image",
124
- "referencedBy": ["route:/", "entry:BlogPost/welcome"],
125
- "uploadError": null
126
- }
127
- ```
128
-
129
- ## Form Item
130
-
131
- ```json
132
- {
133
- "id": "contact",
134
- "name": "contact",
135
- "status": "generated",
136
- "classification": "fimo-native|third-party|unsupported",
137
- "sourceFiles": ["contact.html"],
138
- "targetFiles": ["src/forms/contact.json"],
139
- "action": "https://formspree.io/...",
140
- "method": "post",
141
- "fields": [],
142
- "unsupportedReason": null
143
- }
144
- ```
145
-
146
- ## Unresolved Item
147
-
148
- ```json
149
- {
150
- "id": "mailchimp-newsletter-action",
151
- "area": "forms",
152
- "severity": "medium",
153
- "status": "unresolved",
154
- "message": "Newsletter form posts to Mailchimp and requires integration credentials.",
155
- "suggestedAction": "Create a Fimo form or configure a Mailchimp integration with the owner."
156
- }
157
- ```
158
-
159
- ## Rules
160
-
161
- - Prefer stable source IDs over generated IDs.
162
- - Preserve original field names in `source`; use clean Fimo field IDs in schemas.
163
- - Never delete unresolved items just to make the report cleaner.
164
- - Update item statuses as work progresses.
11
+ JSON remains appropriate for actual Fimo artifacts: schema files and the
12
+ content payloads passed to data-plane commands. It is not needed to describe
13
+ worker ownership, target paths, decisions, timings, or QA status. Put those in
14
+ plain-text plans, worker reports, and the final migration report.