fimo 0.12.0 → 0.12.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 (42) hide show
  1. package/assets/agent-templates/broken-link-sweeper/capabilities.yaml +0 -4
  2. package/assets/agent-templates/content-translator/capabilities.yaml +0 -2
  3. package/assets/agent-templates/seo-audit/capabilities.yaml +0 -1
  4. package/assets/content-templates/types-template.eta +13 -7
  5. package/assets/skills/fimo/SKILL.md +2 -2
  6. package/assets/skills/fimo-cli/SKILL.md +8 -8
  7. package/assets/skills/fimo-cli/references/agent-setup.md +1 -1
  8. package/assets/skills/fimo-cli/references/agents.md +5 -12
  9. package/assets/skills/fimo-cli/references/assets.md +2 -2
  10. package/assets/skills/fimo-cli/references/content.md +16 -30
  11. package/assets/skills/fimo-cli/references/describe.md +1 -1
  12. package/assets/skills/fimo-cli/references/forms.md +8 -8
  13. package/assets/skills/fimo-cli/references/init.md +5 -4
  14. package/assets/skills/fimo-cli/references/labels.md +4 -4
  15. package/assets/skills/fimo-cli/references/locales.md +3 -3
  16. package/assets/skills/fimo-cli/references/project-vars-and-secrets.md +1 -1
  17. package/assets/skills/fimo-code/SKILL.md +40 -50
  18. package/assets/skills/fimo-code/references/assets.md +6 -4
  19. package/assets/skills/fimo-code/references/content/clients.md +130 -0
  20. package/assets/skills/fimo-code/references/content/primitives.md +5 -0
  21. package/assets/skills/fimo-code/references/content/richtext.md +48 -0
  22. package/assets/skills/fimo-code/references/content/schema.md +122 -0
  23. package/assets/skills/fimo-code/references/content.md +12 -597
  24. package/assets/skills/fimo-code/references/design.md +1 -1
  25. package/assets/skills/fimo-code/references/frameworks/next/app-router.md +116 -0
  26. package/assets/skills/fimo-code/references/frameworks/next/locales.md +59 -0
  27. package/assets/skills/fimo-code/references/frameworks/next/pages-router.md +99 -0
  28. package/assets/skills/fimo-code/references/frameworks/next.md +116 -0
  29. package/assets/skills/fimo-code/references/frameworks/react-router.md +295 -0
  30. package/assets/skills/fimo-code/references/frameworks/vite-react.md +225 -0
  31. package/assets/skills/fimo-code/references/labels.md +24 -83
  32. package/assets/skills/fimo-code/references/locales.md +22 -111
  33. package/assets/skills/fimo-code/references/setup-plain-vite.md +3 -227
  34. package/assets/skills/fimo-code/references/setup-react-router.md +3 -276
  35. package/assets/skills/fimo-code/references/ui.md +32 -78
  36. package/dist/cli/bundle.json +2 -2
  37. package/dist/cli/index.js +16 -16
  38. package/dist/scripts/extract-translations.js +8 -1
  39. package/package.json +1 -1
  40. package/templates/react-router/AGENTS.md +10 -10
  41. package/templates/react-router/package.json +1 -1
  42. package/templates/react-router/react-router.config.ts +1 -1
@@ -0,0 +1,225 @@
1
+ # Setup Fimo on plain Vite + React
2
+
3
+ Use this recipe for a Vite + React SPA without React Router framework mode.
4
+ This is also the upgrade path for legacy Fimo v3 projects — v3 was plain Vite,
5
+ so this layout is what those projects look like now.
6
+
7
+ ## When to use this vs. React Router
8
+
9
+ - **Plain Vite (this recipe):** simplest setup; client-side routing via a
10
+ React Router library router (`BrowserRouter`, no framework-mode SSR/SSG);
11
+ SEO via build-time HTML rewrite. Per-route SEO that crawlers see requires
12
+ prerendering (SSG); without it, the SPA serves one `index.html` for every
13
+ URL and crawlers see only the home SEO.
14
+ - **React Router (`references/frameworks/react-router.md`):** framework-mode SSR + per-route
15
+ SEO via `meta` export; recommended when you want real per-route crawler SEO.
16
+
17
+ ## Prerequisites
18
+
19
+ - Node 20+
20
+ - A Fimo project created via `fimo init`.
21
+
22
+ ## Install
23
+
24
+ ```
25
+ pnpm add fimo react react-dom react-router @tanstack/react-query
26
+ pnpm add -D vite @vitejs/plugin-react @types/react @types/react-dom typescript
27
+ ```
28
+
29
+ ## File: `package.json`
30
+
31
+ ```json
32
+ {
33
+ "name": "__PROJECT_SLUG__",
34
+ "version": "0.0.0",
35
+ "private": true,
36
+ "type": "module",
37
+ "scripts": {
38
+ "dev": "vite --host 0.0.0.0 --port 5173",
39
+ "build": "vite build",
40
+ "preview": "vite preview --host 0.0.0.0 --port 4173",
41
+ "typecheck": "tsc --noEmit"
42
+ }
43
+ }
44
+ ```
45
+
46
+ ## File: `vite.config.ts`
47
+
48
+ ```ts
49
+ import { defineConfig } from 'vite';
50
+
51
+ import { fimo } from 'fimo/vite';
52
+
53
+ export default defineConfig(() => ({
54
+ plugins: fimo({ seo: true }),
55
+ }));
56
+ ```
57
+
58
+ Notes:
59
+
60
+ - `fimo({ seo: true })` opts in to the build-time SEO plugin
61
+ (`transformIndexHtml`-based). This is the right tool for plain Vite — there's
62
+ no framework `meta` export to plug into.
63
+ - Add `fimo({ seo: true, sitemap: true, robots: true })` to also emit
64
+ `sitemap.xml` and `robots.txt` at build.
65
+
66
+ ## File: `index.html`
67
+
68
+ ```html
69
+ <!doctype html>
70
+ <html lang="en">
71
+ <head>
72
+ <meta charset="UTF-8" />
73
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
74
+ <title>__PROJECT_SLUG__</title>
75
+ </head>
76
+ <body>
77
+ <div id="root"></div>
78
+ <script type="module" src="/src/main.tsx"></script>
79
+ </body>
80
+ </html>
81
+ ```
82
+
83
+ The `seo` plugin rewrites `<title>`, og, twitter, canonical tags from
84
+ `.fimo/config.json#seo` at build time. You can leave a placeholder title in
85
+ `index.html`; it'll be replaced.
86
+
87
+ ## File: `src/main.tsx`
88
+
89
+ `FimoProviders` requires a React Router `<Router>` ancestor (it reads
90
+ `useLocation`/`useNavigate`). It reuses a host app's
91
+ `@tanstack/react-query` client when one exists and supplies a stable fallback
92
+ for adopted SPAs. This recipe still mounts an explicit provider so the app owns
93
+ the shared cache and its configuration:
94
+
95
+ ```tsx
96
+ import { FimoProviders } from 'fimo/react-router';
97
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
98
+ import React from 'react';
99
+ import { createRoot } from 'react-dom/client';
100
+ import { BrowserRouter } from 'react-router';
101
+
102
+ import { App } from './App';
103
+
104
+ const queryClient = new QueryClient();
105
+
106
+ createRoot(document.getElementById('root')!).render(
107
+ <React.StrictMode>
108
+ <QueryClientProvider client={queryClient}>
109
+ <BrowserRouter>
110
+ <FimoProviders>
111
+ <App />
112
+ </FimoProviders>
113
+ </BrowserRouter>
114
+ </QueryClientProvider>
115
+ </React.StrictMode>
116
+ );
117
+ ```
118
+
119
+ `react-router` and `@tanstack/react-query` are peer dependencies of `fimo`;
120
+ both are in the install command above. `FimoProviders` is exported only from
121
+ the `fimo/react-router` adapter barrel. Keep the explicit QueryClientProvider
122
+ when the app needs custom query defaults or shared cache access; adopted SPAs
123
+ can omit it.
124
+
125
+ ## File: `src/App.tsx`
126
+
127
+ ```tsx
128
+ import { Text, useLabels } from 'fimo/ui';
129
+
130
+ export function App() {
131
+ const { t } = useLabels();
132
+
133
+ return (
134
+ <main>
135
+ <Text value={t('home.hero.title')} as="h1" />
136
+ </main>
137
+ );
138
+ }
139
+ ```
140
+
141
+ ## File: `.fimo/config.json`
142
+
143
+ ```json
144
+ {
145
+ "version": "3",
146
+ "seo": {
147
+ "title": "__PROJECT_SLUG__",
148
+ "siteName": "__PROJECT_SLUG__"
149
+ },
150
+ "routes": {
151
+ "home": {
152
+ "label": "Home",
153
+ "path": "/"
154
+ }
155
+ }
156
+ }
157
+ ```
158
+
159
+ Note: `"version": "3"` marks the legacy plain-Vite (no-RR-framework-mode)
160
+ shape. `fimo()` is version-agnostic — it composes a fixed set of build-time
161
+ plugins from the `seo`/`sitemap`/`robots` options you pass and never reads
162
+ this version field. It also never injects the React Router plugin: in a
163
+ framework-mode project that `reactRouter()` plugin is added by your own
164
+ `vite.config.ts`, not by `fimo/vite`.
165
+
166
+ ## File: `.fimo/project.json`
167
+
168
+ ```json
169
+ {
170
+ "projectId": "__PROJECT_ID__",
171
+ "organizationId": "__ORG_ID__",
172
+ "apiUrl": "__API_URL__"
173
+ }
174
+ ```
175
+
176
+ ## File: `tsconfig.json`
177
+
178
+ ```json
179
+ {
180
+ "compilerOptions": {
181
+ "target": "ES2022",
182
+ "lib": ["DOM", "DOM.Iterable", "ES2022"],
183
+ "module": "ESNext",
184
+ "moduleResolution": "Bundler",
185
+ "jsx": "react-jsx",
186
+ "strict": true,
187
+ "esModuleInterop": true,
188
+ "skipLibCheck": true,
189
+ "resolveJsonModule": true,
190
+ "isolatedModules": true,
191
+ "types": ["vite/client"]
192
+ },
193
+ "include": ["src", "*.config.ts"]
194
+ }
195
+ ```
196
+
197
+ ## Verify and iterate
198
+
199
+ Run the app with the project's package-manager `dev` script (`pnpm dev` /
200
+ `npm run dev` / `yarn dev` / `bun dev` — match the lockfile). It serves the site
201
+ on localhost with live reload — this is your iteration loop: edit, see the change,
202
+ repeat with the developer. `fimo deploy` is on-demand (hosted preview / shareable
203
+ link / go live), run only on the developer's signal; the dashboard's preview iframe
204
+ shows the **deployed** app, not the localhost dev server.
205
+
206
+ ## Known limitations vs. React Router
207
+
208
+ - **Per-route SEO that crawlers see** requires either (a) using React Router
209
+ framework mode with prerender, (b) a Vite SSG plugin like `vite-plugin-ssg`,
210
+ or (c) accepting that the crawler sees the home SEO for every URL.
211
+ - **Dashboard "live edit SEO" preview** requires a reload on plain Vite —
212
+ there's no React-side head-mutation component yet. The static `seo` plugin
213
+ bakes SEO at build time.
214
+ - **Routing**: `FimoProviders` requires a React Router context, so this recipe
215
+ wires `BrowserRouter` from `react-router`. You can swap it for another
216
+ React Router setup (e.g. a `createBrowserRouter` data router with
217
+ `<RouterProvider>`), but a `<Router>` ancestor is mandatory — the runtime's
218
+ preview bridge and pageview tracker call `useLocation`/`useNavigate`.
219
+
220
+ ## What to do next
221
+
222
+ - Add a sitemap: pass `fimo({ seo: true, sitemap: true })` and set
223
+ `.fimo/config.json#seo.url` to your production base URL.
224
+ - Look up exports: see `references/ui.md`.
225
+ - Use schema content: see `references/content.md`.
@@ -1,102 +1,43 @@
1
- # Labels — package surface
1
+ # Labels
2
2
 
3
- > For the CLI workflow (`fimo validate`, `fimo labels set`, bulk updates), see **`fimo-cli/references/labels.md`**.
4
- > For locale-aware routing and links (`fimoRoutes`, `FimoLink`, custom framework contract), see **`references/locales.md`**.
3
+ Labels are project-wide, locale-scoped, editor-managed static copy. Use them for headings, navigation, CTAs, placeholders, empty states, alt text, and metadata. Structured editor content belongs in schemas instead.
5
4
 
6
- This file covers the **package surface**: the `t()` helper, the `useLabels()` hook, and the code-side rules for wrapping strings.
5
+ For label CLI writes and missing-key validation, load `fimo-cli/references/labels.md`.
7
6
 
8
- ## The rule
9
-
10
- Every piece of **user-facing static text** in the app (page titles, button labels, nav items, form placeholders, empty-state copy, alt text, meta tags) MUST be wrapped in `t('key')`.
11
-
12
- Raw string literals in JSX are a bug — they won't show up in the Fimo admin as editable content and won't be translatable. **Hard-coded JSX text (`<h1>Welcome</h1>`) skips the entire i18n + inline-editing pipeline and becomes invisible to the editor.**
13
-
14
- ## Setup (already wired)
15
-
16
- Labels are wired automatically by the `fimo/vite` build plugin. `useLabels()` reads DB-backed label values for the active locale — there's no provider to add or remove. The app entry is `src/root.tsx`, which wraps the app in `<FimoProviders>` from `fimo/react-router`. Pages and components call `useLabels()`.
17
-
18
- `useTranslations()` is kept as a legacy alias for older projects. Use `useLabels()` in new code.
19
-
20
- In development, the generated app reloads when DB label values change. In production, the build embeds the DB-backed label bundle.
21
-
22
- ## Locale behavior
23
-
24
- The default label locale is `i18n.defaultLocale` in `.fimo/config.json`, falling back to `en` when it is not set. `fimo validate`, the generated app runtime, and `fimo labels set` without `--locale` all use that default locale.
25
-
26
- For non-default locales, create explicit DB values with `fimo labels set --locale <locale>` or `fimo labels set-many --locale <locale>`. Keep the code shape the same for every locale: `t('hero.title')` declares the key, and the DB decides which locale value is shown.
27
-
28
- `.fimo/config.json` owns the locale list:
29
-
30
- ```json
31
- {
32
- "i18n": {
33
- "defaultLocale": "en",
34
- "locales": ["en"]
35
- }
36
- }
37
- ```
38
-
39
- - `locales` is the enabled locale list and must include `defaultLocale`. Do not add non-default locales unless the user asks for multiple languages, localized routes, translations, or a specific locale.
40
- - If multiple locales are configured, create or update label values for every configured locale.
41
- - Public locale routing is project/framework code. In React Router projects, prefer `fimoRoutes()` plus `FimoLink`; for custom frameworks, pass the active locale to `FimoProviders`. See `references/locales.md`.
42
-
43
- ## Usage
7
+ ## Stable contract
44
8
 
45
9
  ```tsx
46
- import { useLabels, Text } from 'fimo/ui';
47
-
48
- export function Hero() {
49
- const { t } = useLabels();
50
- return (
51
- <section>
52
- <h1>
53
- <Text value={t('hero.title')} />
54
- </h1>
55
- <p>
56
- <Text value={t('hero.subtitle')} />
57
- </p>
58
- <input placeholder={String(t('hero.emailPlaceholder'))} />
59
- <img alt={String(t('hero.imageAlt'))} src="..." />
60
- </section>
61
- );
62
- }
10
+ const { t } = useLabels();
11
+ return <Text value={t('hero.title')} as="h1" />;
63
12
  ```
64
13
 
65
- - `t(key)` returns a `FimoString` (wrapped for source tracking). Render it via `<Text value={...} />` inside JSX.
66
- - For HTML attributes (`placeholder`, `alt`, `title`, `aria-label`) cast with `String(t(...))` — the attribute can't accept a `FimoString` object directly.
67
- - If a key is missing from the DB, it renders empty. Run `fimo validate` and add missing values with `fimo labels set`.
14
+ `t(key)` returns a source-tracked `FimoString`. Render it with `<Text>` when possible so Studio can select it. Convert with `String(t(...))` only for HTML attributes or framework APIs that require a primitive.
68
15
 
69
- ## Hard rules (enforced by the pre-build linter)
70
-
71
- **The first argument to `t()` MUST be a string literal.** Dynamic keys break source tracking and fail the lint step.
16
+ The first argument must be a string literal so extraction and source tracking remain deterministic:
72
17
 
73
18
  ```tsx
74
- // ❌ BAD — variable key
75
- t(item.key);
19
+ const items = [
20
+ { href: '/', label: t('nav.home') },
21
+ { href: '/about', label: t('nav.about') },
22
+ ];
23
+ ```
76
24
 
77
- // ❌ BAD — template with expression
78
- t(`nav.${page}`);
25
+ Do not use variables or interpolated expressions as label keys. Namespace literal keys by page/section/component, such as `hero.title`, `nav.signIn`, or `contact.form.submit`.
79
26
 
80
- // ✅ GOOD — put the t() call where the literal lives
81
- const items = [{ label: t('nav.home') }, { label: t('nav.about') }];
82
- items.map((item) => <li>{item.label}</li>);
83
- ```
27
+ Missing keys render as an empty tracked value. Run `fimo validate`, then create values with `fimo labels set` or `set-many`; do not add fallback copy to code.
84
28
 
85
- ## Key naming
29
+ ## Framework adapters
86
30
 
87
- - Dot-namespaced, lowercase, kebab or camelCase leaves: `hero.title`, `nav.signIn`, `footer.copyright`, `errors.required`.
88
- - Namespace by **page/section/component**, not by feature (`contact.form.submitLabel`, not `forms.contactSubmit`).
89
- - Values live in the DB. Do not put user-visible fallback copy in code.
31
+ The label contract is shared; acquisition differs by runtime:
90
32
 
91
- ## What NOT to translate
33
+ - Next server: `getLabels({ locale? })` from `fimo/next`.
34
+ - Next client: `useLabels()` from `fimo/next/client`, under `FimoProvider`.
35
+ - React Router/Vite client: `useLabels()` from `fimo/ui`, under the existing framework integration.
92
36
 
93
- - Dynamic content from entries or forms — that's already stored in the DB (content via schemas, submissions via forms).
94
- - Content-type field values rendered via `fimo/ui` primitives (`<Text>`, `<RichText>`, …) — those carry their own admin-editing metadata.
95
- - Purely decorative / non-text (icons, logos).
96
- - Developer-only strings (`console.log`, error messages thrown for debugging).
37
+ Load `references/frameworks/next.md`, `references/frameworks/react-router.md`, or `references/frameworks/vite-react.md` before adding a provider.
97
38
 
98
- ## Rule of thumb
39
+ ## Locale behavior
99
40
 
100
- If a human reader sees the text AND the project owner might want to reword it in the admin, it goes through `t()`. When in doubt: wrap it.
41
+ `.fimo/config.json#i18n.defaultLocale` selects the default (fallback `en`). The application resolves the active locale and gives it to the framework adapter. Create explicit label values for each configured locale the product supports.
101
42
 
102
- After adding or changing `t()` calls, run `fimo validate`, then fill missing values with `fimo labels set` or `fimo labels set-many`. See `fimo-cli/references/labels.md`.
43
+ Do not translate schema content, dynamic form submissions, decorative icons, or developer-only logs through labels.
@@ -1,129 +1,40 @@
1
- # Locales: Routing And Navigation
1
+ # Locale ownership
2
2
 
3
- Fimo provides locale utilities that follow the Fimo standard, but they are helpers, not a mandatory app architecture. A project may use a custom Next, Astro, domain, middleware, or hand-rolled routing strategy as long as it passes the active locale into Fimo and keeps Fimo route metadata canonical.
3
+ The application owns locale resolution and routing. Fimo consumes the resolved locale for labels and localized content.
4
4
 
5
- ## Configuration
5
+ `.fimo/config.json` declares supported/default locales:
6
6
 
7
- `.fimo/config.json` owns the locale list and routing strategy. Keep one locale unless the user asks for multilingual or localized output.
8
-
9
- ```jsonc
7
+ ```json
10
8
  {
11
9
  "i18n": {
12
10
  "defaultLocale": "en",
13
- "locales": ["en"],
14
- "routing": {
15
- "strategy": "path-prefix", // only supported strategy: /es/about for Spanish; default locale can stay /about
16
- "prefixDefaultLocale": false, // when false, omit /en for the default locale
17
- },
18
- },
19
- }
20
- ```
21
-
22
- - `defaultLocale` is the source/default locale.
23
- - `locales` lists enabled locales and must include `defaultLocale`. Do not add non-default locales unless the user asks for multiple languages, localized routes, translations, or a specific locale.
24
- - `routing.strategy` currently supports `path-prefix`.
25
- - If multiple locales are configured, create or update labels and localized content for every configured locale. Create schemas with `i18n: { "enabled": false }` only once; those entries are shared across locales.
26
-
27
- Locale tags should be structurally valid, for example `en`, `es`, `pt-BR`, or `zh-Hans`.
28
-
29
- ## Canonical Routes
30
-
31
- Keep `.fimo/config.json#routes` canonical and unlocalized:
32
-
33
- ```json
34
- {
35
- "routes": {
36
- "pricing": {
37
- "label": "Pricing",
38
- "path": "/pricing"
39
- }
11
+ "locales": ["en", "fr"]
40
12
  }
41
13
  }
42
14
  ```
43
15
 
44
- Do not add separate route metadata for `/es/pricing`. Locale prefixes such as `/es` are reserved when `path-prefix` is enabled, and `fimo validate` reports collisions.
45
-
46
- ## React Router Standard Helper
47
-
48
- For React Router framework mode, write one canonical route list and wrap it:
49
-
50
- ```ts
51
- import type { RouteConfig } from '@react-router/dev/routes';
52
- import { index, route } from '@react-router/dev/routes';
53
- import { fimoRoutes } from 'fimo/react-router/routes';
54
-
55
- const routes = [
56
- index('./pages/Index.tsx', { id: 'home' }),
57
- route('pricing', './pages/Pricing.tsx', { id: 'pricing' }),
58
- route('blog/:slug', './pages/BlogPost.tsx', { id: 'blog-post' }),
59
- ] satisfies RouteConfig;
60
-
61
- export default fimoRoutes(routes) satisfies RouteConfig;
62
- ```
63
-
64
- `fimoRoutes()` expands concrete locale-prefixed aliases from the configured locale list while reusing the same page modules. For `locales: ["en", "es"]` and `prefixDefaultLocale: false`, it adds routes like `/es`, `/es/pricing`, and `/es/blog/:slug`.
65
-
66
- This helper exists so the Fimo UI route selector, preview navigation, labels, and content queries all agree on the same URL shape. It is not required if the project deliberately implements a custom routing strategy.
67
-
68
- Copyable examples live in `assets/react-router-locales/routes.ts` and `assets/react-router-locales/navigation.tsx`.
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
- ## Links
79
-
80
- Use `FimoLink` for internal links that should preserve or switch locale:
81
-
82
- ```tsx
83
- import { FimoLink } from 'fimo/react-router';
84
-
85
- <FimoLink to="/pricing">Pricing</FimoLink>
86
- <FimoLink to="/pricing" locale="es">Spanish pricing</FimoLink>
87
- ```
88
-
89
- `FimoLink` localizes absolute internal paths according to `.fimo/config.json#i18n.routing`. It leaves relative, hash, query-only, and external URLs alone. Use React Router's raw `Link` only when you intentionally want to bypass Fimo's locale behavior.
90
-
91
- Read the active locale with `useLocale()` when component logic needs it:
16
+ Keep one locale unless the product asks for multilingual output. Locale tags should be structurally valid, such as `en`, `pt-BR`, or `zh-Hans`.
92
17
 
93
- ```tsx
94
- import { useLocale } from 'fimo/ui';
18
+ For an already linked project, the same locales must also be enabled in Fimo before writing non-default label or content variants. Local config and `fimo validate` do not currently provision project locales. If the API says a locale is not configured, enable it in Fimo Studio; do not change the application's route strategy to work around it.
95
19
 
96
- const { locale, defaultLocale, locales, routePath, dir } = useLocale();
97
- ```
20
+ ## Application responsibilities
98
21
 
99
- `locales` lists every configured locale, so a language switcher needs no API call and no extra component:
22
+ - Resolve locale from its router, route parameters, domain, request headers, middleware, cookie, existing i18n library, or user preference.
23
+ - Keep its existing public URLs, redirects, links, `<html lang/dir>`, and SEO behavior.
24
+ - Pass the resolved locale to Fimo's server reads and client provider.
25
+ - Treat any optional Studio route catalog as framework-adapter-specific; load the framework reference before creating or changing one.
100
26
 
101
- ```tsx
102
- const { locale, locales, routePath } = useLocale();
103
-
104
- locales.map((code) => (
105
- <FimoLink key={code} to={routePath} locale={code} aria-current={code === locale ? 'true' : undefined}>
106
- {new Intl.DisplayNames([code], { type: 'language' }).of(code)}
107
- </FimoLink>
108
- ));
109
- ```
27
+ ## Fimo responsibilities
110
28
 
111
- ## Custom Frameworks
112
-
113
- For Next, Astro, plain Vite, or custom routers, the same contract applies:
114
-
115
- - The framework owns URL matching.
116
- - The app resolves the active locale from the request, path, domain, middleware, cookie, or user preference.
117
- - The app passes that locale to Fimo:
118
-
119
- ```tsx
120
- <FimoProviders locale={locale}>{children}</FimoProviders>
121
- ```
29
+ - Fetch the correct localized content variant and label dictionary after receiving locale.
30
+ - Use `defaultLocale` when no explicit locale is supplied.
31
+ - Preserve one shared entry for schemas with `i18n.enabled: false`.
32
+ - Preserve source metadata for editing.
122
33
 
123
- When using custom routing, also provide localized internal-link helpers in that framework's style. Fimo's DB labels and localized content will follow the locale passed to `FimoProviders`.
34
+ ## Framework handoff
124
35
 
125
- ## What Not To Do
36
+ - Next.js → load `references/frameworks/next/locales.md`.
37
+ - React Router standard locale routing → load `references/frameworks/react-router.md`.
38
+ - Vite + React/custom React router → load `references/frameworks/vite-react.md` and pass locale through its existing provider seam.
126
39
 
127
- - Do not create `src/pages/__localized/*` copies just for locales.
128
- - Do not duplicate every route in `.fimo/config.json` per locale.
129
- - Do not use `/es` as a normal canonical route when `es` is an enabled locale.
40
+ Do not replace an existing locale system merely to add Fimo. Do not duplicate localized routes in the Studio catalog. Do not assume Fimo's route helpers are universal framework APIs.