mirror of
https://github.com/katanemo/plano.git
synced 2026-04-25 00:36:34 +02:00
* feat: redesign archgw -> plano + website * feat(www): refactor landing page sections, add new diagrams and UI improvements * feat(www): sections enhanced for clarify & diagrams added * feat(www): improvements to mobile design, layout of diagrams * feat(www): clean + typecheck * feat(www): feedback loop changes * feat(www): fix type error * fix lib/utils error * feat(www): ran biome formatting * feat(www): graphic changes * feat(www): web analytics * fea(www): changes * feat(www): introduce monorepo This change brings Turborepo monorepo to independently handle the marketing website, the docs website and any other future use cases for mutli-platform support. They are using internal @katanemo package handlers for the design system and logic. * fix(www): transpiler failure * fix(www): tsconfig issue * fix(www): next.config issue * feat(docs): hold off on docs * Delete next.config.ts * feat(www): content fix * feat(www): introduce blog * feat(www): content changes * Update package-lock.json * feat: update text * Update IntroSection.tsx * feat: Turbopack issue * fix * Update IntroSection.tsx * feat: updated Research page * refactor(www): text clarity, padding adj. * format(www) * fix: add missing lib/ files to git - fixes Vercel GitHub deployment - Updated .gitignore to properly exclude Python lib/ but include Next.js lib/ directories - Added packages/ui/src/lib/utils.ts (cn utility function) - Added apps/www/src/lib/sanity.ts (Sanity client configuration) - Fixes module resolution errors in Vercel GitHub deployments (case-sensitive filesystem) * Update .gitignore * style(www): favicon + metadata * fix(www): links * fix(www): add analytics * fix(www): add * fix(www): fix links + image * fix(www): fix links + image * fix(www): fix links * fix(www): remove from tools testing.md
120 lines
3.1 KiB
TypeScript
120 lines
3.1 KiB
TypeScript
import { Metadata } from "next";
|
|
import { client } from "@/lib/sanity";
|
|
|
|
type Params = Promise<{ slug: string }>;
|
|
|
|
interface BlogPost {
|
|
_id: string;
|
|
title: string;
|
|
slug: { current: string };
|
|
summary?: string;
|
|
publishedAt?: string;
|
|
author?: {
|
|
name?: string;
|
|
title?: string;
|
|
image?: any;
|
|
};
|
|
}
|
|
|
|
async function getBlogPost(slug: string): Promise<BlogPost | null> {
|
|
const query = `*[_type == "blog" && slug.current == $slug && published == true][0] {
|
|
_id,
|
|
title,
|
|
slug,
|
|
summary,
|
|
publishedAt,
|
|
author
|
|
}`;
|
|
|
|
const post = await client.fetch(query, { slug });
|
|
return post || null;
|
|
}
|
|
|
|
export async function generateMetadata({
|
|
params,
|
|
}: {
|
|
params: Params;
|
|
}): Promise<Metadata> {
|
|
try {
|
|
const resolvedParams = await params;
|
|
const post = await getBlogPost(resolvedParams.slug);
|
|
|
|
if (!post) {
|
|
return {
|
|
title: "Post Not Found - Plano",
|
|
description: "The requested blog post could not be found.",
|
|
};
|
|
}
|
|
|
|
// Get baseUrl - use NEXT_PUBLIC_APP_URL if set, otherwise construct from VERCEL_URL
|
|
// Restrict to allowed hosts: localhost:3000, archgw-tau.vercel.app, or plano.katanemo.com
|
|
let baseUrl = "http://localhost:3000";
|
|
|
|
if (process.env.NEXT_PUBLIC_APP_URL) {
|
|
const url = process.env.NEXT_PUBLIC_APP_URL;
|
|
if (
|
|
url.includes("archgw-tau.vercel.app") ||
|
|
url.includes("plano.katanemo.com") ||
|
|
url.includes("localhost:3000")
|
|
) {
|
|
baseUrl = url;
|
|
}
|
|
} else if (process.env.VERCEL_URL) {
|
|
const hostname = process.env.VERCEL_URL;
|
|
// VERCEL_URL is just the hostname, not the full URL
|
|
if (hostname === "archgw-tau.vercel.app") {
|
|
baseUrl = `https://${hostname}`;
|
|
} else if (hostname === "plano.katanemo.com") {
|
|
baseUrl = `https://${hostname}`;
|
|
}
|
|
}
|
|
|
|
const ogImageUrl = `${baseUrl}/api/og/${resolvedParams.slug}`;
|
|
|
|
const metadata: Metadata = {
|
|
title: `${post.title} - Plano Blog`,
|
|
description: post.summary || "Read more on Plano Blog",
|
|
openGraph: {
|
|
title: post.title,
|
|
description: post.summary || "Read more on Plano Blog",
|
|
type: "article",
|
|
publishedTime: post.publishedAt,
|
|
authors: post.author?.name ? [post.author.name] : undefined,
|
|
url: `${baseUrl}/blog/${resolvedParams.slug}`,
|
|
siteName: "Plano",
|
|
images: [
|
|
{
|
|
url: ogImageUrl,
|
|
width: 1200,
|
|
height: 630,
|
|
alt: post.title,
|
|
},
|
|
],
|
|
locale: "en_US",
|
|
},
|
|
twitter: {
|
|
card: "summary_large_image",
|
|
title: post.title,
|
|
description: post.summary || "Read more on Plano Blog",
|
|
images: [ogImageUrl],
|
|
},
|
|
};
|
|
|
|
return metadata;
|
|
} catch (error) {
|
|
console.error("Error generating metadata:", error);
|
|
return {
|
|
title: "Blog Post - Plano",
|
|
description: "Read this post on Plano Blog",
|
|
};
|
|
}
|
|
}
|
|
|
|
interface LayoutProps {
|
|
children: React.ReactNode;
|
|
params: Params;
|
|
}
|
|
|
|
export default async function Layout({ children, params }: LayoutProps) {
|
|
return <>{children}</>;
|
|
}
|