Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apps/docs/app/[lang]/blog/[[...slug]]/page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,6 +3,7 @@ import { blog } from '@/lib/source';
import { getMDXComponents } from '@/mdx-components';
import { HomeLayout } from 'fumadocs-ui/layouts/home';
import { baseOptions } from '@/lib/layout.shared';
import { absoluteUrl } from '@/lib/site';
import Link from 'next/link';
import { ArrowLeft } from 'lucide-react';

Expand DownExpand Up@@ -192,6 +193,9 @@ export async function generateMetadata({
return {
title: 'Blog',
description: 'Insights, updates, and best practices from the ObjectStack team.',
// The index has no MDX file behind it, so its route is spelled out here — the
// same literal `app/sitemap.ts` lists it under.
alternates: { canonical: absoluteUrl('/blog') },
};
}

Expand All@@ -204,5 +208,6 @@ export async function generateMetadata({
return {
title: page.data.title,
description: page.data.description,
alternates: { canonical: absoluteUrl(page.url) },
};
}
8 changes: 8 additions & 0 deletions apps/docs/app/[lang]/docs/[[...slug]]/page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ import { File, Folder, Files } from 'fumadocs-ui/components/files';
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
import { LLMCopyButton, ViewOptions } from '@/components/ai/page-actions';
import { gitConfig } from '@/lib/layout.shared';
import { absoluteUrl } from '@/lib/site';

export default async function Page(props: {
params: Promise<{ lang: string; slug?: string[] }>;
Expand DownExpand Up@@ -63,5 +64,12 @@ export async function generateMetadata(props: {
return {
title: page.data.title,
description: page.data.description,
/**
* `page.url` is the same locale-stripped route fumadocs uses for in-site links
* and that `app/sitemap.ts` lists, so the canonical link and the sitemap entry
* cannot drift apart. `absoluteUrl()` throws rather than emit a URL on another
* host if that ever stops being a site-relative path.
*/
alternates: { canonical: absoluteUrl(page.url) },
};
}
8 changes: 8 additions & 0 deletions apps/docs/app/[lang]/page.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,7 @@ import { ArrowRight, Check } from 'lucide-react';
import { Bricolage_Grotesque, IBM_Plex_Mono } from 'next/font/google';
import { HomeLayout } from 'fumadocs-ui/layouts/home';
import { baseOptions, gitConfig } from '@/lib/layout.shared';
import { absoluteUrl } from '@/lib/site';
import { YouTubeEmbed } from '@/components/youtube-embed';

/** The 90-second overview — the same video the README's hero cover links to. */
Expand All@@ -25,6 +26,13 @@ export const metadata: Metadata = {
title: 'Metadata framework for AI-written apps',
description:
'ObjectStack turns the whole app — data model, UI, workflows, permissions — into typed metadata: a complete CRM in under 150k tokens, one context window.',
/**
* `/` is the one indexable spelling of the homepage: `proxy.ts` rewrites `/` to
* this route internally, and the prefixed form `/en` 307s back to `/`. Every
* other spelling a crawler reaches it by — query strings, tracking parameters —
* points here.
*/
alternates: { canonical: absoluteUrl('/') },
};

const VOCABULARY: { tag: string; title: string; copy: string }[] = [
Expand Down
11 changes: 11 additions & 0 deletions apps/docs/app/layout.tsx
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
import './global.css';
import type { ReactNode } from 'react';
import type { Metadata } from 'next';
import { SITE_ORIGIN } from '@/lib/site';

export const metadata: Metadata = {
/**
* The origin every relative URL in this site's metadata resolves against —
* canonical links today, the Open Graph / Twitter image paths next. Left unset,
* Next resolves them against a build-time guess of the deployment's own origin,
* so a preview build would advertise itself as the real site.
*
* `new URL(...)` at the point of use, so `lib/site.ts` keeps exporting an
* immutable string rather than a `URL` instance shared across every route.
*/
metadataBase: new URL(SITE_ORIGIN),
title: {
template: '%s | ObjectStack',
default: 'ObjectStack',
Expand Down
Loading