diff --git a/docs/404.mdx b/docs/404.mdx
new file mode 100644
index 00000000..d61a9739
--- /dev/null
+++ b/docs/404.mdx
@@ -0,0 +1,28 @@
+---
+title: "Page not found"
+description: "The page you're looking for isn't here. This site was rebuilt with a new structure, so older URLs no longer match."
+template: splash
+hero:
+ title: "Not Found"
+ tagline: "This site has a new structure, so older URLs no longer match. The content you want is likely one click away."
+---
+
+## Browse the guides
+
+Pick a guide that matches what you're building.
+
+- **[All guides](/guides/)**: Task-oriented how-tos for backends, frontends, auth, testing, and deployment.
+- **[Backends](/guides/backends/data-persistence/)**: Persist data, make HTTPS outcalls, schedule timers, and generate randomness.
+- **[Frontends](/guides/frontends/asset-canister/)**: Serve assets, integrate frameworks, configure custom domains, and certify responses.
+- **[Authentication](/guides/authentication/internet-identity/)**: Add passwordless login and verifiable user identity with Internet Identity.
+- **[Chain Fusion](/guides/chain-fusion/bitcoin/)**: Connect canisters to Bitcoin, Ethereum, and Solana.
+- **[Security](/guides/security/access-management/)**: Access control, encryption, DoS prevention, and safe upgrade patterns.
+
+## Other places to look
+
+- **[Quickstart](/getting-started/quickstart/)**: Build and deploy your first canister in minutes.
+- **[Concepts](/concepts/)**: Explanations of ICP architecture and design decisions.
+- **[Languages](/languages/)**: Language-specific guides for Rust and Motoko.
+- **[Reference](/reference/)**: Specifications, canister IDs, cycle costs, and glossary.
+
+You can also use the search bar at the top of the page to find what you need.
diff --git a/plugins/astro-agent-docs.mjs b/plugins/astro-agent-docs.mjs
index ddff8204..bd6bb6e7 100644
--- a/plugins/astro-agent-docs.mjs
+++ b/plugins/astro-agent-docs.mjs
@@ -664,13 +664,19 @@ export default function agentDocs() {
// because Twitter/X rejects SVG for social sharing previews.
const ogSvgPath = path.join(outDir, "og-image.svg");
if (fs.existsSync(ogSvgPath)) {
- const fontDir = path.resolve("node_modules/@fontsource/inter/files");
- const fontBuffers = ["400", "500", "600", "700"]
- .map((w) => {
- const p = path.join(fontDir, `inter-latin-${w}-normal.woff`);
- return fs.existsSync(p) ? fs.readFileSync(p) : null;
- })
- .filter(Boolean);
+ const interDir = path.resolve("node_modules/@fontsource/inter/files");
+ const newsreaderDir = path.resolve("node_modules/@fontsource/newsreader/files");
+ const loadFonts = (dir, prefix, weights) =>
+ weights
+ .map((w) => {
+ const p = path.join(dir, `${prefix}-latin-${w}-normal.woff`);
+ return fs.existsSync(p) ? fs.readFileSync(p) : null;
+ })
+ .filter(Boolean);
+ const fontBuffers = [
+ ...loadFonts(interDir, "inter", ["400", "500", "600", "700"]),
+ ...loadFonts(newsreaderDir, "newsreader", ["400", "500"]),
+ ];
const svg = fs.readFileSync(ogSvgPath, "utf-8");
const resvg = new Resvg(svg, {
@@ -679,6 +685,7 @@ export default function agentDocs() {
loadSystemFonts: false,
defaultFontFamily: "Inter",
sansSerifFamily: "Inter",
+ serifFamily: "Newsreader",
},
fitTo: { mode: "original" },
});
diff --git a/public/og-image.svg b/public/og-image.svg
index 578d5ae2..edacf043 100644
--- a/public/og-image.svg
+++ b/public/og-image.svg
@@ -17,8 +17,8 @@
Developer Docs
+ font-family="Newsreader,'Source Serif 4','EB Garamond',Georgia,ui-serif,serif"
+ font-size="86" font-weight="500" fill="#f0ebe0">Developer Docs
@@ -44,6 +45,11 @@ const { title = data.title } = data.hero || {};
color: var(--sl-color-white);
}
+ .tagline {
+ font-size: clamp(var(--sl-text-base), calc(0.0625rem + 2vw), var(--sl-text-xl));
+ color: var(--sl-color-gray-2);
+ }
+
@media (min-width: 50rem) {
.hero {
padding-block: clamp(2.5rem, calc(1rem + 10vmin), 10rem);