Skip to content

Commit

Permalink
feat(saas): blog slug page, fetch blog according to slug
Browse files Browse the repository at this point in the history
  • Loading branch information
alifarooq9 committed Apr 20, 2024
1 parent 009d354 commit 5dadb94
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 40 deletions.
12 changes: 10 additions & 2 deletions starterkits/saas/src/app/(web)/_components/general-components.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,27 @@
import { Badge } from "@/components/ui/badge";
import { cn } from "@/lib/utils";
import { type ElementType } from "react";
import Balancer from "react-wrap-balancer";

// This is a page wrapper used in all public web pages
export function WebPageWrapper({
children,
as,
className,
}: {
children: React.ReactNode;
as?: ElementType;
className?: string;
}) {
const Comp: ElementType = as ?? "main";

return (
<Comp className="container flex flex-col items-center justify-center gap-24 py-10">
<Comp
className={cn(
"container flex flex-col items-center justify-center gap-24 py-10",
className,
)}
>
{children}
</Comp>
);
Expand All @@ -38,7 +46,7 @@ export function WebPageHeading({
)}
<Balancer
as="h1"
className="font-heading max-w-2xl text-center text-5xl font-bold leading-none sm:text-6xl"
className="max-w-2xl text-center font-heading text-5xl font-bold leading-none sm:text-6xl"
>
{title}
</Balancer>
Expand Down
53 changes: 47 additions & 6 deletions starterkits/saas/src/app/(web)/blog/[...slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,59 @@
import { WebPageWrapper } from "@/app/(web)/_components/general-components";
import { Toc } from "@/components/toc";
import { siteUrls } from "@/config/urls";
import { getBlogs } from "@/server/actions/blog";
import { format } from "date-fns";
import Image from "next/image";
import { notFound, redirect } from "next/navigation";

type BlogSlugPageProps = {
params: {
slug: string[];
};
};

export default function BlogSlugPage({ params }: BlogSlugPageProps) {
export default async function BlogSlugPage({ params }: BlogSlugPageProps) {
if (!params.slug) {
return redirect(siteUrls.blog);
}

const slug = params.slug.join("/");

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

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

return (
<WebPageWrapper>
<div className="w-full">
<h1>Blog Slug Page</h1>
{JSON.stringify(params)}
</div>
<WebPageWrapper className="relative max-w-3xl flex-row items-start gap-8">
<article className="w-full space-y-10">
<div className="space-y-4">
<h1 className="scroll-m-20 font-heading text-4xl font-bold">
{blog.metaData.title}
</h1>

<div className="relative aspect-video max-h-[350px] w-full overflow-hidden rounded-md bg-muted/60">
<Image
src={blog.metaData.tumbnail}
alt={blog.metaData.title}
className="rounded-md"
fill
/>
</div>
<p className="text-sm text-muted-foreground">
{format(new Date(blog.metaData.publishedAt), "PPP")}{" "}
{blog.metaData.readTime} read
</p>
{blog.metaData.updatedAt && (
<p className="text-sm text-muted-foreground">
Last updated at{" "}
{format(new Date(blog.metaData.updatedAt), "PPP")}
</p>
)}
</div>
{blog.content}
</article>
</WebPageWrapper>
);
}
24 changes: 11 additions & 13 deletions starterkits/saas/src/app/(web)/blog/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,21 @@ export default async function BlogsPage() {
<p>{blog.metaData.description}</p>
<div className="grid gap-0.5 font-light">
<p className="text-sm text-muted-foreground">
Created at{" "}
{format(
new Date(blog.metaData.publishedAt),
"PPP",
)}
</p>

<p className="text-sm text-muted-foreground">
Updated at{" "}
{format(
new Date(blog.metaData.updatedAt),
"PPP",
)}
</p>
<p className="text-sm text-muted-foreground">
{blog.metaData.readTime} read
)}{" "}
{blog.metaData.readTime} read
</p>
{blog.metaData.updatedAt && (
<p className="text-sm text-muted-foreground">
Last updated at{" "}
{format(
new Date(blog.metaData.updatedAt),
"PPP",
)}
</p>
)}
</div>
</Link>
))}
Expand Down
3 changes: 2 additions & 1 deletion starterkits/saas/src/app/docs/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { notFound, redirect } from "next/navigation";
import { Toc } from "@/components/toc";
import { getDocs } from "@/server/actions/docs";
import { siteUrls } from "@/config/urls";

type DocsSlugPageProps = {
params: {
Expand All @@ -18,7 +19,7 @@ export async function generateStaticParams() {

export default async function DocsSlugPage({ params }: DocsSlugPageProps) {
if (!params.slug) {
return redirect("/docs/introduction");
return redirect(siteUrls.docs);
}

const doc = (await getDocs()).find(
Expand Down
31 changes: 16 additions & 15 deletions starterkits/saas/src/content/blog/create-saas-in-1-day.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,27 @@
title: Create a SaaS in 1 day
slug: create-saas-in-1-day
publishedAt: 2022-01-01
updatedAt: 2022-01-01
updatedAt: 2024-05-01
readTime: 5 min
tags: ["saas", "introduction"]
description: This is the introduction
tumbnail: https://fakeimg.pl/700x400/d1d1d1/6b6b6b
---

# Create a SaaS in 1 day

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet.


## Heading 2
## This is the introduction

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet.


<Tabs>
<Tabs defaultValue='tab-1'>

<TabsList>
<TabsTrigger value="tab-1">Tab 1</TabsTrigger>
<TabsTrigger value="tab-2">Tab 2</TabsTrigger>
</TabsList>

<Tab>
<TabsContent value="tab-1">

```tsx
import { useState } from "react";
Expand All @@ -40,9 +41,9 @@ function Counter() {
}
```

</Tab>
</TabsContent>

<Tab>
<TabsContent value="tab-2">

```tsx
import { useState } from "react";
Expand All @@ -63,26 +64,26 @@ function Counter() {
export default Counter;
```

</Tab>
</TabsContent>

</Tabs>


### Heading 3
### This is the long heading 3

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet.


#### Heading 4
### This is the long heading 4

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet.


##### Heading 5
### This is the long heading 5

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet.

###### Heading 6
### short heading 6

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet.

Expand Down
3 changes: 1 addition & 2 deletions starterkits/saas/src/content/blog/introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@
title: Introduction
slug: introduction
publishedAt: 2022-01-01
updatedAt: 2022-01-01
readTime: 5 min
tags: ["introduction", "saas"]
description: This is the introduction
tumbnail: https://fakeimg.pl/700x400/d1d1d1/6b6b6b
---

# Introduction
## Introduction

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet.

Expand Down
2 changes: 1 addition & 1 deletion starterkits/saas/src/validations/mdx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const blogMetaSchema = z.object({
title: z.string(),
slug: z.string(),
publishedAt: z.string().datetime(),
updatedAt: z.string().datetime(),
updatedAt: z.string().datetime().optional(),
readTime: z.string(),
tags: z.array(z.string()).optional(),
description: z.string(),
Expand Down

0 comments on commit 5dadb94

Please sign in to comment.