Skip to content

Commit

Permalink
feat(saas): Improved SEO, Metadata to pages
Browse files Browse the repository at this point in the history
  • Loading branch information
alifarooq9 committed May 12, 2024
1 parent 676e55e commit 0181dc9
Show file tree
Hide file tree
Showing 26 changed files with 265 additions and 34 deletions.
18 changes: 18 additions & 0 deletions starterkits/saas/src/app/(web)/blog/[...slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { getBlogs } from "@/server/actions/blog";
import { format } from "date-fns";
import Image from "next/image";
import { notFound, redirect } from "next/navigation";
import { type Metadata } from "next";

export const dynamic = "force-static";

Expand All @@ -14,6 +15,23 @@ type BlogSlugPageProps = {
};
};

export async function generateMetadata({
params,
}: BlogSlugPageProps): Promise<Metadata> {
const slug = params.slug.join("/");

const blog = (await getBlogs()).find((b) => b.metaData.slug === slug);

if (!blog) {
return notFound();
}

return {
title: blog.metaData.title,
description: blog.metaData.description,
};
}

export async function generateStaticParams() {
const blogs = await getBlogs();

Expand Down
3 changes: 3 additions & 0 deletions starterkits/saas/src/app/(web)/blog/_constants/page-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const blogPageConfig = {
title: "Blog",
} as const;
6 changes: 6 additions & 0 deletions starterkits/saas/src/app/(web)/blog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import { getBlogs } from "@/server/actions/blog";
import { format } from "date-fns";
import Image from "next/image";
import Link from "next/link";
import { type Metadata } from "next";
import { blogPageConfig } from "@/app/(web)/blog/_constants/page-config";

export const metadata: Metadata = {
title: blogPageConfig.title,
};

export const dynamic = "force-static";

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const changelogPageConfig = {
title: "Change Log",
} as const;
6 changes: 6 additions & 0 deletions starterkits/saas/src/app/(web)/changelog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ import { siteConfig } from "@/config/site";
import { getChangelogs } from "@/server/actions/changelog";
import { format } from "date-fns";
import Image from "next/image";
import type { Metadata } from "next";
import { changelogPageConfig } from "@/app/(web)/changelog/_constants/page-config";

export const metadata: Metadata = {
title: changelogPageConfig.title,
};

export const dynamic = "force-static";

Expand Down
7 changes: 6 additions & 1 deletion starterkits/saas/src/app/(web)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ import { siteUrls } from "@/config/urls";
import Image from "next/image";
import Link from "next/link";
import Balancer from "react-wrap-balancer";
import type { Metadata } from "next";

export const metadata: Metadata = {
title: "Build Your MVP in Days, not weeks. Next.js Starter Kit",
};

export const dynamic = "force-static";

Expand All @@ -19,7 +24,7 @@ export default async function HomePage() {
<WebPageWrapper>
<WebPageHeader
badge="Launch your saas in 24 hours"
title="Rapidly launch your MVP with Beautiful Starterkits, Blocks, and more."
title="Build Your MVP in Days, not weeks. Open Source Starter Kit"
>
<Balancer
as="p"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const pricingPageConfig = {
title: "Pricing",
} as const;
6 changes: 6 additions & 0 deletions starterkits/saas/src/app/(web)/pricing/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {
WebPageHeader,
WebPageWrapper,
} from "@/app/(web)/_components/general-components";
import { type Metadata } from "next";
import { pricingPageConfig } from "@/app/(web)/pricing/_constants/page-config";

/**
* Customize the pricing page to your needs. You can use the `PricingPlans` component to display the pricing plans.
Expand All @@ -11,6 +13,10 @@ import {
* To customize the pricing plans, you can modify the `PricingPlans` component. @see /app/(web)/pricing/components/pricing-plans.tsx
*/

export const metadata: Metadata = {
title: pricingPageConfig.title,
};

export default function PricingPage() {
return (
<WebPageWrapper>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { siteConfig } from "@/config/site";

export const supportPageConfig = {
title: "Support",
description: `Get support from ${siteConfig.name} to get started building your next project.`,
} as const;
12 changes: 11 additions & 1 deletion starterkits/saas/src/app/(web)/support/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,21 @@ import {
import { type SupportInfo, supportInfos } from "@/config/support";
import { ArrowRightIcon } from "lucide-react";
import Link from "next/link";
import { type Metadata } from "next";
import { supportPageConfig } from "@/app/(web)/support/_constants/page-config";

export const metadata: Metadata = {
title: supportPageConfig.title,
description: supportPageConfig.description,
};

export default function ContactPage() {
return (
<WebPageWrapper>
<WebPageHeader title="Support for You" badge="Get in touch with us">
<WebPageHeader
title={supportPageConfig.title}
badge="Get in touch with us"
>
<p>
If you have any questions or need help, feel free to reach
out to us.
Expand Down
6 changes: 6 additions & 0 deletions starterkits/saas/src/app/auth/login/_constants/page-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { siteConfig } from "@/config/site";

export const loginPageConfig = {
title: "Login",
description: `Login to ${siteConfig.name} to get started building your next project.`,
} as const;
7 changes: 7 additions & 0 deletions starterkits/saas/src/app/auth/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { AuthForm } from "@/app/auth/_components/auth-form";
import { loginPageConfig } from "@/app/auth/login/_constants/page-config";
import { type Metadata } from "next";

export const metadata: Metadata = {
title: loginPageConfig.title,
description: loginPageConfig.description,
};

export default function Login() {
return <AuthForm type="login" />;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { siteConfig } from "@/config/site";

export const signupPageConfig = {
title: "Signup",
description: `Signup to ${siteConfig.name} to get started building your next project.`,
} as const;
7 changes: 7 additions & 0 deletions starterkits/saas/src/app/auth/signup/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { AuthForm } from "@/app/auth/_components/auth-form";
import { signupPageConfig } from "@/app/auth/signup/_constants/page-config";
import { type Metadata } from "next";

export const metadata: Metadata = {
title: signupPageConfig.title,
description: signupPageConfig.description,
};

export default function Signup() {
return <AuthForm type="signup" />;
Expand Down
18 changes: 18 additions & 0 deletions starterkits/saas/src/app/docs/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { notFound } from "next/navigation";
import { Toc } from "@/components/toc";
import { getDocs } from "@/server/actions/docs";
import { type Metadata } from "next";

export const dynamic = "force-static";

Expand All @@ -10,6 +11,23 @@ type DocsSlugPageProps = {
};
};

export async function generateMetadata({
params,
}: DocsSlugPageProps): Promise<Metadata> {
const slug = Array.isArray(params.slug) ? params.slug.join("/") : "/";

const doc = (await getDocs()).find((doc) => doc.metaData.slug === slug);

if (!doc) {
return notFound();
}

return {
title: doc.metaData.title,
description: doc.metaData.description,
};
}

export async function generateStaticParams() {
const docs = await getDocs();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const invitePageConfig = {
title: ({ orgName }: { orgName: string }) => `Invite to ${orgName}`,
description: ({ orgName }: { orgName: string }) =>
`Invite your team to ${orgName} and get started building your next project.`,
} as const;
18 changes: 17 additions & 1 deletion starterkits/saas/src/app/invite/org/[orgId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { getOrgByIdQuery } from "@/server/actions/organization/queries";
import { RequestCard } from "@/app/invite/org/[orgId]/_components/request-card";
import { notFound } from "next/navigation";
import { type Metadata } from "next";

type OrgRequestProps = {
export type OrgRequestProps = {
params: {
orgId: string;
};
Expand All @@ -23,3 +24,18 @@ export default async function OrgRequestPage({
</main>
);
}

export async function generateMetadata({
params,
}: OrgRequestProps): Promise<Metadata> {
const org = await getOrgByIdQuery({ orgId: params.orgId });

if (!org) {
return notFound();
}

return {
title: `Invite to ${org.name}`,
description: `Invite your team to ${org.name} and get started building your next project.`,
};
}
19 changes: 14 additions & 5 deletions starterkits/saas/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,21 @@ import { Toaster } from "@/components/ui/sonner";
import "@/styles/globals.css";
import "@/styles/prism.css";
import { fontHeading, fontSans } from "@/lib/fonts";
import { type Metadata } from "next";
import {
defaultMetadata,
twitterMetadata,
ogMetadata,
} from "@/app/shared-metadata";

export const metadata = {
title: "RapidLaunch - Next.js Boilerplate",
description:
"Next.js boilerplate with shadcn ui, TRPC, TailwindCSS, and Drizzle.",
icons: [{ rel: "icon", url: "/favicon.ico" }],
export const metadata: Metadata = {
...defaultMetadata,
twitter: {
...twitterMetadata,
},
openGraph: {
...ogMetadata,
},
};

export default function RootLayout({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const maintenancePageConfig = {
title: "Maintenance",
description:
"We&apos;re currently undergoing maintenance. Please check back later.",
} as const;
7 changes: 7 additions & 0 deletions starterkits/saas/src/app/maintenance/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { maintenancePageConfig } from "@/app/maintenance/_constants/page-config";
import { siteConfig } from "@/config/site";
import { type Metadata } from "next";

export const metadata: Metadata = {
title: maintenancePageConfig.title,
description: maintenancePageConfig.description,
};

export default function Maintenance() {
return (
Expand Down
39 changes: 39 additions & 0 deletions starterkits/saas/src/app/shared-metadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { siteConfig } from "@/config/site";
import { siteUrls } from "@/config/urls";
import type { Metadata } from "next";

export const defaultMetadata: Metadata = {
title: {
template: `%s | ${siteConfig.name}`,
default: siteConfig.name,
},
description: siteConfig.description,
metadataBase: new URL(siteUrls.publicUrl),
keywords: [
"Next.js",
"React",
"Next.js Starter kit",
"SaaS Starter Kit",
"Shadcn UI",
],
authors: [{ name: "Ali Farooq", url: "https://twitter.com/alifarooqdev" }],
creator: "AliFarooqDev",
};

export const twitterMetadata: Metadata["twitter"] = {
title: siteConfig.name,
description: siteConfig.description,
card: "summary_large_image",
images: [siteConfig.orgImage],
creator: "@alifarooqdev",
};

export const ogMetadata: Metadata["openGraph"] = {
title: siteConfig.name,
description: siteConfig.description,
type: "website",
images: [{ url: siteConfig.orgImage, alt: siteConfig.name }],
locale: "en_US",
url: siteUrls.publicUrl,
siteName: siteConfig.name,
};
5 changes: 5 additions & 0 deletions starterkits/saas/src/app/waitlist/_constants/page-config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const waitlistPageConfig = {
title: "Join the waitlist",
description:
"Welcome to Rapidlaunch, a platform which provides resources for building applications faster. We're currently working on adding more features and improving the user experience. In the meantime, you can join our waitlist!",
} as const;
7 changes: 7 additions & 0 deletions starterkits/saas/src/app/waitlist/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { WaitlistForm } from "@/app/waitlist/_components/waitlist-form";
import { waitlistPageConfig } from "@/app/waitlist/_constants/page-config";
import { Icons } from "@/components/ui/icons";
import { siteConfig } from "@/config/site";
import { type Metadata } from "next";

export const metadata: Metadata = {
title: waitlistPageConfig.title,
description: waitlistPageConfig.description,
};

export default function Waitlist() {
return (
Expand Down
6 changes: 4 additions & 2 deletions starterkits/saas/src/config/site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
*/

export const siteConfig = {
name: "RapidLaunch",
name: "Rapidlaunch",
description:
"Build your SaaS with ease, using our beautiful starterkit. Rapidlaunch is a powerful and flexible SaaS platform that allows you to build and deploy your SaaS quickly and easily.",
"Get your startup off the ground quickly with RapidLaunch! This open source Next.js starter kit provides the foundation you need to build your MVP fast – pre-built components, optimized performance, and ready-to-go styling",
orgImage:
"https://utfs.io/f/4ae0ddb1-4260-46f5-aa7c-70408cc192b9-aadavt.png",
contactEmail: "[email protected]",
noReplyEmail: "[email protected]",
} as const;
20 changes: 20 additions & 0 deletions starterkits/saas/src/config/urls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,23 @@ export const publicRoutes: string[] = [
siteUrls.waitlist,
siteUrls.rapidlaunch,
];

export const protectedRoutes: string[] = [
siteUrls.dashboard.home,
siteUrls.feedback,
siteUrls.organization.members.home,
siteUrls.organization.members.invite,
siteUrls.organization.settings,
siteUrls.organization.plansAndBilling,
siteUrls.auth.login,
siteUrls.auth.signup,
siteUrls.admin.dashboard,
siteUrls.admin.users,
siteUrls.admin.organizations,
siteUrls.admin.settings,
siteUrls.admin.waitlist,
siteUrls.admin.feedbacks,
siteUrls.admin.analytics,
siteUrls.profile.settings,
siteUrls.profile.billing,
];
Loading

0 comments on commit 0181dc9

Please sign in to comment.