fimo 2.9.0-staging.4 → 2.9.0-staging.6

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.
@@ -1,4 +1,5 @@
1
1
  export * from './resolver.js';
2
2
  export * from './head.js';
3
+ export * from './schemas.js';
3
4
  export type { FimoSEO } from '../shared/fimo-config.types.js';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1,2 +1,3 @@
1
1
  export * from './resolver.js';
2
2
  export * from './head.js';
3
+ export * from './schemas.js';
@@ -28,6 +28,7 @@ import type { FimoRouteConfig, FimoSEO, RouteSEO } from '../shared/fimo-config.t
28
28
  */
29
29
  export declare const SEO_FIELD_KEYS: readonly ["title", "description", "siteName", "url", "image", "favicon", "twitterSite", "robots", "themeColor", "locale"];
30
30
  export declare function normalizePathname(pathname: string): string;
31
+ export declare function buildCanonicalUrl(seoUrl: string | undefined, pathname: string): string | undefined;
31
32
  /**
32
33
  * Whether one pattern matches one path, and how specific the match is (the
33
34
  * number of static segments it pinned down). Locale-aware: a pattern with a
@@ -46,6 +46,17 @@ export function normalizePathname(pathname) {
46
46
  }
47
47
  return normalized;
48
48
  }
49
+ export function buildCanonicalUrl(seoUrl, pathname) {
50
+ if (!seoUrl) {
51
+ return undefined;
52
+ }
53
+ try {
54
+ return new URL(normalizePathname(pathname), seoUrl).toString();
55
+ }
56
+ catch {
57
+ return undefined;
58
+ }
59
+ }
49
60
  /**
50
61
  * Whether one pattern matches one path, and how specific the match is (the
51
62
  * number of static segments it pinned down). Locale-aware: a pattern with a
@@ -0,0 +1,11 @@
1
+ import type { FimoSEO } from '../shared/fimo-config.types.js';
2
+ export type SiteSchema = Record<string, unknown>;
3
+ /**
4
+ * Schema.org Organization and WebSite for the whole site, built from global SEO.
5
+ * Returns nothing unless both `siteName` and `url` are set. Render each entry
6
+ * with `serializeJsonLd` in its own `<script type="application/ld+json">`.
7
+ */
8
+ export declare function buildSiteSchemas(seo?: FimoSEO): SiteSchema[];
9
+ /** JSON for a `<script type="application/ld+json">` body. Escapes `<` so a value cannot close the tag. */
10
+ export declare function serializeJsonLd(value: unknown): string;
11
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Schema.org Organization and WebSite for the whole site, built from global SEO.
3
+ * Returns nothing unless both `siteName` and `url` are set. Render each entry
4
+ * with `serializeJsonLd` in its own `<script type="application/ld+json">`.
5
+ */
6
+ export function buildSiteSchemas(seo = {}) {
7
+ if (!seo.siteName || !seo.url) {
8
+ return [];
9
+ }
10
+ const organization = {
11
+ '@context': 'https://schema.org',
12
+ '@type': 'Organization',
13
+ name: seo.siteName,
14
+ url: seo.url,
15
+ };
16
+ if (seo.favicon) {
17
+ organization.logo = seo.favicon;
18
+ }
19
+ const website = {
20
+ '@context': 'https://schema.org',
21
+ '@type': 'WebSite',
22
+ name: seo.siteName,
23
+ url: seo.url,
24
+ };
25
+ return [organization, website];
26
+ }
27
+ /** JSON for a `<script type="application/ld+json">` body. Escapes `<` so a value cannot close the tag. */
28
+ export function serializeJsonLd(value) {
29
+ return JSON.stringify(value).replace(/</g, '\\u003c');
30
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fimo",
3
- "version": "2.9.0-staging.4",
3
+ "version": "2.9.0-staging.6",
4
4
  "description": "Fimo CLI - create, deploy, and manage Fimo sites",
5
5
  "keywords": [
6
6
  "astro-component"
@@ -194,13 +194,13 @@
194
194
  "devDependencies": {
195
195
  "@clack/core": "^1.2.0",
196
196
  "@clack/prompts": "^1.2.0",
197
- "@fimo/agents-bundle": "2.9.0-staging.4",
198
- "@fimo/api-contracts": "2.9.0-staging.4",
199
- "@fimo/cli-kit": "2.9.0-staging.4",
200
- "@fimo/framework-detect": "2.9.0-staging.4",
201
- "@fimo/routes": "2.9.0-staging.4",
202
- "@fimo/sdk": "2.9.0-staging.4",
203
- "@fimo/tsconfig": "2.9.0-staging.4",
197
+ "@fimo/agents-bundle": "2.9.0-staging.6",
198
+ "@fimo/api-contracts": "2.9.0-staging.6",
199
+ "@fimo/cli-kit": "2.9.0-staging.6",
200
+ "@fimo/framework-detect": "2.9.0-staging.6",
201
+ "@fimo/routes": "2.9.0-staging.6",
202
+ "@fimo/sdk": "2.9.0-staging.6",
203
+ "@fimo/tsconfig": "2.9.0-staging.6",
204
204
  "@types/node": "22.18.6",
205
205
  "agent-install": "^0.0.5",
206
206
  "astro": "^7.1.6",
@@ -9,9 +9,9 @@
9
9
  "check": "astro sync && astro check"
10
10
  },
11
11
  "dependencies": {
12
- "fimo": "2.9.0-staging.4",
13
- "fimo-analytics": "2.9.0-staging.4",
14
- "fimo-astro": "2.9.0-staging.4",
12
+ "fimo": "2.9.0-staging.6",
13
+ "fimo-analytics": "2.9.0-staging.6",
14
+ "fimo-astro": "2.9.0-staging.6",
15
15
  "zod": "^4.4.3"
16
16
  },
17
17
  "devDependencies": {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  import Analytics from 'fimo-analytics/astro';
3
- import { resolveSeoForPath, toSeoHead, type FimoSEO } from 'fimo/seo';
3
+ import { buildSiteSchemas, resolveSeoForPath, serializeJsonLd, toSeoHead, type FimoSEO } from 'fimo/seo';
4
4
 
5
5
  import fimoConfig from '../../.fimo/config.json';
6
6
 
@@ -21,6 +21,7 @@ const head = toSeoHead({
21
21
  ...(title !== undefined ? { title } : {}),
22
22
  ...(description !== undefined ? { description } : {}),
23
23
  }, { canonicalUrl });
24
+ const siteSchemas = buildSiteSchemas(seo);
24
25
  ---
25
26
 
26
27
  <!doctype html>
@@ -31,6 +32,7 @@ const head = toSeoHead({
31
32
  <title>{head.title ?? 'Fimo + Astro'}</title>
32
33
  {head.meta.map((attributes) => <meta {...attributes} />)}
33
34
  {head.links.map((attributes) => <link {...attributes} />)}
35
+ {siteSchemas.map((schema) => <script type="application/ld+json" set:html={serializeJsonLd(schema)} />)}
34
36
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
35
37
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
36
38
  </head>
@@ -12,10 +12,10 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@tanstack/react-query": "^5.80.6",
15
- "fimo": "2.9.0-staging.4",
16
- "fimo-analytics": "2.9.0-staging.4",
17
- "fimo-next": "2.9.0-staging.4",
18
- "fimo-react": "2.9.0-staging.4",
15
+ "fimo": "2.9.0-staging.6",
16
+ "fimo-analytics": "2.9.0-staging.6",
17
+ "fimo-next": "2.9.0-staging.6",
18
+ "fimo-react": "2.9.0-staging.6",
19
19
  "next": "16.4.2",
20
20
  "react": "^19.2.7",
21
21
  "react-dom": "^19.2.7",
@@ -1,6 +1,7 @@
1
1
  import { Analytics } from 'fimo-analytics/next';
2
2
  import { FimoProvider } from 'fimo-next';
3
3
  import { toNextMetadata, toNextViewport } from 'fimo-next/seo';
4
+ import { buildSiteSchemas, serializeJsonLd } from 'fimo/seo';
4
5
  import { getFimoSeo } from 'fimo/seo/server';
5
6
  import type { ReactNode } from 'react';
6
7
 
@@ -15,6 +16,13 @@ export default function RootLayout({ children }: Readonly<{ children: ReactNode
15
16
  return (
16
17
  <html lang={defaultLocale}>
17
18
  <body>
19
+ {buildSiteSchemas(getFimoSeo()).map((schema) => (
20
+ <script
21
+ key={String(schema['@type'])}
22
+ type="application/ld+json"
23
+ dangerouslySetInnerHTML={{ __html: serializeJsonLd(schema) }}
24
+ />
25
+ ))}
18
26
  <FimoProvider locale={defaultLocale}>{children}</FimoProvider>
19
27
  <Analytics />
20
28
  </body>
@@ -21,11 +21,11 @@
21
21
  "cn": "0.2.4",
22
22
  "date-fns": "^4.1.0",
23
23
  "embla-carousel-react": "^8.6.0",
24
- "fimo": "2.9.0-staging.4",
25
- "fimo-analytics": "2.9.0-staging.4",
26
- "fimo-react": "2.9.0-staging.4",
27
- "fimo-react-router": "2.9.0-staging.4",
28
- "fimo-vite": "2.9.0-staging.4",
24
+ "fimo": "2.9.0-staging.6",
25
+ "fimo-analytics": "2.9.0-staging.6",
26
+ "fimo-react": "2.9.0-staging.6",
27
+ "fimo-react-router": "2.9.0-staging.6",
28
+ "fimo-vite": "2.9.0-staging.6",
29
29
  "input-otp": "^1.4.2",
30
30
  "isbot": "^5",
31
31
  "lucide-react": "^0.577.0",
@@ -11,9 +11,9 @@
11
11
  "prepare": "svelte-kit sync"
12
12
  },
13
13
  "dependencies": {
14
- "fimo": "2.9.0-staging.4",
15
- "fimo-analytics": "2.9.0-staging.4",
16
- "fimo-sveltekit": "2.9.0-staging.4",
14
+ "fimo": "2.9.0-staging.6",
15
+ "fimo-analytics": "2.9.0-staging.6",
16
+ "fimo-sveltekit": "2.9.0-staging.6",
17
17
  "zod": "^4.4.3"
18
18
  },
19
19
  "devDependencies": {
@@ -1,5 +1,5 @@
1
1
  import { getLabels } from 'fimo-sveltekit';
2
- import { resolveSeoForPath, toSeoHead } from 'fimo/seo';
2
+ import { buildSiteSchemas, resolveSeoForPath, serializeJsonLd, toSeoHead } from 'fimo/seo';
3
3
 
4
4
  import fimoConfig from '../../.fimo/config.json';
5
5
  import { resolveLocale } from '../locales';
@@ -11,6 +11,7 @@ export async function load(event) {
11
11
  return {
12
12
  locale,
13
13
  seoHead: toSeoHead(seo, { canonicalUrl: seo?.url ? new URL(event.url.pathname, seo.url).href : undefined }),
14
+ siteSchemas: buildSiteSchemas(seo).map(serializeJsonLd),
14
15
  labels: await getLabels({ event, locale }),
15
16
  };
16
17
  }
@@ -23,6 +23,9 @@
23
23
  {#each head.links as attributes}
24
24
  <link {...attributes} />
25
25
  {/each}
26
+ {#each data.siteSchemas as schema}
27
+ {@html `<script type="application/ld+json">${schema}</script>`}
28
+ {/each}
26
29
  </svelte:head>
27
30
 
28
31
  <FimoProvider labels={data.labels}>
@@ -11,11 +11,11 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "@tanstack/react-query": "^5.80.6",
14
- "fimo": "2.9.0-staging.4",
15
- "fimo-analytics": "2.9.0-staging.4",
16
- "fimo-react": "2.9.0-staging.4",
17
- "fimo-react-router": "2.9.0-staging.4",
18
- "fimo-vite": "2.9.0-staging.4",
14
+ "fimo": "2.9.0-staging.6",
15
+ "fimo-analytics": "2.9.0-staging.6",
16
+ "fimo-react": "2.9.0-staging.6",
17
+ "fimo-react-router": "2.9.0-staging.6",
18
+ "fimo-vite": "2.9.0-staging.6",
19
19
  "react": "^19.2.7",
20
20
  "react-dom": "^19.2.7",
21
21
  "react-router": "^8.3.0",