fimo 0.7.0-experimental.3 → 0.7.0-experimental.4
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/README.md +2 -3
- package/assets/content-templates/hooks-template.eta +27 -73
- package/assets/content-templates/types-template.eta +1 -4
- package/assets/skills/fimo/SKILL.md +3 -3
- package/assets/skills/fimo/references/assets.md +2 -2
- package/assets/skills/fimo/references/content.md +43 -47
- package/assets/skills/fimo/references/design.md +1 -1
- package/assets/skills/fimo/references/locales.md +0 -8
- package/assets/skills/fimo/references/setup-react-router.md +2 -2
- package/assets/skills/fimo/references/ui.md +1 -1
- package/assets/skills/fimo-cli/SKILL.md +1 -1
- package/assets/skills/fimo-cli/references/assets.md +24 -7
- package/assets/skills/fimo-cli/references/content.md +16 -19
- package/assets/skills/fimo-cli/references/domains.md +1 -1
- package/assets/skills/fimo-cli/references/locales.md +0 -6
- package/assets/skills/fimo-cli/references/media.md +142 -132
- package/assets/skills/fimo-migration/SKILL.md +22 -2
- package/assets/skills/fimo-migration/references/content.md +8 -0
- package/assets/skills/fimo-migration/references/manifest.md +35 -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 +582 -0
- package/assets/skills/fimo-studio/references/custom-domains.md +1 -1
- package/assets/skills/fimo-studio/references/visual-editing.md +5 -3
- package/dist/build/vite/index.d.ts.map +1 -0
- package/dist/build/vite/plugins/content-sync.d.ts.map +1 -0
- package/dist/build/vite/plugins/content-sync.test.d.ts +2 -0
- package/dist/build/vite/plugins/content-sync.test.d.ts.map +1 -0
- package/dist/build/vite/plugins/content-sync.test.js +64 -0
- package/dist/build/vite/plugins/data-id.d.ts.map +1 -0
- package/dist/build/vite/plugins/fimo-config.d.ts.map +1 -0
- package/dist/build/vite/plugins/fimo-config.test.d.ts +2 -0
- package/dist/build/vite/plugins/fimo-config.test.d.ts.map +1 -0
- package/dist/build/vite/plugins/fimo-config.test.js +46 -0
- package/dist/build/vite/plugins/overlay.d.ts.map +1 -0
- package/dist/build/vite/plugins/robots.d.ts.map +1 -0
- package/dist/build/vite/plugins/seo.d.ts.map +1 -0
- package/dist/build/vite/plugins/server-config.d.ts.map +1 -0
- package/dist/build/vite/plugins/sitemap.d.ts.map +1 -0
- package/dist/build/vite/plugins/translations.d.ts +2 -8
- package/dist/build/vite/plugins/translations.d.ts.map +1 -0
- package/dist/build/vite/plugins/translations.js +3 -121
- package/dist/build/vite/plugins/translations.test.d.ts +2 -0
- package/dist/build/vite/plugins/translations.test.d.ts.map +1 -0
- package/dist/build/vite/plugins/translations.test.js +266 -0
- package/dist/cli/bundle.json +2 -3
- package/dist/cli/index.js +117939 -1186
- package/dist/runtime/app/FimoProviders.d.ts +1 -11
- package/dist/runtime/app/FimoProviders.d.ts.map +1 -0
- package/dist/runtime/app/FimoProviders.js +2 -23
- package/dist/runtime/app/FimoScripts.d.ts.map +1 -0
- package/dist/runtime/app/index.d.ts.map +1 -0
- package/dist/runtime/app/prefetch.d.ts.map +1 -0
- package/dist/runtime/astro/index.d.ts +2 -0
- package/dist/runtime/astro/index.d.ts.map +1 -0
- package/dist/runtime/astro/index.js +3 -0
- package/dist/runtime/astro/server.d.ts +3 -0
- package/dist/runtime/astro/server.d.ts.map +1 -0
- package/dist/runtime/astro/server.js +6 -0
- package/dist/runtime/content/DataSourcesProvider.d.ts.map +1 -0
- package/dist/runtime/content/RefreshContentProvider.d.ts.map +1 -0
- package/dist/runtime/content/RefreshContentProvider.test.d.ts +2 -0
- package/dist/runtime/content/RefreshContentProvider.test.d.ts.map +1 -0
- package/dist/runtime/content/RefreshContentProvider.test.js +33 -0
- package/dist/runtime/content/parseCollectionResponse.d.ts.map +1 -0
- package/dist/runtime/content/parseCollectionResponse.test.d.ts +2 -0
- package/dist/runtime/content/parseCollectionResponse.test.d.ts.map +1 -0
- package/dist/runtime/content/parseCollectionResponse.test.js +20 -0
- package/dist/runtime/content/utils/retrieve-data-sources.d.ts +0 -1
- package/dist/runtime/content/utils/retrieve-data-sources.d.ts.map +1 -0
- package/dist/runtime/content/utils/retrieve-data-sources.js +4 -27
- package/dist/runtime/core/AppErrorBoundary.d.ts.map +1 -0
- package/dist/runtime/core/ViteLifecycles.d.ts.map +1 -0
- package/dist/runtime/i18n/FimoLocaleContext.d.ts.map +1 -0
- package/dist/runtime/i18n/FimoLocaleContext.js +1 -0
- package/dist/runtime/i18n/locale.d.ts.map +1 -0
- package/dist/runtime/i18n/locale.test.d.ts +2 -0
- package/dist/runtime/i18n/locale.test.d.ts.map +1 -0
- package/dist/runtime/i18n/locale.test.js +58 -0
- package/dist/runtime/iframe/ConsoleErrorProvider.d.ts.map +1 -0
- package/dist/runtime/iframe/ScreenshotProvider.d.ts.map +1 -0
- package/dist/runtime/iframe/runtime/overlay-hmr.d.ts.map +1 -0
- package/dist/runtime/iframe/runtime/overlay-hmr.js +0 -3
- package/dist/runtime/iframe/runtime/overlay-runtime.d.ts.map +1 -0
- package/dist/runtime/index.d.ts +0 -3
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +0 -2
- package/dist/runtime/next/FimoNextProviders.d.ts +24 -0
- package/dist/runtime/next/FimoNextProviders.d.ts.map +1 -0
- package/dist/runtime/next/FimoNextProviders.js +20 -0
- package/dist/runtime/next/FimoNextScripts.d.ts +10 -0
- package/dist/runtime/next/FimoNextScripts.d.ts.map +1 -0
- package/dist/runtime/next/FimoNextScripts.js +19 -0
- package/dist/runtime/next/index.d.ts +14 -0
- package/dist/runtime/next/index.d.ts.map +1 -0
- package/dist/runtime/next/index.js +14 -0
- package/dist/runtime/next/server.d.ts +2 -0
- package/dist/runtime/next/server.d.ts.map +1 -0
- package/dist/runtime/next/server.js +4 -0
- package/dist/runtime/nuxt/composables.d.ts +9 -0
- package/dist/runtime/nuxt/composables.d.ts.map +1 -0
- package/dist/runtime/nuxt/composables.js +57 -0
- package/dist/runtime/nuxt/index.d.ts +3 -0
- package/dist/runtime/nuxt/index.d.ts.map +1 -0
- package/dist/runtime/nuxt/index.js +6 -0
- package/dist/runtime/nuxt/server.d.ts +3 -0
- package/dist/runtime/nuxt/server.d.ts.map +1 -0
- package/dist/runtime/nuxt/server.js +6 -0
- package/dist/runtime/paths/get-fimo-paths.d.ts.map +1 -0
- package/dist/runtime/paths/get-fimo-paths.js +5 -15
- package/dist/runtime/paths/index.d.ts.map +1 -0
- package/dist/runtime/paths/types.d.ts.map +1 -0
- package/dist/runtime/primitives/components/Boolean.d.ts.map +1 -0
- package/dist/runtime/primitives/components/Date.d.ts.map +1 -0
- package/dist/runtime/primitives/components/Image.d.ts.map +1 -0
- package/dist/runtime/primitives/components/RichText.d.ts.map +1 -0
- package/dist/runtime/primitives/components/StaticImage.d.ts.map +1 -0
- package/dist/runtime/primitives/components/Text.d.ts.map +1 -0
- package/dist/runtime/primitives/components/Video.d.ts.map +1 -0
- package/dist/runtime/primitives/components/index.d.ts.map +1 -0
- package/dist/runtime/primitives/index.d.ts.map +1 -0
- package/dist/runtime/primitives/labels-hook.d.ts +33 -0
- package/dist/runtime/primitives/labels-hook.d.ts.map +1 -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.d.ts.map +1 -0
- package/dist/runtime/primitives/labels-store.js +60 -0
- package/dist/runtime/primitives/labels-store.test.d.ts +2 -0
- package/dist/runtime/primitives/labels-store.test.d.ts.map +1 -0
- package/dist/runtime/primitives/labels-store.test.js +66 -0
- package/dist/runtime/primitives/lib/image-optimization.d.ts.map +1 -0
- package/dist/runtime/primitives/lib/index.d.ts.map +1 -0
- package/dist/runtime/primitives/lib/primitives.d.ts +2 -2
- package/dist/runtime/primitives/lib/primitives.d.ts.map +1 -0
- package/dist/runtime/primitives/lib/query.d.ts +3 -5
- package/dist/runtime/primitives/lib/query.d.ts.map +1 -0
- package/dist/runtime/primitives/lib/template.d.ts.map +1 -0
- package/dist/runtime/primitives/lib/useFimoLiveValue.d.ts +5 -3
- package/dist/runtime/primitives/lib/useFimoLiveValue.d.ts.map +1 -0
- package/dist/runtime/primitives/lib/useFimoLiveValue.js +11 -4
- package/dist/runtime/primitives/public-surface.test.d.ts +2 -0
- package/dist/runtime/primitives/public-surface.test.d.ts.map +1 -0
- package/dist/runtime/primitives/public-surface.test.js +45 -0
- package/dist/runtime/primitives/translations.d.ts +1 -27
- package/dist/runtime/primitives/translations.d.ts.map +1 -0
- package/dist/runtime/primitives/translations.js +7 -85
- package/dist/runtime/react/FimoSpaProviders.d.ts +36 -0
- package/dist/runtime/react/FimoSpaProviders.d.ts.map +1 -0
- package/dist/runtime/react/FimoSpaProviders.js +63 -0
- package/dist/runtime/react/index.d.ts +33 -0
- package/dist/runtime/react/index.d.ts.map +1 -0
- package/dist/runtime/react/index.js +39 -0
- package/dist/runtime/react-router/index.d.ts.map +1 -0
- package/dist/runtime/react-router/navigation-utils.d.ts.map +1 -0
- package/dist/runtime/react-router/navigation.d.ts.map +1 -0
- package/dist/runtime/react-router/navigation.test.d.ts +2 -0
- package/dist/runtime/react-router/navigation.test.d.ts.map +1 -0
- package/dist/runtime/react-router/navigation.test.js +35 -0
- package/dist/runtime/react-router/routes.d.ts.map +1 -0
- package/dist/runtime/react-router/routes.test.d.ts +2 -0
- package/dist/runtime/react-router/routes.test.d.ts.map +1 -0
- package/dist/runtime/react-router/routes.test.js +67 -0
- package/dist/runtime/remix/FimoRemixProviders.d.ts +16 -0
- package/dist/runtime/remix/FimoRemixProviders.d.ts.map +1 -0
- package/dist/runtime/remix/FimoRemixProviders.js +12 -0
- package/dist/runtime/remix/FimoRemixScripts.d.ts +10 -0
- package/dist/runtime/remix/FimoRemixScripts.d.ts.map +1 -0
- package/dist/runtime/remix/FimoRemixScripts.js +19 -0
- package/dist/runtime/remix/index.d.ts +12 -0
- package/dist/runtime/remix/index.d.ts.map +1 -0
- package/dist/runtime/remix/index.js +11 -0
- package/dist/runtime/remix/server.d.ts +2 -0
- package/dist/runtime/remix/server.d.ts.map +1 -0
- package/dist/runtime/remix/server.js +2 -0
- package/dist/runtime/routing/AppResetScrollOnNavigate.d.ts.map +1 -0
- package/dist/runtime/routing/AppRoutesProvider.d.ts.map +1 -0
- package/dist/runtime/seo/buildSeoForPath.d.ts +3 -1
- package/dist/runtime/seo/buildSeoForPath.d.ts.map +1 -0
- package/dist/runtime/seo/buildSeoForPath.js +1 -4
- package/dist/runtime/seo/htmlProps.d.ts.map +1 -0
- package/dist/runtime/seo/index.d.ts.map +1 -0
- package/dist/runtime/seo/resolver.d.ts.map +1 -0
- package/dist/runtime/shared/display-routes.d.ts +14 -0
- package/dist/runtime/shared/display-routes.d.ts.map +1 -0
- package/dist/runtime/shared/display-routes.js +25 -0
- package/dist/runtime/shared/fimo-config.server.d.ts.map +1 -0
- package/dist/runtime/shared/fimo-config.server.js +1 -0
- package/dist/runtime/shared/fimo-config.types.d.ts +2 -0
- package/dist/runtime/shared/fimo-config.types.d.ts.map +1 -0
- package/dist/runtime/shared/i18n-messages.d.ts +29 -0
- package/dist/runtime/shared/i18n-messages.d.ts.map +1 -0
- package/dist/runtime/shared/i18n-messages.js +79 -0
- package/dist/runtime/shared/i18n-messages.test.d.ts +2 -0
- package/dist/runtime/shared/i18n-messages.test.d.ts.map +1 -0
- package/dist/runtime/shared/i18n-messages.test.js +39 -0
- package/dist/runtime/shared/labels-fetch.pure.d.ts +17 -0
- package/dist/runtime/shared/labels-fetch.pure.d.ts.map +1 -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.d.ts.map +1 -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.d.ts.map +1 -0
- package/dist/runtime/shared/labels-t.pure.js +10 -0
- package/dist/runtime/svelte/index.d.ts +3 -0
- package/dist/runtime/svelte/index.d.ts.map +1 -0
- package/dist/runtime/svelte/index.js +7 -0
- package/dist/runtime/svelte/server.d.ts +3 -0
- package/dist/runtime/svelte/server.d.ts.map +1 -0
- package/dist/runtime/svelte/server.js +6 -0
- package/dist/runtime/t/OptionalTracking.d.ts.map +1 -0
- package/dist/runtime/t/OptionalTracking.test.d.ts +2 -0
- package/dist/runtime/t/OptionalTracking.test.d.ts.map +1 -0
- package/dist/runtime/t/OptionalTracking.test.js +11 -0
- package/dist/runtime/t/Pageview.d.ts.map +1 -0
- package/dist/runtime/templates.d.ts.map +1 -0
- package/dist/runtime/vue/index.d.ts +3 -0
- package/dist/runtime/vue/index.d.ts.map +1 -0
- package/dist/runtime/vue/index.js +5 -0
- package/dist/runtime/vue/server.d.ts +3 -0
- package/dist/runtime/vue/server.d.ts.map +1 -0
- package/dist/runtime/vue/server.js +6 -0
- package/dist/runtime/wrapped/FimoFileLink.d.ts +17 -0
- package/dist/runtime/wrapped/FimoFileLink.d.ts.map +1 -0
- package/dist/runtime/wrapped/FimoFileLink.js +19 -0
- package/dist/runtime/wrapped/FimoMediaImage.d.ts +14 -0
- package/dist/runtime/wrapped/FimoMediaImage.d.ts.map +1 -0
- package/dist/runtime/wrapped/FimoMediaImage.js +20 -0
- package/dist/runtime/wrapped/FimoMediaVideo.d.ts +14 -0
- package/dist/runtime/wrapped/FimoMediaVideo.d.ts.map +1 -0
- package/dist/runtime/wrapped/FimoMediaVideo.js +20 -0
- package/dist/runtime/wrapped/FimoRichTextBlock.d.ts +23 -0
- package/dist/runtime/wrapped/FimoRichTextBlock.d.ts.map +1 -0
- package/dist/runtime/wrapped/FimoRichTextBlock.js +22 -0
- package/dist/runtime/wrapped/FimoText.d.ts +22 -0
- package/dist/runtime/wrapped/FimoText.d.ts.map +1 -0
- package/dist/runtime/wrapped/FimoText.js +20 -0
- package/dist/runtime/wrapped/WrappedContentContext.d.ts +28 -0
- package/dist/runtime/wrapped/WrappedContentContext.d.ts.map +1 -0
- package/dist/runtime/wrapped/WrappedContentContext.js +30 -0
- package/dist/runtime/wrapped/WrappedProviders.d.ts +33 -0
- package/dist/runtime/wrapped/WrappedProviders.d.ts.map +1 -0
- package/dist/runtime/wrapped/WrappedProviders.js +101 -0
- package/dist/runtime/wrapped/dom.d.ts +4 -0
- package/dist/runtime/wrapped/dom.d.ts.map +1 -0
- package/dist/runtime/wrapped/dom.js +23 -0
- package/dist/runtime/wrapped/dom.test.d.ts +2 -0
- package/dist/runtime/wrapped/dom.test.d.ts.map +1 -0
- package/dist/runtime/wrapped/dom.test.js +16 -0
- package/dist/runtime/wrapped/server.d.ts +77 -0
- package/dist/runtime/wrapped/server.d.ts.map +1 -0
- package/dist/runtime/wrapped/server.js +237 -0
- package/dist/runtime/wrapped/server.test.d.ts +2 -0
- package/dist/runtime/wrapped/server.test.d.ts.map +1 -0
- package/dist/runtime/wrapped/server.test.js +91 -0
- package/dist/scripts/apply-wrap-templates.d.ts +61 -0
- package/dist/scripts/apply-wrap-templates.js +132 -0
- package/dist/scripts/apply-wrap-templates.test.js +199 -0
- package/dist/scripts/apply-wrap.d.ts +46 -0
- package/dist/scripts/apply-wrap.js +278 -0
- package/dist/scripts/apply-wrap.test.d.ts +1 -0
- package/dist/scripts/apply-wrap.test.js +226 -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 +32 -0
- package/dist/scripts/cms/example-content.js +87 -0
- package/dist/scripts/cms/example-content.test.d.ts +1 -0
- package/dist/scripts/cms/example-content.test.js +57 -0
- package/dist/scripts/cms/strapi/detect.d.ts +2 -0
- package/dist/scripts/cms/strapi/detect.js +185 -0
- package/dist/scripts/cms/strapi/detect.test.d.ts +1 -0
- package/dist/scripts/cms/strapi/detect.test.js +56 -0
- package/dist/scripts/cms/strapi/index.d.ts +3 -0
- package/dist/scripts/cms/strapi/index.js +15 -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/list-source.test.d.ts +1 -0
- package/dist/scripts/cms/strapi/list-source.test.js +33 -0
- package/dist/scripts/cms/strapi/schema-map.d.ts +9 -0
- package/dist/scripts/cms/strapi/schema-map.js +138 -0
- package/dist/scripts/cms/strapi/schema-map.test.d.ts +1 -0
- package/dist/scripts/cms/strapi/schema-map.test.js +87 -0
- package/dist/scripts/cms/types.d.ts +76 -0
- package/dist/scripts/cms/types.js +11 -0
- package/dist/scripts/detect-framework.d.ts +39 -0
- package/dist/scripts/detect-framework.js +133 -0
- package/dist/scripts/detect-framework.test.d.ts +1 -0
- package/dist/scripts/detect-framework.test.js +122 -0
- package/dist/scripts/draft-rows.d.ts +19 -0
- package/dist/scripts/draft-rows.js +135 -0
- package/dist/scripts/draft-rows.test.d.ts +1 -0
- package/dist/scripts/draft-rows.test.js +113 -0
- package/dist/scripts/draft-schemas.d.ts +27 -0
- package/dist/scripts/draft-schemas.js +188 -0
- package/dist/scripts/draft-schemas.test.d.ts +1 -0
- package/dist/scripts/draft-schemas.test.js +152 -0
- package/dist/scripts/frameworks/astro/routes.d.ts +3 -0
- package/dist/scripts/frameworks/astro/routes.js +55 -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 +70 -0
- package/dist/scripts/frameworks/discover.js +171 -0
- package/dist/scripts/frameworks/next/rewire.d.ts +30 -0
- package/dist/scripts/frameworks/next/rewire.js +258 -0
- package/dist/scripts/frameworks/next/rewire.test.d.ts +1 -0
- package/dist/scripts/frameworks/next/rewire.test.js +134 -0
- package/dist/scripts/frameworks/next/routes.d.ts +17 -0
- package/dist/scripts/frameworks/next/routes.js +134 -0
- package/dist/scripts/frameworks/next/routes.test.d.ts +1 -0
- package/dist/scripts/frameworks/next/routes.test.js +64 -0
- package/dist/scripts/frameworks/next/wiring.d.ts +26 -0
- package/dist/scripts/frameworks/next/wiring.js +163 -0
- package/dist/scripts/frameworks/next/wiring.test.d.ts +1 -0
- package/dist/scripts/frameworks/next/wiring.test.js +146 -0
- package/dist/scripts/frameworks/nuxt/routes.d.ts +3 -0
- package/dist/scripts/frameworks/nuxt/routes.js +54 -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 +50 -0
- package/dist/scripts/frameworks/sveltekit/routes.d.ts +3 -0
- package/dist/scripts/frameworks/sveltekit/routes.js +50 -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 +15 -0
- package/dist/scripts/frameworks/vite/routes.js +93 -0
- package/dist/scripts/frameworks/vite/routes.test.d.ts +1 -0
- package/dist/scripts/frameworks/vite/routes.test.js +73 -0
- package/dist/scripts/frameworks/vite/wiring.d.ts +10 -0
- package/dist/scripts/frameworks/vite/wiring.js +99 -0
- package/dist/scripts/frameworks/vite/wiring.test.d.ts +1 -0
- package/dist/scripts/frameworks/vite/wiring.test.js +88 -0
- package/dist/scripts/generated-types.test.d.ts +1 -0
- package/dist/scripts/generated-types.test.js +212 -0
- package/dist/scripts/lib/validation-report.d.ts +1 -0
- package/dist/scripts/lib/validation-report.js +3 -0
- package/dist/scripts/lint-translation-keys.test.d.ts +1 -0
- package/dist/scripts/lint-translation-keys.test.js +16 -0
- package/dist/scripts/render-parity/capture.d.ts +56 -0
- package/dist/scripts/render-parity/capture.js +366 -0
- package/dist/scripts/render-parity/capture.test.d.ts +1 -0
- package/dist/scripts/render-parity/capture.test.js +306 -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/compare.test.d.ts +1 -0
- package/dist/scripts/render-parity/compare.test.js +98 -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/normalize-html.test.d.ts +1 -0
- package/dist/scripts/render-parity/normalize-html.test.js +58 -0
- package/dist/scripts/render-parity/types.d.ts +41 -0
- package/dist/scripts/render-parity/types.js +1 -0
- package/dist/scripts/resolve-routes.js +1 -1
- package/dist/scripts/scan-wrappable.d.ts +196 -0
- package/dist/scripts/scan-wrappable.js +1221 -0
- package/dist/scripts/scan-wrappable.test.d.ts +1 -0
- package/dist/scripts/scan-wrappable.test.js +502 -0
- package/dist/scripts/sync-schemas.test.d.ts +1 -0
- package/dist/scripts/sync-schemas.test.js +124 -0
- package/dist/scripts/validate-route-metadata.js +11 -0
- package/dist/scripts/validate-route-metadata.test.d.ts +1 -0
- package/dist/scripts/validate-route-metadata.test.js +116 -0
- package/dist/scripts/validate-schemas.test.d.ts +1 -0
- package/dist/scripts/validate-schemas.test.js +263 -0
- package/package.json +85 -20
- package/scripts/add-ext.mjs +47 -0
- package/scripts/bump-version.mjs +58 -0
- package/scripts/bundle-cli.mjs +123 -0
- package/scripts/install-cli.mjs +36 -0
- package/scripts/lib/channels.mjs +70 -0
- package/scripts/lib/dev-release-state.mjs +44 -0
- package/scripts/lib/dev-release-state.test.ts +36 -0
- package/scripts/lib/postinstall-onboarding.test.ts +82 -0
- package/scripts/lib/release-core.mjs +225 -0
- package/scripts/lib/release-core.test.ts +147 -0
- package/scripts/migration-qa-gate.test.ts +155 -0
- package/scripts/publish-npm.mjs +180 -0
- package/templates/react-router/package.json +7 -10
- package/templates/react-router/src/pages/Index.tsx +1 -1
- package/dist/runtime/content/client/createContentClient.d.ts +0 -5
- package/dist/runtime/content/client/createContentClient.js +0 -300
- package/dist/runtime/content/client/createSingletonClient.d.ts +0 -5
- package/dist/runtime/content/client/createSingletonClient.js +0 -108
- package/dist/runtime/content/client/internal.d.ts +0 -44
- package/dist/runtime/content/client/internal.js +0 -236
- package/dist/runtime/content/client/types.d.ts +0 -136
- package/dist/runtime/content/client/useQueryLocale.d.ts +0 -2
- package/dist/runtime/content/client/useQueryLocale.js +0 -6
- /package/dist/{runtime/content/client/types.js → scripts/apply-wrap-templates.test.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -49,8 +49,7 @@ Manage content, schemas, media, and labels from the CLI:
|
|
|
49
49
|
```bash
|
|
50
50
|
fimo schemas push # sync your content models
|
|
51
51
|
fimo entries list # browse content
|
|
52
|
-
fimo assets upload <file> # add
|
|
53
|
-
fimo image generate --prompt "..." # create an image with AI
|
|
52
|
+
fimo assets upload <file> # add media (or `fimo assets generate` with AI)
|
|
54
53
|
fimo labels list # manage labels and localized copy
|
|
55
54
|
```
|
|
56
55
|
|
|
@@ -86,4 +85,4 @@ fimo domains add example.com
|
|
|
86
85
|
|
|
87
86
|
## Documentation
|
|
88
87
|
|
|
89
|
-
Full documentation lives at **[fimo.ai
|
|
88
|
+
Full documentation lives at **[docs.fimo.ai](https://docs.fimo.ai)**. Run `fimo --help` to see every command.
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// AUTO-GENERATED ⚠️ – do not edit by hand
|
|
12
12
|
import { <% if (!model.isSingleton) { %>useInfiniteQuery, <% } %>useSuspenseQuery, useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
13
13
|
<% if (!model.isSingleton) { -%>
|
|
14
|
-
import type { InfiniteData, UseInfiniteQueryResult, UseQueryResult
|
|
14
|
+
import type { InfiniteData, UseInfiniteQueryResult, UseQueryResult } from "@tanstack/react-query";
|
|
15
15
|
<% } -%>
|
|
16
16
|
import { FimoString, FimoMedia, FimoBoolean, FimoRichText, useLocale<% if (!model.isSingleton) { %>, parseCollectionResponse<% } %> } from "fimo/ui";
|
|
17
17
|
// @ts-ignore - virtual module provided by Fimo's Vite plugin
|
|
@@ -37,21 +37,15 @@ export type { <%= model.pascal %>, <%= model.pascal %>Fields, <%= model.pascal %
|
|
|
37
37
|
*/
|
|
38
38
|
export function wrapWithSource(entry: Record<string, any>): <%= model.pascal %> {
|
|
39
39
|
const id = entry.id;
|
|
40
|
-
const
|
|
41
|
-
const documentId = entry.documentId ?? id;
|
|
42
|
-
const locale = entry.locale ?? defaultLocale();
|
|
43
|
-
const sourcePrefix = `<%= model.pascal %>.id:${id}:${encodeURIComponent(locale)}`;
|
|
40
|
+
const sourcePrefix = `<%= model.pascal %>.${id}`;
|
|
44
41
|
const entryFimo = entry.__fimo && typeof entry.__fimo === "object" ? entry.__fimo : {};
|
|
45
42
|
|
|
46
43
|
return {
|
|
47
44
|
id,
|
|
48
|
-
|
|
49
|
-
documentId,
|
|
45
|
+
documentId: entry.documentId,
|
|
50
46
|
slug: entry.slug != null ? new FimoString(entry.slug, `${sourcePrefix}.slug`) : entry.slug,
|
|
51
|
-
<% if (
|
|
52
|
-
locale,
|
|
53
|
-
<% } else { -%>
|
|
54
|
-
...(entry.locale ? { locale } : {}),
|
|
47
|
+
<% if (model.localized) { -%>
|
|
48
|
+
locale: entry.locale,
|
|
55
49
|
<% } -%>
|
|
56
50
|
createdAt: entry.createdAt,
|
|
57
51
|
updatedAt: entry.updatedAt,
|
|
@@ -107,11 +101,11 @@ if (model.fields) {
|
|
|
107
101
|
const wrapper = field.target === model.uid ? 'wrapWithSource' : `wrap${field.targetPascal}WithSource`;
|
|
108
102
|
if (field.many) {
|
|
109
103
|
-%>
|
|
110
|
-
<%= key %>: Array.isArray(entry.<%= key %>) ? entry.<%= key %>.map((value: any) =>
|
|
104
|
+
<%= key %>: Array.isArray(entry.<%= key %>) ? entry.<%= key %>.map((value: any) => value != null && typeof value === "object" && typeof value.id === "string" ? <%= wrapper %>(value) : value) : entry.<%= key %>,
|
|
111
105
|
<%
|
|
112
106
|
} else {
|
|
113
107
|
-%>
|
|
114
|
-
<%= key %>:
|
|
108
|
+
<%= key %>: entry.<%= key %> != null && typeof entry.<%= key %> === "object" && typeof entry.<%= key %>.id === "string" ? <%= wrapper %>(entry.<%= key %>) : entry.<%= key %>,
|
|
115
109
|
<%
|
|
116
110
|
}
|
|
117
111
|
break;
|
|
@@ -127,23 +121,6 @@ if (model.fields) {
|
|
|
127
121
|
} as <%= model.pascal %>;
|
|
128
122
|
}
|
|
129
123
|
|
|
130
|
-
interface PopulatedEntryRecord extends Record<string, unknown> {
|
|
131
|
-
id: string;
|
|
132
|
-
__fimo: { contentType: string };
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function isPopulatedEntry(value: unknown): value is PopulatedEntryRecord {
|
|
136
|
-
if (value == null || typeof value !== "object") {
|
|
137
|
-
return false;
|
|
138
|
-
}
|
|
139
|
-
const entry = value as Record<string, unknown>;
|
|
140
|
-
const fimo = entry.__fimo;
|
|
141
|
-
return typeof entry.id === "string"
|
|
142
|
-
&& fimo != null
|
|
143
|
-
&& typeof fimo === "object"
|
|
144
|
-
&& typeof (fimo as Record<string, unknown>).contentType === "string";
|
|
145
|
-
}
|
|
146
|
-
|
|
147
124
|
<%
|
|
148
125
|
const hasPolymorphicReferences = model.fields && Object.values(model.fields).some((field) => field.type === 'reference' && Array.isArray(field.targetRefs) && field.targetRefs.length > 0);
|
|
149
126
|
if (hasPolymorphicReferences) {
|
|
@@ -155,9 +132,7 @@ if (hasPolymorphicReferences) {
|
|
|
155
132
|
* (unpopulated) values pass through untouched.
|
|
156
133
|
*/
|
|
157
134
|
function wrapPolymorphic(value: any, wrappers: Record<string, (entry: Record<string, any>) => any>): any {
|
|
158
|
-
if (
|
|
159
|
-
return value;
|
|
160
|
-
}
|
|
135
|
+
if (value == null || typeof value !== "object" || typeof value.id !== "string") return value;
|
|
161
136
|
const contentType = value.__fimo && typeof value.__fimo.contentType === "string" ? value.__fimo.contentType : null;
|
|
162
137
|
const wrapper = contentType ? wrappers[contentType] : undefined;
|
|
163
138
|
if (!wrapper) return value;
|
|
@@ -184,11 +159,6 @@ function useQueryLocale(locale?: string): string {
|
|
|
184
159
|
return locale ?? activeLocale ?? defaultLocale();
|
|
185
160
|
}
|
|
186
161
|
|
|
187
|
-
function withMutationLocale<T extends object>(payload: T, activeLocale: string): T & { locale: string } {
|
|
188
|
-
const locale = (payload as { locale?: string }).locale;
|
|
189
|
-
return { ...payload, locale: locale ?? activeLocale };
|
|
190
|
-
}
|
|
191
|
-
|
|
192
162
|
const LOCALIZED_CONTENT = <%= model.localized ? 'true' : 'false' %>;
|
|
193
163
|
const LOCALIZED_REFERENCE_FIELDS = new Set<string>(<%= JSON.stringify(model.localizedReferenceFields) %>);
|
|
194
164
|
|
|
@@ -202,12 +172,8 @@ function readLocale(
|
|
|
202
172
|
ownerUsesLocale: boolean,
|
|
203
173
|
fallbackLocale = defaultLocale()
|
|
204
174
|
): string | undefined {
|
|
205
|
-
<% if (!model.isSingleton) { -%>
|
|
206
|
-
return options.locale ?? fallbackLocale;
|
|
207
|
-
<% } else { -%>
|
|
208
175
|
const populatesLocalizedTarget = populateFields(options.populate).some((field) => LOCALIZED_REFERENCE_FIELDS.has(field));
|
|
209
176
|
return ownerUsesLocale || populatesLocalizedTarget ? options.locale ?? fallbackLocale : undefined;
|
|
210
|
-
<% } -%>
|
|
211
177
|
}
|
|
212
178
|
|
|
213
179
|
function fimoHeaders(extra?: Record<string, string>): Record<string, string> {
|
|
@@ -236,7 +202,6 @@ function withReadOptions<TPopulate extends <%= model.pascal %>Populate | undefin
|
|
|
236
202
|
function splitWritePayload(payload: Partial<<%= model.pascal %>Input>): Record<string, unknown> {
|
|
237
203
|
const {
|
|
238
204
|
id,
|
|
239
|
-
entryId,
|
|
240
205
|
documentId,
|
|
241
206
|
locale,
|
|
242
207
|
createdAt,
|
|
@@ -288,7 +253,7 @@ export async function getById<TPopulate extends <%= model.pascal %>Populate | un
|
|
|
288
253
|
id: string,
|
|
289
254
|
options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}
|
|
290
255
|
): Promise<<%= model.pascal %>Result<undefined, TPopulate>> {
|
|
291
|
-
const res = await fetch(`${base}${withReadOptions(`/entries/<%= model.uid %>/${id}`, options)}`, { headers: fimoHeaders() });
|
|
256
|
+
const res = await fetch(`${base}${withReadOptions(`/entries/<%= model.uid %>/${id}`, options, false)}`, { headers: fimoHeaders() });
|
|
292
257
|
if (!res.ok) throw new Error(await res.text());
|
|
293
258
|
const data = await res.json();
|
|
294
259
|
return wrapWithSource(data.data) as <%= model.pascal %>Result<undefined, TPopulate>;
|
|
@@ -389,21 +354,18 @@ export async function create(payload: <%= model.pascal %>Input): Promise<<%= mod
|
|
|
389
354
|
}
|
|
390
355
|
|
|
391
356
|
export async function update(id: string, payload: Partial<<%= model.pascal %>Input>): Promise<<%= model.pascal %>> {
|
|
392
|
-
const
|
|
393
|
-
const url = withReadOptions(`/entries/<%= model.uid %>/${id}`, { locale: write.locale });
|
|
394
|
-
const res = await fetch(`${base}${url}`, {
|
|
357
|
+
const res = await fetch(`${base}/entries/<%= model.uid %>/${id}`, {
|
|
395
358
|
method: "PUT",
|
|
396
359
|
headers: fimoHeaders({ "Content-Type": "application/json" }),
|
|
397
|
-
body: JSON.stringify(
|
|
360
|
+
body: JSON.stringify(splitWritePayload(payload))
|
|
398
361
|
});
|
|
399
362
|
if (!res.ok) throw new Error(await res.text());
|
|
400
363
|
const data = await res.json();
|
|
401
364
|
return wrapWithSource(data.data);
|
|
402
365
|
}
|
|
403
366
|
|
|
404
|
-
export async function remove(id: string
|
|
405
|
-
const
|
|
406
|
-
const res = await fetch(`${base}${url}`, { method: "DELETE", headers: fimoHeaders() });
|
|
367
|
+
export async function remove(id: string): Promise<void> {
|
|
368
|
+
const res = await fetch(`${base}/entries/<%= model.uid %>/${id}`, { method: "DELETE", headers: fimoHeaders() });
|
|
407
369
|
if (!res.ok) throw new Error(await res.text());
|
|
408
370
|
}
|
|
409
371
|
<% } else { -%>
|
|
@@ -437,7 +399,7 @@ export async function update(payload: Partial<<%= model.pascal %>Input>): Promis
|
|
|
437
399
|
<% if (!model.isSingleton) { -%>
|
|
438
400
|
const qk = {
|
|
439
401
|
root : ["<%= model.pascal %>"] as const,
|
|
440
|
-
byId : <TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(id: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}) => ["<%= model.pascal %>",
|
|
402
|
+
byId : <TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(id: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}) => ["<%= model.pascal %>", id, options.locale, options.populate] as const,
|
|
441
403
|
bySlug : <TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(slug: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}) => ["<%= model.pascal %>", "slug", slug, options.locale, options.populate] as const,
|
|
442
404
|
byField : <TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(field: string, value: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}) => ["<%= model.pascal %>", field, value, options.locale, options.populate] as const,
|
|
443
405
|
list : (params: <%= model.pascal %>Query) => ["<%= model.pascal %>", params] as const,
|
|
@@ -447,8 +409,8 @@ const qk = {
|
|
|
447
409
|
>(params: InfiniteListQuery<TFields, TPopulate>) => ["<%= model.pascal %>", "infinite", params] as const
|
|
448
410
|
};
|
|
449
411
|
|
|
450
|
-
export function useGetById<TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(id: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {})
|
|
451
|
-
const locale = useQueryLocale(options.locale);
|
|
412
|
+
export function useGetById<TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(id: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}) {
|
|
413
|
+
const locale = readLocale(options, false, useQueryLocale(options.locale));
|
|
452
414
|
const localizedOptions = { ...options, locale };
|
|
453
415
|
return useQuery<<%= model.pascal %>Result<undefined, TPopulate>, Error>({ queryKey: qk.byId(id, localizedOptions), queryFn: () => getById(id, localizedOptions) });
|
|
454
416
|
}
|
|
@@ -513,8 +475,8 @@ export function useInfiniteList<
|
|
|
513
475
|
};
|
|
514
476
|
}
|
|
515
477
|
|
|
516
|
-
export function useSuspenseGetById<TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(id: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {})
|
|
517
|
-
const locale = useQueryLocale(options.locale);
|
|
478
|
+
export function useSuspenseGetById<TPopulate extends <%= model.pascal %>Populate | undefined = undefined>(id: string, options: { locale?: string; populate?: TPopulate; localeFallbacks?: boolean } = {}) {
|
|
479
|
+
const locale = readLocale(options, false, useQueryLocale(options.locale));
|
|
518
480
|
const localizedOptions = { ...options, locale };
|
|
519
481
|
return useSuspenseQuery<<%= model.pascal %>Result<undefined, TPopulate>, Error>({ queryKey: qk.byId(id, localizedOptions), queryFn: () => getById(id, localizedOptions) });
|
|
520
482
|
}
|
|
@@ -546,37 +508,30 @@ export function useSuspenseGet<
|
|
|
546
508
|
|
|
547
509
|
export function useCreate() {
|
|
548
510
|
const qc = useQueryClient();
|
|
549
|
-
const activeLocale = useQueryLocale();
|
|
550
511
|
return useMutation<<%= model.pascal %>, Error, <%= model.pascal %>Input>({
|
|
551
|
-
mutationFn :
|
|
512
|
+
mutationFn : create,
|
|
552
513
|
onSuccess : () => qc.invalidateQueries({ queryKey: qk.root })
|
|
553
514
|
});
|
|
554
515
|
}
|
|
555
516
|
|
|
556
517
|
export function useUpdate() {
|
|
557
518
|
const qc = useQueryClient();
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
mutationFn : ({ id, ...patch }) => update(id, withMutationLocale(patch, activeLocale)),
|
|
519
|
+
return useMutation<<%= model.pascal %>, Error, { id: string } & Partial<<%= model.pascal %>Input>>({
|
|
520
|
+
mutationFn : ({ id, ...patch }) => update(id, patch),
|
|
561
521
|
onSuccess : (_data, vars) => {
|
|
562
522
|
qc.invalidateQueries({ queryKey: qk.root });
|
|
563
|
-
qc.invalidateQueries({ queryKey: qk.byId(vars.id
|
|
523
|
+
qc.invalidateQueries({ queryKey: qk.byId(vars.id) });
|
|
564
524
|
}
|
|
565
525
|
});
|
|
566
526
|
}
|
|
567
527
|
|
|
568
528
|
export function useRemove() {
|
|
569
529
|
const qc = useQueryClient();
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
const { id, locale } = typeof value === "string" ? { id: value, locale: activeLocale } : { ...value, locale: value.locale ?? activeLocale };
|
|
574
|
-
return remove(id, { locale });
|
|
575
|
-
},
|
|
576
|
-
onSuccess : (_data, value) => {
|
|
577
|
-
const { id, locale } = typeof value === "string" ? { id: value, locale: activeLocale } : { ...value, locale: value.locale ?? activeLocale };
|
|
530
|
+
return useMutation<void, Error, string>({
|
|
531
|
+
mutationFn : remove,
|
|
532
|
+
onSuccess : (_data, id) => {
|
|
578
533
|
qc.invalidateQueries({ queryKey: qk.root });
|
|
579
|
-
qc.removeQueries({ queryKey:
|
|
534
|
+
qc.removeQueries({ queryKey: ["<%= model.pascal %>", id], exact: false });
|
|
580
535
|
}
|
|
581
536
|
});
|
|
582
537
|
}
|
|
@@ -600,9 +555,8 @@ export function useSuspenseGet<TPopulate extends <%= model.pascal %>Populate | u
|
|
|
600
555
|
|
|
601
556
|
export function useUpdate() {
|
|
602
557
|
const qc = useQueryClient();
|
|
603
|
-
const activeLocale = useQueryLocale();
|
|
604
558
|
return useMutation<<%= model.pascal %>, Error, Partial<<%= model.pascal %>Input>>({
|
|
605
|
-
mutationFn:
|
|
559
|
+
mutationFn: update,
|
|
606
560
|
onSuccess: () => qc.invalidateQueries({ queryKey: qk.root })
|
|
607
561
|
});
|
|
608
562
|
}
|
|
@@ -33,13 +33,10 @@ export interface <%= model.pascal %>FimoMeta {
|
|
|
33
33
|
|
|
34
34
|
export interface <%= model.pascal %> extends WithReferences<<%= model.pascal %>References> {
|
|
35
35
|
id: string;
|
|
36
|
-
entryId: string;
|
|
37
36
|
documentId: string;
|
|
38
37
|
slug: FimoString;
|
|
39
|
-
<% if (
|
|
38
|
+
<% if (model.localized) { -%>
|
|
40
39
|
locale: string;
|
|
41
|
-
<% } else { -%>
|
|
42
|
-
locale?: string;
|
|
43
40
|
<% } -%>
|
|
44
41
|
createdAt: string;
|
|
45
42
|
updatedAt: string;
|
|
@@ -14,7 +14,7 @@ You are writing code in a Fimo project — a content + media + forms + analytics
|
|
|
14
14
|
|
|
15
15
|
This skill is version-locked to this project's installed `fimo` package — the shapes here match what your code can actually use.
|
|
16
16
|
|
|
17
|
-
For CLI commands and workflows (creating a project, pushing schemas/forms, deploying, managing labels, etc.), the **`fimo-cli`** skill is the source of truth. Run every CLI command as `npx fimo
|
|
17
|
+
For CLI commands and workflows (creating a project, pushing schemas/forms, deploying, managing labels, etc.), the **`fimo-cli`** skill is the source of truth. Run every CLI command as `npx fimo <command>` when the project declares a `fimo` dependency (it pins the version matching the project's backend); otherwise use `npx fimo@latest`. If `fimo-cli` isn't loaded for your AI tool, register it with `npx fimo skills install --mode=copy`.
|
|
18
18
|
|
|
19
19
|
## Critical: NEVER hardcode user-facing things
|
|
20
20
|
|
|
@@ -43,7 +43,7 @@ Workflow / CLI-side concerns (pushing schemas, generating images, managing label
|
|
|
43
43
|
## Decision Tree (specific tasks)
|
|
44
44
|
|
|
45
45
|
- **Setting up Fimo in a new project** — pick the framework:
|
|
46
|
-
- React Router framework mode
|
|
46
|
+
- React Router 7 framework mode → `references/setup-react-router.md`
|
|
47
47
|
- Plain Vite + React (or upgrading a legacy v3 project) → `references/setup-plain-vite.md`
|
|
48
48
|
- Writing schema JSON / picking field types / Tiptap richtext → `references/content.md`
|
|
49
49
|
- Writing form JSON / generated form client / form code → `references/forms.md`
|
|
@@ -58,7 +58,7 @@ Workflow / CLI-side concerns (pushing schemas, generating images, managing label
|
|
|
58
58
|
- **Hardcoding content in JSX** — `<h1>My Blog</h1>` + an array of posts in code. Use schemas + entries + `t()`.
|
|
59
59
|
- **Raw HTML for schema content** — `<img src={post.coverImage.url}>` instead of `<Image value={post.coverImage}>`. The `fimo/ui` components carry metadata for inline editing in the admin.
|
|
60
60
|
- **Raw `<a href>` for internal navigation** — causes full page reloads. Use `<FimoLink>` for locale-aware internal links or React Router `<Link>` when intentionally bypassing locale helpers. Reserve `<a>` for external links.
|
|
61
|
-
- **Pulling stock photos from external URLs** — editors can't manage them. Use
|
|
61
|
+
- **Pulling stock photos from external URLs** — editors can't manage them. Use `fimo generate` (CLI).
|
|
62
62
|
- **Editing generated `.ts` files** under `src/schemas/` or `src/forms/` — regenerate them through `fimo validate` or the matching push command.
|
|
63
63
|
- **Writing raw HTML in `richtext` fields** — must be Tiptap JSONContent.
|
|
64
64
|
- **Calling `t()` with a dynamic first argument** — the key must be a string literal so the extractor finds it.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Assets — package surface
|
|
2
2
|
|
|
3
|
-
> For the CLI commands (`fimo assets upload`, `fimo
|
|
3
|
+
> For the CLI commands (`fimo assets upload`, `fimo generate`, folder management) and the "when to generate AI images" workflow rules, see **`fimo-cli/references/assets.md`**.
|
|
4
4
|
|
|
5
5
|
This file covers the **package surface** for working with assets in code: the `media` field value shape, how to render assets with `fimo/ui` components, the URL format.
|
|
6
6
|
|
|
7
7
|
## `media` field value (stored/wire shape)
|
|
8
8
|
|
|
9
|
-
Asset values returned from `fimo assets upload` or
|
|
9
|
+
Asset values returned from `fimo assets upload` or `fimo generate`, and stored in `media` content-type fields:
|
|
10
10
|
|
|
11
11
|
```json
|
|
12
12
|
{
|
|
@@ -34,9 +34,9 @@ Every entry already carries this metadata automatically. Declaring any of them a
|
|
|
34
34
|
schema field is rejected by `fimo schemas push` with a 400 (e.g. `fields.slug: "slug" is
|
|
35
35
|
reserved entry metadata and cannot be used as a content field.`):
|
|
36
36
|
|
|
37
|
-
`id`, `
|
|
37
|
+
`id`, `documentId`, `slug`, `locale`, `createdAt`, `updatedAt`, `__fimo`.
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
Localized entries expose `locale`; non-localized entries omit it. It remains reserved in both schemas.
|
|
40
40
|
|
|
41
41
|
In particular **do not add a `slug` field** — every entry gets a `slug` for free. You still
|
|
42
42
|
pass `slug` inside `data` when _creating an entry_ (see "Entry body shape" below); it just
|
|
@@ -45,16 +45,16 @@ something else (e.g. `handle`, `permalink`).
|
|
|
45
45
|
|
|
46
46
|
## Field types
|
|
47
47
|
|
|
48
|
-
| Type | `data` JSON shape
|
|
49
|
-
| ----------- |
|
|
50
|
-
| `string` | `"..."`
|
|
51
|
-
| `richtext` | Tiptap JSONContent (see below)
|
|
52
|
-
| `number` | `42`
|
|
53
|
-
| `boolean` | `true` / `false`
|
|
54
|
-
| `date` | ISO date string, e.g. `"2026-06-03"`
|
|
55
|
-
| `media` | `{ "source": "local"\|"external", "url": "https://...", "alt": "..." }`
|
|
56
|
-
| `json` | any JSON
|
|
57
|
-
| `reference` | `{ "
|
|
48
|
+
| Type | `data` JSON shape | Use for |
|
|
49
|
+
| ----------- | ------------------------------------------------------------------------------------- | --------------------------------- |
|
|
50
|
+
| `string` | `"..."` | Titles, short text |
|
|
51
|
+
| `richtext` | Tiptap JSONContent (see below) | Blog body, descriptions, articles |
|
|
52
|
+
| `number` | `42` | Counts, quantities |
|
|
53
|
+
| `boolean` | `true` / `false` | Flags |
|
|
54
|
+
| `date` | ISO date string, e.g. `"2026-06-03"` | Publish dates, timestamps |
|
|
55
|
+
| `media` | `{ "source": "local"\|"external", "url": "https://...", "alt": "..." }` | Images, video |
|
|
56
|
+
| `json` | any JSON | Structured metadata |
|
|
57
|
+
| `reference` | `{ "documentId": "..." }`, `null`, or an array of reference objects when `many: true` | References to another schema |
|
|
58
58
|
|
|
59
59
|
A `date` field currently generates as `any` in the TS client, so for typed access (and the `<Date>` component) prefer a `string` field holding an ISO date — which is what the `publishDate` examples below do.
|
|
60
60
|
|
|
@@ -79,7 +79,7 @@ Rules:
|
|
|
79
79
|
- `target` is required and must be the PascalCase schema `uid` of the referenced content type.
|
|
80
80
|
- Omit `many` for a to-one reference. Use `"many": true` for a to-many reference.
|
|
81
81
|
- Self-references are allowed, e.g. a `Category` schema can have `parent: { "type": "reference", "target": "Category" }`.
|
|
82
|
-
- Entry values
|
|
82
|
+
- Entry values store reference objects with the target `documentId`, not row `id` values: `{ "documentId": "..." }`.
|
|
83
83
|
- Do not include `contentType` for normal fixed-target references; the schema's `target` already defines it.
|
|
84
84
|
- Do not add `localized` or field-level `i18n` to a reference. The reference value belongs to the entry variant that stores it.
|
|
85
85
|
- Use `null` for an empty to-one reference and `[]` for an empty to-many reference.
|
|
@@ -92,22 +92,22 @@ Entry payload example:
|
|
|
92
92
|
"data": {
|
|
93
93
|
"slug": "reference-example",
|
|
94
94
|
"title": "Reference example",
|
|
95
|
-
"author": { "
|
|
96
|
-
"contributors": [{ "
|
|
95
|
+
"author": { "documentId": "750e8400-e29b-41d4-a716-446655440000" },
|
|
96
|
+
"contributors": [{ "documentId": "750e8400-e29b-41d4-a716-446655440000" }]
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
## Schema transitions
|
|
102
102
|
|
|
103
|
-
After editing schema JSON, run `fimo schemas push {Uid}` and then `fimo validate`. Push regenerates the schema client and applies the schema change to
|
|
103
|
+
After editing schema JSON, run `fimo schemas push {Uid}` and then `fimo validate`. Push regenerates the schema client and applies the schema change to stored content automatically:
|
|
104
104
|
|
|
105
105
|
- Adding fields and changing labels preserve entries.
|
|
106
106
|
- Removing a field removes only that field's values.
|
|
107
107
|
- A one-to-many reference change wraps each existing reference in an array.
|
|
108
108
|
- A many-to-one change, reference target change, scalar type change, or scalar/reference change clears only the changed field.
|
|
109
109
|
- Collection-to-singleton removes that type's entries and cleans references to those documents.
|
|
110
|
-
- Singleton-to-collection preserves the existing
|
|
110
|
+
- Singleton-to-collection preserves the existing row.
|
|
111
111
|
|
|
112
112
|
There are no reset or data-loss flags. Do not invent one or promise that incompatible field values survive; the schema change itself selects the behavior above.
|
|
113
113
|
|
|
@@ -176,7 +176,7 @@ Always provide a meaningful `slug` when creating an entry — it appears in URLs
|
|
|
176
176
|
- **Stable** — once an entry is live, changing the slug breaks inbound links. Only update intentionally.
|
|
177
177
|
- If you omit `slug`, the backend generates a random one — never rely on this for content you want to link to.
|
|
178
178
|
|
|
179
|
-
For `media` fields, prefer `source: "local"` with assets uploaded via `fimo assets upload` or generated
|
|
179
|
+
For `media` fields, prefer `source: "local"` with assets uploaded via `fimo assets upload` or generated via `fimo generate` (see `fimo-cli/assets.md`).
|
|
180
180
|
|
|
181
181
|
## Generated React Query hooks
|
|
182
182
|
|
|
@@ -192,10 +192,9 @@ Import from the public schema module, e.g. `import BlogPost from '@/schemas/Blog
|
|
|
192
192
|
```ts
|
|
193
193
|
interface BlogPost {
|
|
194
194
|
id: string;
|
|
195
|
-
entryId: string;
|
|
196
195
|
documentId: string;
|
|
197
196
|
slug: FimoString;
|
|
198
|
-
locale: string;
|
|
197
|
+
locale: string; // localized schemas only; omitted when i18n.enabled is false
|
|
199
198
|
createdAt: string;
|
|
200
199
|
updatedAt: string;
|
|
201
200
|
__fimo: {
|
|
@@ -214,14 +213,13 @@ Content fields live at the top level. Fimo-owned metadata that is not part of th
|
|
|
214
213
|
|
|
215
214
|
## Localized and shared content
|
|
216
215
|
|
|
217
|
-
Localized content
|
|
216
|
+
Localized content is stored per locale. Generated hooks read the active Fimo locale automatically.
|
|
218
217
|
|
|
219
218
|
When a project has multiple configured locales, create and update each localized content variant explicitly. Use the default locale first, then create non-default variants with the same `documentId` and the target `locale` through the content tools or `fimo entries` commands.
|
|
220
219
|
|
|
221
220
|
For shared content, set `i18n: { "enabled": false }` on the schema and create each entry once. Shared entries:
|
|
222
221
|
|
|
223
|
-
-
|
|
224
|
-
- omit `locale` from raw API responses because there is no localized variant;
|
|
222
|
+
- have no public `locale` property;
|
|
225
223
|
- are returned in every locale context without duplication;
|
|
226
224
|
- ignore locale on owner reads and writes;
|
|
227
225
|
- still use the active/requested locale when a populated reference targets a localized schema.
|
|
@@ -230,7 +228,7 @@ Do not duplicate shared entries across locales or add field-level localization s
|
|
|
230
228
|
|
|
231
229
|
A populated reference whose target has no variant in the requested locale resolves to null. Reads accept an opt-in `localeFallbacks: true` that resolves those to the best available variant instead (project default first), marked by its `locale` field — never implement fallbacks by hand; public reads stay strict unless the option is passed.
|
|
232
230
|
|
|
233
|
-
**Polymorphic references:** a field may declare `targets: ["Post", "Video"]` instead of a single `target` (never both) when one slot genuinely holds different types — mixed feeds, hero blocks, curated collections. Prefer a fixed `target` whenever every value is the same type: fixed fields keep `where` filtering and simpler generated types. Polymorphic values
|
|
231
|
+
**Polymorphic references:** a field may declare `targets: ["Post", "Video"]` instead of a single `target` (never both) when one slot genuinely holds different types — mixed feeds, hero blocks, curated collections. Prefer a fixed `target` whenever every value is the same type: fixed fields keep `where` filtering and simpler generated types. Polymorphic values store `{ contentType, documentId }`; populated values in generated hooks carry a top-level `$type` that narrows the union:
|
|
234
232
|
|
|
235
233
|
```ts
|
|
236
234
|
for (const item of page.featured) {
|
|
@@ -247,21 +245,19 @@ Filtering on polymorphic fields is not supported yet.
|
|
|
247
245
|
|
|
248
246
|
**Generated API:**
|
|
249
247
|
|
|
250
|
-
Collection responses use `id` as the stable identity shared by all locale variants. `locale` selects the variant, and generated hooks use the active Fimo locale when it is omitted. `entryId` identifies the exact variant returned by Fimo and is only for diagnostics or migrations. `documentId` remains a compatibility alias for `id`; reference inputs use `{ id: entry.id }`. Filters and sorts follow the same rule: `where.id` and `sort: "id"` use stable identity, while `entryId` addresses an exact variant.
|
|
251
|
-
|
|
252
248
|
```ts
|
|
253
249
|
// low-level fetch helpers
|
|
254
|
-
getById<TPopulate extends BlogPostPopulate | undefined>(id: string, options?: {
|
|
250
|
+
getById<TPopulate extends BlogPostPopulate | undefined>(id: string, options?: { populate?: TPopulate }): Promise<BlogPostResult<undefined, TPopulate>>
|
|
255
251
|
getBySlug<TPopulate extends BlogPostPopulate | undefined>(slug: string, options?: { populate?: TPopulate }): Promise<BlogPostResult<undefined, TPopulate> | null>
|
|
256
252
|
getByField<TPopulate extends BlogPostPopulate | undefined>(fieldName: string, value: string, options?: { populate?: TPopulate }): Promise<BlogPostResult<undefined, TPopulate> | null>
|
|
257
253
|
list<TFields extends BlogPostFields | undefined, TPopulate extends BlogPostPopulate | undefined>(params?: BlogPostQuery<TFields, TPopulate>): Promise<CollectionPage<BlogPostResult<TFields, TPopulate>>>
|
|
258
254
|
get<TFields extends BlogPostFields | undefined, TPopulate extends BlogPostPopulate | undefined>(params?: BlogPostQuery<TFields, TPopulate>): Promise<BlogPostResult<TFields, TPopulate>[]>
|
|
259
255
|
create(payload: BlogPostInput): Promise<BlogPost>
|
|
260
256
|
update(id: string, payload: Partial<BlogPostInput>): Promise<BlogPost>
|
|
261
|
-
remove(id: string
|
|
257
|
+
remove(id: string): Promise<void>
|
|
262
258
|
|
|
263
259
|
// react-query hooks
|
|
264
|
-
useGetById(id, {
|
|
260
|
+
useGetById(id, { populate? }) // → { data: BlogPostResult<undefined, TPopulate> | undefined, isLoading, ... }
|
|
265
261
|
useGetBySlug(slug, { populate? }) // → { data: BlogPostResult<undefined, TPopulate> | null | undefined, ... } — ideal for /:slug detail routes
|
|
266
262
|
useGetByField(fieldName, value, { populate? })
|
|
267
263
|
useList<TFields, TPopulate>(params?) // → { data: CollectionPage<BlogPostResult<TFields, TPopulate>> | undefined, ... }
|
|
@@ -283,7 +279,7 @@ update(payload: Partial<SettingsInput>): Promise<Settings>
|
|
|
283
279
|
useGet(options?) / useSuspenseGet(options?) / useUpdate()
|
|
284
280
|
```
|
|
285
281
|
|
|
286
|
-
Singleton clients do not expose `create`, `remove`, `getById`, or list queries. Localized singletons have one variant per locale;
|
|
282
|
+
Singleton clients do not expose `create`, `remove`, `getById`, or list queries. Localized singletons have one variant per locale; non-localized singletons have one locale-free row.
|
|
287
283
|
|
|
288
284
|
Choose the collection interface from the UI behavior. Use `useList` when the UI controls a page, and read pagination state from `pageInfo`:
|
|
289
285
|
|
|
@@ -339,10 +335,10 @@ BlogPost.useGet({
|
|
|
339
335
|
```
|
|
340
336
|
|
|
341
337
|
Operators: scalar equality, `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`, `$contains`, `$startsWith`, `$null`.
|
|
342
|
-
Reference field values are reference objects, but reference filters use the target `
|
|
338
|
+
Reference field values are reference objects, but reference filters use the target `documentId` string, for example `where: { author: "750e..." }`; for to-many references that means "contains this target document".
|
|
343
339
|
For to-many references, `$eq` and `$contains` mean membership, `$in` means any listed document is present, `$ne` and `$nin` mean none are present, and `$null: true` means empty or missing. Reference fields cannot be sorted.
|
|
344
340
|
|
|
345
|
-
Use `fields` to keep list payloads small. The API always keeps `id`,
|
|
341
|
+
Use `fields` to keep list payloads small. The API always keeps `id`, and returns only the requested fields beyond that:
|
|
346
342
|
|
|
347
343
|
```tsx
|
|
348
344
|
const { data: summaries = [] } = BlogPost.useGet({
|
|
@@ -350,7 +346,7 @@ const { data: summaries = [] } = BlogPost.useGet({
|
|
|
350
346
|
sort: '-publishedAt',
|
|
351
347
|
limit: 12,
|
|
352
348
|
});
|
|
353
|
-
// summaries: Array<Pick<BlogPost, 'id' | '
|
|
349
|
+
// summaries: Array<Pick<BlogPost, 'id' | 'slug' | 'title' | 'excerpt' | 'coverImage'>>
|
|
354
350
|
```
|
|
355
351
|
|
|
356
352
|
Use `populate` to embed reference targets in read results:
|
|
@@ -360,7 +356,7 @@ const { data: posts = [] } = BlogPost.useGet({
|
|
|
360
356
|
fields: ['slug', 'title', 'author'] as const,
|
|
361
357
|
populate: ['author'] as const,
|
|
362
358
|
});
|
|
363
|
-
// Without populate: post.author is {
|
|
359
|
+
// Without populate: post.author is { documentId: "..." }.
|
|
364
360
|
// With populate: post.author is the target Author entry object, or null.
|
|
365
361
|
```
|
|
366
362
|
|
|
@@ -388,16 +384,16 @@ Populate is depth-one. It only works for reference fields; trying to populate a
|
|
|
388
384
|
|
|
389
385
|
The entry objects a hook returns are **not** plain JS values. The generated client wraps each _trackable_ field in a `fimo/ui` primitive that carries source metadata for inline editing. Which fields wrap, and which stay plain:
|
|
390
386
|
|
|
391
|
-
| Schema field type | Field value you get | Notes
|
|
392
|
-
| ----------------- | ----------------------------------- |
|
|
393
|
-
| `string` | `FimoString` | `extends String` — **not** a primitive `string`
|
|
394
|
-
| `richtext` | `FimoRichText` | Tiptap JSONContent + source metadata
|
|
395
|
-
| `boolean` | `FimoBoolean` | class; `.valueOf()` → `boolean`
|
|
396
|
-
| `media` | `FimoMedia` / `FimoMedia[]` | shape + rendering in `references/assets.md`
|
|
397
|
-
| `number` | `number` | plain — not wrapped
|
|
398
|
-
| `json` | `Record<string, any>` | plain — not wrapped
|
|
399
|
-
| `date` | `any` (raw ISO date string) | not wrapped (`FimoDate` is not emitted — see below)
|
|
400
|
-
| `reference` | `FimoReference` / `FimoReference[]` | reference object(s) with target `
|
|
387
|
+
| Schema field type | Field value you get | Notes |
|
|
388
|
+
| ----------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
389
|
+
| `string` | `FimoString` | `extends String` — **not** a primitive `string` |
|
|
390
|
+
| `richtext` | `FimoRichText` | Tiptap JSONContent + source metadata |
|
|
391
|
+
| `boolean` | `FimoBoolean` | class; `.valueOf()` → `boolean` |
|
|
392
|
+
| `media` | `FimoMedia` / `FimoMedia[]` | shape + rendering in `references/assets.md` |
|
|
393
|
+
| `number` | `number` | plain — not wrapped |
|
|
394
|
+
| `json` | `Record<string, any>` | plain — not wrapped |
|
|
395
|
+
| `date` | `any` (raw ISO date string) | not wrapped (`FimoDate` is not emitted — see below) |
|
|
396
|
+
| `reference` | `FimoReference` / `FimoReference[]` | reference object(s) with target `documentId`; use `populate` when embedded target rows are needed |
|
|
401
397
|
|
|
402
398
|
Rules of thumb:
|
|
403
399
|
|
|
@@ -438,7 +434,7 @@ export function BlogList() {
|
|
|
438
434
|
return (
|
|
439
435
|
<ul>
|
|
440
436
|
{page.items.map((post) => (
|
|
441
|
-
<li key={
|
|
437
|
+
<li key={post.id}>
|
|
442
438
|
<Text value={post.title} as="h2" />
|
|
443
439
|
<Image value={post.coverImage} width={800} height={400} fit="cover" />
|
|
444
440
|
<RichText value={post.body} className="prose" />
|
|
@@ -455,9 +451,9 @@ For the `<Text>` / `<RichText>` / `<Image>` / `<Date>` components and the rules
|
|
|
455
451
|
## Read path (published app, no auth)
|
|
456
452
|
|
|
457
453
|
```ts
|
|
458
|
-
const res = await fetch(`${import.meta.env.VITE_API_URL}/entries/<typeName>?
|
|
454
|
+
const res = await fetch(`${import.meta.env.VITE_API_URL}/entries/<typeName>?fields=slug,title&limit=12`);
|
|
459
455
|
const { data, meta } = await res.json();
|
|
460
|
-
// data: Entry[] — fields flattened at top level (id,
|
|
456
|
+
// data: Entry[] — fields flattened at top level (id, slug, title, ...)
|
|
461
457
|
// meta: { limit, offset, total, hasMore }
|
|
462
458
|
```
|
|
463
459
|
|
|
@@ -124,7 +124,7 @@ Write into `src/index.css` as shadcn CSS variables, then use `bg-background` / `
|
|
|
124
124
|
- **Treatment:** Full-bleed, contained, overlays, filters
|
|
125
125
|
- **Hero:** Specific direction for hero imagery
|
|
126
126
|
|
|
127
|
-
If the user hasn't supplied images and one is needed,
|
|
127
|
+
If the user hasn't supplied images and one is needed, generate via `fimo generate <model> --prompt "..."` (run `fimo models list` to pick a model, `fimo models show <model>` for its flags) and reuse the returned `url` / `id`. See `references/assets.md`.
|
|
128
128
|
|
|
129
129
|
### Iconography
|
|
130
130
|
|
|
@@ -67,14 +67,6 @@ This helper exists so the Fimo UI route selector, preview navigation, labels, an
|
|
|
67
67
|
|
|
68
68
|
Copyable examples live in `assets/react-router-locales/routes.ts` and `assets/react-router-locales/navigation.tsx`.
|
|
69
69
|
|
|
70
|
-
## Existing Custom Locale Systems
|
|
71
|
-
|
|
72
|
-
Before changing a multilingual app, inspect its locale provider, route table, language switcher, redirects, and current public URLs. Preserve that behavior while migrating.
|
|
73
|
-
|
|
74
|
-
For React Router projects, prefer converging on one locale contract owned by `fimo-config.json`, `fimoRoutes()`, and `FimoLink`. Move existing providers and language-switcher UI into the framework root instead of replacing them or adding a second locale context. Keep route metadata canonical and reuse page modules across locales.
|
|
75
|
-
|
|
76
|
-
If adopting the standard helper would change established public URLs, do not silently rewrite them. Keep the custom router temporarily, pass its resolved locale to `<FimoProviders locale={locale}>`, and ask the user to choose the canonical URLs and redirects before normalizing the route table.
|
|
77
|
-
|
|
78
70
|
## Links
|
|
79
71
|
|
|
80
72
|
Use `FimoLink` for internal links that should preserve or switch locale:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Setup Fimo on React Router
|
|
1
|
+
# Setup Fimo on React Router 7
|
|
2
2
|
|
|
3
3
|
This recipe describes the canonical Fimo + React Router framework-mode setup.
|
|
4
4
|
It mirrors what `fimo init` scaffolds today; you can also apply it to an
|
|
@@ -6,7 +6,7 @@ existing RR project.
|
|
|
6
6
|
|
|
7
7
|
## Prerequisites
|
|
8
8
|
|
|
9
|
-
- Node
|
|
9
|
+
- Node 20+
|
|
10
10
|
- A Fimo project created via `fimo init` (gives you `projectId`,
|
|
11
11
|
`organizationId`, and an `apiUrl`).
|
|
12
12
|
|
|
@@ -42,7 +42,7 @@ The template uses **Vite + React 19 + TypeScript + Tailwind v4 + shadcn/ui + rea
|
|
|
42
42
|
|
|
43
43
|
### Routing
|
|
44
44
|
|
|
45
|
-
- This template uses React Router
|
|
45
|
+
- This template uses React Router v7 framework mode (file-based route config in `src/routes.ts`). Use `<FimoLink>` from `fimo/react-router` for locale-aware internal links, especially in projects with more than one configured locale. Use React Router `<Link>` / `<NavLink>` only when you intentionally do not want Fimo's locale behavior. Never raw `<a href="/...">` for internal navigation because it causes full page reloads.
|
|
46
46
|
- Reserve `<a>` for external links, with `target="_blank" rel="noreferrer"`.
|
|
47
47
|
|
|
48
48
|
### Loading states
|
|
@@ -73,7 +73,7 @@ Load the matching reference when the user's request fires its trigger. Recipes t
|
|
|
73
73
|
- "Add a contact / signup / feedback / newsletter form" → `references/forms.md` (workflow) **+ load `fimo/references/forms.md` for the JSON spec and generated client**
|
|
74
74
|
- "View form submissions / who filled out the contact form / inspect what users sent / how many signups" → `references/forms.md` § Reading submissions
|
|
75
75
|
- "Upload an image / hero / cover / existing media file" → `references/assets.md` (workflow: upload, browse, open, delete) **+ load `fimo/references/assets.md` for the `FimoMedia` shape and rendering**
|
|
76
|
-
- "Generate AI image / video / draft preview / image edit / cover from a prompt" → `references/media.md` (
|
|
76
|
+
- "Generate AI image / video / draft preview / image edit / cover from a prompt" → `references/media.md` (the `fimo generate <model>` surface — recipes, defaults, the one-verb shape) **+ load `fimo/references/assets.md` for the `FimoMedia` shape if you'll plug the result into UI**
|
|
77
77
|
- "Add labels / update static copy / fix missing `t()` values" → `references/labels.md` (workflow) **+ load `fimo/references/labels.md` for the `t()` helper and wrap rules**
|
|
78
78
|
- "Enable locales / configure default locale / route by locale prefix / fix locale route validation" → `references/locales.md` **+ load `fimo/references/locales.md` for code helpers**
|
|
79
79
|
- "What's in this project / show the project structure / describe the project / what schemas does it have / how many routes / project tree / show me what's here" → `references/describe.md`
|