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
43 changes: 42 additions & 1 deletion docs/app/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,55 @@
import { GitHubButton } from "@/app/(home)/components/GitHubButton/GitHubButton";
import { Footer } from "@/app/(home)/sections/Footer/Footer";
import { JsonLd } from "@/components/seo/JsonLd";
import { blogOgImage } from "@/lib/og/content";
import { ogImageUrl } from "@/lib/og/images";
import { withOgImage } from "@/lib/page-metadata";
import { blog } from "@/lib/source";
import { BASE_URL, blog } from "@/lib/source";
import { getMDXComponents } from "@/mdx-components";
import { TOCProvider, TOCScrollArea } from "fumadocs-ui/components/toc";
import { TOCItem, TOCItems } from "fumadocs-ui/components/toc/default";
import type { Metadata } from "next";
import { notFound } from "next/navigation";
import { BlogFaq } from "../components/BlogFaq";

type BlogSourcePage = NonNullable<ReturnType<typeof blog.getPage>>;

/* BlogPosting and breadcrumb structured data: gives Google the post's dates and author. */
function blogStructuredData(page: BlogSourcePage) {
const url = `${BASE_URL}${page.url}`;
const { title, description, author, date } = page.data;
return [
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"@id": `${url}#article`,
headline: title,
description,
image: `${BASE_URL}${ogImageUrl(blogOgImage(page))}`,
datePublished: new Date(date).toISOString(),
dateModified: new Date(date).toISOString(),
// Bylines are a person or a team ("Thesys Engineering Team").
author: { "@type": /\bteam\b/i.test(author) ? "Organization" : "Person", name: author },
publisher: {
"@type": "Organization",
"@id": "https://www.thesys.dev/#organization",
name: "Thesys",
url: "https://www.thesys.dev",
},
mainEntityOfPage: url,
url,
},
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
itemListElement: [
{ "@type": "ListItem", position: 1, name: "Blog", item: `${BASE_URL}/blog` },
{ "@type": "ListItem", position: 2, name: title, item: url },
],
},
];
}

export default async function BlogPostPage(props: { params: Promise<{ slug: string }> }) {
const params = await props.params;
const page = blog.getPage([params.slug]);
Expand All @@ -23,6 +63,7 @@ export default async function BlogPostPage(props: { params: Promise<{ slug: stri

return (
<TOCProvider toc={toc}>
<JsonLd data={blogStructuredData(page)} />
{/* Blend from the menu bar's surface color into a gray band, then back into the
footer's surface — matching the home content band (light: foreground->background->foreground;
dark: black -> neutral-950 -> black, so the edges meet the black menu + footer). */}
Expand Down
6 changes: 4 additions & 2 deletions docs/app/components/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type { PageMetadataInput } from "@/lib/page-metadata";

export default {
pathname: "/components",
title: "OpenUI Design System",
description: "Foundation, Blocks, and Compose documentation",
title: "Generative UI component library",
description:
"The OpenUI Design System: charts, tables, form inputs and layout blocks that agents compose into Generative UI, with design foundations and a theme builder.",
openGraph: { title: "OpenUI Design System" },
} satisfies PageMetadataInput;
7 changes: 7 additions & 0 deletions docs/app/sitemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ const STATIC_PATHS = [
"/chat",
"/demo/f1-dashboard",
"/demo/trip-planner",
"/demo/github",
"/pricing",
"/cloud/gateway",
"/cloud/gateway/models",
"/cloud/observability",
"/openclaw-os",
"/components",
"/blog",
"/benchmarks",
"/benchmarks/language",
Expand Down
31 changes: 29 additions & 2 deletions docs/components/docs-page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { LLMCopyButton, ViewOptions } from "@/components/ai/page-actions";
import { JsonLd } from "@/components/seo/JsonLd";
import { gitConfig } from "@/lib/layout.shared";
import { docsOgImage } from "@/lib/og/content";
import { ogImageUrl } from "@/lib/og/images";
import { withOgImage } from "@/lib/page-metadata";
import { source } from "@/lib/source";
import { BASE_URL, source } from "@/lib/source";
import { getMDXComponents, MdxLink } from "@/mdx-components";
import { DocsBody, DocsDescription, DocsPage, DocsTitle } from "fumadocs-ui/layouts/docs/page";
import { createRelativeLink } from "fumadocs-ui/mdx";
Expand All @@ -24,6 +26,7 @@ export function DocsPageView({ page }: { page: DocsSourcePage }) {
// Without a sidebar there is room for the `full` page width next to the TOC (see global.css).
data-no-sidebar={!page.data.sidebar || undefined}
>
<JsonLd data={docsStructuredData(page)} />
{!page.data.customHeader && (
<>
<DocsTitle>{page.data.title}</DocsTitle>
Expand Down Expand Up @@ -57,9 +60,33 @@ export function getDocsPageMetadata(page: DocsSourcePage): Metadata {
return withOgImage({ ...docsMetadata(page), description }, image, { description });
}

/* TechArticle structured data: gives Google the page's last-modified date and publisher. */
function docsStructuredData(page: DocsSourcePage) {
const url = `${BASE_URL}${page.url}`;
return {
"@context": "https://schema.org",
"@type": "TechArticle",
"@id": `${url}#article`,
headline: page.data.title,
description: page.data.description,
image: `${BASE_URL}${ogImageUrl(docsOgImage(page))}`,
...(page.data.lastModified && {
dateModified: new Date(page.data.lastModified).toISOString(),
}),
publisher: {
"@type": "Organization",
"@id": "https://www.thesys.dev/#organization",
name: "Thesys",
url: "https://www.thesys.dev",
},
mainEntityOfPage: url,
url,
};
}

function docsMetadata(page: DocsSourcePage): Metadata {
return {
title: page.data.title,
title: page.data.seoTitle ?? page.data.title,
description: page.data.description,
alternates: {
canonical: page.url,
Expand Down
12 changes: 12 additions & 0 deletions docs/components/seo/JsonLd.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Renders a JSON-LD structured-data block, server-rendered so crawlers see it in the initial HTML.
* `<` is escaped so text inside the data can't close the script tag.
*/
export function JsonLd({ data }: { data: Record<string, unknown> | Record<string, unknown>[] }) {
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(data).replaceAll("<", "\\u003c") }}
/>
);
}
1 change: 1 addition & 0 deletions docs/content/docs/api-reference/a2ui.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
title: "@openuidev/a2ui"
seoTitle: "A2UI v1.0 protocol client and React renderer with OpenUI Lang"
description: A2UI v1.0 protocol support with OpenUI Lang component updates and an optional React renderer.
---

Expand Down
2 changes: 1 addition & 1 deletion docs/content/docs/openui-lang/comparison.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: OpenUI vs others
title: OpenUI vs A2UI vs json-render vs OpenGenerativeUI
description: OpenUI vs json-render (Vercel), A2UI (Google), and CopilotKit OpenGenerativeUI.
---

Expand Down
2 changes: 2 additions & 0 deletions docs/source.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import lastModified from "fumadocs-mdx/plugins/last-modified";
import { z } from "zod";

const docsPageSchema = pageSchema.extend({
// Search title for <title>; the H1 and sidebar keep `title`.
seoTitle: z.string().optional(),
customHeader: z.boolean().optional().default(false),
// Hides the previous/next page links at the bottom of the page.
hideFooter: z.boolean().optional().default(false),
Expand Down
Loading