diff --git a/app/(docs)/docs/[[...slug]]/page.tsx b/app/(docs)/docs/[[...slug]]/page.tsx index 8c24a765..6edad185 100644 --- a/app/(docs)/docs/[[...slug]]/page.tsx +++ b/app/(docs)/docs/[[...slug]]/page.tsx @@ -1,18 +1,17 @@ -import { notFound } from "next/navigation"; import { allDocs } from "contentlayer/generated"; +import { notFound } from "next/navigation"; -import { getTableOfContents } from "@/lib/toc"; import { Mdx } from "@/components/content/mdx-components"; import { DocsPageHeader } from "@/components/docs/page-header"; import { DocsPager } from "@/components/docs/pager"; import { DashboardTableOfContents } from "@/components/shared/toc"; +import { getTableOfContents } from "@/lib/toc"; import "@/styles/mdx.css"; import { Metadata } from "next"; -import { env } from "@/env.mjs"; -import { absoluteUrl } from "@/lib/utils"; +import { constructMetadata } from "@/lib/utils"; interface DocPageProps { params: { @@ -24,9 +23,7 @@ async function getDocFromParams(params) { const slug = params.slug?.join("/") || ""; const doc = allDocs.find((doc) => doc.slugAsParams === slug); - if (!doc) { - null; - } + if (!doc) return null; return doc; } @@ -36,41 +33,14 @@ export async function generateMetadata({ }: DocPageProps): Promise { const doc = await getDocFromParams(params); - if (!doc) { - return {}; - } + if (!doc) return {}; - const url = env.NEXT_PUBLIC_APP_URL; - - const ogUrl = new URL(`${url}/api/og`); - ogUrl.searchParams.set("heading", doc.description ?? doc.title); - ogUrl.searchParams.set("type", "Documentation"); - ogUrl.searchParams.set("mode", "dark"); - - return { - title: doc.title, - description: doc.description, - openGraph: { - title: doc.title, - description: doc.description, - type: "article", - url: absoluteUrl(doc.slug), - images: [ - { - url: ogUrl.toString(), - width: 1200, - height: 630, - alt: doc.title, - }, - ], - }, - twitter: { - card: "summary_large_image", - title: doc.title, - description: doc.description, - images: [ogUrl.toString()], - }, - }; + const { title, description } = doc; + + return constructMetadata({ + title: `${title} – SaaS Starter`, + description: description, + }); } export async function generateStaticParams(): Promise< diff --git a/app/(docs)/guides/[...slug]/page.tsx b/app/(docs)/guides/[slug]/page.tsx similarity index 56% rename from app/(docs)/guides/[...slug]/page.tsx rename to app/(docs)/guides/[slug]/page.tsx index 9ea605bf..54e8dd25 100644 --- a/app/(docs)/guides/[...slug]/page.tsx +++ b/app/(docs)/guides/[slug]/page.tsx @@ -1,91 +1,53 @@ +import { allGuides } from "contentlayer/generated"; import Link from "next/link"; import { notFound } from "next/navigation"; -import { allGuides } from "contentlayer/generated"; -import { getTableOfContents } from "@/lib/toc"; import { Mdx } from "@/components/content/mdx-components"; import { DocsPageHeader } from "@/components/docs/page-header"; import { Icons } from "@/components/shared/icons"; import { DashboardTableOfContents } from "@/components/shared/toc"; +import { getTableOfContents } from "@/lib/toc"; import "@/styles/mdx.css"; import { Metadata } from "next"; -import { env } from "@/env.mjs"; -import { absoluteUrl, cn } from "@/lib/utils"; -import { buttonVariants } from "@/components/ui/button"; import MaxWidthWrapper from "@/components/shared/max-width-wrapper"; +import { buttonVariants } from "@/components/ui/button"; +import { cn, constructMetadata } from "@/lib/utils"; -interface GuidePageProps { - params: { - slug: string[]; - }; -} - -async function getGuideFromParams(params) { - const slug = params?.slug?.join("/"); - const guide = allGuides.find((guide) => guide.slugAsParams === slug); - - if (!guide) { - null; - } - - return guide; +export async function generateStaticParams() { + return allGuides.map((guide) => ({ + slug: guide.slugAsParams, + })); } export async function generateMetadata({ params, -}: GuidePageProps): Promise { - const guide = await getGuideFromParams(params); - +}: { + params: { slug: string }; +}): Promise { + const guide = allGuides.find((guide) => guide.slugAsParams === params.slug); if (!guide) { - return {}; + return; } - const url = env.NEXT_PUBLIC_APP_URL; + const { title, description } = guide; - const ogUrl = new URL(`${url}/api/og`); - ogUrl.searchParams.set("heading", guide.title); - ogUrl.searchParams.set("type", "Guide"); - ogUrl.searchParams.set("mode", "dark"); - - return { - title: guide.title, - description: guide.description, - openGraph: { - title: guide.title, - description: guide.description, - type: "article", - url: absoluteUrl(guide.slug), - images: [ - { - url: ogUrl.toString(), - width: 1200, - height: 630, - alt: guide.title, - }, - ], - }, - twitter: { - card: "summary_large_image", - title: guide.title, - description: guide.description, - images: [ogUrl.toString()], - }, - }; + return constructMetadata({ + title: `${title} – SaaS Starter`, + description: description, + }); } -export async function generateStaticParams(): Promise< - GuidePageProps["params"][] -> { - return allGuides.map((guide) => ({ - slug: guide.slugAsParams.split("/"), - })); -} - -export default async function GuidePage({ params }: GuidePageProps) { - const guide = await getGuideFromParams(params); +export default async function GuidePage({ + params, +}: { + params: { + slug: string; + }; +}) { + const guide = allGuides.find((guide) => guide.slugAsParams === params.slug); if (!guide) { notFound(); diff --git a/app/(marketing)/[...slug]/page.tsx b/app/(marketing)/[...slug]/page.tsx deleted file mode 100644 index bced8ebe..00000000 --- a/app/(marketing)/[...slug]/page.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import { notFound } from "next/navigation" -import { allPages } from "contentlayer/generated" - -import { Mdx } from "@/components/content/mdx-components" - -import "@/styles/mdx.css" -import { Metadata } from "next" - -import { env } from "@/env.mjs" -import { siteConfig } from "@/config/site" -import { absoluteUrl } from "@/lib/utils" - -interface PageProps { - params: { - slug: string[] - } -} - -async function getPageFromParams(params) { - const slug = params?.slug?.join("/") - const page = allPages.find((page) => page.slugAsParams === slug) - - if (!page) { - null - } - - return page -} - -export async function generateMetadata({ - params, -}: PageProps): Promise { - const page = await getPageFromParams(params) - - if (!page) { - return {} - } - - const url = env.NEXT_PUBLIC_APP_URL - - const ogUrl = new URL(`${url}/api/og`) - ogUrl.searchParams.set("heading", page.title) - ogUrl.searchParams.set("type", siteConfig.name) - ogUrl.searchParams.set("mode", "light") - - return { - title: page.title, - description: page.description, - openGraph: { - title: page.title, - description: page.description, - type: "article", - url: absoluteUrl(page.slug), - images: [ - { - url: ogUrl.toString(), - width: 1200, - height: 630, - alt: page.title, - }, - ], - }, - twitter: { - card: "summary_large_image", - title: page.title, - description: page.description, - images: [ogUrl.toString()], - }, - } -} - -export async function generateStaticParams(): Promise { - return allPages.map((page) => ({ - slug: page.slugAsParams.split("/"), - })) -} - -export default async function PagePage({ params }: PageProps) { - const page = await getPageFromParams(params) - - if (!page) { - notFound() - } - - return ( -
-
-

- {page.title} -

- {page.description && ( -

{page.description}

- )} -
-
- -
- ) -} diff --git a/app/(marketing)/[slug]/page.tsx b/app/(marketing)/[slug]/page.tsx new file mode 100644 index 00000000..c2852b95 --- /dev/null +++ b/app/(marketing)/[slug]/page.tsx @@ -0,0 +1,63 @@ +import { allPages } from "contentlayer/generated"; +import { notFound } from "next/navigation"; + +import { Mdx } from "@/components/content/mdx-components"; + +import "@/styles/mdx.css"; + +import { Metadata } from "next"; + +import { constructMetadata } from "@/lib/utils"; + +export async function generateStaticParams() { + return allPages.map((page) => ({ + slug: page.slugAsParams, + })); +} + +export async function generateMetadata({ + params, +}: { + params: { slug: string }; +}): Promise { + const page = allPages.find((page) => page.slugAsParams === params.slug); + if (!page) { + return; + } + + const { title, description } = page; + + return constructMetadata({ + title: `${title} – SaaS Starter`, + description: description, + }); +} + +export default async function PagePage({ + params, +}: { + params: { + slug: string; + }; +}) { + const page = allPages.find((page) => page.slugAsParams === params.slug); + + if (!page) { + notFound(); + } + + return ( +
+
+

+ {page.title} +

+ {page.description && ( +

{page.description}

+ )} +
+
+ +
+ ); +} diff --git a/app/(marketing)/blog/[...slug]/page.tsx b/app/(marketing)/blog/[slug]/page.tsx similarity index 54% rename from app/(marketing)/blog/[...slug]/page.tsx rename to app/(marketing)/blog/[slug]/page.tsx index 159e4fe8..139b0b42 100644 --- a/app/(marketing)/blog/[...slug]/page.tsx +++ b/app/(marketing)/blog/[slug]/page.tsx @@ -1,98 +1,59 @@ -import { notFound } from "next/navigation" -import { allAuthors, allPosts } from "contentlayer/generated" +import { notFound } from "next/navigation"; +import { allAuthors, allPosts } from "contentlayer/generated"; -import { Mdx } from "@/components/content/mdx-components" +import { Mdx } from "@/components/content/mdx-components"; -import "@/styles/mdx.css" -import { Metadata } from "next" -import Image from "next/image" -import Link from "next/link" +import "@/styles/mdx.css"; -import { env } from "@/env.mjs" -import { absoluteUrl, cn, formatDate } from "@/lib/utils" -import { buttonVariants } from "@/components/ui/button" -import { Icons } from "@/components/shared/icons" +import { Metadata } from "next"; +import Image from "next/image"; +import Link from "next/link"; -interface PostPageProps { - params: { - slug: string[] - } -} - -async function getPostFromParams(params) { - const slug = params?.slug?.join("/") - const post = allPosts.find((post) => post.slugAsParams === slug) +import { cn, constructMetadata, formatDate } from "@/lib/utils"; +import { buttonVariants } from "@/components/ui/button"; +import { Icons } from "@/components/shared/icons"; - if (!post) { - null - } - - return post +export async function generateStaticParams() { + return allPosts.map((post) => ({ + slug: post.slugAsParams, + })); } export async function generateMetadata({ params, -}: PostPageProps): Promise { - const post = await getPostFromParams(params) - +}: { + params: { slug: string }; +}): Promise { + const post = allPosts.find((post) => post.slugAsParams === params.slug); if (!post) { - return {} + return; } - const url = env.NEXT_PUBLIC_APP_URL - - const ogUrl = new URL(`${url}/api/og`) - ogUrl.searchParams.set("heading", post.title) - ogUrl.searchParams.set("type", "Blog Post") - ogUrl.searchParams.set("mode", "dark") - - return { - title: post.title, - description: post.description, - authors: post.authors.map((author) => ({ - name: author, - })), - openGraph: { - title: post.title, - description: post.description, - type: "article", - url: absoluteUrl(post.slug), - images: [ - { - url: ogUrl.toString(), - width: 1200, - height: 630, - alt: post.title, - }, - ], - }, - twitter: { - card: "summary_large_image", - title: post.title, - description: post.description, - images: [ogUrl.toString()], - }, - } -} + const { title, description, image } = post; -export async function generateStaticParams(): Promise< - PostPageProps["params"][] -> { - return allPosts.map((post) => ({ - slug: post.slugAsParams.split("/"), - })) + return constructMetadata({ + title: `${title} – SaaS Starter`, + description: description, + image, + }); } -export default async function PostPage({ params }: PostPageProps) { - const post = await getPostFromParams(params) +export default async function PostPage({ + params, +}: { + params: { + slug: string; + }; +}) { + const post = allPosts.find((post) => post.slugAsParams === params.slug); if (!post) { - notFound() + notFound(); } const authors = post.authors.map((author) => - allAuthors.find(({ slug }) => slug === `/authors/${author}`) - ) + allAuthors.find(({ slug }) => slug === `/authors/${author}`), + ); return (
@@ -100,7 +61,7 @@ export default async function PostPage({ params }: PostPageProps) { href="/blog" className={cn( buttonVariants({ variant: "ghost" }), - "absolute left-[-200px] top-14 hidden xl:inline-flex" + "absolute left-[-200px] top-14 hidden xl:inline-flex", )} > @@ -116,7 +77,7 @@ export default async function PostPage({ params }: PostPageProps) { )}

- {post.title} + {post.title}

{authors?.length ? (
@@ -141,7 +102,7 @@ export default async function PostPage({ params }: PostPageProps) {

- ) : null + ) : null, )} ) : null} @@ -165,5 +126,5 @@ export default async function PostPage({ params }: PostPageProps) {
- ) + ); }