Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 493c0d1

Browse files
itsarghyadasdillionverma
andauthoredJan 31, 2025
feat: all blogs migrated to content-collection (magicuidesign#527)
* feat: all blogs migrated to content-collection * fix: remove middleware and update promo * fix: rename slugs * fix: add rehype pretty code * fix: lint * fix: rename blogs to blog * fix: update sitemap * fix: small bug fix * fix: lint * fix: update link title tags * fix: update footer title --------- Co-authored-by: Dillion Verma <[email protected]>
1 parent ba17556 commit 493c0d1

File tree

106 files changed

+34160
-39
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

106 files changed

+34160
-39
lines changed
 

‎app/(blog)/blog/[slug]/page.tsx

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
/* eslint-disable jsx-a11y/alt-text */
2+
/* eslint-disable @next/next/no-img-element */
3+
4+
import MoreArticles, { getReadingTime } from "@/components/blog/more-articles";
5+
import PromoSection from "@/components/blog/promo-section";
6+
import BlogTableOfContents from "@/components/blog/table-of-contents";
7+
import { siteConfig } from "@/config/site";
8+
import { absoluteUrl } from "@/lib/utils";
9+
import { MDXContent } from "@content-collections/mdx/react";
10+
import { allBlogs } from "content-collections";
11+
import { ArrowLeftIcon } from "lucide-react";
12+
import type { Metadata } from "next";
13+
import Link from "next/link";
14+
import type { ComponentProps } from "react";
15+
16+
const components = {
17+
h1: ({ children, ...props }: ComponentProps<"h1">) => (
18+
<h1
19+
className="my-7 mb-5 scroll-m-20 text-3xl font-semibold tracking-tighter first:mt-0"
20+
{...props}
21+
>
22+
{children}
23+
</h1>
24+
),
25+
h2: ({ children, ...props }: ComponentProps<"h2">) => (
26+
<h2
27+
id={
28+
typeof children === "string"
29+
? children.toLowerCase().replace(/\s+/g, "-")
30+
: undefined
31+
}
32+
className="my-5 mb-3 scroll-m-20 text-2xl font-semibold tracking-tighter"
33+
{...props}
34+
>
35+
{children}
36+
</h2>
37+
),
38+
h3: ({ children, ...props }: ComponentProps<"h3">) => (
39+
<h3
40+
className="my-5 mb-3 scroll-m-20 text-lg font-semibold tracking-tighter"
41+
{...props}
42+
>
43+
{children}
44+
</h3>
45+
),
46+
h4: ({ children, ...props }: ComponentProps<"h4">) => (
47+
<h4
48+
className="my-5 mb-3 scroll-m-20 text-lg font-semibold tracking-tighter"
49+
{...props}
50+
>
51+
{children}
52+
</h4>
53+
),
54+
p: ({ children, ...props }: ComponentProps<"p">) => (
55+
<p className="my-3" {...props}>
56+
{children}
57+
</p>
58+
),
59+
ul: ({ children, ...props }: ComponentProps<"ul">) => (
60+
<ul className="my-6 ml-6 list-disc [&>li]:mt-2" {...props}>
61+
{children}
62+
</ul>
63+
),
64+
ol: ({ children, ...props }: ComponentProps<"ol">) => (
65+
<ol className="my-6 ml-6 list-decimal [&>li]:mt-2" {...props}>
66+
{children}
67+
</ol>
68+
),
69+
li: ({ children, ...props }: ComponentProps<"li">) => (
70+
<li className="" {...props}>
71+
{children}
72+
</li>
73+
),
74+
table: ({ children, ...props }: ComponentProps<"table">) => (
75+
<div className="table-container my-6 w-full overflow-y-auto rounded-lg border border-border">
76+
<table className="table-container my-0 w-full overflow-hidden" {...props}>
77+
{children}
78+
</table>
79+
</div>
80+
),
81+
th: ({ children, ...props }: ComponentProps<"th">) => (
82+
<th
83+
className="text-balance border-r border-border bg-neutral-50 px-6 py-3 text-left font-mono text-sm font-semibold tracking-tight text-secondary-foreground last:border-r-0 dark:bg-neutral-900"
84+
{...props}
85+
>
86+
{children}
87+
</th>
88+
),
89+
tr: ({ children, ...props }: ComponentProps<"tr">) => (
90+
<tr
91+
className="border-b last:border-b-0 odd:bg-background even:bg-background/50"
92+
{...props}
93+
>
94+
{children}
95+
</tr>
96+
),
97+
td: ({ children, ...props }: ComponentProps<"td">) => (
98+
<td
99+
className="border-r border-border px-6 py-4 text-sm text-secondary-foreground last:border-r-0"
100+
{...props}
101+
>
102+
{children}
103+
</td>
104+
),
105+
pre: ({ children, ...props }: ComponentProps<"pre">) => (
106+
<pre
107+
className="flex h-fit items-center justify-start gap-x-2 overflow-x-auto rounded-md border border-border bg-primary/5 px-2 py-1 font-mono text-sm text-secondary-foreground"
108+
{...props}
109+
>
110+
{children}
111+
</pre>
112+
),
113+
code: ({ children, ...props }: ComponentProps<"code">) => (
114+
<code
115+
className="rounded-md bg-primary/5 px-2 py-1 font-mono text-sm text-secondary-foreground"
116+
{...props}
117+
>
118+
{children}
119+
</code>
120+
),
121+
img: ({ children, ...props }: ComponentProps<"img">) => (
122+
<img className="my-2 rounded-xl border border-border" {...props} />
123+
),
124+
a: ({ children, ...props }: ComponentProps<"a">) => {
125+
const linkText = typeof children === "string" ? children : "Link";
126+
const autoTitle = props.href ? `Visit ${props.href}` : `Go to ${linkText}`;
127+
128+
return (
129+
<a
130+
className="text-primary underline underline-offset-4"
131+
title={props.title || autoTitle}
132+
{...props}
133+
>
134+
{children}
135+
</a>
136+
);
137+
},
138+
};
139+
140+
export async function generateMetadata({
141+
params,
142+
}: {
143+
params: { slug: string[] };
144+
}): Promise<Metadata> {
145+
const postSlug = Array.isArray(params.slug) ? params.slug[0] : params.slug;
146+
const post = allBlogs.find((post) => post._meta.path === postSlug);
147+
148+
if (!post) {
149+
return {};
150+
}
151+
152+
return {
153+
title: `${post.title} | ${siteConfig.name}`,
154+
description: post.description,
155+
openGraph: {
156+
title: post.title,
157+
description: post.description,
158+
type: "article",
159+
url: absoluteUrl(`/blog/${postSlug}`),
160+
images: [
161+
{
162+
url: post.image || "",
163+
width: 1200,
164+
height: 630,
165+
alt: post.title,
166+
},
167+
],
168+
},
169+
twitter: {
170+
card: "summary_large_image",
171+
title: post.title,
172+
description: post.description,
173+
images: [post.image || ""],
174+
creator: "@dillionverma",
175+
},
176+
};
177+
}
178+
179+
export default function BlogPage({ params }: { params: { slug: string[] } }) {
180+
const { slug } = params;
181+
182+
const postSlug = Array.isArray(slug) ? slug[0] : slug;
183+
const currentIndex = allBlogs.findIndex(
184+
(post) => post._meta.path === postSlug,
185+
);
186+
const post = allBlogs[currentIndex];
187+
188+
// Initialize with empty headings array - they will be populated after render
189+
const headings: string[] = [];
190+
191+
return (
192+
<div className="mx-auto mt-5 max-w-6xl px-5 xl:px-0">
193+
<div className="mb-4">
194+
<Link
195+
href="/blog"
196+
className="flex h-8 w-fit items-center justify-center rounded-full border border-border bg-muted px-4 text-sm text-secondary-foreground"
197+
>
198+
<ArrowLeftIcon className="mr-2 h-4 w-4" />
199+
Back to Blog
200+
</Link>
201+
</div>
202+
<article className="mx-auto mt-5 max-w-6xl rounded-xl border border-border">
203+
{post && (
204+
<div>
205+
<div className="relative overflow-hidden rounded-xl p-5 md:p-10">
206+
<img
207+
src={post.image}
208+
alt={post.title}
209+
className="h-full w-full rounded-xl border border-border object-cover object-left"
210+
/>
211+
</div>
212+
<div className="mx-auto flex flex-col items-center justify-center gap-y-2 border-y border-border p-5">
213+
<div className="mx-auto flex max-w-4xl flex-col items-center justify-center gap-y-2">
214+
<h1 className="text-balance text-center text-3xl font-semibold tracking-tighter md:text-5xl">
215+
{post.title}
216+
</h1>
217+
<p className="text-balance text-center text-secondary-foreground md:text-lg">
218+
{post.description}
219+
</p>
220+
</div>
221+
</div>
222+
<div className="flex items-center justify-center gap-x-2 border-b border-border p-3 text-sm text-secondary-foreground">
223+
<span>{getReadingTime(post.body.raw)} min read</span>
224+
{post.tag && (
225+
<>
226+
<span>·</span>
227+
<span className="rounded-full border border-border bg-primary/5 px-2.5 py-0.5">
228+
{post.tag}
229+
</span>
230+
</>
231+
)}
232+
</div>
233+
</div>
234+
)}
235+
<div className="grid grid-cols-1 gap-x-1 lg:grid-cols-7">
236+
<div className="article-content col-span-5 border-border p-5 lg:border-r lg:p-10">
237+
<MDXContent code={post?.body.code} components={components} />
238+
</div>
239+
<div className="sticky top-16 col-span-2 hidden h-fit w-full flex-col items-start justify-start p-5 text-primary lg:flex ">
240+
<PromoSection />
241+
<div className="mt-10 w-full">
242+
<BlogTableOfContents headings={headings} />
243+
</div>
244+
</div>
245+
</div>
246+
</article>
247+
{post && <MoreArticles currentPost={post} />}
248+
</div>
249+
);
250+
}

‎app/(blog)/blog/layout.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { SiteFooter } from "@/components/site-footer";
2+
import { SiteHeader } from "@/components/site-header";
3+
4+
export default function Layout({ children }: { children: React.ReactNode }) {
5+
return (
6+
<>
7+
<SiteHeader />
8+
<main className="min-h-screen w-full">{children}</main>
9+
<SiteFooter />
10+
</>
11+
);
12+
}

0 commit comments

Comments
 (0)
Please sign in to comment.