diff --git a/starterkits/saas/src/app/(web)/blog/[...slug]/page.tsx b/starterkits/saas/src/app/(web)/blog/[slug]/page.tsx similarity index 84% rename from starterkits/saas/src/app/(web)/blog/[...slug]/page.tsx rename to starterkits/saas/src/app/(web)/blog/[slug]/page.tsx index 8f11473..833e423 100644 --- a/starterkits/saas/src/app/(web)/blog/[...slug]/page.tsx +++ b/starterkits/saas/src/app/(web)/blog/[slug]/page.tsx @@ -5,20 +5,38 @@ 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"; type BlogSlugPageProps = { params: { - slug: string[]; + slug: string; }; }; +export async function generateMetadata({ + params, +}: BlogSlugPageProps): Promise { + const slug = params.slug; + + 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(); return blogs.map((blog) => ({ - slug: blog.metaData.slug.split("/"), + slug: blog.metaData.slug, })); } @@ -27,7 +45,7 @@ export default async function BlogSlugPage({ params }: BlogSlugPageProps) { return redirect(siteUrls.blog); } - const slug = params.slug.join("/"); + const slug = params.slug; const blog = (await getBlogs()).find((b) => b.metaData.slug === slug); diff --git a/starterkits/saas/src/app/(web)/blog/_constants/page-config.ts b/starterkits/saas/src/app/(web)/blog/_constants/page-config.ts new file mode 100644 index 0000000..1bfb27d --- /dev/null +++ b/starterkits/saas/src/app/(web)/blog/_constants/page-config.ts @@ -0,0 +1,3 @@ +export const blogPageConfig = { + title: "Blog", +} as const; diff --git a/starterkits/saas/src/app/(web)/blog/page.tsx b/starterkits/saas/src/app/(web)/blog/page.tsx index cd6794a..ccdb5a5 100644 --- a/starterkits/saas/src/app/(web)/blog/page.tsx +++ b/starterkits/saas/src/app/(web)/blog/page.tsx @@ -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"; diff --git a/starterkits/saas/src/app/(web)/changelog/_constants/page-config.ts b/starterkits/saas/src/app/(web)/changelog/_constants/page-config.ts new file mode 100644 index 0000000..044c199 --- /dev/null +++ b/starterkits/saas/src/app/(web)/changelog/_constants/page-config.ts @@ -0,0 +1,3 @@ +export const changelogPageConfig = { + title: "Change Log", +} as const; diff --git a/starterkits/saas/src/app/(web)/changelog/page.tsx b/starterkits/saas/src/app/(web)/changelog/page.tsx index 09386f9..58a2ac2 100644 --- a/starterkits/saas/src/app/(web)/changelog/page.tsx +++ b/starterkits/saas/src/app/(web)/changelog/page.tsx @@ -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"; @@ -35,11 +41,8 @@ export default async function ChangeLogPage() {

- {changelogs.map((changelog) => ( - + {changelogs.map((changelog, index) => ( + ))}
diff --git a/starterkits/saas/src/app/(web)/page.tsx b/starterkits/saas/src/app/(web)/page.tsx index 8591bf4..e07ad7b 100644 --- a/starterkits/saas/src/app/(web)/page.tsx +++ b/starterkits/saas/src/app/(web)/page.tsx @@ -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"; @@ -19,7 +24,7 @@ export default async function HomePage() { diff --git a/starterkits/saas/src/app/(web)/support/_constants/page-config.ts b/starterkits/saas/src/app/(web)/support/_constants/page-config.ts new file mode 100644 index 0000000..31806e9 --- /dev/null +++ b/starterkits/saas/src/app/(web)/support/_constants/page-config.ts @@ -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; diff --git a/starterkits/saas/src/app/(web)/support/page.tsx b/starterkits/saas/src/app/(web)/support/page.tsx index b5f2c19..3c2225d 100644 --- a/starterkits/saas/src/app/(web)/support/page.tsx +++ b/starterkits/saas/src/app/(web)/support/page.tsx @@ -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 ( - +

If you have any questions or need help, feel free to reach out to us. diff --git a/starterkits/saas/src/app/auth/login/_constants/page-config.ts b/starterkits/saas/src/app/auth/login/_constants/page-config.ts new file mode 100644 index 0000000..d2797b9 --- /dev/null +++ b/starterkits/saas/src/app/auth/login/_constants/page-config.ts @@ -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; diff --git a/starterkits/saas/src/app/auth/login/page.tsx b/starterkits/saas/src/app/auth/login/page.tsx index cae58a0..e5d92b1 100644 --- a/starterkits/saas/src/app/auth/login/page.tsx +++ b/starterkits/saas/src/app/auth/login/page.tsx @@ -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 ; diff --git a/starterkits/saas/src/app/auth/signup/_constants/page-config.ts b/starterkits/saas/src/app/auth/signup/_constants/page-config.ts new file mode 100644 index 0000000..ac783bc --- /dev/null +++ b/starterkits/saas/src/app/auth/signup/_constants/page-config.ts @@ -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; diff --git a/starterkits/saas/src/app/auth/signup/page.tsx b/starterkits/saas/src/app/auth/signup/page.tsx index 7e4f572..327138a 100644 --- a/starterkits/saas/src/app/auth/signup/page.tsx +++ b/starterkits/saas/src/app/auth/signup/page.tsx @@ -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 ; diff --git a/starterkits/saas/src/app/docs/[[...slug]]/page.tsx b/starterkits/saas/src/app/docs/[[...slug]]/page.tsx index 20f176d..5f74f6e 100644 --- a/starterkits/saas/src/app/docs/[[...slug]]/page.tsx +++ b/starterkits/saas/src/app/docs/[[...slug]]/page.tsx @@ -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"; @@ -10,13 +11,26 @@ type DocsSlugPageProps = { }; }; +export async function generateMetadata({ + params, +}: DocsSlugPageProps): Promise { + 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(); - docs.map((doc) => { - console.log(doc.metaData.slug.split("/") || ["/"]); - }); - return docs.map((doc) => ({ slug: doc.metaData.slug.split("/") || ["/"], })); @@ -27,6 +41,8 @@ export default async function DocsSlugPage({ params }: DocsSlugPageProps) { const doc = (await getDocs()).find((doc) => doc.metaData.slug === slug); + console.log(["gettings-started", "installation"].join("/"), params.slug); + if (!doc) { return notFound(); } diff --git a/starterkits/saas/src/app/invite/org/[orgId]/_constants/page-config.ts b/starterkits/saas/src/app/invite/org/[orgId]/_constants/page-config.ts new file mode 100644 index 0000000..7284ceb --- /dev/null +++ b/starterkits/saas/src/app/invite/org/[orgId]/_constants/page-config.ts @@ -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; diff --git a/starterkits/saas/src/app/invite/org/[orgId]/page.tsx b/starterkits/saas/src/app/invite/org/[orgId]/page.tsx index a582e8a..2149e7c 100644 --- a/starterkits/saas/src/app/invite/org/[orgId]/page.tsx +++ b/starterkits/saas/src/app/invite/org/[orgId]/page.tsx @@ -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; }; @@ -23,3 +24,18 @@ export default async function OrgRequestPage({ ); } + +export async function generateMetadata({ + params, +}: OrgRequestProps): Promise { + 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.`, + }; +} diff --git a/starterkits/saas/src/app/layout.tsx b/starterkits/saas/src/app/layout.tsx index c3ed38e..f98910c 100644 --- a/starterkits/saas/src/app/layout.tsx +++ b/starterkits/saas/src/app/layout.tsx @@ -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({ diff --git a/starterkits/saas/src/app/maintenance/_constants/page-config.ts b/starterkits/saas/src/app/maintenance/_constants/page-config.ts new file mode 100644 index 0000000..52aa684 --- /dev/null +++ b/starterkits/saas/src/app/maintenance/_constants/page-config.ts @@ -0,0 +1,5 @@ +export const maintenancePageConfig = { + title: "Maintenance", + description: + "We're currently undergoing maintenance. Please check back later.", +} as const; diff --git a/starterkits/saas/src/app/maintenance/page.tsx b/starterkits/saas/src/app/maintenance/page.tsx index f8f68fd..7cff144 100644 --- a/starterkits/saas/src/app/maintenance/page.tsx +++ b/starterkits/saas/src/app/maintenance/page.tsx @@ -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 ( diff --git a/starterkits/saas/src/app/robots.ts b/starterkits/saas/src/app/robots.ts new file mode 100644 index 0000000..559d2af --- /dev/null +++ b/starterkits/saas/src/app/robots.ts @@ -0,0 +1,12 @@ +import { siteUrls } from "@/config/urls"; +import type { MetadataRoute } from "next"; + +export default function robots(): MetadataRoute.Robots { + return { + rules: { + userAgent: "*", + allow: "/", + }, + sitemap: `${siteUrls.publicUrl}/sitemap.xml`, + }; +} diff --git a/starterkits/saas/src/app/shared-metadata.ts b/starterkits/saas/src/app/shared-metadata.ts new file mode 100644 index 0000000..63818fe --- /dev/null +++ b/starterkits/saas/src/app/shared-metadata.ts @@ -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, +}; diff --git a/starterkits/saas/src/app/sitemap.ts b/starterkits/saas/src/app/sitemap.ts new file mode 100644 index 0000000..ec8ac6e --- /dev/null +++ b/starterkits/saas/src/app/sitemap.ts @@ -0,0 +1,36 @@ +import { publicRoutes, siteUrls } from "@/config/urls"; +import { getBlogs } from "@/server/actions/blog"; +import { getDocs } from "@/server/actions/docs"; +import type { MetadataRoute } from "next"; + +const addPathToBaseURL = (path: string) => `${siteUrls.publicUrl}${path}`; + +export default async function sitemap(): Promise { + const allBlogs = await getBlogs(); + + const blogs = allBlogs.map((blog) => ({ + url: addPathToBaseURL(`${siteUrls.blog}/${blog.metaData.slug}`), + lastModified: new Date(blog.metaData.updatedAt), + })); + + const allDocs = await getDocs(); + + const docs = allDocs.map((doc) => ({ + url: addPathToBaseURL( + `${siteUrls.docs}/${doc.metaData.slug === "/" ? "" : doc.metaData.slug}`, + ), + lastModified: new Date(doc.metaData.publishedAt), + })); + + const publicRoutesWithoutPublicUrl = publicRoutes.filter( + (route) => + route !== siteUrls.publicUrl && route !== siteUrls.rapidlaunch, + ); + + const routes = publicRoutesWithoutPublicUrl.map((route) => ({ + url: addPathToBaseURL(route), + lastModified: new Date(), + })); + + return [...routes, ...blogs, ...docs]; +} diff --git a/starterkits/saas/src/app/waitlist/_constants/page-config.ts b/starterkits/saas/src/app/waitlist/_constants/page-config.ts new file mode 100644 index 0000000..ecaeb6e --- /dev/null +++ b/starterkits/saas/src/app/waitlist/_constants/page-config.ts @@ -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; diff --git a/starterkits/saas/src/app/waitlist/page.tsx b/starterkits/saas/src/app/waitlist/page.tsx index f322bc8..cfab349 100644 --- a/starterkits/saas/src/app/waitlist/page.tsx +++ b/starterkits/saas/src/app/waitlist/page.tsx @@ -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 ( diff --git a/starterkits/saas/src/config/site.ts b/starterkits/saas/src/config/site.ts index 9574491..c467552 100644 --- a/starterkits/saas/src/config/site.ts +++ b/starterkits/saas/src/config/site.ts @@ -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: "hello@support.rapidlaunch.xyz", noReplyEmail: "Rapidlaunch@support.rapidlaunch.xyz", } as const; diff --git a/starterkits/saas/src/config/urls.ts b/starterkits/saas/src/config/urls.ts index fb069b8..d9c25bd 100644 --- a/starterkits/saas/src/config/urls.ts +++ b/starterkits/saas/src/config/urls.ts @@ -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, +]; diff --git a/starterkits/saas/src/content/blog/introduction.mdx b/starterkits/saas/src/content/blog/introduction.mdx index 1f99c33..4984257 100644 --- a/starterkits/saas/src/content/blog/introduction.mdx +++ b/starterkits/saas/src/content/blog/introduction.mdx @@ -2,6 +2,7 @@ title: Introduction slug: introduction publishedAt: 2022-01-01 +updatedAt: 2024-05-01 readTime: 5 min tags: ["introduction", "saas"] description: This is the introduction diff --git a/starterkits/saas/src/content/changelogs/version-0.0.0.mdx b/starterkits/saas/src/content/changelogs/version-0.0.0.mdx index c2de931..9c5774a 100644 --- a/starterkits/saas/src/content/changelogs/version-0.0.0.mdx +++ b/starterkits/saas/src/content/changelogs/version-0.0.0.mdx @@ -1,6 +1,5 @@ --- title: "Launch of RapidLaunch" -slug: "launch-of-rapidlaunch" description: "RapidLaunch is a platform to create and launch SaaS products quickly." version: "0.0.0" publishedAt: 2024-04-01 diff --git a/starterkits/saas/src/content/changelogs/version-0.1.0.mdx b/starterkits/saas/src/content/changelogs/version-0.1.0.mdx index 3e3f2de..7ccbe3a 100644 --- a/starterkits/saas/src/content/changelogs/version-0.1.0.mdx +++ b/starterkits/saas/src/content/changelogs/version-0.1.0.mdx @@ -1,6 +1,5 @@ --- title: "Launch of RapidLaunch 2" -slug: "launch-of-rapidlaunch-2" description: "RapidLaunch is a platform to create and launch SaaS products quickly." version: "0.1.0" publishedAt: 2024-08-01 diff --git a/starterkits/saas/src/content/changelogs/version-0.2.4.mdx b/starterkits/saas/src/content/changelogs/version-0.2.4.mdx index 0a31bde..11018c6 100644 --- a/starterkits/saas/src/content/changelogs/version-0.2.4.mdx +++ b/starterkits/saas/src/content/changelogs/version-0.2.4.mdx @@ -1,6 +1,5 @@ --- title: "Launch of RapidLaunch 2" -slug: "launch-of-rapidlaunch-2" description: "RapidLaunch is a platform to create and launch SaaS products quickly." version: "0.4.0" publishedAt: 2024-10-06 diff --git a/starterkits/saas/src/content/docs/installation.mdx b/starterkits/saas/src/content/docs/installation.mdx index 81195b1..07030a8 100644 --- a/starterkits/saas/src/content/docs/installation.mdx +++ b/starterkits/saas/src/content/docs/installation.mdx @@ -2,6 +2,7 @@ title: "Installation" slug: "getting-started/installation" description: "Learn how to install rapidlaunch" +publishedAt: 2024-01-01 --- Added your your own doumentation by create a .mdx file in "*src/content/docs*" folder. diff --git a/starterkits/saas/src/content/docs/introduction.mdx b/starterkits/saas/src/content/docs/introduction.mdx index 0de1cc8..2225ede 100644 --- a/starterkits/saas/src/content/docs/introduction.mdx +++ b/starterkits/saas/src/content/docs/introduction.mdx @@ -2,6 +2,7 @@ title: "Introduction" slug: "/" description: "Rapidlaunch is an open-source Next.js SaaS Starterkit/Boilerplate designed to expedite the development process of Software as a Service (SaaS) applications. Launch your MVP in days." +publishedAt: 2024-01-01 --- ## Creator diff --git a/starterkits/saas/src/middleware.ts b/starterkits/saas/src/middleware.ts index 6fdb8eb..64139de 100644 --- a/starterkits/saas/src/middleware.ts +++ b/starterkits/saas/src/middleware.ts @@ -1,7 +1,7 @@ import { getToken } from "next-auth/jwt"; import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; -import { publicRoutes, siteUrls } from "@/config/urls"; +import { protectedRoutes, siteUrls } from "@/config/urls"; import { getAbsoluteUrl } from "@/lib/utils"; import { env } from "@/env"; @@ -31,36 +31,42 @@ export async function middleware(request: NextRequest) { } /** if path is public route than do nothing */ - if ( - publicRoutes - .map((route) => route.startsWith(request.nextUrl.pathname)) - .includes(true) - ) { - return NextResponse.next(); - } + if (protectedRoutes.includes(request.nextUrl.pathname)) { + const session = await getToken({ req: request }); - const session = await getToken({ req: request }); + /** if path name starts from /auth, and session is there redirect to dashboard */ + if (session && request.nextUrl.pathname.startsWith("/auth")) { + return NextResponse.redirect( + getAbsoluteUrl(siteUrls.dashboard.home), + ); + } - /** if path name starts from /auth, and session is there redirect to dashboard */ - if (session && request.nextUrl.pathname.startsWith("/auth")) { - return NextResponse.redirect(getAbsoluteUrl(siteUrls.dashboard.home)); - } - - /** if path name does not start from /auth, and session is not there redirect to login */ - if (!session && !request.nextUrl.pathname.startsWith("/auth")) { - return NextResponse.redirect(getAbsoluteUrl(siteUrls.auth.login)); - } + /** if path name does not start from /auth, and session is not there redirect to login */ + if (!session && !request.nextUrl.pathname.startsWith("/auth")) { + return NextResponse.redirect(getAbsoluteUrl(siteUrls.auth.login)); + } - /** if path name start from admin, and session role is not admin or super admin redirect to dashboard */ - const isAdmin = - session?.role === "Admin" || session?.role === "Super Admin"; + /** if path name start from admin, and session role is not admin or super admin redirect to dashboard */ + const isAdmin = + session?.role === "Admin" || session?.role === "Super Admin"; - if (session && request.nextUrl.pathname.startsWith("/admin") && !isAdmin) { - return NextResponse.redirect(getAbsoluteUrl(siteUrls.dashboard.home)); + if ( + session && + request.nextUrl.pathname.startsWith("/admin") && + !isAdmin + ) { + return NextResponse.redirect( + getAbsoluteUrl(siteUrls.dashboard.home), + ); + } + } else { + return NextResponse.next(); } } // See "Matching Paths" below to learn more export const config = { - matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"], + matcher: [ + "/((?!api|assets|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)", + ], }; diff --git a/starterkits/saas/src/validations/mdx-content.ts b/starterkits/saas/src/validations/mdx-content.ts index 28da78f..c51ccde 100644 --- a/starterkits/saas/src/validations/mdx-content.ts +++ b/starterkits/saas/src/validations/mdx-content.ts @@ -3,6 +3,7 @@ import { z } from "zod"; export const docsMetaSchema = z.object({ title: z.string(), slug: z.string(), + publishedAt: z.date(), tags: z.array(z.string()).optional(), description: z.string().optional(), isDraft: z.boolean().optional(), @@ -14,7 +15,7 @@ export const blogMetaSchema = z.object({ title: z.string(), slug: z.string(), publishedAt: z.date(), - updatedAt: z.date().optional(), + updatedAt: z.date(), readTime: z.string(), tags: z.array(z.string()).optional(), description: z.string(), @@ -27,7 +28,6 @@ export type BlogMetaData = z.infer; export const changelogMetaSchema = z.object({ title: z.string(), - slug: z.string(), publishedAt: z.date(), thumbnail: z.string().url(), description: z.string(),