Skip to content

Commit a9cd027

Browse files
committed
refactor: add constructMetadata() and update layouts
1 parent 1d31d8f commit a9cd027

File tree

10 files changed

+161
-127
lines changed

10 files changed

+161
-127
lines changed

app/(dashboard)/dashboard/billing/page.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
import { redirect } from "next/navigation";
22

3-
import { getCurrentUser } from "@/lib/session";
4-
import { getUserSubscriptionPlan } from "@/lib/subscription";
5-
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
63
import { BillingInfo } from "@/components/billing-info";
74
import { DashboardHeader } from "@/components/dashboard/header";
85
import { DashboardShell } from "@/components/dashboard/shell";
96
import { Icons } from "@/components/shared/icons";
7+
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
8+
import { getCurrentUser } from "@/lib/session";
9+
import { getUserSubscriptionPlan } from "@/lib/subscription";
10+
import { constructMetadata } from "@/lib/utils";
1011

11-
export const metadata = {
12-
title: "Billing",
12+
export const metadata = constructMetadata({
13+
title: "Billing – SaaS Starter",
1314
description: "Manage billing and your subscription plan.",
14-
};
15+
});
1516

1617
export default async function BillingPage() {
1718
const user = await getCurrentUser();

app/(dashboard)/dashboard/layout.tsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { dashboardConfig } from "@/config/dashboard";
22
import { DashboardNav } from "@/components/layout/nav";
33
import { NavBar } from "@/components/layout/navbar";
44
import { SiteFooter } from "@/components/layout/site-footer";
5+
import MaxWidthWrapper from "@/components/shared/max-width-wrapper";
56

67
interface DashboardLayoutProps {
78
children?: React.ReactNode;
@@ -12,14 +13,16 @@ export default function DashboardLayout({ children }: DashboardLayoutProps) {
1213
<div className="flex min-h-screen flex-col space-y-6">
1314
<NavBar items={dashboardConfig.mainNav} scroll={false} />
1415

15-
<div className="container grid flex-1 gap-12 md:grid-cols-[200px_1fr]">
16-
<aside className="hidden w-[200px] flex-col md:flex">
17-
<DashboardNav items={dashboardConfig.sidebarNav} />
18-
</aside>
19-
<main className="flex w-full flex-1 flex-col overflow-hidden">
20-
{children}
21-
</main>
22-
</div>
16+
<MaxWidthWrapper className="min-h-svh">
17+
<div className="grid flex-1 gap-12 md:grid-cols-[200px_1fr]">
18+
<aside className="hidden w-[200px] flex-col md:flex">
19+
<DashboardNav items={dashboardConfig.sidebarNav} />
20+
</aside>
21+
<main className="flex w-full flex-1 flex-col overflow-hidden">
22+
{children}
23+
</main>
24+
</div>
25+
</MaxWidthWrapper>
2326
<SiteFooter className="border-t" />
2427
</div>
2528
);

app/(dashboard)/dashboard/page.tsx

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
1-
import { redirect } from "next/navigation"
1+
import { redirect } from "next/navigation";
22

3-
import { getCurrentUser } from "@/lib/session"
4-
import { EmptyPlaceholder } from "@/components/shared/empty-placeholder"
5-
import { DashboardHeader } from "@/components/dashboard/header"
6-
import { DashboardShell } from "@/components/dashboard/shell"
7-
import { Button } from "@/components/ui/button"
3+
import { DashboardHeader } from "@/components/dashboard/header";
4+
import { DashboardShell } from "@/components/dashboard/shell";
5+
import { EmptyPlaceholder } from "@/components/shared/empty-placeholder";
6+
import { Button } from "@/components/ui/button";
7+
import { getCurrentUser } from "@/lib/session";
8+
import { constructMetadata } from "@/lib/utils";
89

9-
export const metadata = {
10-
title: "Dashboard",
11-
}
10+
export const metadata = constructMetadata({
11+
title: "Settings – SaaS Starter",
12+
description: "Overview of your account and activities.",
13+
});
1214

1315
export default async function DashboardPage() {
14-
const user = await getCurrentUser()
16+
const user = await getCurrentUser();
1517

1618
if (!user) {
17-
redirect("/login")
19+
redirect("/login");
1820
}
1921

2022
return (
@@ -33,5 +35,5 @@ export default async function DashboardPage() {
3335
</EmptyPlaceholder>
3436
</div>
3537
</DashboardShell>
36-
)
38+
);
3739
}
Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
1-
import { redirect } from "next/navigation"
1+
import { redirect } from "next/navigation";
22

3-
import { getCurrentUser } from "@/lib/session"
4-
import { DashboardHeader } from "@/components/dashboard/header"
5-
import { DashboardShell } from "@/components/dashboard/shell"
6-
import { UserNameForm } from "@/components/forms/user-name-form"
3+
import { DashboardHeader } from "@/components/dashboard/header";
4+
import { DashboardShell } from "@/components/dashboard/shell";
5+
import { UserNameForm } from "@/components/forms/user-name-form";
6+
import { getCurrentUser } from "@/lib/session";
7+
import { constructMetadata } from "@/lib/utils";
78

8-
export const metadata = {
9-
title: "Settings",
10-
description: "Manage account and website settings.",
11-
}
9+
export const metadata = constructMetadata({
10+
title: "Settings – SaaS Starter",
11+
description: "Configure your account and website settings.",
12+
});
1213

1314
export default async function SettingsPage() {
14-
const user = await getCurrentUser()
15+
const user = await getCurrentUser();
1516

1617
if (!user) {
17-
redirect("/login")
18+
redirect("/login");
1819
}
1920

2021
return (
@@ -27,5 +28,5 @@ export default async function SettingsPage() {
2728
<UserNameForm user={{ id: user.id, name: user.name || "" }} />
2829
</div>
2930
</DashboardShell>
30-
)
31+
);
3132
}

app/(docs)/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const rightHeader = () => (
3232
export default function DocsLayout({ children }: DocsLayoutProps) {
3333
return (
3434
<div className="flex min-h-screen flex-col">
35-
<NavBar items={docsConfig.mainNav} rightElements={rightHeader()}>
35+
<NavBar items={docsConfig.mainNav} rightElements={rightHeader()} large={true}>
3636
<DocsSidebarNav items={docsConfig.sidebarNav} />
3737
</NavBar>
3838
<div className="container flex-1">{children}</div>

app/(marketing)/blog/page.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1-
import { allPosts } from "contentlayer/generated"
2-
import { compareDesc } from "date-fns"
1+
import { allPosts } from "contentlayer/generated";
2+
import { compareDesc } from "date-fns";
33

4-
import { BlogPosts } from "@/components/blog-posts"
4+
import { BlogPosts } from "@/components/blog-posts";
5+
import { constructMetadata } from "@/lib/utils";
56

6-
export const metadata = {
7-
title: "Blog",
8-
}
7+
export const metadata = constructMetadata({
8+
title: "Blog – SaaS Starter",
9+
description: "Manage billing and your subscription plan.",
10+
});
911

1012
export default async function BlogPage() {
1113
const posts = allPosts
1214
.filter((post) => post.published)
1315
.sort((a, b) => {
14-
return compareDesc(new Date(a.date), new Date(b.date))
15-
})
16+
return compareDesc(new Date(a.date), new Date(b.date));
17+
});
1618

1719
return (
1820
<main>
1921
<BlogPosts posts={posts} />
2022
</main>
21-
)
23+
);
2224
}

app/(marketing)/pricing/page.tsx

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
1+
import { PricingCards } from "@/components/pricing-cards";
2+
import { PricingFaq } from "@/components/pricing-faq";
3+
import { getCurrentUser } from "@/lib/session";
4+
import { getUserSubscriptionPlan } from "@/lib/subscription";
5+
import { constructMetadata } from "@/lib/utils";
16

2-
import { PricingCards } from '@/components/pricing-cards';
3-
import { PricingFaq } from '@/components/pricing-faq';
4-
import { Skeleton } from '@/components/ui/skeleton';
5-
import { getCurrentUser } from '@/lib/session';
6-
import { getUserSubscriptionPlan } from '@/lib/subscription';
7-
8-
export const metadata = {
9-
title: "Pricing",
10-
}
7+
export const metadata = constructMetadata({
8+
title: "Pricing – SaaS Starter",
9+
description: "Explore our subscription plans.",
10+
});
1111

1212
export default async function PricingPage() {
13-
const user = await getCurrentUser()
13+
const user = await getCurrentUser();
1414
let subscriptionPlan;
1515

1616
if (user) {
17-
subscriptionPlan = await getUserSubscriptionPlan(user.id)
17+
subscriptionPlan = await getUserSubscriptionPlan(user.id);
1818
}
1919

2020
return (
2121
<div className="flex w-full flex-col gap-16 py-8 md:py-8">
2222
<PricingCards userId={user?.id} subscriptionPlan={subscriptionPlan} />
23-
<hr className='container' />
23+
<hr className="container" />
2424
<PricingFaq />
2525
</div>
26-
)
27-
}
26+
);
27+
}

app/layout.tsx

Lines changed: 2 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import { fontHeading, fontSans, fontUrban } from "@/assets/fonts";
44
import { SessionProvider } from "next-auth/react";
55
import { ThemeProvider } from "next-themes";
66

7-
import { siteConfig } from "@/config/site";
8-
import { cn } from "@/lib/utils";
7+
import { cn, constructMetadata } from "@/lib/utils";
98
import { Toaster } from "@/components/ui/toaster";
109
import { Analytics } from "@/components/analytics";
1110
import { ModalProvider } from "@/components/modal-provider";
@@ -15,52 +14,7 @@ interface RootLayoutProps {
1514
children: React.ReactNode;
1615
}
1716

18-
export const metadata = {
19-
title: {
20-
default: siteConfig.name,
21-
template: `%s | ${siteConfig.name}`,
22-
},
23-
description: siteConfig.description,
24-
keywords: [
25-
"Next.js",
26-
"React",
27-
"Prisma",
28-
"Neon",
29-
"Auth.js",
30-
"shadcn ui",
31-
"Resend",
32-
"React Email",
33-
"Stripe",
34-
],
35-
authors: [
36-
{
37-
name: "mickasmt",
38-
},
39-
],
40-
creator: "mickasmt",
41-
metadataBase: new URL(siteConfig.url),
42-
openGraph: {
43-
type: "website",
44-
locale: "en_US",
45-
url: siteConfig.url,
46-
title: siteConfig.name,
47-
description: siteConfig.description,
48-
siteName: siteConfig.name,
49-
},
50-
twitter: {
51-
card: "summary_large_image",
52-
title: siteConfig.name,
53-
description: siteConfig.description,
54-
images: [siteConfig.ogImage],
55-
creator: "@miickasmt",
56-
},
57-
icons: {
58-
icon: "/favicon.ico",
59-
shortcut: "/favicon-16x16.png",
60-
apple: "/apple-touch-icon.png",
61-
},
62-
manifest: `${siteConfig.url}/site.webmanifest`,
63-
};
17+
export const metadata = constructMetadata();
6418

6519
export default function RootLayout({ children }: RootLayoutProps) {
6620
return (

components/blog-posts.tsx

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
import { formatDate } from '@/lib/utils';
2-
import Image from 'next/image';
3-
import Link from 'next/link';
1+
import Image from "next/image";
2+
import Link from "next/link";
3+
4+
import { formatDate } from "@/lib/utils";
5+
6+
import MaxWidthWrapper from "./shared/max-width-wrapper";
47

58
export function BlogPosts({ posts }) {
69
return (
7-
<div className="container space-y-10 py-6 md:py-10">
10+
<MaxWidthWrapper className="space-y-10 py-6 md:py-10">
811
<section>
912
<h2 className="mb-4 font-heading text-3xl">Last Post</h2>
1013
<article className="relative grid grid-cols-1 gap-6 md:grid-cols-2">
@@ -39,7 +42,10 @@ export function BlogPosts({ posts }) {
3942
<h2 className="mb-4 font-heading text-3xl">Blog Posts</h2>
4043
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
4144
{posts.slice(1).map((post) => (
42-
<article key={post._id} className="group relative flex flex-col space-y-2">
45+
<article
46+
key={post._id}
47+
className="group relative flex flex-col space-y-2"
48+
>
4349
{post.image && (
4450
<Image
4551
alt={post.title}
@@ -49,9 +55,13 @@ export function BlogPosts({ posts }) {
4955
className="rounded-md border bg-muted transition-colors"
5056
/>
5157
)}
52-
<h2 className="line-clamp-1 font-heading text-2xl">{post.title}</h2>
58+
<h2 className="line-clamp-1 font-heading text-2xl">
59+
{post.title}
60+
</h2>
5361
{post.description && (
54-
<p className="line-clamp-1 text-muted-foreground">{post.description}</p>
62+
<p className="line-clamp-1 text-muted-foreground">
63+
{post.description}
64+
</p>
5565
)}
5666
{post.date && (
5767
<p className="text-sm text-muted-foreground">
@@ -65,7 +75,6 @@ export function BlogPosts({ posts }) {
6575
))}
6676
</div>
6777
</section>
68-
</div>
78+
</MaxWidthWrapper>
6979
);
7080
}
71-

0 commit comments

Comments
 (0)