Some checks are pending
Deploy to Cloudflare Workers (OpenNext) / deploy (push) Waiting to run
Use mainwhite.svg on white sections with curvy green transitions into flat green bands, improve text and button contrast, and deploy via OpenNext on Cloudflare Workers. Co-authored-by: Cursor <cursoragent@cursor.com>
107 lines
3.1 KiB
TypeScript
107 lines
3.1 KiB
TypeScript
import type { Metadata } from "next";
|
|
import { site } from "@/content/site";
|
|
|
|
export const SITE_URL =
|
|
process.env.NEXT_PUBLIC_SITE_URL?.replace(/\/$/, "") || "https://grvsummit.com";
|
|
|
|
export const defaultKeywords = [
|
|
"Great Rift Valley Innovation Summit",
|
|
"GRV Summit",
|
|
"Ethiopia innovation",
|
|
"Addis Ababa conference",
|
|
"EDTF",
|
|
"startup pitch Ethiopia",
|
|
"agriculture health education innovation",
|
|
"Skylight Hotel summit",
|
|
];
|
|
|
|
export const staticRoutes = [
|
|
{ path: "/", priority: 1, changeFrequency: "weekly" as const },
|
|
{ path: "/program", priority: 0.9, changeFrequency: "weekly" as const },
|
|
{ path: "/speakers", priority: 0.9, changeFrequency: "weekly" as const },
|
|
{ path: "/pitch-competition", priority: 0.9, changeFrequency: "weekly" as const },
|
|
{ path: "/partners", priority: 0.85, changeFrequency: "monthly" as const },
|
|
{ path: "/exhibit", priority: 0.85, changeFrequency: "monthly" as const },
|
|
{ path: "/sponsor", priority: 0.85, changeFrequency: "monthly" as const },
|
|
{ path: "/payment", priority: 0.8, changeFrequency: "weekly" as const },
|
|
{ path: "/contact", priority: 0.75, changeFrequency: "monthly" as const },
|
|
{ path: "/privacy", priority: 0.3, changeFrequency: "yearly" as const },
|
|
];
|
|
|
|
type PageMetaInput = {
|
|
title: string;
|
|
description: string;
|
|
path?: string;
|
|
keywords?: string[];
|
|
noIndex?: boolean;
|
|
ogImage?: string;
|
|
};
|
|
|
|
export function absoluteUrl(path = ""): string {
|
|
const normalized = path.startsWith("/") ? path : path ? `/${path}` : "";
|
|
return `${SITE_URL}${normalized}`;
|
|
}
|
|
|
|
export function createPageMetadata({
|
|
title,
|
|
description,
|
|
path = "",
|
|
keywords = [],
|
|
noIndex = false,
|
|
ogImage = "/branding/logo.png",
|
|
}: PageMetaInput): Metadata {
|
|
const url = absoluteUrl(path);
|
|
const fullTitle = title === site.name ? title : title;
|
|
const ogTitle = title.includes(site.shortName) ? title : `${title} | ${site.shortName}`;
|
|
|
|
return {
|
|
title: fullTitle,
|
|
description,
|
|
keywords: [...defaultKeywords, ...keywords],
|
|
alternates: { canonical: url },
|
|
robots: noIndex
|
|
? { index: false, follow: false }
|
|
: { index: true, follow: true, googleBot: { index: true, follow: true } },
|
|
openGraph: {
|
|
type: "website",
|
|
locale: "en_US",
|
|
url,
|
|
siteName: site.name,
|
|
title: ogTitle,
|
|
description,
|
|
images: [
|
|
{
|
|
url: ogImage,
|
|
width: 1200,
|
|
height: 630,
|
|
alt: site.name,
|
|
},
|
|
],
|
|
},
|
|
twitter: {
|
|
card: "summary_large_image",
|
|
title: ogTitle,
|
|
description,
|
|
images: [ogImage],
|
|
},
|
|
};
|
|
}
|
|
|
|
export const rootMetadata: Metadata = {
|
|
metadataBase: new URL(SITE_URL),
|
|
...createPageMetadata({
|
|
title: site.name,
|
|
description: `${site.tagline} ${site.dates.label} at ${site.venue.name}, ${site.venue.address}. Presented by ${site.presentedBy}.`,
|
|
path: "/",
|
|
}),
|
|
title: {
|
|
default: site.name,
|
|
template: `%s | ${site.shortName}`,
|
|
},
|
|
/** Static files in /public — avoids ImageResponse on Cloudflare Workers (500 on /favicon.ico). */
|
|
icons: {
|
|
icon: [{ url: "/favicon.ico", sizes: "any" }],
|
|
apple: "/apple-touch-icon.png",
|
|
},
|
|
};
|