diff --git a/web/app/[locale]/blog/cmux-finder/page.tsx b/web/app/[locale]/blog/cmux-finder/page.tsx new file mode 100644 index 000000000000..de95ed6c8bc5 --- /dev/null +++ b/web/app/[locale]/blog/cmux-finder/page.tsx @@ -0,0 +1,74 @@ +import { useTranslations } from "next-intl"; +import { getTranslations } from "next-intl/server"; +import { buildAlternates } from "../../../../i18n/seo"; +import { Link } from "../../../../i18n/navigation"; + +export async function generateMetadata({ + params, +}: { + params: Promise<{ locale: string }>; +}) { + const { locale } = await params; + const t = await getTranslations({ locale, namespace: "blog.cmuxFinder" }); + const rawKeywords = t.raw("metaKeywords"); + const keywords = Array.isArray(rawKeywords) + ? rawKeywords.filter((keyword): keyword is string => typeof keyword === "string") + : []; + return { + title: t("metaTitle"), + description: t("metaDescription"), + keywords, + openGraph: { + title: t("metaTitle"), + description: t("metaDescription"), + type: "article", + publishedTime: "2026-05-22T00:00:00Z", + }, + twitter: { + card: "summary_large_image", + title: t("metaTitle"), + description: t("metaDescription"), + }, + alternates: buildAlternates(locale, "/blog/cmux-finder"), + }; +} + +export default function CmuxFinderPage() { + const t = useTranslations("blog.posts.cmuxFinder"); + const tc = useTranslations("common"); + + return ( + <> +
+ + ← {tc("backToBlog")} + +
+ +

{t("title")}

+ + +