fimo 0.14.0 → 0.15.0-staging.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/README.md +1 -0
  2. package/assets/astro/components/Boolean.astro +14 -0
  3. package/assets/astro/components/Date.astro +23 -0
  4. package/assets/astro/components/Image.astro +79 -0
  5. package/assets/astro/components/Json.astro +14 -0
  6. package/assets/astro/components/RichText.astro +17 -0
  7. package/assets/astro/components/StaticImage.astro +66 -0
  8. package/assets/astro/components/Text.astro +23 -0
  9. package/assets/astro/components/Video.astro +47 -0
  10. package/assets/astro/components/index.d.ts +8 -0
  11. package/assets/astro/components/index.js +8 -0
  12. package/assets/content-templates/shared/server.eta +56 -0
  13. package/assets/content-templates/sveltekit/content.eta +86 -0
  14. package/assets/skills/fimo/SKILL.md +2 -0
  15. package/assets/skills/fimo-cli/SKILL.md +0 -1
  16. package/assets/skills/fimo-cli/references/branches.md +14 -13
  17. package/assets/skills/fimo-cli/references/deploy.md +4 -3
  18. package/assets/skills/fimo-cli/references/describe.md +1 -1
  19. package/assets/skills/fimo-cli/references/init.md +11 -11
  20. package/assets/skills/fimo-cli/references/labels.md +3 -3
  21. package/assets/skills/fimo-cli/references/locales.md +1 -1
  22. package/assets/skills/fimo-cli/references/project-vars-and-secrets.md +1 -1
  23. package/assets/skills/fimo-code/SKILL.md +11 -3
  24. package/assets/skills/fimo-code/references/assets.md +2 -2
  25. package/assets/skills/fimo-code/references/content/clients.md +5 -1
  26. package/assets/skills/fimo-code/references/content.md +3 -1
  27. package/assets/skills/fimo-code/references/frameworks/astro.md +127 -0
  28. package/assets/skills/fimo-code/references/frameworks/compatibility.md +19 -0
  29. package/assets/skills/fimo-code/references/frameworks/hosting.md +15 -3
  30. package/assets/skills/fimo-code/references/frameworks/react-router.md +37 -209
  31. package/assets/skills/fimo-code/references/frameworks/sveltekit.md +110 -0
  32. package/assets/skills/fimo-code/references/frameworks/vite-react.md +35 -166
  33. package/assets/skills/fimo-code/references/labels.md +16 -6
  34. package/assets/skills/fimo-code/references/locales.md +3 -1
  35. package/assets/skills/fimo-code/references/ui.md +19 -15
  36. package/assets/starters/fimo-site/template/.fimo/agents/content-guide/capabilities.yaml +0 -1
  37. package/assets/starters/fimo-site/template/.fimo/agents/site-review/capabilities.yaml +0 -1
  38. package/assets/sveltekit/components/Boolean.svelte +19 -0
  39. package/assets/sveltekit/components/Date.svelte +33 -0
  40. package/assets/sveltekit/components/FimoProvider.svelte +35 -0
  41. package/assets/sveltekit/components/Image.svelte +80 -0
  42. package/assets/sveltekit/components/Json.svelte +18 -0
  43. package/assets/sveltekit/components/Label.svelte +16 -0
  44. package/assets/sveltekit/components/Number.svelte +21 -0
  45. package/assets/sveltekit/components/RichText.svelte +19 -0
  46. package/assets/sveltekit/components/Text.svelte +30 -0
  47. package/assets/sveltekit/components/Video.svelte +37 -0
  48. package/assets/sveltekit/components/index.d.ts +10 -0
  49. package/assets/sveltekit/components/index.js +10 -0
  50. package/dist/build/astro/config.d.ts +4 -0
  51. package/dist/build/astro/config.js +45 -0
  52. package/dist/build/next/config.js +16 -0
  53. package/dist/build/sveltekit/config.d.ts +6 -0
  54. package/dist/build/sveltekit/config.js +8 -0
  55. package/dist/build/sveltekit/data-id.d.ts +3 -0
  56. package/dist/build/sveltekit/data-id.js +171 -0
  57. package/dist/build/sveltekit/vite.d.ts +13 -0
  58. package/dist/build/sveltekit/vite.js +15 -0
  59. package/dist/build/vite/index.js +2 -0
  60. package/dist/build/vite/plugins/data-id.d.ts +9 -0
  61. package/dist/build/vite/plugins/data-id.js +6 -1
  62. package/dist/build/vite/plugins/runtime-env.d.ts +21 -0
  63. package/dist/build/vite/plugins/runtime-env.js +68 -0
  64. package/dist/cli/bundle.json +1 -1
  65. package/dist/cli/index.js +100 -99
  66. package/dist/runtime/app/FimoProviders.d.ts +1 -1
  67. package/dist/runtime/app/FimoProviders.js +11 -5
  68. package/dist/runtime/astro/internal.d.ts +6 -0
  69. package/dist/runtime/astro/internal.js +16 -0
  70. package/dist/runtime/astro/preview.d.ts +14 -0
  71. package/dist/runtime/astro/preview.js +103 -0
  72. package/dist/runtime/astro/render-rich-text.d.ts +2 -0
  73. package/dist/runtime/astro/render-rich-text.js +1 -0
  74. package/dist/runtime/astro/server-runtime.d.ts +3 -0
  75. package/dist/runtime/astro/server-runtime.js +20 -0
  76. package/dist/runtime/astro/server.d.ts +15 -0
  77. package/dist/runtime/astro/server.js +14 -0
  78. package/dist/runtime/content/client/collection-core.d.ts +2 -17
  79. package/dist/runtime/content/client/collection-core.js +15 -8
  80. package/dist/runtime/content/client/core-types.d.ts +96 -0
  81. package/dist/runtime/content/client/core-types.js +1 -0
  82. package/dist/runtime/content/client/internal.d.ts +4 -4
  83. package/dist/runtime/content/client/internal.js +4 -3
  84. package/dist/runtime/content/client/runtime.d.ts +1 -1
  85. package/dist/runtime/content/client/server-content-client.d.ts +3 -3
  86. package/dist/runtime/content/client/server-content-client.js +2 -29
  87. package/dist/runtime/content/client/singleton-core.d.ts +2 -9
  88. package/dist/runtime/content/client/singleton-core.js +9 -4
  89. package/dist/runtime/content/client/types.d.ts +5 -115
  90. package/dist/runtime/content/index.d.ts +3 -3
  91. package/dist/runtime/labels/fetch.js +5 -3
  92. package/dist/runtime/next/client.d.ts +2 -1
  93. package/dist/runtime/next/facade.d.ts +1 -1
  94. package/dist/runtime/next/provider.js +1 -1
  95. package/dist/runtime/next/server-runtime.js +1 -1
  96. package/dist/runtime/next/server.d.ts +5 -4
  97. package/dist/runtime/paths/get-fimo-paths.js +8 -3
  98. package/dist/runtime/preview/bridge.d.ts +8 -0
  99. package/dist/runtime/preview/bridge.js +20 -0
  100. package/dist/runtime/preview/location.d.ts +23 -0
  101. package/dist/runtime/preview/location.js +93 -0
  102. package/dist/runtime/preview/routes.d.ts +10 -0
  103. package/dist/runtime/preview/routes.js +29 -0
  104. package/dist/runtime/primitives/index.d.ts +4 -1
  105. package/dist/runtime/primitives/index.js +1 -0
  106. package/dist/runtime/primitives/lib/image-optimization.d.ts +27 -2
  107. package/dist/runtime/primitives/lib/image-optimization.js +40 -0
  108. package/dist/runtime/primitives/lib/index.d.ts +1 -1
  109. package/dist/runtime/primitives/lib/primitives.d.ts +0 -54
  110. package/dist/runtime/primitives/lib/primitives.js +6 -0
  111. package/dist/runtime/primitives/lib/render-rich-text.d.ts +3 -0
  112. package/dist/runtime/primitives/lib/render-rich-text.js +112 -0
  113. package/dist/runtime/react/primitives/contracts.d.ts +40 -2
  114. package/dist/runtime/react/primitives/renderers/ImageRenderer.js +15 -34
  115. package/dist/runtime/react/primitives/renderers/RichTextRenderer.d.ts +2 -1
  116. package/dist/runtime/react/primitives/renderers/StaticImage.js +13 -30
  117. package/dist/runtime/routing/AppRoutesProvider.js +20 -8
  118. package/dist/runtime/shared/env-identity.d.ts +43 -0
  119. package/dist/runtime/shared/env-identity.js +88 -0
  120. package/dist/runtime/shared/local-runtime-env.d.ts +65 -0
  121. package/dist/runtime/shared/local-runtime-env.js +169 -0
  122. package/dist/runtime/{react-router → shared}/preview-location.d.ts +7 -13
  123. package/dist/runtime/{react-router → shared}/preview-location.js +26 -27
  124. package/dist/runtime/sveltekit/content.d.ts +25 -0
  125. package/dist/runtime/sveltekit/content.js +33 -0
  126. package/dist/runtime/sveltekit/context-contract.d.ts +5 -0
  127. package/dist/runtime/sveltekit/context-contract.js +2 -0
  128. package/dist/runtime/sveltekit/context.d.ts +8 -0
  129. package/dist/runtime/sveltekit/context.js +25 -0
  130. package/dist/runtime/sveltekit/index.d.ts +7 -0
  131. package/dist/runtime/sveltekit/index.js +4 -0
  132. package/dist/runtime/sveltekit/internal.d.ts +6 -0
  133. package/dist/runtime/sveltekit/internal.js +12 -0
  134. package/dist/runtime/sveltekit/labels.d.ts +16 -0
  135. package/dist/runtime/sveltekit/labels.js +13 -0
  136. package/dist/runtime/sveltekit/preview.d.ts +19 -0
  137. package/dist/runtime/sveltekit/preview.js +77 -0
  138. package/dist/runtime/sveltekit/runtime.d.ts +8 -0
  139. package/dist/runtime/sveltekit/runtime.js +17 -0
  140. package/dist/runtime/templates.d.ts +1 -1
  141. package/dist/runtime/templates.js +1 -1
  142. package/dist/runtime/vite/Label.d.ts +13 -0
  143. package/dist/runtime/vite/Label.js +16 -0
  144. package/dist/scripts/extract-translations.js +103 -43
  145. package/dist/scripts/sync-forms.js +1 -1
  146. package/dist/scripts/sync-schemas.js +83 -16
  147. package/package.json +56 -2
  148. package/release.json +2 -2
  149. package/templates/nextjs/_gitignore +1 -0
  150. package/templates/react-router/package.json +1 -1
  151. package/templates/sveltekit/.fimo/config.json +15 -0
  152. package/templates/sveltekit/AGENTS.md +16 -0
  153. package/templates/sveltekit/CLAUDE.md +5 -0
  154. package/templates/sveltekit/_gitignore +16 -0
  155. package/templates/sveltekit/package.json +28 -0
  156. package/templates/sveltekit/pnpm-workspace.yaml +4 -0
  157. package/templates/sveltekit/src/app.html +11 -0
  158. package/templates/sveltekit/src/routes/+layout.server.ts +8 -0
  159. package/templates/sveltekit/src/routes/+layout.svelte +12 -0
  160. package/templates/sveltekit/src/routes/+page.svelte +48 -0
  161. package/templates/sveltekit/svelte.config.js +5 -0
  162. package/templates/sveltekit/tsconfig.json +14 -0
  163. package/templates/sveltekit/vite.config.ts +5 -0
  164. /package/assets/content-templates/{form-template.eta → forms/react.eta} +0 -0
  165. /package/assets/content-templates/{next-client-template.eta → next/client.eta} +0 -0
  166. /package/assets/content-templates/{next-server-template.eta → next/server.eta} +0 -0
  167. /package/assets/content-templates/{hooks-template.eta → react/client.eta} +0 -0
  168. /package/assets/content-templates/{types-template.eta → shared/types.eta} +0 -0
package/README.md CHANGED
@@ -29,6 +29,7 @@ Run the CLI with `npx` — no global install, always the latest:
29
29
  npx fimo@latest login
30
30
  npx fimo@latest init my-site # default React Router scaffold
31
31
  # or: npx fimo@latest init my-next-site --framework nextjs
32
+ # or: npx fimo@latest init my-svelte-site --framework sveltekit
32
33
  cd my-site
33
34
  ```
34
35
 
@@ -0,0 +1,14 @@
1
+ ---
2
+ import { getFimoSource } from 'fimo/astro';
3
+
4
+ interface Props {
5
+ value: { valueOf(): boolean } | null | undefined;
6
+ as?: keyof astroHTML.JSX.IntrinsicElements;
7
+ [key: string]: unknown;
8
+ }
9
+
10
+ const { value, as: Component = 'span', ...props } = Astro.props;
11
+ const source = getFimoSource(value);
12
+ ---
13
+
14
+ {value != null && <Component {...props} data-fimo-source={source}>{String(value.valueOf())}</Component>}
@@ -0,0 +1,23 @@
1
+ ---
2
+ import { getFimoSource } from 'fimo/astro';
3
+
4
+ interface Props {
5
+ value: globalThis.Date | String | string | number | null | undefined;
6
+ locale?: string;
7
+ options?: Intl.DateTimeFormatOptions;
8
+ [key: string]: unknown;
9
+ }
10
+
11
+ const { value, locale, options, ...props } = Astro.props;
12
+ const rawValue = value instanceof String ? value.toString() : value;
13
+ const date = rawValue == null ? null : new globalThis.Date(rawValue as string | number | globalThis.Date);
14
+ const validDate = date && !Number.isNaN(date.getTime()) ? date : null;
15
+ const dateTime = validDate?.toISOString().split('T')[0];
16
+ const content = validDate?.toLocaleDateString(
17
+ locale,
18
+ options ?? { year: 'numeric', month: 'short', day: 'numeric' }
19
+ );
20
+ const source = getFimoSource(value);
21
+ ---
22
+
23
+ {validDate && <time {...props} datetime={dateTime} data-fimo-source={source}>{content}</time>}
@@ -0,0 +1,79 @@
1
+ ---
2
+ import type { FimoMedia } from 'fimo/astro';
3
+ import { getFimoSource } from 'fimo/astro';
4
+
5
+ import {
6
+ mergeAstroImageStyle,
7
+ resolveImagePresentation,
8
+ type ImageFit,
9
+ } from 'fimo/astro/internal';
10
+
11
+ interface Props {
12
+ value: FimoMedia | null | undefined;
13
+ alt?: string;
14
+ quality?: number;
15
+ fit?: ImageFit;
16
+ unoptimized?: boolean;
17
+ overrideSrc?: string;
18
+ width?: string | number;
19
+ height?: string | number;
20
+ sizes?: string;
21
+ srcset?: string;
22
+ srcSet?: string;
23
+ hostSuffixes?: readonly string[];
24
+ style?: string | Record<string, unknown>;
25
+ [key: string]: unknown;
26
+ }
27
+
28
+ const {
29
+ value,
30
+ alt,
31
+ quality,
32
+ fit,
33
+ unoptimized,
34
+ overrideSrc,
35
+ width,
36
+ height,
37
+ sizes,
38
+ srcset,
39
+ srcSet,
40
+ hostSuffixes,
41
+ style,
42
+ ...props
43
+ } = Astro.props;
44
+ const image = value
45
+ ? resolveImagePresentation({
46
+ src: value.url,
47
+ alt: alt ?? value.alt,
48
+ mediaWidth: value.width,
49
+ mediaHeight: value.height,
50
+ quality,
51
+ fit,
52
+ unoptimized,
53
+ overrideSrc,
54
+ width,
55
+ height,
56
+ sizes,
57
+ srcSet: srcset ?? srcSet,
58
+ hostSuffixes,
59
+ })
60
+ : null;
61
+ const imageStyle = image ? mergeAstroImageStyle(style, image.objectFit) : style;
62
+ const source = getFimoSource(value);
63
+ ---
64
+
65
+ {
66
+ image && (
67
+ <img
68
+ {...props}
69
+ src={image.src}
70
+ alt={image.alt}
71
+ width={image.width}
72
+ height={image.height}
73
+ sizes={image.sizes}
74
+ srcset={image.srcSet}
75
+ style={imageStyle}
76
+ data-fimo-source={source}
77
+ />
78
+ )
79
+ }
@@ -0,0 +1,14 @@
1
+ ---
2
+ import { getFimoSource } from 'fimo/astro';
3
+
4
+ interface Props {
5
+ value: unknown;
6
+ as?: keyof astroHTML.JSX.IntrinsicElements;
7
+ [key: string]: unknown;
8
+ }
9
+
10
+ const { value, as: Component = 'span', ...props } = Astro.props;
11
+ const source = getFimoSource(value);
12
+ ---
13
+
14
+ {value != null && <Component {...props} data-fimo-source={source}>{JSON.stringify(value)}</Component>}
@@ -0,0 +1,17 @@
1
+ ---
2
+ import type { FimoRichText } from 'fimo/astro';
3
+ import { getFimoSource } from 'fimo/astro';
4
+
5
+ import { renderRichTextHtml } from 'fimo/astro/internal';
6
+
7
+ interface Props {
8
+ value: FimoRichText | null | undefined;
9
+ [key: string]: unknown;
10
+ }
11
+
12
+ const { value, ...props } = Astro.props;
13
+ const source = getFimoSource(value);
14
+ const html = renderRichTextHtml(value?.content);
15
+ ---
16
+
17
+ {value && <div {...props} data-fimo-source={source} data-fimo-richtext="" set:html={html} />}
@@ -0,0 +1,66 @@
1
+ ---
2
+ import {
3
+ mergeAstroImageStyle,
4
+ resolveImagePresentation,
5
+ type ImageFit,
6
+ } from 'fimo/astro/internal';
7
+
8
+ interface Props {
9
+ src: string;
10
+ alt: string;
11
+ quality?: number;
12
+ fit?: ImageFit;
13
+ unoptimized?: boolean;
14
+ overrideSrc?: string;
15
+ width?: string | number;
16
+ height?: string | number;
17
+ sizes?: string;
18
+ srcset?: string;
19
+ srcSet?: string;
20
+ hostSuffixes?: readonly string[];
21
+ style?: string | Record<string, unknown>;
22
+ [key: string]: unknown;
23
+ }
24
+
25
+ const {
26
+ src,
27
+ alt,
28
+ quality,
29
+ fit,
30
+ unoptimized,
31
+ overrideSrc,
32
+ width,
33
+ height,
34
+ sizes,
35
+ srcset,
36
+ srcSet,
37
+ hostSuffixes,
38
+ style,
39
+ ...props
40
+ } = Astro.props;
41
+ const image = resolveImagePresentation({
42
+ src,
43
+ alt,
44
+ quality,
45
+ fit,
46
+ unoptimized,
47
+ overrideSrc,
48
+ width,
49
+ height,
50
+ sizes,
51
+ srcSet: srcset ?? srcSet,
52
+ hostSuffixes,
53
+ });
54
+ const imageStyle = mergeAstroImageStyle(style, image.objectFit);
55
+ ---
56
+
57
+ <img
58
+ {...props}
59
+ src={image.src}
60
+ alt={image.alt}
61
+ width={image.width}
62
+ height={image.height}
63
+ sizes={image.sizes}
64
+ srcset={image.srcSet}
65
+ style={imageStyle}
66
+ />
@@ -0,0 +1,23 @@
1
+ ---
2
+ import { getFimoParts, getFimoSource } from 'fimo/astro';
3
+
4
+ interface Props {
5
+ value: unknown;
6
+ as?: keyof astroHTML.JSX.IntrinsicElements;
7
+ [key: string]: unknown;
8
+ }
9
+
10
+ const { value, as: Component = 'span', ...props } = Astro.props;
11
+ const parts = getFimoParts(value);
12
+ const source = getFimoSource(value);
13
+ ---
14
+
15
+ <Component {...props} data-fimo-source={source}>
16
+ {
17
+ parts && parts.length > 1
18
+ ? parts.map((part) =>
19
+ part.source ? <span data-fimo-source={part.source}>{part.text}</span> : part.text
20
+ )
21
+ : String(value ?? '')
22
+ }
23
+ </Component>
@@ -0,0 +1,47 @@
1
+ ---
2
+ import type { FimoMedia } from 'fimo/astro';
3
+ import { getFimoSource } from 'fimo/astro';
4
+
5
+ interface Props {
6
+ value: FimoMedia | null | undefined;
7
+ overrideSrc?: string;
8
+ autoplay?: boolean;
9
+ autoPlay?: boolean;
10
+ loop?: boolean;
11
+ muted?: boolean;
12
+ playsinline?: boolean;
13
+ playsInline?: boolean;
14
+ [key: string]: unknown;
15
+ }
16
+
17
+ const {
18
+ value,
19
+ overrideSrc,
20
+ autoplay,
21
+ autoPlay,
22
+ loop = true,
23
+ muted = true,
24
+ playsinline,
25
+ playsInline,
26
+ ...props
27
+ } = Astro.props;
28
+ const source = getFimoSource(value);
29
+ const shouldAutoplay = autoplay ?? autoPlay ?? true;
30
+ const shouldPlayInline = playsinline ?? playsInline ?? true;
31
+ ---
32
+
33
+ {
34
+ value && (
35
+ <video
36
+ {...props}
37
+ src={overrideSrc ?? value.url}
38
+ width={value.width}
39
+ height={value.height}
40
+ autoplay={shouldAutoplay}
41
+ loop={loop}
42
+ muted={muted}
43
+ playsinline={shouldPlayInline}
44
+ data-fimo-source={source}
45
+ />
46
+ )
47
+ }
@@ -0,0 +1,8 @@
1
+ export { default as Boolean } from './Boolean.astro';
2
+ export { default as Date } from './Date.astro';
3
+ export { default as Image } from './Image.astro';
4
+ export { default as Json } from './Json.astro';
5
+ export { default as RichText } from './RichText.astro';
6
+ export { default as StaticImage } from './StaticImage.astro';
7
+ export { default as Text } from './Text.astro';
8
+ export { default as Video } from './Video.astro';
@@ -0,0 +1,8 @@
1
+ export { default as Boolean } from './Boolean.astro';
2
+ export { default as Date } from './Date.astro';
3
+ export { default as Image } from './Image.astro';
4
+ export { default as Json } from './Json.astro';
5
+ export { default as RichText } from './RichText.astro';
6
+ export { default as StaticImage } from './StaticImage.astro';
7
+ export { default as Text } from './Text.astro';
8
+ export { default as Video } from './Video.astro';
@@ -0,0 +1,56 @@
1
+ // AUTO-GENERATED by `fimo` from src/schemas/<%= model.uid %>.json - DO NOT EDIT.
2
+ // Runtime implementation lives in the project-local <%= runtimeImport %> package export.
3
+ <% if (model.isSingleton) { -%>
4
+ import { createSingletonClient } from "<%= runtimeImport %>";
5
+ import type { ContentSchema, SingletonContentClient } from "<%= runtimeImport %>";
6
+ <% } else { -%>
7
+ import { createContentClient } from "<%= runtimeImport %>";
8
+ import type { CollectionContentClient, ContentSchema } from "<%= runtimeImport %>";
9
+ <% } -%>
10
+
11
+ import schema from "./<%= model.uid %>.json";
12
+ <%
13
+ if (model.referenceImports && model.referenceImports.length > 0) {
14
+ model.referenceImports.forEach((referenceImport) => {
15
+ -%>
16
+ import * as <%= referenceImport.pascal %> from "./<%= referenceImport.pascal %>";
17
+ <%
18
+ });
19
+ }
20
+ if (model.isSingleton) {
21
+ -%>
22
+ import type { <%= model.pascal %>, <%= model.pascal %>Input } from "./<%= model.pascal %>.types";
23
+ <% } else { -%>
24
+ import type { <%= model.pascal %>, <%= model.pascal %>Fields, <%= model.pascal %>Input, <%= model.pascal %>Populate, <%= model.pascal %>Query } from "./<%= model.pascal %>.types";
25
+ <% } -%>
26
+
27
+ export type { <%= model.pascal %>, <%= model.pascal %>Fields, <%= model.pascal %>FimoMeta, <%= model.pascal %>Input, <%= model.pascal %>Populate, <%= model.pascal %>Query, <%= model.pascal %>References, <%= model.pascal %>Result, <%= model.pascal %>Sort, <%= model.pascal %>Where } from "./<%= model.pascal %>.types";
28
+ <% if (!model.isSingleton) { -%>
29
+ export type { CollectionPage, CollectionPageInfo } from "<%= runtimeImport %>";
30
+ <% } -%>
31
+
32
+ <% if (model.isSingleton) { -%>
33
+ const client: SingletonContentClient<<%= model.pascal %>, <%= model.pascal %>Input> = createSingletonClient<
34
+ <%= model.pascal %>,
35
+ <%= model.pascal %>Input
36
+ >({
37
+ schema: schema as unknown as ContentSchema,
38
+ <% } else { -%>
39
+ const client: CollectionContentClient<<%= model.pascal %>, <%= model.pascal %>Input> = createContentClient<
40
+ <%= model.pascal %>,
41
+ <%= model.pascal %>Input
42
+ >({
43
+ schema: schema as unknown as ContentSchema,
44
+ <% } -%>
45
+ <% if (model.referenceImports && model.referenceImports.length > 0) { -%>
46
+ references: { <%= model.referenceImports.map((referenceImport) => referenceImport.pascal).join(", ") %> },
47
+ <% } -%>
48
+ });
49
+
50
+ <% if (model.isSingleton) { -%>
51
+ export const { get, update, wrapWithSource, meta } = client;
52
+ <% } else { -%>
53
+ export const { wrapWithSource, meta, getById, getBySlug, getByField, list, get, create, update, remove } = client;
54
+ <% } -%>
55
+
56
+ export default client;
@@ -0,0 +1,86 @@
1
+ // AUTO-GENERATED by `fimo` from src/schemas/<%= model.uid %>.json - DO NOT EDIT.
2
+ // This isomorphic module is safe in SvelteKit server and universal load functions.
3
+ import { env } from "$env/dynamic/public";
4
+ <% if (model.isSingleton) { -%>
5
+ import { createSingletonClient, serializeContent } from "<%= runtimeImport %>";
6
+ import type { ContentSchema, SerializedContent, SingletonContentClient } from "<%= runtimeImport %>";
7
+ <% } else { -%>
8
+ import { createContentClient, serializeContent } from "<%= runtimeImport %>";
9
+ import type { CollectionContentClient, ContentSchema, SerializedContent } from "<%= runtimeImport %>";
10
+ <% } -%>
11
+
12
+ import schema from "./<%= model.uid %>.json";
13
+ import fimoConfig from "../../.fimo/config.json";
14
+ <%
15
+ if (model.referenceImports && model.referenceImports.length > 0) {
16
+ model.referenceImports.forEach((referenceImport) => {
17
+ -%>
18
+ import * as <%= referenceImport.pascal %> from "./<%= referenceImport.pascal %>";
19
+ <%
20
+ });
21
+ }
22
+ if (model.isSingleton) {
23
+ -%>
24
+ import type { <%= model.pascal %>, <%= model.pascal %>Input } from "./<%= model.pascal %>.types";
25
+ <% } else { -%>
26
+ import type { <%= model.pascal %>, <%= model.pascal %>Fields, <%= model.pascal %>Input, <%= model.pascal %>Populate, <%= model.pascal %>Query } from "./<%= model.pascal %>.types";
27
+ <% } -%>
28
+
29
+ export type { <%= model.pascal %>, <%= model.pascal %>Fields, <%= model.pascal %>FimoMeta, <%= model.pascal %>Input, <%= model.pascal %>Populate, <%= model.pascal %>Query, <%= model.pascal %>References, <%= model.pascal %>Result, <%= model.pascal %>Sort, <%= model.pascal %>Where } from "./<%= model.pascal %>.types";
30
+ <% if (!model.isSingleton) { -%>
31
+ export type { CollectionPage, CollectionPageInfo } from "<%= runtimeImport %>";
32
+ <% } -%>
33
+
34
+ <% if (model.isSingleton) { -%>
35
+ const client: SingletonContentClient<<%= model.pascal %>, <%= model.pascal %>Input> = createSingletonClient<
36
+ <%= model.pascal %>,
37
+ <%= model.pascal %>Input
38
+ >({
39
+ schema: schema as unknown as ContentSchema,
40
+ apiUrl: env.PUBLIC_FIMO_API_URL,
41
+ defaultLocale: (fimoConfig as { i18n?: { defaultLocale?: string } }).i18n?.defaultLocale,
42
+ <% } else { -%>
43
+ const client: CollectionContentClient<<%= model.pascal %>, <%= model.pascal %>Input> = createContentClient<
44
+ <%= model.pascal %>,
45
+ <%= model.pascal %>Input
46
+ >({
47
+ schema: schema as unknown as ContentSchema,
48
+ apiUrl: env.PUBLIC_FIMO_API_URL,
49
+ defaultLocale: (fimoConfig as { i18n?: { defaultLocale?: string } }).i18n?.defaultLocale,
50
+ <% } -%>
51
+ <% if (model.referenceImports && model.referenceImports.length > 0) { -%>
52
+ references: { <%= model.referenceImports.map((referenceImport) => referenceImport.pascal).join(", ") %> },
53
+ <% } -%>
54
+ });
55
+
56
+ type <%= model.pascal %>Source = Pick<<%= model.pascal %>, "id" | "__fimo">;
57
+ declare const SERIALIZED_CONTENT: unique symbol;
58
+
59
+ /** Plain data for passing <%= model.pascal %> content through a SvelteKit load boundary. */
60
+ export type Serialized<%= model.pascal %><
61
+ TValue extends <%= model.pascal %>Source | readonly <%= model.pascal %>Source[] = <%= model.pascal %>,
62
+ > = SerializedContent<TValue> & { readonly [SERIALIZED_CONTENT]: TValue };
63
+
64
+ export function serialize<TValue extends <%= model.pascal %>Source | readonly <%= model.pascal %>Source[]>(
65
+ value: TValue
66
+ ): Serialized<%= model.pascal %><TValue> {
67
+ return serializeContent(value) as Serialized<%= model.pascal %><TValue>;
68
+ }
69
+
70
+ <% if (model.isSingleton) { -%>
71
+ export const { get, update, wrapWithSource, meta } = client;
72
+ <% } else { -%>
73
+ export const { wrapWithSource, meta, getById, getBySlug, getByField, list, get, create, update, remove } = client;
74
+ <% } -%>
75
+
76
+ /** Restore Fimo source tracking after content crosses a SvelteKit load boundary. */
77
+ export function hydrate<TValue extends <%= model.pascal %>Source | readonly <%= model.pascal %>Source[]>(
78
+ value: Serialized<%= model.pascal %><TValue>
79
+ ): TValue {
80
+ if (Array.isArray(value)) {
81
+ return value.map((entry) => wrapWithSource(entry)) as unknown as TValue;
82
+ }
83
+ return wrapWithSource(value as unknown as Record<string, unknown>) as unknown as TValue;
84
+ }
85
+
86
+ export default client;
@@ -17,6 +17,8 @@ When you are about to do Fimo work:
17
17
  1. List what's available: `npx fimo@latest skills list`
18
18
  2. Load the relevant skill: `npx fimo@latest skills get <name>` (add `--ref <doc>` for a reference doc)
19
19
 
20
+ Streamed output opens with the fimo version that produced it. An older project runtime is normal, so never "fix" it. Quote that line when reporting bad guidance.
21
+
20
22
  Reference paths mentioned in streamed skill output, such as `references/media.md`, are identifiers,
21
23
  not files in the project. Load them through the CLI, for example
22
24
  `npx fimo@latest skills get fimo-cli --ref media`. Do not use a filesystem read tool for them.
@@ -52,7 +52,6 @@ A project can have multiple **envs** — each is a git branch _plus_ its own DB,
52
52
  npx fimo@latest login # authenticate via browser
53
53
  npx fimo@latest skills install # install the global Fimo skill for your AI tools
54
54
  npx fimo@latest init my-site --org <id> # one-stop setup: sign in, create/link a project, install deps + skills. Use the org **id** from `fimo orgs list`, NOT the slug.
55
- npx fimo@latest init my-next-site --framework nextjs --org <id> # opt-in Next.js App Router scaffold
56
55
  npx fimo@latest init my-site --starter fimo-site@1 --org <id> --yes --no-skills # opt-in content-led starter for a new project
57
56
  npx fimo@latest init --project-id <id> my-site # link an EXISTING project instead of creating one
58
57
  npx fimo@latest clone # interactively choose an existing project to clone locally
@@ -25,18 +25,18 @@ fimo --env <name> <command> # peek at another env for one command (does not
25
25
 
26
26
  ## Commands
27
27
 
28
- | Command | git analogue | What it does |
29
- | ----------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
30
- | `fimo branch` | `git branch` | List envs (current marked `*`). `-v` adds preview URLs + deleted envs. |
31
- | `fimo branch <name>` | `git branch <name>` | Create an env off the current one. `--from <env>` forks from a different parent. Provisions DB + sandbox + preview + R2 prefix. |
32
- | `fimo branch -d <name>` | `git branch -d` | Delete an env — tears down its sandbox, Neon branch, and R2 prefix. Refuses `main` and `prod`. |
33
- | `fimo checkout <name>` | `git checkout` | Switch to an env (checks out the matching git branch too). `-b` creates + switches; `--from <env>` sets the parent (with `-b`). |
34
- | `fimo switch <name>` | `git switch` | Switch to an existing env. Takes only `<name>` (no `-b`/`--from`) — use `fimo checkout -b` to create + switch. |
35
- | `fimo pull` | `git pull` | Sync the current env's data plane (DB/assets) down from its parent. `--from <env>` syncs from an explicit ancestor. |
36
- | `fimo diff [from] [to]` | `git diff` | Two-env diff across all surfaces. Defaults `from` = current env, `to` = `main`. `--surface <name>` limits to one; `--json`; `--no-color`. |
37
- | `fimo status` | `git status` | Multi-surface status for the current env vs its parent. See below. |
38
- | `fimo merge <from>` | `git merge` | Merge another env into the current one (multi-surface, atomic, interactive conflict resolver). See below. |
39
- | `fimo publish` | — | Tag `main@HEAD` as `release/<version>` and trigger the prod swap. See "Publishing" below. |
28
+ | Command | git analogue | What it does |
29
+ | ----------------------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
30
+ | `fimo branch` | `git branch` | List envs (current marked `*`). `-v` adds preview URLs + deleted envs. |
31
+ | `fimo branch <name>` | `git branch <name>` | Create an env off the current one. `--from <env>` forks from a different parent. Provisions DB + sandbox + preview + R2 prefix. |
32
+ | `fimo branch -d <name>` | `git branch -d` | Delete an env — tears down its sandbox, Neon branch, and R2 prefix. Refuses `main` and `prod`. |
33
+ | `fimo checkout <name>` | `git checkout` | Switch to an env (checks out the matching git branch; the app derives its env from that branch at startup). `-b` creates + switches; `--from <env>` sets the parent (with `-b`). |
34
+ | `fimo switch <name>` | `git switch` | Switch to an existing env. Takes only `<name>` (no `-b`/`--from`) — use `fimo checkout -b` to create + switch. |
35
+ | `fimo pull` | `git pull` | Sync the current env's data plane (DB/assets) down from its parent. `--from <env>` syncs from an explicit ancestor. |
36
+ | `fimo diff [from] [to]` | `git diff` | Two-env diff across all surfaces. Defaults `from` = current env, `to` = `main`. `--surface <name>` limits to one; `--json`; `--no-color`. |
37
+ | `fimo status` | `git status` | Multi-surface status for the current env vs its parent. See below. |
38
+ | `fimo merge <from>` | `git merge` | Merge another env into the current one (multi-surface, atomic, interactive conflict resolver). See below. |
39
+ | `fimo publish` | — | Tag `main@HEAD` as `release/<version>` and trigger the prod swap. See "Publishing" below. |
40
40
 
41
41
  All of these accept the global `--env` override. `diff`, `status`, `merge`, and `publish` additionally accept `-C, --cwd <dir>` to point at a project directory.
42
42
 
@@ -105,7 +105,8 @@ Use `fimo publish` for versioned prod releases; use `fimo deploy --publish` for
105
105
 
106
106
  ## Anti-patterns
107
107
 
108
- - **Using `git checkout -b` instead of `fimo checkout -b`** — raw git creates the branch but **not** the env's DB / sandbox / preview. Always use `fimo` for branch operations so resources are provisioned atomically. (Running `fimo branch <name>` after the fact provisions them.)
108
+ - **Using `git checkout -b` instead of `fimo checkout -b`** — raw git creates the branch but **not** the env's DB / sandbox / preview. Always use `fimo` for branch operations so resources are provisioned atomically. (Running `fimo branch <name>` after the fact provisions them.) The running app itself follows the git branch either way.
109
+ - **Hardcoding the tenant API URL** — the app derives it from the git branch and `.fimo/project.json`. Set `VITE_API_URL` / `NEXT_PUBLIC_FIMO_API_URL` yourself only as a deliberate override (e.g. a local API); it then wins over derivation on every branch.
109
110
  - **Trying to push to or delete `prod` / `release/*`** — these are read-only/protected. Publish to update prod; never push.
110
111
  - **`fimo merge` straight onto `main` as a habit** — it's gated for a reason. Merge on a branch, then publish.
111
112
  - **Confusing `fimo switch` (env) with `fimo orgs switch` (org).**
@@ -54,9 +54,10 @@ framework default. Production uses `.fimo/config.json#runtime.framework` and
54
54
  the same bounded build/install overrides. Existing applications keep their
55
55
  router and hosting behavior: do not replace the router or derive
56
56
  deployment rewrites from `.fimo/config.json#routes`. When setup changes are
57
- needed, load the `fimo-code` skill's `references/frameworks/hosting.md` recipe;
58
- it covers the React Router `fimoPreset()` connector and the explicit catch-all
59
- used only by plain Vite `BrowserRouter` SPAs.
57
+ needed, load the `fimo-code` skill's framework reference:
58
+ `references/frameworks/hosting.md` covers the React Router `fimoPreset()`
59
+ connector and the explicit catch-all used only by plain Vite `BrowserRouter`
60
+ SPAs; Astro's `fimo()` integration lives in `references/frameworks/astro.md`.
60
61
 
61
62
  ## Warm the sandbox early in a session (optional)
62
63
 
@@ -77,5 +77,5 @@ The scoped view still emits the project-level metadata header (name, framework,
77
77
  ## Notes for AI tools
78
78
 
79
79
  - The JSON shape is stable; parse it rather than scraping the human output when you need a specific field.
80
- - The `framework` field uses Fimo's shared Vercel filesystem detector, which considers package dependencies, configuration files, and framework-specific file layout. For unusual or deliberately mixed projects it may be `null`; inspect `package.json` and the application tree before choosing a framework reference.
80
+ - `framework` is normally auto-detected. If it is `null`, inspect the project before choosing framework-specific guidance.
81
81
  - The command runs in any directory that contains `.fimo/project.json` or one of its ancestors. If you're not in a Fimo project, `describe` will run against whatever directory you point it at (it doesn't require Fimo credentials).
@@ -13,7 +13,7 @@ fimo init [dir] [options]
13
13
  `fimo init` runs the full onboarding in one shot:
14
14
 
15
15
  1. **Signs in automatically** — if there's no session it opens the browser loopback login. In `--json` / non-TTY with no session it fails with `NOT_AUTHENTICATED` (run `fimo login` first).
16
- 2. **Resolves the project** — with `--project-id <id>` it links an EXISTING project (clones it); without it, it creates a NEW project. An interactive TTY shows a "Create new / Link existing" picker; non-interactive shells default to create-new. New projects use React Router by default; `--framework nextjs` selects the minimal Next.js App Router scaffold. An optional `--starter fimo-site@1` adds a React-Router content starter only to a newly created project.
16
+ 2. **Resolves the project** — with `--project-id <id>` it links an EXISTING project (clones it); without it, it creates a NEW project. An interactive TTY shows a "Create new / Link existing" picker; non-interactive shells default to create-new. New projects use React Router by default; `--framework nextjs` and `--framework sveltekit` select minimal framework-native shells. An optional `--starter fimo-site@1` adds a React-Router content starter only to a newly created project.
17
17
  3. **Installs dependencies** — prompts for the package manager, or honor `--package-manager <pm>` / `--no-install`.
18
18
  4. **Optionally sets up Fimo skills** — confirm prompt, or `--skills` / `--no-skills`.
19
19
 
@@ -23,7 +23,7 @@ fimo init [dir] [options]
23
23
  | `--project-id <id>` | no | Link an EXISTING project instead of creating one (clones it). |
24
24
  | `--org <id>` | no | Target organization **id** when creating (use the `ID` column from `fimo orgs list`, NOT the slug). Picker shown interactively if omitted and TTY. |
25
25
  | `--env <name>` | no | Env to check out when linking an existing project (defaults to `main`). |
26
- | `--framework <framework>` | no | New-project scaffold: `react-router` (default) or `nextjs` (App Router). Existing repositories are preserved. |
26
+ | `--framework <framework>` | no | New-project scaffold: `react-router` (default), `nextjs` (App Router), or `sveltekit`. Existing repositories are preserved. |
27
27
  | `--starter <id>` | no | Opt-in project starter for create-new (currently `fimo-site@1`). It seeds CMS content, labels, a contact form, and manual-only agents. Rejects `--project-id`. |
28
28
  | `--package-manager <pm>` | no | `npm` \| `pnpm` \| `yarn` \| `bun`. |
29
29
  | `--install` / `--no-install` | yes in non-TTY | Install deps after checkout (or skip it). |
@@ -63,15 +63,16 @@ writing anything. If dependencies were skipped, install them and run
63
63
 
64
64
  ### Choose the application framework
65
65
 
66
- Omit `--framework` for the existing React Router scaffold, or select the
67
- minimal Next.js App Router shell explicitly:
66
+ Omit `--framework` for the existing React Router scaffold, or select a
67
+ minimal framework-native shell explicitly:
68
68
 
69
69
  ```bash
70
70
  npx fimo@latest init my-next-site --framework nextjs --org <organizationId>
71
+ npx fimo@latest init my-svelte-site --framework sveltekit --org <organizationId>
71
72
  ```
72
73
 
73
- The Next scaffold includes `src/app`, `FimoProvider`, the hosted-preview config,
74
- and `.fimo/config.json#runtime.framework`. It intentionally contains no schema,
74
+ Both shells include their framework adapter, hosted-preview connector, and
75
+ `.fimo/config.json#runtime.framework`. They intentionally contain no schema,
75
76
  labels, or designed website. After init, load the project rules and `fimo-code`
76
77
  to build the requested site. The current `fimo-site@1` content starter supports
77
78
  React Router only.
@@ -86,11 +87,11 @@ Pass `--project-id <id>` to link an EXISTING project instead of creating one. Th
86
87
 
87
88
  `fimo init` (create-new path) scaffolds:
88
89
 
89
- - The selected project shell: React Router by default, or Next.js App Router with `--framework nextjs`
90
+ - The selected project shell: React Router by default, Next.js App Router with `--framework nextjs`, or SvelteKit with `--framework sveltekit`
90
91
  - `.fimo/project.json` — links this directory to the remote project (read-only after creation)
91
92
  - `.fimo/config.json` — project, route, locale, SEO, and agent policy
92
93
  - `.fimo/agents/` — versioned agent bundles
93
- - `.env` — tenant content API URLs for Vite and Next runtimes
94
+ - `.env` — framework-specific tenant content API URLs for local development
94
95
  - `AGENTS.md` + `CLAUDE.md` — project rules (from the template) read by AGENTS.md-compatible tools and Claude Code. Both point the agent at `fimo skills get` to load the real skills on demand.
95
96
  - A git repository with `fimo` as the remote, and — after dependencies install — an initial commit (including the lockfile) plus an initial push
96
97
 
@@ -106,7 +107,7 @@ Nothing is written into per-agent skill dirs: the rich skills are fetched on dem
106
107
 
107
108
  Codex, OpenCode, Aider, and similar AGENTS.md-native tools work directly off AGENTS.md.
108
109
 
109
- `.env` is only the bootstrap app env so local `pnpm dev` works immediately. User-managed public variables are stored with `fimo vars add` and synced into a managed `.env.local` block; hidden values use `fimo secrets add`. See `references/project-vars-and-secrets.md`.
110
+ `.env` is only the bootstrap app env so local `pnpm dev` works immediately. Fimo writes the tenant API aliases used by its supported frameworks; users should not discover or set those URLs manually. User-managed public variables are stored with `fimo vars add` and synced into a managed `.env.local` block; hidden values use `fimo secrets add`. See `references/project-vars-and-secrets.md`.
110
111
 
111
112
  ## Right after scaffolding
112
113
 
@@ -137,7 +138,7 @@ After `fimo init` completes, the project root has `AGENTS.md` (universal) and `C
137
138
  2. `Read` the project rules file: `AGENTS.md` (or `CLAUDE.md` if you're Claude Code).
138
139
  3. Run `npx fimo@latest describe --json` and read the detected framework, schemas, locales, and tree.
139
140
  4. Load the code skill on demand: `npx fimo@latest skills get fimo-code`.
140
- 5. Follow its decision tree and load only the task reference plus the detected framework reference. For Next.js, start with `npx fimo@latest skills get fimo-code --ref frameworks/next`, then load App Router, Pages Router, or locales only when the project shape requires it.
141
+ 5. Follow its decision tree and load only the task reference plus the detected framework reference. For Next.js, start with `npx fimo@latest skills get fimo-code --ref frameworks/next`, then load App Router, Pages Router, or locales only when the project shape requires it. For SvelteKit, start with `npx fimo@latest skills get fimo-code --ref frameworks/sveltekit`. For Astro, `--ref frameworks/astro` is the single framework reference.
141
142
 
142
143
  Do not batch-load every reference. Progressive disclosure keeps unrelated framework and product guidance out of the coding context.
143
144
 
@@ -155,4 +156,3 @@ The first installs the global bootstrap skill for the new agent; the second gene
155
156
  ## Multi-org accounts
156
157
 
157
158
  If you belong to a single organization, `fimo init` defaults to it. If you belong to multiple and don't pass `--org`, the CLI shows an interactive picker. For `fimo init`, pass the org **id** (from the `ID` column of `fimo orgs list`) — not the slug. Use `fimo orgs switch --org <id-or-slug>` to set a default for future `fimo init` invocations. See `references/account.md`.
158
- </content>