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
14 changes: 14 additions & 0 deletions packages/docs/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,18 @@ export default withNextra({
// would externalize it and fail to `require()` it at runtime. Transpiling the
// package makes Next bundle it instead of externalizing.
transpilePackages: ["@theguild/remark-mermaid"],
// Because midrender.com proxies /revideo* to this deployment via its
// *.vercel.app URL, Vercel automatically injects `X-Robots-Tag: noindex` on the
// proxied response, which would keep the docs out of Google. Setting the header
// here — at the source, before the response leaves this deployment — replaces
// that value so the proxy forwards a single, clean `index, follow`. basePath is
// applied to `source`, so `/:path*` covers every route under /revideo.
async headers() {
return [
{
source: "/:path*",
headers: [{key: "X-Robots-Tag", value: "index, follow"}],
},
];
},
});
5 changes: 0 additions & 5 deletions packages/docs/public/robots.txt

This file was deleted.

12 changes: 11 additions & 1 deletion packages/docs/src/app/docs/[[...mdxPath]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,17 @@ import {useMDXComponents} from "../../../../mdx-components";
export async function generateMetadata(props: {params: Promise<{mdxPath: string[]}>}) {
const params = await props.params;
const {metadata} = await importPage(params.mdxPath);
return metadata;
// Self-referencing canonical so Google settles on the new URL (important for
// the docs.re.video -> midrender.com/revideo/docs migration). Absolute URL:
// metadataBase doesn't include the "/revideo" basePath.
const path = params.mdxPath?.length ? `/${params.mdxPath.join("/")}` : "";
return {
...metadata,
alternates: {
...metadata?.alternates,
canonical: `https://midrender.com/revideo/docs${path}`,
},
};
}

const Wrapper = useMDXComponents().wrapper;
Expand Down
4 changes: 4 additions & 0 deletions packages/docs/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export const metadata: Metadata = {
title: 'Revideo',
description:
'Revideo, the open-source framework for programmatic video creation, is now part of Midrender.',
// Absolute canonical: metadataBase doesn't include the "/revideo" basePath.
alternates: {
canonical: 'https://midrender.com/revideo',
},
openGraph: {
title: 'The next chapter of Revideo',
description:
Expand Down
13 changes: 13 additions & 0 deletions packages/docs/src/app/robots.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type {MetadataRoute} from "next";

// NOTE: with basePath "/revideo" this is served at /revideo/robots.txt. Crawlers
// only read robots.txt from the domain root (midrender.com/robots.txt), which is
// owned by the main app, so the authoritative robots.txt must live there and
// reference this sitemap. This file keeps the docs zone self-describing and works
// if the docs are ever served on their own domain.
export default function robots(): MetadataRoute.Robots {
return {
rules: {userAgent: "*", allow: "/"},
sitemap: "https://midrender.com/revideo/sitemap.xml",
};
}
40 changes: 40 additions & 0 deletions packages/docs/src/app/sitemap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type {MetadataRoute} from "next";
import {readdirSync, statSync} from "node:fs";
import {join, relative} from "node:path";

// Absolute origin (no basePath); the docs are served under midrender.com/revideo.
const ORIGIN = "https://midrender.com";
const CONTENT_DIR = join(process.cwd(), "src", "content");

/** Collect every doc page (content-relative route + last-modified time). */
function collect(dir: string, out: {route: string; mtime: Date}[]) {
for (const entry of readdirSync(dir)) {
const full = join(dir, entry);
const stat = statSync(full);
if (stat.isDirectory()) {
collect(full, out);
} else if (/\.mdx?$/.test(entry)) {
const route = relative(CONTENT_DIR, full)
.replace(/\\/g, "/")
.replace(/\.mdx?$/, "")
.replace(/(^|\/)index$/, ""); // index -> its folder
out.push({route, mtime: stat.mtime});
}
}
}

export default function sitemap(): MetadataRoute.Sitemap {
const pages: {route: string; mtime: Date}[] = [];
collect(CONTENT_DIR, pages);

const docs = pages
.map(({route, mtime}) => ({
url: `${ORIGIN}/revideo/docs${route ? `/${route}` : ""}`,
lastModified: mtime,
}))
.sort((a, b) => a.url.localeCompare(b.url));

// The marketing landing page lives at /revideo (app/page.tsx), outside the
// docs content tree, so add it explicitly.
return [{url: `${ORIGIN}/revideo`}, ...docs];
}
Loading