Skip to content

Commit

Permalink
Refactor community layout and enhance metadata generation
Browse files Browse the repository at this point in the history
- Replaced the `getCommunity` function with `fetchCommunity` to streamline data fetching.
- Introduced `generateMetadata` function to dynamically create Open Graph and Twitter card metadata based on community data.
- Added a new API route for generating OG images with customizable titles and accent colors.
- Improved layout styling to support dark mode and responsive design.
- Removed obsolete color adjustment function to simplify the codebase.
  • Loading branch information
tinypell3ts committed Jan 2, 2025
1 parent f2869a2 commit c803e75
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 18 deletions.
66 changes: 48 additions & 18 deletions src/app/[slug]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,45 @@
import { getCommunity } from "@/db";
import { fetchCommunity } from "@/lib/openformat";
import { cn } from "@/lib/utils";
import type { Metadata } from "next";

export async function generateMetadata({ params }: { params: { slug: string } }): Promise<Metadata> {
const community = await fetchCommunity(params.slug);

// Use VERCEL_URL in production, fallback to localhost in development
const baseUrl = process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
: process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000";

// Generate the OG image URL
const ogImageUrl =
community?.metadata?.banner_url ||
`${baseUrl}/api/og?title=${encodeURIComponent(
community?.metadata?.title || "Community"
)}&accent=${encodeURIComponent(community?.metadata?.accent_color || "#6366F1")}`;

return {
title: community?.metadata?.title ?? "Community",
description: community?.metadata?.description ?? "Welcome to our community",
openGraph: {
title: community?.metadata?.title ?? "Community",
description: community?.metadata?.description ?? "Welcome to our community",
images: [
{
url: ogImageUrl,
width: 1200,
height: 630,
alt: community?.metadata?.title ?? "Community",
},
],
},
twitter: {
card: "summary_large_image",
title: community?.metadata?.title ?? "Community",
description: community?.metadata?.description ?? "Welcome to our community",
images: [ogImageUrl],
},
};
}

export default async function ProfileLayout({
children,
Expand All @@ -8,27 +49,16 @@ export default async function ProfileLayout({
params: Promise<{ slug: string }>;
}) {
const slug = (await params).slug;
const community = await getCommunity(slug);
const community = await fetchCommunity(slug);

return (
<div
className="px-24 py-2"
style={{
background: community?.background_color
? `linear-gradient(to bottom, ${community.background_color}, ${adjustColor(community.background_color, -10)})`
: undefined,
}}
className={cn(
"md:px-24 h-full py-2 min-h-screen bg-background",
community?.metadata?.dark_mode ? "dark" : "light"
)}
>
{children}
</div>
);
}

// Helper function to darken/lighten hex colors
function adjustColor(color: string, amount: number): string {
const hex = color.replace("#", "");
const r = Math.max(Math.min(Number.parseInt(hex.substring(0, 2), 16) + amount, 255), 0);
const g = Math.max(Math.min(Number.parseInt(hex.substring(2, 4), 16) + amount, 255), 0);
const b = Math.max(Math.min(Number.parseInt(hex.substring(4, 6), 16) + amount, 255), 0);

return `#${r.toString(16).padStart(2, "0")}${g.toString(16).padStart(2, "0")}${b.toString(16).padStart(2, "0")}`;
}
55 changes: 55 additions & 0 deletions src/app/api/og/route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { getContrastSafeColor } from "@/lib/utils";
import { ImageResponse } from "next/og";

export const runtime = "edge";

export async function GET(request: Request) {
try {
const { searchParams } = new URL(request.url);
const title = searchParams.get("title") ?? "Community";
const accent = searchParams.get("accent") ?? "#6366F1";

// Simple gradient using the accent color (similar to community banner)
const gradient = `linear-gradient(45deg, ${accent}, ${accent}88)`;

return new ImageResponse(
(
<div
style={{
height: "100%",
width: "100%",
display: "flex",
flexDirection: "column",
alignItems: "flex-start", // Align to the left
justifyContent: "flex-end", // Align to the bottom
background: gradient,
fontFamily: "Manrope",
padding: "48px", // Add some padding
}}
>
<div
style={{
fontSize: 72,
fontWeight: 700,
color: getContrastSafeColor(accent),
textAlign: "left",
lineHeight: 1.1,
textShadow: "0 2px 4px rgba(0,0,0,0.1)",
}}
>
{title}
</div>
</div>
),
{
width: 1200,
height: 630,
}
);
} catch (e) {
console.log(`${e.message}`);
return new Response(`Failed to generate the image`, {
status: 500,
});
}
}

0 comments on commit c803e75

Please sign in to comment.