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
3 changes: 2 additions & 1 deletion website-next/app/blog/[...slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
import { compileDoc } from "@/src/helpers/compileDoc";
import { readFrontmatter } from "@/src/helpers/readFrontmatter";
import { estimateReadingTime } from "@/src/helpers/readingTime";
import { getShareImageSrc } from "@/src/image-optimization/manifest";
import { toAbsoluteUrl } from "@/src/helpers/siteUrl";

type BlogFrontmatter = {
Expand Down Expand Up @@ -88,7 +89,7 @@ export async function generateMetadata({
const stem = stemForSlug(slug);
const summary = listBlogPostSummaries().find((s) => s.stem === stem);
const featuredImageAbs = summary?.featuredImage
? toAbsoluteUrl(summary.featuredImage)
? toAbsoluteUrl(getShareImageSrc(summary.featuredImage))
: undefined;
const images = featuredImageAbs ? [featuredImageAbs] : undefined;

Expand Down
18 changes: 16 additions & 2 deletions website-next/app/blog/rss.xml/route.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { listBlogPostSummaries } from "@/src/helpers/blogPosts";
import { SITE_URL } from "@/src/helpers/siteUrl";
import { getShareImageSrc } from "@/src/image-optimization/manifest";

export const dynamic = "force-static";

Expand All @@ -16,6 +17,16 @@ function escape(text: string): string {
.replace(/'/g, "'");
}

function imageMimeType(src: string): string {
if (/\.jpe?g$/i.test(src)) {
return "image/jpeg";
}
if (/\.webp$/i.test(src)) {
return "image/webp";
}
return "image/png";
}

function asRfc822(iso: string): string {
const d = new Date(iso);
if (Number.isNaN(d.getTime())) {
Expand All @@ -32,8 +43,11 @@ export function GET() {
.map((post) => {
const url = `${SITE_URL}${post.href}`;
const description = post.description ?? "";
const enclosure = post.featuredImage
? `<enclosure url="${SITE_URL}${escape(post.featuredImage)}" type="image/png" />`
const shareImage = post.featuredImage
? getShareImageSrc(post.featuredImage)
: null;
const enclosure = shareImage
? `<enclosure url="${SITE_URL}${escape(shareImage)}" type="${imageMimeType(shareImage)}" />`
: "";
Comment thread
tobias-tengler marked this conversation as resolved.
const categories = post.tags
.map((tag) => `<category>${escape(tag)}</category>`)
Expand Down
21 changes: 21 additions & 0 deletions website-next/app/sitemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,33 @@ const EXCLUDED_PATHS = new Set(["/services/support/thank-you"]);

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
return [
...(await rootPages()),
...(await staticPages()),
...(await docsPages()),
...(await blogPosts()),
];
}

// Pages that live outside the `(content)` route group: the homepage and the
// docs/blog hub pages. These are the highest-value URLs on the site and must
// be listed explicitly since `staticPages()` only walks `(content)`.
async function rootPages(): Promise<MetadataRoute.Sitemap> {
const pages = [
{ file: path.join(process.cwd(), "app", "page.tsx"), urlPath: "/" },
{ file: path.join(process.cwd(), "app", "docs", "page.tsx"), urlPath: "/docs" },
{ file: path.join(process.cwd(), "app", "blog", "page.tsx"), urlPath: "/blog" },
];
return Promise.all(
pages.map(async ({ file, urlPath }) => ({
url: urlPath === "/" ? `${SITE_URL}/` : `${SITE_URL}${urlPath}`,
lastModified:
(await getLastModifiedFromGit(file)) ?? fs.statSync(file).mtime,
changeFrequency: "weekly" as const,
priority: urlPath === "/" ? 1 : 0.8,
})),
);
}

async function staticPages(): Promise<MetadataRoute.Sitemap> {
return Promise.all(
walk(CONTENT_PAGES_ROOT)
Expand Down
2 changes: 1 addition & 1 deletion website-next/content/blog/2026-05-11-hot-chocolate-16.md
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ These deserve their own posts, so I will keep this short. v16 ships two new adap
- **MCP**, a [Model Context Protocol](https://modelcontextprotocol.io/) server adapter that exposes GraphQL operations as MCP tools for LLM agents. It also supports agentic UI through the MCP app extension.
- **OpenAPI**, an adapter for projecting GraphQL operations as OpenAPI definitions.

Both will get their own posts in the next few weeks. If you do not want to wait, the docs are already up for the [MCP adapter](../docs/hotchocolate/guides/mcp-adapter.md) and the [OpenAPI adapter](../docs/hotchocolate/guides/openapi-adapter.md).
Both will get their own posts in the next few weeks. If you do not want to wait, the docs are already up for the [MCP adapter](../docs/hotchocolate/build/adapters/mcp.md) and the [OpenAPI adapter](../docs/hotchocolate/build/adapters/openapi.md).

## Wrapping up

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,4 +189,4 @@ Storage is registered but returned no definitions. With Nitro, ensure a publishe
## Next Steps

- Author tools and prompts and publish them with Nitro in the [Nitro MCP](../../../nitro/adapters/mcp.md) section.
- Customize how GraphQL errors surface in MCP tool results with [Error handling](../../guides/error-handling.md).
- Customize how GraphQL errors surface in MCP tool results with [Errors](../../resolvers/errors.md).
Original file line number Diff line number Diff line change
Expand Up @@ -272,5 +272,5 @@ The Fusion gateway composes schemas from multiple subgraphs. The OpenAPI adapter

# Next Steps

- [MCP Adapter](./mcp-adapter.md) to expose your GraphQL schema as MCP tools for AI agents.
- [Error Handling](./error-handling.md) to customize error responses in generated endpoints.
- [MCP](./mcp.md) to expose your GraphQL schema as MCP tools for AI agents.
- [Errors](../../resolvers/errors.md) to customize error responses in generated endpoints.
226 changes: 0 additions & 226 deletions website-next/content/docs/hotchocolate/guides/dynamic-schemas.md

This file was deleted.

Loading
Loading