fimo 0.17.0 → 0.19.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 (164) 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 +8 -6
  6. package/assets/skills/fimo-cli/references/branches.md +2 -2
  7. package/assets/skills/fimo-cli/references/content.md +2 -2
  8. package/assets/skills/fimo-cli/references/deploy.md +17 -9
  9. package/assets/skills/fimo-cli/references/hosting.md +114 -0
  10. package/assets/skills/fimo-cli/references/init.md +13 -6
  11. package/assets/skills/fimo-cli/references/integrations/firecrawl.md +2 -0
  12. package/assets/skills/fimo-cli/references/locales.md +38 -14
  13. package/assets/skills/fimo-cli/references/pages.md +70 -0
  14. package/assets/skills/fimo-cli/references/preview.md +26 -20
  15. package/assets/skills/fimo-cli/references/webhooks.md +1 -1
  16. package/assets/skills/fimo-code/SKILL.md +11 -0
  17. package/assets/skills/fimo-code/assets/react-router-locales/LocaleLayout.tsx +12 -0
  18. package/assets/skills/fimo-code/assets/react-router-locales/routes.ts +7 -6
  19. package/assets/skills/fimo-code/references/best-practices/astro.md +47 -0
  20. package/assets/skills/fimo-code/references/best-practices/next.md +42 -0
  21. package/assets/skills/fimo-code/references/best-practices/sveltekit.md +17 -0
  22. package/assets/skills/fimo-code/references/content/richtext.md +5 -0
  23. package/assets/skills/fimo-code/references/content/schema.md +4 -1
  24. package/assets/skills/fimo-code/references/frameworks/astro.md +5 -3
  25. package/assets/skills/fimo-code/references/frameworks/hosting.md +5 -2
  26. package/assets/skills/fimo-code/references/frameworks/next/app-router.md +6 -0
  27. package/assets/skills/fimo-code/references/frameworks/next/locales.md +12 -2
  28. package/assets/skills/fimo-code/references/frameworks/next.md +7 -0
  29. package/assets/skills/fimo-code/references/frameworks/react-router.md +15 -7
  30. package/assets/skills/fimo-code/references/frameworks/sveltekit.md +15 -8
  31. package/assets/skills/fimo-code/references/labels.md +9 -1
  32. package/assets/skills/fimo-code/references/locales.md +8 -2
  33. package/assets/skills/fimo-code/references/migrations/react-router-route-ownership.md +93 -0
  34. package/assets/skills/fimo-code/references/ui.md +21 -2
  35. package/assets/skills/fimo-migration/SKILL.md +276 -51
  36. package/assets/skills/fimo-migration/references/content.md +119 -35
  37. package/assets/skills/fimo-migration/references/decision.md +72 -0
  38. package/assets/skills/fimo-migration/references/forms.md +38 -6
  39. package/assets/skills/fimo-migration/references/frameworks/nextjs.md +179 -23
  40. package/assets/skills/fimo-migration/references/import-contract.md +71 -19
  41. package/assets/skills/fimo-migration/references/manifest.md +11 -161
  42. package/assets/skills/fimo-migration/references/media.md +33 -1
  43. package/assets/skills/fimo-migration/references/platforms.md +26 -2
  44. package/assets/skills/fimo-migration/references/qa.md +167 -13
  45. package/assets/skills/fimo-migration/references/workers/content-execution.md +39 -0
  46. package/assets/skills/fimo-migration/references/workers/content-planner.md +64 -0
  47. package/assets/skills/fimo-migration/references/workers/framework.md +37 -0
  48. package/assets/skills/fimo-migration/references/workers/validator.md +25 -0
  49. package/assets/skills/fimo-migration/references/workers.md +82 -0
  50. package/assets/skills/fimo-migration/references/workflow.md +140 -192
  51. package/assets/skills/fimo-migration/scripts/apply-decision.mjs +534 -0
  52. package/assets/skills/fimo-migration/scripts/build-canonical-manifest.mjs +7 -4
  53. package/assets/skills/fimo-migration/scripts/write-migration-report.mjs +191 -4
  54. package/assets/skills/fimo-studio/references/ai-chat.md +1 -1
  55. package/assets/skills/fimo-studio/references/cms.md +25 -7
  56. package/assets/skills/fimo-studio/references/webhooks.md +1 -1
  57. package/assets/sveltekit/components/DateTime.svelte +35 -0
  58. package/assets/sveltekit/components/FimoProvider.svelte +2 -2
  59. package/assets/sveltekit/components/index.d.ts +1 -0
  60. package/assets/sveltekit/components/index.js +1 -0
  61. package/dist/build/next/config.d.ts +4 -1
  62. package/dist/build/next/config.js +21 -5
  63. package/dist/build/sveltekit/vite.d.ts +3 -4
  64. package/dist/build/sveltekit/vite.js +3 -4
  65. package/dist/build/vite/plugins/runtime-env.d.ts +2 -1
  66. package/dist/build/vite/plugins/runtime-env.js +14 -10
  67. package/dist/cli/bundle.json +2 -2
  68. package/dist/cli/index.js +113 -108
  69. package/dist/runtime/app/FimoProviders.js +25 -14
  70. package/dist/runtime/app/prefetch.d.ts +3 -1
  71. package/dist/runtime/app/prefetch.js +11 -55
  72. package/dist/runtime/astro/preview.js +7 -9
  73. package/dist/runtime/content/client/internal.js +1 -0
  74. package/dist/runtime/i18n/locale.d.ts +6 -3
  75. package/dist/runtime/i18n/locale.js +16 -41
  76. package/dist/runtime/next/client-runtime.js +5 -1
  77. package/dist/runtime/next/client.d.ts +3 -2
  78. package/dist/runtime/next/client.js +2 -1
  79. package/dist/runtime/next/labels.d.ts +2 -2
  80. package/dist/runtime/next/labels.js +2 -2
  81. package/dist/runtime/next/preview.d.ts +13 -0
  82. package/dist/runtime/next/preview.js +34 -0
  83. package/dist/runtime/next/primitives/server.d.ts +2 -0
  84. package/dist/runtime/next/primitives/server.js +8 -0
  85. package/dist/runtime/next/provider.d.ts +5 -0
  86. package/dist/runtime/next/provider.js +17 -3
  87. package/dist/runtime/next/server-runtime.js +4 -1
  88. package/dist/runtime/next/server.d.ts +1 -1
  89. package/dist/runtime/next/server.js +1 -1
  90. package/dist/runtime/paths/get-fimo-paths.d.ts +6 -5
  91. package/dist/runtime/paths/get-fimo-paths.js +43 -42
  92. package/dist/runtime/preview/location.d.ts +19 -2
  93. package/dist/runtime/preview/location.js +16 -2
  94. package/dist/runtime/primitives/index.d.ts +1 -0
  95. package/dist/runtime/primitives/index.js +1 -0
  96. package/dist/runtime/react/primitives/editable/DateTime.d.ts +4 -0
  97. package/dist/runtime/react/primitives/editable/DateTime.js +13 -0
  98. package/dist/runtime/react/primitives/renderers/DateRenderer.d.ts +7 -1
  99. package/dist/runtime/react/primitives/renderers/DateRenderer.js +11 -8
  100. package/dist/runtime/react-router/{routes.d.ts → legacy/routes.d.ts} +6 -1
  101. package/dist/runtime/react-router/{routes.js → legacy/routes.js} +22 -7
  102. package/dist/runtime/routes/index.d.ts +162 -0
  103. package/dist/runtime/routes/index.js +335 -0
  104. package/dist/runtime/routing/AppRoutesProvider.js +4 -3
  105. package/dist/runtime/seo/resolver.d.ts +5 -0
  106. package/dist/runtime/seo/resolver.js +10 -42
  107. package/dist/runtime/shared/fimo-config.types.d.ts +14 -13
  108. package/dist/runtime/shared/preview-location.d.ts +1 -22
  109. package/dist/runtime/shared/preview-location.js +5 -93
  110. package/dist/runtime/sveltekit/preview.d.ts +12 -3
  111. package/dist/runtime/sveltekit/preview.js +13 -8
  112. package/dist/runtime/templates.d.ts +19 -0
  113. package/dist/runtime/templates.js +33 -0
  114. package/dist/scripts/sync-forms.js +1 -1
  115. package/dist/scripts/sync-schemas.js +1 -4
  116. package/dist/scripts/validate-fimo-config.js +5 -1
  117. package/dist/scripts/validate-page-registry.d.ts +2 -0
  118. package/dist/scripts/validate-page-registry.js +167 -0
  119. package/dist/scripts/validate-route-metadata.js +132 -41
  120. package/package.json +10 -5
  121. package/templates/astro/.fimo/config.json +13 -5
  122. package/templates/astro/AGENTS.md +5 -1
  123. package/templates/astro/astro.config.mjs +7 -0
  124. package/templates/astro/pnpm-workspace.yaml +0 -3
  125. package/templates/astro/src/components/ProjectOverview.astro +9 -6
  126. package/templates/astro/src/layouts/Base.astro +1 -1
  127. package/templates/astro/src/locales.ts +4 -0
  128. package/templates/astro/src/pages/[locale]/index.astro +19 -0
  129. package/templates/astro/src/pages/[locale]/projects/[slug].astro +35 -0
  130. package/templates/astro/src/pages/[locale]/projects/index.astro +19 -0
  131. package/templates/astro/src/pages/index.astro +5 -2
  132. package/templates/astro/src/pages/projects/[slug].astro +4 -2
  133. package/templates/astro/src/pages/projects/index.astro +5 -2
  134. package/templates/nextjs/.fimo/config.json +2 -1
  135. package/templates/nextjs/AGENTS.md +5 -0
  136. package/templates/nextjs/src/app/(default)/layout.tsx +10 -0
  137. package/templates/nextjs/src/app/[locale]/layout.tsx +22 -0
  138. package/templates/nextjs/src/app/[locale]/page.tsx +1 -0
  139. package/templates/nextjs/src/components/Document.tsx +26 -0
  140. package/templates/nextjs/src/components/FimoPreviewBridge.tsx +13 -0
  141. package/templates/nextjs/src/locales.ts +13 -0
  142. package/templates/react-router/.fimo/config.json +3 -6
  143. package/templates/react-router/AGENTS.md +4 -0
  144. package/templates/react-router/package.json +1 -1
  145. package/templates/react-router/pnpm-workspace.yaml +1 -3
  146. package/templates/react-router/react-router.config.ts +4 -10
  147. package/templates/react-router/src/pages/LocaleLayout.tsx +12 -0
  148. package/templates/react-router/src/root.tsx +2 -4
  149. package/templates/react-router/src/routes.ts +5 -3
  150. package/templates/sveltekit/.fimo/config.json +2 -1
  151. package/templates/sveltekit/AGENTS.md +5 -0
  152. package/templates/sveltekit/src/app.html +1 -1
  153. package/templates/sveltekit/src/hooks.server.ts +11 -0
  154. package/templates/sveltekit/src/locales.ts +8 -0
  155. package/templates/sveltekit/src/params/locale.ts +5 -0
  156. package/templates/sveltekit/src/routes/+layout.server.ts +6 -1
  157. package/templates/sveltekit/src/routes/+layout.svelte +5 -0
  158. package/assets/skills/fimo-migration/references/inventory/coordinator.md +0 -40
  159. package/assets/skills/fimo-migration/references/inventory/locales/next-intl.md +0 -39
  160. package/assets/skills/fimo-migration/references/inventory/locales.md +0 -41
  161. package/assets/skills/fimo-migration/scripts/inventory/locales/next-intl.mjs +0 -459
  162. package/templates/nextjs/src/app/layout.tsx +0 -17
  163. /package/templates/nextjs/src/app/{page.tsx → (default)/page.tsx} +0 -0
  164. /package/templates/sveltekit/src/routes/{+page.svelte → [[locale=locale]]/+page.svelte} +0 -0
@@ -2,24 +2,72 @@
2
2
 
3
3
  Model CMS content before page implementation.
4
4
 
5
+ ## Editorial Modeling
6
+
7
+ Model editorial content the way an editor should see it in Fimo, and keep the
8
+ source's behavior and content shape. A better model never silently redesigns the
9
+ site: the same routes render the same content, in the same order, with the same
10
+ copy. Record the source-to-Fimo mapping - source file, frontmatter key, or
11
+ export column -> content type, field, block, or reference - in the canonical
12
+ manifest and the content plan.
13
+
14
+ - **Blocks first.** Repeatable or structured editorial sections (hero, feature
15
+ grid, FAQ, testimonial list, pricing tiers, a page's section stack) become a
16
+ `blocks` field with named variants; rich bodies become `richtext`. Blocks and
17
+ references are content-editable, so model the structure instead of flattening
18
+ a section stack into loose strings or one opaque value.
19
+ - **JSON is the last resort.** Use `json` only for opaque or
20
+ application-owned data that no Fimo-native model fits, and record the concise
21
+ reason in the content plan and the report. A `json` blob holding editorial
22
+ copy is unmodeled content, not a migrated model.
23
+ - **Global chrome is content.** Header, footer, navigation, and site settings an
24
+ owner edits become singleton content types (navigation items as blocks or
25
+ references, not one label per link). Labels stay for genuinely small UI copy
26
+ and reusable translations.
27
+ - **Names are editor-facing.** `heroHeading`, not `H1`; `features`, not
28
+ `field_04`; `Navigation`, not `NavigationEs`. Never name a content type,
29
+ field, or block variant after a markup tag, an HTML attribute, a locale code,
30
+ or a source column index, and group related fields in the order an editor
31
+ reads them.
32
+
33
+ ## Markdown/MDX is source evidence, not a runtime source
34
+
35
+ Markdown/MDX files in the source tree or under `.fimo/migration/` are evidence
36
+ for the migration, never the migrated app's runtime content source. Claiming
37
+ content was migrated requires that the content was pushed to Fimo and the
38
+ consuming pages read it back through the Fimo content APIs. A page still
39
+ reading `.md`/`.mdx` files at build or request time is unmigrated content, not
40
+ a covered item.
41
+
42
+ - Long prose bodies belong in `richtext` fields and must render through the
43
+ Fimo rich-text primitives, not a Markdown pipeline.
44
+ - Custom MDX/React components embedded in prose are application code: preserve
45
+ them as components rendered by the consuming page, or record them as
46
+ unresolved. Never silently drop them during HTML-to-richtext conversion.
47
+ - Split editable prose around executable React/MDX children. Keep the children
48
+ in their original render order and wire the surrounding text to Fimo; do not
49
+ flatten or replace executable nodes with one additive “Page content” block.
50
+
5
51
  ## Detecting Dynamic Collections (no CMS export)
6
52
 
7
53
  When there is no first-party CMS export (most url-only and website-builder
8
54
  migrations), dynamic content still exists and must be modeled. It shows up two
9
55
  ways:
10
56
 
11
- 1. **Repeated route groups** - many sibling routes share a path prefix
12
- (`/blog/*`, `/vr-games/*`, `/locations/*`). Each group is a collection.
13
- Ignore locale prefixes (`/en-be/`, `/fr/`): a locale segment is never a
14
- collection name.
15
- 2. **Repeated in-page blocks** - a single page renders an array of
16
- structurally-identical items: card grids, list rows, tiles, carousels, logo
17
- walls. Games, locations, team members, testimonials, pricing tiers, FAQs,
18
- news teasers, and feature lists are almost always collections even when the
19
- source renders them inside one page.
20
-
21
- After the source-faithful rebuild, treat **any hardcoded array of 3+ items with
22
- the same shape** as a collection candidate. Do not leave it hardcoded.
57
+ 1. **Repeated route groups** - many sibling routes may share a path prefix
58
+ (`/blog/*`, `/vr-games/*`, `/locations/*`). Treat the group as a collection
59
+ candidate and inspect the route modules, identity, and editability before
60
+ deciding. Ignore locale prefixes (`/en-be/`, `/fr/`): a locale segment is
61
+ never a collection name.
62
+ 2. **Repeated in-page sections** - a single page may render an array of
63
+ structurally-identical items: card grids, list rows, tiles, carousels, or
64
+ logo walls. Read the consuming code and source intent before deciding whether
65
+ the values are a collection, a `blocks` field on a single, labels, or
66
+ application-owned data.
67
+
68
+ Repetition is evidence, not an automatic threshold. Do not convert every array
69
+ or object into content, and do not leave a collection-shaped source structure
70
+ hardcoded after the worker has established that editors should manage it.
23
71
 
24
72
  For each candidate:
25
73
 
@@ -27,35 +75,67 @@ For each candidate:
27
75
  `location`/Locations, `newsPost`/News, `testimonial`/Testimonials,
28
76
  `pricingPlan`/Pricing). Never name a collection after a locale code or a
29
77
  generic page route (no `EnBe`, no `Page`).
30
- - infer fields from the item shape using the Field Mapping below.
78
+ - infer fields from the item shape using the Field Mapping below, while keeping
79
+ source-specific constraints and rationale in the plain-text migration plan.
31
80
  - push the schema, then create one entry per item.
32
81
  - upload each item's image with `fimo assets upload` and store the returned Fimo
33
82
  asset URL in the entry's `media` field (never the source URL or a local
34
83
  `public/` path).
35
84
  - wire the component to render from the collection (Fimo content
36
85
  query/primitives) with a seed/empty state. The hardcoded array is removed.
37
- - record source/generated/imported counts per content type in the manifest.
86
+ - record source/generated/imported counts per content type in the migration
87
+ plan/report.
38
88
 
39
- Genuinely one-off blocks (a single hero, the footer) stay static. If unsure
40
- whether a block is a collection, prefer modeling it as one when items share a
41
- clear repeated shape and could plausibly be edited or extended.
89
+ A genuinely one-off section with no editorial owner may stay in application
90
+ code, but shared chrome - header, footer, navigation, site settings - belongs in
91
+ a singleton content type. If the evidence is ambiguous, preserve the source
92
+ value and record the decision or unresolved question rather than forcing a
93
+ schema merely because a shape repeats.
42
94
 
43
95
  ## Field Mapping
44
96
 
45
- Use source headers, values, and repeated patterns:
97
+ Choose from source semantics and the editing experience, not the source
98
+ container type. An object or array is not by itself a reason to use generic
99
+ JSON.
100
+
101
+ - Editor-authored prose, Markdown, HTML, or other portable formatted content ->
102
+ `richtext`; convert it to the current Fimo richtext contract and render it
103
+ with the corresponding Fimo primitive.
104
+ - Repeatable editor-authored structures such as FAQs, cards, features, pricing
105
+ items, testimonials, and page sections -> `blocks`, with nested richtext,
106
+ media, or references where their semantics require them.
107
+ - Reusable, independently editable categories, tags, authors, and similar
108
+ concepts -> `reference`, or blocks containing references, only when stable
109
+ source records or clear independent management prove the relationship.
110
+ - Opaque or unconstrained metadata, third-party payloads, and intentionally
111
+ non-editor-authored data -> generic `json`, with a concise rationale in the
112
+ content plan and worker report.
113
+
114
+ Then use source headers, values, and repeated patterns:
46
115
 
47
116
  - title/name/heading -> `string`
48
117
  - slug/path/url/permalink -> `string`
49
- - body/content/post/html/description -> `richtext`
118
+ - body/content/post/html/description -> `richtext` when editor-authored prose
50
119
  - excerpt/summary/dek -> `text`
51
- - image/photo/thumbnail/media/asset/file -> `media`
52
- - date/published/created/updated/event time -> `datetime`
120
+ - image/photo/thumbnail/media/asset/file -> `media`, carrying the source alt on
121
+ the media value; never add a separate alt field (`references/media.md`)
122
+ - date/published/created/updated -> `date`; use `datetime` only when the crawled
123
+ values carry a time and a UTC offset, which `datetime` requires
124
+ - event start/end time -> `datetime`
53
125
  - price/amount/rating/order/count -> `number`
54
126
  - featured/draft/published/enabled/archived -> `boolean`
55
- - category/tag/author/reference -> `reference` only when verified, otherwise
56
- `string` or tag-like text
57
-
58
- If unsure, preserve the raw value in the migration artifacts and add a note.
127
+ - repeated section/section stack/nested item list -> `blocks` with one named
128
+ variant per distinct section shape
129
+ - category/tag/author/related item/shared entity -> `reference` to the content
130
+ type that models it (see References below)
131
+ - structured data with no Fimo-native equivalent -> `json`, with the reason
132
+ recorded
133
+
134
+ Keep media as `media`, including inside blocks, and preserve proven relationship
135
+ targets, direction, and cardinality. Do not turn a fixed enum, application-owned
136
+ taxonomy, or accidental string match into a reference. If unsure, preserve the
137
+ exact raw value in the migration artifacts and record the mapping as unresolved
138
+ or incompatible rather than losing content.
59
139
 
60
140
  ## Entries
61
141
 
@@ -65,33 +145,37 @@ For every content type:
65
145
  - preserve slugs
66
146
  - preserve SEO title, description, share image, canonical URL when available
67
147
  - preserve publish status and dates
68
- - preserve authors, categories, and tags
148
+ - preserve authors, categories, and tags as references to their content types
149
+ - preserve each media value's source alt text on the media value itself
69
150
  - convert rich HTML to the current Fimo rich text representation
70
151
  - keep source count, generated count, imported count, and skipped count in the
71
- manifest
152
+ migration plan/report
72
153
 
73
154
  Do not wire a page to remote Fimo content until the matching schema exists and
74
155
  the page has a seed/empty state for local development.
75
156
 
76
157
  ## References
77
158
 
78
- Create references only when:
79
-
80
- - exports contain stable reference IDs
81
- - repeated values clearly match another exported collection
82
- - the user confirms the relationship
159
+ Model categories, tags, authors, related items, shared entities, and repeated
160
+ taxonomies as `reference` fields pointing at their own content type. An editor
161
+ picks an entry; they do not retype a string, maintain a list of raw IDs, or edit
162
+ an opaque JSON array. When the source has no schema for that entity, infer a
163
+ clean editor-facing one from the values themselves - a `Category` with `name`
164
+ and `slug` - instead of leaving the value hardcoded.
83
165
 
84
166
  Use a two-pass import for references:
85
167
 
86
168
  1. import all referenced entries with source IDs and slugs
87
169
  2. resolve reference fields to target IDs/slugs
88
170
 
89
- If reference confidence is low, keep a string/tag field and record an unresolved
90
- item.
171
+ The source still bounds the model. A repeated value is proof of a shared entity;
172
+ it is not proof of a link the source never makes. Keep free text that has no
173
+ shared identity as a string, and leave an unproven relationship unresolved with
174
+ an owner action rather than synthesizing an ID.
91
175
 
92
176
  ## Skips
93
177
 
94
- Skipped fields or entries require a manifest note with:
178
+ Skipped fields or entries require a note in the migration plan/report with:
95
179
 
96
180
  - source location
97
181
  - reason
@@ -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.