fimo 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/astro/components/DateTime.astro +22 -0
- package/assets/astro/components/index.d.ts +1 -0
- package/assets/astro/components/index.js +1 -0
- package/assets/content-templates/shared/types.eta +2 -0
- package/assets/skills/fimo-cli/SKILL.md +8 -6
- package/assets/skills/fimo-cli/references/branches.md +2 -2
- package/assets/skills/fimo-cli/references/content.md +2 -2
- package/assets/skills/fimo-cli/references/deploy.md +17 -9
- package/assets/skills/fimo-cli/references/hosting.md +114 -0
- package/assets/skills/fimo-cli/references/init.md +13 -6
- package/assets/skills/fimo-cli/references/integrations/firecrawl.md +2 -0
- package/assets/skills/fimo-cli/references/locales.md +38 -14
- package/assets/skills/fimo-cli/references/pages.md +70 -0
- package/assets/skills/fimo-cli/references/preview.md +26 -20
- package/assets/skills/fimo-cli/references/webhooks.md +1 -1
- package/assets/skills/fimo-code/SKILL.md +11 -0
- package/assets/skills/fimo-code/assets/react-router-locales/LocaleLayout.tsx +12 -0
- package/assets/skills/fimo-code/assets/react-router-locales/routes.ts +7 -6
- package/assets/skills/fimo-code/references/best-practices/astro.md +47 -0
- package/assets/skills/fimo-code/references/best-practices/next.md +42 -0
- package/assets/skills/fimo-code/references/best-practices/sveltekit.md +17 -0
- package/assets/skills/fimo-code/references/content/richtext.md +5 -0
- package/assets/skills/fimo-code/references/content/schema.md +4 -1
- package/assets/skills/fimo-code/references/frameworks/astro.md +5 -3
- package/assets/skills/fimo-code/references/frameworks/hosting.md +5 -2
- package/assets/skills/fimo-code/references/frameworks/next/app-router.md +6 -0
- package/assets/skills/fimo-code/references/frameworks/next/locales.md +12 -2
- package/assets/skills/fimo-code/references/frameworks/next.md +7 -0
- package/assets/skills/fimo-code/references/frameworks/react-router.md +15 -7
- package/assets/skills/fimo-code/references/frameworks/sveltekit.md +15 -8
- package/assets/skills/fimo-code/references/labels.md +9 -1
- package/assets/skills/fimo-code/references/locales.md +8 -2
- package/assets/skills/fimo-code/references/migrations/react-router-route-ownership.md +93 -0
- package/assets/skills/fimo-code/references/ui.md +21 -2
- package/assets/skills/fimo-migration/SKILL.md +276 -51
- package/assets/skills/fimo-migration/references/content.md +119 -35
- package/assets/skills/fimo-migration/references/decision.md +72 -0
- package/assets/skills/fimo-migration/references/forms.md +38 -6
- package/assets/skills/fimo-migration/references/frameworks/nextjs.md +179 -23
- package/assets/skills/fimo-migration/references/import-contract.md +71 -19
- package/assets/skills/fimo-migration/references/manifest.md +11 -161
- package/assets/skills/fimo-migration/references/media.md +33 -1
- package/assets/skills/fimo-migration/references/platforms.md +26 -2
- package/assets/skills/fimo-migration/references/qa.md +167 -13
- package/assets/skills/fimo-migration/references/workers/content-execution.md +39 -0
- package/assets/skills/fimo-migration/references/workers/content-planner.md +64 -0
- package/assets/skills/fimo-migration/references/workers/framework.md +37 -0
- package/assets/skills/fimo-migration/references/workers/validator.md +25 -0
- package/assets/skills/fimo-migration/references/workers.md +82 -0
- package/assets/skills/fimo-migration/references/workflow.md +140 -192
- package/assets/skills/fimo-migration/scripts/apply-decision.mjs +534 -0
- package/assets/skills/fimo-migration/scripts/build-canonical-manifest.mjs +7 -4
- package/assets/skills/fimo-migration/scripts/write-migration-report.mjs +191 -4
- package/assets/skills/fimo-studio/references/ai-chat.md +1 -1
- package/assets/skills/fimo-studio/references/cms.md +25 -7
- package/assets/skills/fimo-studio/references/webhooks.md +1 -1
- package/assets/sveltekit/components/DateTime.svelte +35 -0
- package/assets/sveltekit/components/FimoProvider.svelte +2 -2
- package/assets/sveltekit/components/index.d.ts +1 -0
- package/assets/sveltekit/components/index.js +1 -0
- package/dist/build/next/config.d.ts +4 -1
- package/dist/build/next/config.js +21 -5
- package/dist/build/sveltekit/vite.d.ts +3 -4
- package/dist/build/sveltekit/vite.js +3 -4
- package/dist/build/vite/plugins/runtime-env.d.ts +2 -1
- package/dist/build/vite/plugins/runtime-env.js +14 -10
- package/dist/cli/bundle.json +2 -2
- package/dist/cli/index.js +113 -108
- package/dist/runtime/app/FimoProviders.js +25 -14
- package/dist/runtime/app/prefetch.d.ts +3 -1
- package/dist/runtime/app/prefetch.js +11 -55
- package/dist/runtime/astro/preview.js +7 -9
- package/dist/runtime/content/client/internal.js +1 -0
- package/dist/runtime/i18n/locale.d.ts +6 -3
- package/dist/runtime/i18n/locale.js +16 -41
- package/dist/runtime/next/client-runtime.js +5 -1
- package/dist/runtime/next/client.d.ts +3 -2
- package/dist/runtime/next/client.js +2 -1
- package/dist/runtime/next/labels.d.ts +2 -2
- package/dist/runtime/next/labels.js +2 -2
- package/dist/runtime/next/preview.d.ts +13 -0
- package/dist/runtime/next/preview.js +34 -0
- package/dist/runtime/next/primitives/server.d.ts +2 -0
- package/dist/runtime/next/primitives/server.js +8 -0
- package/dist/runtime/next/provider.d.ts +5 -0
- package/dist/runtime/next/provider.js +17 -3
- package/dist/runtime/next/server-runtime.js +4 -1
- package/dist/runtime/next/server.d.ts +1 -1
- package/dist/runtime/next/server.js +1 -1
- package/dist/runtime/paths/get-fimo-paths.d.ts +6 -5
- package/dist/runtime/paths/get-fimo-paths.js +43 -42
- package/dist/runtime/preview/location.d.ts +19 -2
- package/dist/runtime/preview/location.js +16 -2
- package/dist/runtime/primitives/index.d.ts +1 -0
- package/dist/runtime/primitives/index.js +1 -0
- package/dist/runtime/react/primitives/editable/DateTime.d.ts +4 -0
- package/dist/runtime/react/primitives/editable/DateTime.js +13 -0
- package/dist/runtime/react/primitives/renderers/DateRenderer.d.ts +7 -1
- package/dist/runtime/react/primitives/renderers/DateRenderer.js +11 -8
- package/dist/runtime/react-router/{routes.d.ts → legacy/routes.d.ts} +6 -1
- package/dist/runtime/react-router/{routes.js → legacy/routes.js} +22 -7
- package/dist/runtime/routes/index.d.ts +162 -0
- package/dist/runtime/routes/index.js +335 -0
- package/dist/runtime/routing/AppRoutesProvider.js +4 -3
- package/dist/runtime/seo/resolver.d.ts +5 -0
- package/dist/runtime/seo/resolver.js +10 -42
- package/dist/runtime/shared/fimo-config.types.d.ts +14 -13
- package/dist/runtime/shared/preview-location.d.ts +1 -22
- package/dist/runtime/shared/preview-location.js +5 -93
- package/dist/runtime/sveltekit/preview.d.ts +12 -3
- package/dist/runtime/sveltekit/preview.js +13 -8
- package/dist/runtime/templates.d.ts +19 -0
- package/dist/runtime/templates.js +33 -0
- package/dist/scripts/sync-forms.js +1 -1
- package/dist/scripts/sync-schemas.js +1 -4
- package/dist/scripts/validate-fimo-config.js +5 -1
- package/dist/scripts/validate-page-registry.d.ts +2 -0
- package/dist/scripts/validate-page-registry.js +167 -0
- package/dist/scripts/validate-route-metadata.js +132 -41
- package/package.json +10 -5
- package/templates/astro/.fimo/config.json +13 -5
- package/templates/astro/AGENTS.md +5 -1
- package/templates/astro/astro.config.mjs +7 -0
- package/templates/astro/pnpm-workspace.yaml +0 -3
- package/templates/astro/src/components/ProjectOverview.astro +9 -6
- package/templates/astro/src/layouts/Base.astro +1 -1
- package/templates/astro/src/locales.ts +4 -0
- package/templates/astro/src/pages/[locale]/index.astro +19 -0
- package/templates/astro/src/pages/[locale]/projects/[slug].astro +35 -0
- package/templates/astro/src/pages/[locale]/projects/index.astro +19 -0
- package/templates/astro/src/pages/index.astro +5 -2
- package/templates/astro/src/pages/projects/[slug].astro +4 -2
- package/templates/astro/src/pages/projects/index.astro +5 -2
- package/templates/nextjs/.fimo/config.json +2 -1
- package/templates/nextjs/AGENTS.md +5 -0
- package/templates/nextjs/src/app/(default)/layout.tsx +10 -0
- package/templates/nextjs/src/app/[locale]/layout.tsx +22 -0
- package/templates/nextjs/src/app/[locale]/page.tsx +1 -0
- package/templates/nextjs/src/components/Document.tsx +26 -0
- package/templates/nextjs/src/components/FimoPreviewBridge.tsx +13 -0
- package/templates/nextjs/src/locales.ts +13 -0
- package/templates/react-router/.fimo/config.json +3 -6
- package/templates/react-router/AGENTS.md +4 -0
- package/templates/react-router/package.json +1 -1
- package/templates/react-router/pnpm-workspace.yaml +1 -3
- package/templates/react-router/react-router.config.ts +4 -10
- package/templates/react-router/src/pages/LocaleLayout.tsx +12 -0
- package/templates/react-router/src/root.tsx +2 -4
- package/templates/react-router/src/routes.ts +5 -3
- package/templates/sveltekit/.fimo/config.json +2 -1
- package/templates/sveltekit/AGENTS.md +5 -0
- package/templates/sveltekit/src/app.html +1 -1
- package/templates/sveltekit/src/hooks.server.ts +11 -0
- package/templates/sveltekit/src/locales.ts +8 -0
- package/templates/sveltekit/src/params/locale.ts +5 -0
- package/templates/sveltekit/src/routes/+layout.server.ts +6 -1
- package/templates/sveltekit/src/routes/+layout.svelte +5 -0
- package/assets/skills/fimo-migration/references/inventory/coordinator.md +0 -40
- package/assets/skills/fimo-migration/references/inventory/locales/next-intl.md +0 -39
- package/assets/skills/fimo-migration/references/inventory/locales.md +0 -41
- package/assets/skills/fimo-migration/scripts/inventory/locales/next-intl.mjs +0 -459
- package/templates/nextjs/src/app/layout.tsx +0 -17
- /package/templates/nextjs/src/app/{page.tsx → (default)/page.tsx} +0 -0
- /package/templates/sveltekit/src/routes/{+page.svelte → [[locale=locale]]/+page.svelte} +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fimo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "Fimo CLI - create, deploy, and manage Fimo projects",
|
|
5
5
|
"bin": {
|
|
6
6
|
"fimo": "dist/cli/index.js"
|
|
@@ -64,8 +64,8 @@
|
|
|
64
64
|
"import": "./dist/runtime/react-router/index.js"
|
|
65
65
|
},
|
|
66
66
|
"./react-router/routes": {
|
|
67
|
-
"types": "./dist/runtime/react-router/routes.d.ts",
|
|
68
|
-
"import": "./dist/runtime/react-router/routes.js"
|
|
67
|
+
"types": "./dist/runtime/react-router/legacy/routes.d.ts",
|
|
68
|
+
"import": "./dist/runtime/react-router/legacy/routes.js"
|
|
69
69
|
},
|
|
70
70
|
"./react-router/preset": {
|
|
71
71
|
"types": "./dist/runtime/react-router/preset.d.ts",
|
|
@@ -96,6 +96,10 @@
|
|
|
96
96
|
"types": "./dist/runtime/paths/index.d.ts",
|
|
97
97
|
"import": "./dist/runtime/paths/index.js"
|
|
98
98
|
},
|
|
99
|
+
"./routes": {
|
|
100
|
+
"types": "./dist/runtime/routes/index.d.ts",
|
|
101
|
+
"import": "./dist/runtime/routes/index.js"
|
|
102
|
+
},
|
|
99
103
|
"./vite": {
|
|
100
104
|
"types": "./dist/build/vite/index.d.ts",
|
|
101
105
|
"import": "./dist/build/vite/index.js"
|
|
@@ -114,13 +118,13 @@
|
|
|
114
118
|
},
|
|
115
119
|
"scripts": {
|
|
116
120
|
"build": "pnpm run clean && tsc -b tsconfig.json && chmod +x dist/cli/index.js",
|
|
117
|
-
"build:bundle": "node scripts/bundle-cli.mjs && node scripts/bundle-sveltekit.mjs",
|
|
121
|
+
"build:bundle": "node scripts/bundle-cli.mjs && node scripts/bundle-routes.mjs && node scripts/bundle-sveltekit.mjs",
|
|
118
122
|
"check:types": "tsc -b tsconfig.json && tsc -p tsconfig.test.json",
|
|
119
123
|
"start": "tsx src/cli/index.ts",
|
|
120
124
|
"install-cli": "pnpm build && node scripts/install-cli.mjs",
|
|
121
125
|
"publish-cli": "node scripts/publish-tarball.mjs",
|
|
122
126
|
"publish:npm": "node scripts/publish-npm.mjs",
|
|
123
|
-
"prepublishOnly": "pnpm run build && pnpm run build:bundle",
|
|
127
|
+
"prepublishOnly": "pnpm -F @fimo/routes build && pnpm run build && pnpm run build:bundle",
|
|
124
128
|
"release:bump": "node scripts/bump-version.mjs",
|
|
125
129
|
"publish:dry-run": "npm publish --dry-run",
|
|
126
130
|
"postinstall": "node scripts/postinstall.mjs",
|
|
@@ -152,6 +156,7 @@
|
|
|
152
156
|
"@fimo/cli-kit": "workspace:*",
|
|
153
157
|
"@fimo/framework-detect": "workspace:*",
|
|
154
158
|
"@fimo/mcp": "workspace:*",
|
|
159
|
+
"@fimo/routes": "workspace:*",
|
|
155
160
|
"@fimo/tsconfig": "workspace:*",
|
|
156
161
|
"@modelcontextprotocol/sdk": "1.27.1",
|
|
157
162
|
"@sveltejs/adapter-vercel": "6.3.4",
|
|
@@ -2,16 +2,24 @@
|
|
|
2
2
|
"runtime": { "framework": "astro" },
|
|
3
3
|
"i18n": {
|
|
4
4
|
"defaultLocale": "en",
|
|
5
|
-
"locales": ["en"]
|
|
6
|
-
"routing": { "strategy": "path-prefix" }
|
|
5
|
+
"locales": ["en"]
|
|
7
6
|
},
|
|
8
7
|
"routes": {
|
|
9
|
-
"home": {
|
|
10
|
-
|
|
8
|
+
"home": {
|
|
9
|
+
"label": "Home",
|
|
10
|
+
"path": "/:locale",
|
|
11
|
+
"params": { "locale": { "type": "locale", "optional": true } }
|
|
12
|
+
},
|
|
13
|
+
"projects": {
|
|
14
|
+
"label": "Projects",
|
|
15
|
+
"path": "/:locale/projects",
|
|
16
|
+
"params": { "locale": { "type": "locale", "optional": true } }
|
|
17
|
+
},
|
|
11
18
|
"project": {
|
|
12
19
|
"label": "Project",
|
|
13
|
-
"path": "/projects/:slug",
|
|
20
|
+
"path": "/:locale/projects/:slug",
|
|
14
21
|
"params": {
|
|
22
|
+
"locale": { "type": "locale", "optional": true },
|
|
15
23
|
"slug": { "schema": "Project", "queryField": "slug", "displayField": "title" }
|
|
16
24
|
}
|
|
17
25
|
}
|
|
@@ -27,7 +27,11 @@ a code-only task, or use `npx fimo@latest` for project-local code generation and
|
|
|
27
27
|
## Project rules
|
|
28
28
|
|
|
29
29
|
- **Deploy is on-demand**, not a save step. Batch related edits into one deploy.
|
|
30
|
-
-
|
|
30
|
+
- With pnpm, run `pnpm install --config.dangerouslyAllowAllBuilds=true`; a bare install can skip the build scripts required by Fimo and the framework toolchain.
|
|
31
|
+
- Treat the user's language request as part of setup. The first explicitly requested locale is the primary locale; put it first and set it as `i18n.defaultLocale` in `.fimo/config.json`. If no language is requested, keep `en` and state that choice. Astro reads this configuration directly, keeps the default locale unprefixed, and prefixes the others.
|
|
32
|
+
- Preserve both the unprefixed default pages and the `[locale]` page tree. Astro has no optional single-segment file route, so the paired native pages keep one-locale URLs clean and allow another locale without changing the route shape. Use `Astro.currentLocale` for Fimo content reads, `getLabels`, and document language.
|
|
33
|
+
- Keep `.fimo/config.json#routes` as Studio metadata aligned with Astro's page files. It does not configure Astro routing.
|
|
34
|
+
- Astro owns routes, locale resolution, links, HTML language/direction, and SEO. Fimo connects to those decisions.
|
|
31
35
|
- Use generated schema clients, `getLabels({ locale })`, and native components from `fimo/astro/components` for editable values.
|
|
32
36
|
- Do not add React or a second deployment platform.
|
|
33
37
|
- Never edit `.fimo/project.json`; it links this directory to the remote project.
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { defineConfig } from 'astro/config';
|
|
2
2
|
import { fimo } from 'fimo/astro/config';
|
|
3
3
|
|
|
4
|
+
import fimoConfig from './.fimo/config.json' with { type: 'json' };
|
|
5
|
+
|
|
4
6
|
export default defineConfig({
|
|
5
7
|
integrations: [fimo()],
|
|
8
|
+
i18n: {
|
|
9
|
+
defaultLocale: fimoConfig.i18n.defaultLocale,
|
|
10
|
+
locales: fimoConfig.i18n.locales,
|
|
11
|
+
routing: { prefixDefaultLocale: false },
|
|
12
|
+
},
|
|
6
13
|
output: 'server',
|
|
7
14
|
});
|
|
@@ -6,11 +6,14 @@ import * as Project from '../schemas/Project';
|
|
|
6
6
|
import * as SiteSettings from '../schemas/SiteSettings';
|
|
7
7
|
|
|
8
8
|
interface Props {
|
|
9
|
-
locale:
|
|
9
|
+
locale: string;
|
|
10
|
+
localePrefix?: string;
|
|
10
11
|
rendering: 'static' | 'server';
|
|
11
12
|
}
|
|
12
13
|
|
|
13
|
-
const { locale, rendering } = Astro.props;
|
|
14
|
+
const { locale, localePrefix, rendering } = Astro.props;
|
|
15
|
+
const prefix = localePrefix ? `/${localePrefix}` : '';
|
|
16
|
+
const localize = (path: string) => `${prefix}${path}`;
|
|
14
17
|
const [settings, projects, labels] = await Promise.all([
|
|
15
18
|
SiteSettings.get({ locale }),
|
|
16
19
|
Project.list({ locale, limit: 12 }),
|
|
@@ -19,13 +22,13 @@ const [settings, projects, labels] = await Promise.all([
|
|
|
19
22
|
---
|
|
20
23
|
|
|
21
24
|
<main data-framework="astro" data-rendering={rendering} data-locale={locale} data-fimo-starter="projects">
|
|
22
|
-
<nav aria-label="
|
|
23
|
-
<a href=
|
|
25
|
+
<nav aria-label="Primary">
|
|
26
|
+
<a href={localize('/')}>Home</a>
|
|
24
27
|
</nav>
|
|
25
28
|
<header>
|
|
26
29
|
<Text as="h1" value={settings.studioName} />
|
|
27
30
|
<Text as="p" value={settings.intro} />
|
|
28
|
-
<a href=
|
|
31
|
+
<a href={localize('/projects')}><Text as="span" value={labels.t('navigation.projects')} /></a>
|
|
29
32
|
</header>
|
|
30
33
|
<section>
|
|
31
34
|
<Text as="h2" value={labels.t('projects.heading')} />
|
|
@@ -34,7 +37,7 @@ const [settings, projects, labels] = await Promise.all([
|
|
|
34
37
|
<article data-project-slug={String(project.slug)}>
|
|
35
38
|
<Text as="h3" value={project.title} />
|
|
36
39
|
<Text as="p" value={project.summary} />
|
|
37
|
-
<a href={`/projects/${String(project.slug)}`}><Text as="span" value={project.title} /></a>
|
|
40
|
+
<a href={localize(`/projects/${String(project.slug)}`)}><Text as="span" value={project.title} /></a>
|
|
38
41
|
</article>
|
|
39
42
|
))
|
|
40
43
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
import ProjectOverview from '../../components/ProjectOverview.astro';
|
|
3
|
+
import Base from '../../layouts/Base.astro';
|
|
4
|
+
import { prefixedLocales } from '../../locales';
|
|
5
|
+
|
|
6
|
+
export const prerender = false;
|
|
7
|
+
|
|
8
|
+
const routeLocale = Astro.params.locale;
|
|
9
|
+
|
|
10
|
+
if (!routeLocale || !prefixedLocales.has(routeLocale)) {
|
|
11
|
+
return new Response(null, { status: 404, statusText: 'Not found' });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const locale = Astro.currentLocale ?? routeLocale;
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
<Base lang={locale} title="Fimo + Astro">
|
|
18
|
+
<ProjectOverview {locale} localePrefix={locale} rendering="server" />
|
|
19
|
+
</Base>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { getLabels } from 'fimo/astro';
|
|
3
|
+
import { Text } from 'fimo/astro/components';
|
|
4
|
+
|
|
5
|
+
import Base from '../../../layouts/Base.astro';
|
|
6
|
+
import { prefixedLocales } from '../../../locales';
|
|
7
|
+
import * as Project from '../../../schemas/Project';
|
|
8
|
+
|
|
9
|
+
export const prerender = false;
|
|
10
|
+
|
|
11
|
+
const routeLocale = Astro.params.locale;
|
|
12
|
+
const slug = Astro.params.slug ?? '';
|
|
13
|
+
|
|
14
|
+
if (!routeLocale || !prefixedLocales.has(routeLocale)) {
|
|
15
|
+
return new Response(null, { status: 404, statusText: 'Not found' });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const locale = Astro.currentLocale ?? routeLocale;
|
|
19
|
+
|
|
20
|
+
const [project, labels] = await Promise.all([Project.getBySlug(slug, { locale }), getLabels({ locale })]);
|
|
21
|
+
|
|
22
|
+
if (!project) {
|
|
23
|
+
return Astro.redirect('/404');
|
|
24
|
+
}
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
<Base lang={locale} title={String(project.title)}>
|
|
28
|
+
<main data-framework="astro" data-rendering="server" data-project-slug={slug}>
|
|
29
|
+
<a href={`/${locale}/projects`}><Text as="span" value={labels.t('navigation.projects')} /></a>
|
|
30
|
+
<article>
|
|
31
|
+
<Text as="h1" value={project.title} />
|
|
32
|
+
<Text as="p" value={project.summary} />
|
|
33
|
+
</article>
|
|
34
|
+
</main>
|
|
35
|
+
</Base>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
import ProjectOverview from '../../../components/ProjectOverview.astro';
|
|
3
|
+
import Base from '../../../layouts/Base.astro';
|
|
4
|
+
import { prefixedLocales } from '../../../locales';
|
|
5
|
+
|
|
6
|
+
export const prerender = false;
|
|
7
|
+
|
|
8
|
+
const routeLocale = Astro.params.locale;
|
|
9
|
+
|
|
10
|
+
if (!routeLocale || !prefixedLocales.has(routeLocale)) {
|
|
11
|
+
return new Response(null, { status: 404, statusText: 'Not found' });
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const locale = Astro.currentLocale ?? routeLocale;
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
<Base lang={locale} title="Projects">
|
|
18
|
+
<ProjectOverview {locale} localePrefix={locale} rendering="server" />
|
|
19
|
+
</Base>
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
import ProjectOverview from '../components/ProjectOverview.astro';
|
|
3
3
|
import Base from '../layouts/Base.astro';
|
|
4
|
+
import { defaultLocale } from '../locales';
|
|
4
5
|
|
|
5
6
|
export const prerender = true;
|
|
7
|
+
|
|
8
|
+
const locale = Astro.currentLocale ?? defaultLocale;
|
|
6
9
|
---
|
|
7
10
|
|
|
8
|
-
<Base lang=
|
|
9
|
-
<ProjectOverview locale
|
|
11
|
+
<Base lang={locale} title="Fimo + Astro">
|
|
12
|
+
<ProjectOverview {locale} rendering="static" />
|
|
10
13
|
</Base>
|
|
@@ -3,19 +3,21 @@ import { getLabels } from 'fimo/astro';
|
|
|
3
3
|
import { Text } from 'fimo/astro/components';
|
|
4
4
|
|
|
5
5
|
import Base from '../../layouts/Base.astro';
|
|
6
|
+
import { defaultLocale } from '../../locales';
|
|
6
7
|
import * as Project from '../../schemas/Project';
|
|
7
8
|
|
|
8
9
|
export const prerender = false;
|
|
9
10
|
|
|
11
|
+
const locale = Astro.currentLocale ?? defaultLocale;
|
|
10
12
|
const slug = Astro.params.slug ?? '';
|
|
11
|
-
const [project, labels] = await Promise.all([Project.getBySlug(slug, { locale
|
|
13
|
+
const [project, labels] = await Promise.all([Project.getBySlug(slug, { locale }), getLabels({ locale })]);
|
|
12
14
|
|
|
13
15
|
if (!project) {
|
|
14
16
|
return Astro.redirect('/404');
|
|
15
17
|
}
|
|
16
18
|
---
|
|
17
19
|
|
|
18
|
-
<Base lang=
|
|
20
|
+
<Base lang={locale} title={String(project.title)}>
|
|
19
21
|
<main data-framework="astro" data-rendering="server" data-project-slug={slug}>
|
|
20
22
|
<a href="/projects"><Text as="span" value={labels.t('navigation.projects')} /></a>
|
|
21
23
|
<article>
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
import ProjectOverview from '../../components/ProjectOverview.astro';
|
|
3
3
|
import Base from '../../layouts/Base.astro';
|
|
4
|
+
import { defaultLocale } from '../../locales';
|
|
4
5
|
|
|
5
6
|
export const prerender = false;
|
|
7
|
+
|
|
8
|
+
const locale = Astro.currentLocale ?? defaultLocale;
|
|
6
9
|
---
|
|
7
10
|
|
|
8
|
-
<Base lang=
|
|
9
|
-
<ProjectOverview locale
|
|
11
|
+
<Base lang={locale} title="Projects">
|
|
12
|
+
<ProjectOverview {locale} rendering="server" />
|
|
10
13
|
</Base>
|
|
@@ -35,6 +35,11 @@ The scaffolded homepage is disposable. Replace it on the first real generation.
|
|
|
35
35
|
## Project rules
|
|
36
36
|
|
|
37
37
|
- **Deploy is on-demand**, not a save step. Batch related edits into one deploy.
|
|
38
|
+
- With pnpm, run `pnpm install --config.dangerouslyAllowAllBuilds=true`; a bare install can skip the build scripts required by Fimo and the framework toolchain.
|
|
39
|
+
- Treat the user's language request as part of setup. The first explicitly requested locale is the primary locale; put it first and set it as `i18n.defaultLocale` in `.fimo/config.json`, with every requested locale in `i18n.locales`. If no language is requested, keep `en` and state that choice. That file is the only place to change: `src/locales.ts` reads it, so the served language, `<html lang>`, and the prefixed URLs follow. Never introduce a default-locale environment variable.
|
|
40
|
+
- Preserve the unprefixed `app/(default)` route group and the native `app/[locale]` boundary. Each is its own root layout, so each renders `src/components/Document.tsx` with the locale that tree serves; that is what makes `<html lang>` and the Fimo locale context correct on both. Mirror new routes in both groups when they are localized. Next.js has no optional single-segment folder, so do not replace this small pattern with middleware, rewrites, or a catch-all locale router.
|
|
41
|
+
- Keep the client-only `src/components/FimoPreviewBridge.tsx` inside `Document`. It reports the native Next pathname and settled locale to Studio and sends Studio navigation through Next's router; keep Next imports out of Fimo's shared runtime.
|
|
42
|
+
- Keep `.fimo/config.json#routes` as Studio metadata, not as the Next.js router. In that metadata, `params.locale.optional: true` means omit the configured default locale from the URL; use `optional: false` only when every locale, including the default, must be prefixed.
|
|
38
43
|
- The application owns routes, locale resolution, links, HTML language/direction, and SEO. Fimo connects to those decisions.
|
|
39
44
|
- Do not add a second deployment platform.
|
|
40
45
|
- Never edit `.fimo/project.json`; it links this directory to the remote project.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import Document from '../../components/Document';
|
|
4
|
+
import { defaultLocale } from '../../locales';
|
|
5
|
+
|
|
6
|
+
import '../globals.css';
|
|
7
|
+
|
|
8
|
+
export default function DefaultLocaleLayout({ children }: Readonly<{ children: ReactNode }>) {
|
|
9
|
+
return <Document locale={defaultLocale}>{children}</Document>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { notFound } from 'next/navigation';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
import Document from '../../components/Document';
|
|
5
|
+
import { prefixedLocales } from '../../locales';
|
|
6
|
+
|
|
7
|
+
import '../globals.css';
|
|
8
|
+
|
|
9
|
+
export default async function LocaleLayout({
|
|
10
|
+
children,
|
|
11
|
+
params,
|
|
12
|
+
}: Readonly<{ children: ReactNode; params: Promise<{ locale: string }> }>) {
|
|
13
|
+
const { locale } = await params;
|
|
14
|
+
|
|
15
|
+
// The default locale is served unprefixed by `app/(default)`, so its prefix
|
|
16
|
+
// is not a second URL for the same page.
|
|
17
|
+
if (!prefixedLocales.has(locale)) {
|
|
18
|
+
notFound();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return <Document locale={locale}>{children}</Document>;
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '../(default)/page';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { FimoProvider } from 'fimo/next/client';
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
import FimoPreviewBridge from './FimoPreviewBridge';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The HTML document for one locale tree. Only a root layout may render `<html>`
|
|
8
|
+
* in the App Router, so each locale tree has its own root layout and renders
|
|
9
|
+
* this with the locale that tree serves. That is what makes `<html lang>` and
|
|
10
|
+
* the Fimo locale context correct on both the unprefixed and prefixed routes.
|
|
11
|
+
*/
|
|
12
|
+
export default function Document({ children, locale }: Readonly<{ children: ReactNode; locale: string }>) {
|
|
13
|
+
const previewScriptUrl = process.env.NEXT_PUBLIC_FIMO_PREVIEW_SCRIPT_URL;
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<html lang={locale}>
|
|
17
|
+
<body>
|
|
18
|
+
<FimoProvider locale={locale}>
|
|
19
|
+
<FimoPreviewBridge />
|
|
20
|
+
{children}
|
|
21
|
+
</FimoProvider>
|
|
22
|
+
{previewScriptUrl ? <script src={previewScriptUrl} defer /> : null}
|
|
23
|
+
</body>
|
|
24
|
+
</html>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { FimoPreviewBridge as RuntimeFimoPreviewBridge } from 'fimo/next/client';
|
|
4
|
+
import { usePathname, useRouter } from 'next/navigation';
|
|
5
|
+
import { useCallback } from 'react';
|
|
6
|
+
|
|
7
|
+
export default function FimoPreviewBridge() {
|
|
8
|
+
const pathname = usePathname();
|
|
9
|
+
const router = useRouter();
|
|
10
|
+
const navigate = useCallback((to: string) => router.push(to), [router]);
|
|
11
|
+
|
|
12
|
+
return <RuntimeFimoPreviewBridge pathname={pathname} navigate={navigate} />;
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import fimoConfig from '../.fimo/config.json';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Locale policy read from the same file Fimo and Studio read, so the site
|
|
5
|
+
* language cannot drift from the project configuration. Change the locales in
|
|
6
|
+
* `.fimo/config.json#i18n`; nothing here needs editing.
|
|
7
|
+
*/
|
|
8
|
+
export const defaultLocale: string = fimoConfig.i18n.defaultLocale;
|
|
9
|
+
|
|
10
|
+
/** Only non-default locales carry a URL prefix; the default locale stays at the site root. */
|
|
11
|
+
export const prefixedLocales: ReadonlySet<string> = new Set(
|
|
12
|
+
fimoConfig.i18n.locales.filter((locale) => locale !== defaultLocale)
|
|
13
|
+
);
|
|
@@ -11,16 +11,13 @@
|
|
|
11
11
|
},
|
|
12
12
|
"i18n": {
|
|
13
13
|
"defaultLocale": "en",
|
|
14
|
-
"locales": ["en"]
|
|
15
|
-
"routing": {
|
|
16
|
-
"strategy": "path-prefix",
|
|
17
|
-
"prefixDefaultLocale": false
|
|
18
|
-
}
|
|
14
|
+
"locales": ["en"]
|
|
19
15
|
},
|
|
20
16
|
"routes": {
|
|
21
17
|
"home": {
|
|
22
18
|
"label": "Home",
|
|
23
|
-
"path": "
|
|
19
|
+
"path": "/:locale",
|
|
20
|
+
"params": { "locale": { "type": "locale", "optional": true } },
|
|
24
21
|
"seo": {
|
|
25
22
|
"title": "Home",
|
|
26
23
|
"description": "Welcome"
|
|
@@ -40,6 +40,10 @@ breaks that. Load `fimo-code` for the exact primitives, but the rule is:
|
|
|
40
40
|
## Project rules
|
|
41
41
|
|
|
42
42
|
- **Deploy is on-demand**, not a save step. Batch related edits into one deploy.
|
|
43
|
+
- With pnpm, run `pnpm install --config.dangerouslyAllowAllBuilds=true`; a bare install can skip the build scripts required by Fimo and the framework toolchain.
|
|
44
|
+
- Treat the user's language request as part of setup. The first explicitly requested locale is the primary locale; put it first and set it as `i18n.defaultLocale` in `.fimo/config.json`. If no language is requested, keep `en` and state that choice.
|
|
45
|
+
- Preserve the application-owned `:locale?` route boundary in `src/routes.ts` and pass its route parameter to `FimoProviders` in `LocaleLayout.tsx`. The missing parameter uses the configured default, so a one-locale site stays at `/`. Add locales in `.fimo/config.json` without rebuilding the route tree; use `:locale` without `?` only when every locale must be prefixed.
|
|
46
|
+
- Keep `.fimo/config.json#routes` aligned as Studio metadata, not as the React Router source of truth. Do not add a global locale-routing strategy, a Fimo route helper, or a Fimo-owned route tree.
|
|
43
47
|
- Do not add a second deploy tool (Vercel, Netlify, etc.).
|
|
44
48
|
- **Never edit `.fimo/project.json`** — it links this folder to the remote project.
|
|
45
49
|
- **Keep `.fimo/config.json#runtime` true to the code** — framework, `dev`/`build`/`install` commands, output directory. Update it when you rename a package script, move the build output, or change framework; the reference is `fimo skills get fimo-code --ref frameworks/hosting`.
|
|
@@ -5,16 +5,10 @@ export default {
|
|
|
5
5
|
appDirectory: 'src',
|
|
6
6
|
ssr: false,
|
|
7
7
|
presets: [fimoPreset()],
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// import { getFimoPaths } from 'fimo/paths';
|
|
13
|
-
// prerender: async () => (await getFimoPaths()).map((p) => p.path),
|
|
14
|
-
//
|
|
15
|
-
// `getFimoPaths()` expands dynamic routes (e.g. `/blog/:slug`) by fetching
|
|
16
|
-
// schema entries from the content API. See `references/frameworks/react-router.md`
|
|
17
|
-
// in the fimo skill for the full setup pattern.
|
|
8
|
+
// Pages metadata is optional Studio editing context; it does not configure
|
|
9
|
+
// the app router or build-time paths. Existing projects that still need the
|
|
10
|
+
// legacy sitemap/simple-SSG helper can import `fimo/paths` in their own build
|
|
11
|
+
// configuration.
|
|
18
12
|
buildDirectory: 'dist',
|
|
19
13
|
// Feed Vite's dependency scanner the client entry + every route module.
|
|
20
14
|
// Without it React Router hands Vite an EMPTY entry list, nothing is
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FimoProviders } from 'fimo/react-router';
|
|
2
|
+
import { Outlet, useParams } from 'react-router';
|
|
3
|
+
|
|
4
|
+
export default function LocaleLayout() {
|
|
5
|
+
const { locale } = useParams();
|
|
6
|
+
|
|
7
|
+
return (
|
|
8
|
+
<FimoProviders locale={locale}>
|
|
9
|
+
<Outlet />
|
|
10
|
+
</FimoProviders>
|
|
11
|
+
);
|
|
12
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
2
|
-
import {
|
|
2
|
+
import { FimoScripts, loadFimoMetaData, buildFimoMeta, fimoHtmlProps } from 'fimo/react-router';
|
|
3
3
|
import React from 'react';
|
|
4
4
|
import type { MetaFunction } from 'react-router';
|
|
5
5
|
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from 'react-router';
|
|
@@ -45,9 +45,7 @@ export function Layout({ children }: { children: React.ReactNode }) {
|
|
|
45
45
|
export default function AppRoot() {
|
|
46
46
|
return (
|
|
47
47
|
<QueryClientProvider client={queryClient}>
|
|
48
|
-
<
|
|
49
|
-
<Outlet />
|
|
50
|
-
</FimoProviders>
|
|
48
|
+
<Outlet />
|
|
51
49
|
</QueryClientProvider>
|
|
52
50
|
);
|
|
53
51
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { RouteConfig } from '@react-router/dev/routes';
|
|
2
|
+
import { layout, route } from '@react-router/dev/routes';
|
|
3
3
|
|
|
4
4
|
// Examples of React Router route patterns:
|
|
5
5
|
// index('./pages/Index.tsx'),
|
|
@@ -12,4 +12,6 @@ import { fimoRoutes } from 'fimo/react-router/routes';
|
|
|
12
12
|
// route('settings', './pages/dashboard/Settings.tsx'),
|
|
13
13
|
// ]),
|
|
14
14
|
|
|
15
|
-
export default
|
|
15
|
+
export default [
|
|
16
|
+
layout('./pages/LocaleLayout.tsx', [route(':locale?', './pages/Index.tsx', { id: 'home' })]),
|
|
17
|
+
] satisfies RouteConfig;
|
|
@@ -27,6 +27,11 @@ a code-only task, or use `npx fimo@latest` for project-local code generation and
|
|
|
27
27
|
## Project rules
|
|
28
28
|
|
|
29
29
|
- **Deploy is on-demand**, not a save step. Batch related edits into one deploy.
|
|
30
|
+
- With pnpm, run `pnpm install --config.dangerouslyAllowAllBuilds=true`; a bare install can skip the build scripts required by Fimo and the framework toolchain.
|
|
31
|
+
- Treat the user's language request as part of setup. The first explicitly requested locale is the primary locale; put it first and set it as `i18n.defaultLocale` in `.fimo/config.json`. If no language is requested, keep `en` and state that choice. `src/locales.ts` derives the default and prefixed locale set from that config.
|
|
32
|
+
- Preserve the native `[[locale=locale]]` route boundary. The optional parameter keeps the default locale at `/`; the matcher prevents ordinary top-level routes from being mistaken for locales. The root server layout passes the tracked `event.params` through `resolveLocale`, then sends that locale to `getLabels` and `FimoProvider`. Remove the extra brackets only when every locale must be prefixed.
|
|
33
|
+
- Keep the document language request-aware: `src/hooks.server.ts` renders the initial `<html lang>`, and the root layout updates it after client navigation.
|
|
34
|
+
- Keep `.fimo/config.json#routes` as Studio metadata aligned with SvelteKit's route files. It does not configure SvelteKit routing.
|
|
30
35
|
- The application owns routes, locale resolution, links, HTML language/direction, and SEO. Fimo connects to those decisions.
|
|
31
36
|
- Do not add a second deployment platform.
|
|
32
37
|
- Never edit `.fimo/project.json`; it links this directory to the remote project.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Handle } from '@sveltejs/kit';
|
|
2
|
+
|
|
3
|
+
import { resolveLocale } from './locales';
|
|
4
|
+
|
|
5
|
+
export const handle: Handle = ({ event, resolve }) => {
|
|
6
|
+
const locale = resolveLocale(event.params);
|
|
7
|
+
|
|
8
|
+
return resolve(event, {
|
|
9
|
+
transformPageChunk: ({ html }) => html.replace('%lang%', locale),
|
|
10
|
+
});
|
|
11
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import fimoConfig from '../.fimo/config.json';
|
|
2
|
+
|
|
3
|
+
export const defaultLocale: string = fimoConfig.i18n.defaultLocale;
|
|
4
|
+
export const prefixedLocales = new Set(fimoConfig.i18n.locales.filter((locale) => locale !== defaultLocale));
|
|
5
|
+
|
|
6
|
+
export function resolveLocale(params: { locale?: string }): string {
|
|
7
|
+
return params.locale ?? defaultLocale;
|
|
8
|
+
}
|