Skip to content

Commit

Permalink
Feat/move to builtin mdx (#304)
Browse files Browse the repository at this point in the history
* chore: update deps

* feat: replace next-mdx-remote with builtin mdx

* chore: format
  • Loading branch information
nikhilsnayak authored Dec 5, 2024
1 parent f0bbc97 commit e2d85a0
Show file tree
Hide file tree
Showing 61 changed files with 231 additions and 337 deletions.
68 changes: 21 additions & 47 deletions app/blogs/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { Suspense } from 'react';
import type { Metadata } from 'next';
import { notFound } from 'next/navigation';
import { Metadata } from 'next';
import { Eye } from 'lucide-react';

import { BASE_URL } from '~/lib/constants';
import { formatDate } from '~/lib/utils';
import { ErrorBoundary } from '~/components/error-boundary';
import { CustomMDX } from '~/components/mdx';
import { Spinner } from '~/components/spinner';
import { SummarizeButton } from '~/features/ai/components/summarize-button';
import { CommentsSection } from '~/features/blog/components/comments-section';
Expand All @@ -15,16 +13,16 @@ import { Hearts } from '~/features/blog/components/hearts';
import { SocialShare } from '~/features/blog/components/social-share';
import { BlogViewsCount } from '~/features/blog/components/views';
import {
getBlogPostBySlug,
getBlogPosts,
getBlogMetadataBySlug,
getBlogsMetadata,
} from '~/features/blog/functions/queries';

interface BlogProps {
params: Promise<{ slug: string }>;
}

export async function generateStaticParams() {
const posts = await getBlogPosts();
const posts = await getBlogsMetadata();

return posts.map((post) => ({
slug: post.slug,
Expand All @@ -35,19 +33,14 @@ export async function generateMetadata({
params,
}: BlogProps): Promise<Metadata> {
const { slug } = await params;
const post = await getBlogPostBySlug(slug);
if (!post) {
const metadata = await getBlogMetadataBySlug(slug);
if (!metadata) {
return {};
}

const {
title,
publishedAt: publishedTime,
summary: description,
image,
} = post.metadata;
const ogImage =
image ?? `${BASE_URL}/api/og?title=${encodeURIComponent(title)}`;
const { title, publishedAt: publishedTime, summary: description } = metadata;

const ogImage = `${BASE_URL}/api/og?title=${encodeURIComponent(title)}`;

return {
title,
Expand Down Expand Up @@ -76,27 +69,10 @@ export async function generateMetadata({

export default async function BlogPage({ params }: Readonly<BlogProps>) {
const { slug } = await params;
const post = await getBlogPostBySlug(slug);

if (!post) {
notFound();
}

const { metadata } = post;
let components = null;
const { publishedAt, summary, title } = await getBlogMetadataBySlug(slug);

if (metadata.components) {
const componentNames = JSON.parse(metadata.components);
const importedComponents = await Promise.all(
(componentNames as string[]).map(async (name) => {
const mod = await import(`../../../content/components/${slug}/${name}`);
return { [name]: mod.default };
})
);
components = Object.assign({}, ...importedComponents);
}
const { default: Blog } = await import(`../../../content/${slug}/post.mdx`);

const blogTitle = post.metadata.title;
return (
<section>
<script
Expand All @@ -106,13 +82,11 @@ export default async function BlogPage({ params }: Readonly<BlogProps>) {
__html: JSON.stringify({
'@context': 'https://schema.org',
'@type': 'BlogPosting',
headline: post.metadata.title,
datePublished: post.metadata.publishedAt,
dateModified: post.metadata.publishedAt,
description: post.metadata.summary,
image: post.metadata.image
? `${BASE_URL}${post.metadata.image}`
: `/api/og?title=${encodeURIComponent(post.metadata.title)}`,
headline: title,
datePublished: publishedAt,
dateModified: publishedAt,
description: summary,
image: `/api/og?title=${encodeURIComponent(title)}`,
url: `${BASE_URL}/blogs/${slug}`,
author: {
'@type': 'Person',
Expand All @@ -127,14 +101,14 @@ export default async function BlogPage({ params }: Readonly<BlogProps>) {
viewTransitionName: slug,
}}
>
{post.metadata.title}
{title}
</h1>
<div className='mb-8 mt-4 flex flex-col justify-between gap-3 text-sm sm:flex-row sm:items-center'>
<div className='flex items-center gap-3'>
<p className='text-sm text-neutral-600 dark:text-neutral-400'>
{formatDate(post.metadata.publishedAt)}
{formatDate(publishedAt)}
</p>
<SummarizeButton blogTitle={blogTitle} />
<SummarizeButton blogTitle={title} />
</div>
<ErrorBoundary fallback={<span>{"Couldn't load views"}</span>}>
<Suspense fallback={<Spinner variant='ellipsis' />}>
Expand All @@ -149,13 +123,13 @@ export default async function BlogPage({ params }: Readonly<BlogProps>) {
</ErrorBoundary>
</div>
<article className='prose min-w-full dark:prose-invert'>
<CustomMDX source={post.content} components={components} />
<Blog />
</article>
<div className='mt-8 space-y-4'>
<p className='dark:text-fluorescent'>
If you enjoyed this blog, share it on social media to help others find
it too
<SocialShare title={post.metadata.title} slug={slug} />
<SocialShare title={title} slug={slug} />
</p>
<ErrorBoundary fallback={<span>{"Couldn't load hearts"}</span>}>
<Suspense fallback={<HeartButton />}>
Expand Down
4 changes: 2 additions & 2 deletions app/blogs/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ArrowUpRight, Rss } from 'lucide-react';
import { Link } from 'next-view-transitions';

import { formatDate } from '~/lib/utils';
import { getBlogPosts } from '~/features/blog/functions/queries';
import { getBlogsMetadata } from '~/features/blog/functions/queries';

export const dynamic = 'force-static';

Expand All @@ -13,7 +13,7 @@ export const metadata: Metadata = {
};

export default async function BlogsPage() {
const allBlogs = await getBlogPosts();
const allBlogs = await getBlogsMetadata();

return (
<section>
Expand Down
4 changes: 2 additions & 2 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@ import { cn, formatDate } from '~/lib/utils';
import { ErrorBoundary } from '~/components/error-boundary';
import { Spinner } from '~/components/spinner';
import { BlogViewsCount } from '~/features/blog/components/views';
import { getBlogPosts } from '~/features/blog/functions/queries';
import { getBlogsMetadata } from '~/features/blog/functions/queries';

const sourceCodePro = Source_Code_Pro({
weight: ['600'],
subsets: ['latin'],
});

export default async function HomePage() {
const recentBlogs = await getBlogPosts();
const recentBlogs = await getBlogsMetadata();

return (
<section>
Expand Down
10 changes: 2 additions & 8 deletions app/rss.xml/route.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import { BASE_URL } from '~/lib/constants';
import { getBlogPosts } from '~/features/blog/functions/queries';
import { getBlogsMetadata } from '~/features/blog/functions/queries';

export const dynamic = 'force-static';

export async function GET() {
const allBlogs = await getBlogPosts();
const allBlogs = await getBlogsMetadata();

const itemsXml = allBlogs
.sort((a, b) => {
if (new Date(a.metadata.publishedAt) > new Date(b.metadata.publishedAt)) {
return -1;
}
return 1;
})
.map(
(post) =>
`<item>
Expand Down
4 changes: 2 additions & 2 deletions app/sitemap.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { BASE_URL } from '~/lib/constants';
import { getBlogPosts } from '~/features/blog/functions/queries';
import { getBlogsMetadata } from '~/features/blog/functions/queries';

export default async function sitemap() {
const routes = ['', '/work', '/bot', '/blogs', '/rss.xml'];
const blogs = await getBlogPosts();
const blogs = await getBlogsMetadata();

return [
...routes.map((route) => ({
Expand Down
Binary file modified bun.lockb
Binary file not shown.
23 changes: 0 additions & 23 deletions content/components/llm-and-rsc/StockDisplayDemo.tsx

This file was deleted.

5 changes: 5 additions & 0 deletions content/dissecting-partial-pre-rendering/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"title": "Dissecting Partial Pre Rendering",
"publishedAt": "2024-07-06",
"summary": "Fast initial loads, dynamic content, and rich interactivity in a single HTTP request!"
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
title: 'Dissecting Partial Pre Rendering'
publishedAt: '2024-07-06'
summary: 'Fast initial loads, dynamic content, and rich interactivity in a single HTTP request!'
---
import buildOutput1 from './build-output-1.png';
import buildOutput2 from './build-output-2.png';
import buildOutput3 from './build-output-3.png';
import courseDetailsPage from './course-details-page.png';
import customerReviewSection from './customer-review-section.png';

## Prelude

Expand Down Expand Up @@ -98,12 +98,7 @@ Consider a Course Details Page as shown below.

> Note: This is just an example for illustration purposes and the use case might vary in real scenarios. In this example, I assume that course details don't change very often.
<Image
src='/blogs/dissecting-partial-pre-rendering/course-details-page.png'
alt='Course Details page'
width={1168}
height={929}
/>
<Image src={courseDetailsPage} alt='Course Details page' />

The corresponding JSX to render this page looks like this:

Expand Down Expand Up @@ -223,21 +218,11 @@ So, technically, we generate a static HTML page with this information (SSG), res

Here is the build logs for the above use case:

<Image
src='/blogs/dissecting-partial-pre-rendering/build-output-1.png'
alt='Build output 1'
width={805}
height={307}
/>
<Image src={buildOutput1} alt='Build output 1' />

Now let's increase the complexity a bit more. We need to add a customer review section as shown below:

<Image
src='/blogs/dissecting-partial-pre-rendering/customer-review-section.png'
alt='Course Details page'
width={1121}
height={183}
/>
<Image src={customerReviewSection} alt='Customer Review Section' />

The tricky part here is that the reviews get added and edited very often since our platform is very popular. Therefore, the reviews must be dynamically generated for each request.

Expand Down Expand Up @@ -287,12 +272,7 @@ With the above changes, our entire route is now dynamically rendered because we

Here the build logs for the above use case:

<Image
src='/blogs/dissecting-partial-pre-rendering/build-output-2.png'
alt='Build output 2'
width={811}
height={322}
/>
<Image src={buildOutput2} alt='Build output 2' />

Now comes the actual fun part. Remember earlier I said the PPR is built on top of existing React APIs? We have used the `Suspense` boundary in the above code to show a fallback UI while our `Reviews` component is suspended to get the data from the database.

Expand Down Expand Up @@ -321,12 +301,7 @@ export default nextConfig;

With this one change we are now PPRing our page. Here is the build output with PPR turned ON

<Image
src='/blogs/dissecting-partial-pre-rendering/build-output-3.png'
alt='Build output 3'
width={1122}
height={322}
/>
<Image src={buildOutput3} alt='Build output 3' />

### Chapter 3 - How It Compares to Other Rendering Strategies

Expand Down
5 changes: 5 additions & 0 deletions content/how-i-built-my-portfolio/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"title": "How I Built My Portfolio",
"publishedAt": "2024-06-02",
"summary": "Sneak Peak of tech I used to build my portfolio"
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
---
title: 'How I Built My Portfolio'
publishedAt: '2024-06-02'
summary: 'Sneak Peak of tech I used to build my portfolio'
---
import speedInsights from './speed-insights.png';

## Prerequisites

Expand All @@ -24,12 +20,7 @@ However, these days, websites are much more than static HTML documents. People s

A glimpse of the benefits of the tech stack I used.

<Image
src='/blogs/how-i-built-my-portfolio/speed-insights.png'
alt='Speed Insights'
width={870}
height={751}
/>
<Image src={speedInsights} alt='Speed Insights' />

Here is a rundown of the technologies I chose for building my portfolio:

Expand Down
File renamed without changes.
File renamed without changes
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Markdown from 'react-markdown';
import { Spinner } from '~/components/spinner';

import { askAI, getStockPrice } from './ai';
import type { Message } from './GenUI';
import type { Message } from './gen-ui';
import { StockDisplay } from './stock-display';

async function StockCard({ symbol }: { symbol: string }) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface Message {
display: ReactNode;
}

export default function GenUI() {
export function GenUI() {
const [messages, setMessages] = useState([] as Message[]);
const [isPending, startTransition] = useTransition();

Expand Down
5 changes: 5 additions & 0 deletions content/llm-and-rsc/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"title": "LLM and RSC: A match made in Heaven",
"publishedAt": "2024-08-30",
"summary": "Powerful synergy between advanced AI tools and modern web technologies to enhance user interfaces."
}
21 changes: 5 additions & 16 deletions content/llm-and-rsc.mdx → content/llm-and-rsc/post.mdx
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
---
title: 'LLM and RSC: A match made in Heaven'
publishedAt: '2024-08-30'
summary: 'Powerful synergy between advanced AI tools and modern web technologies to enhance user interfaces.'
image: '/blogs/llm-and-rsc/cover.png'
components: '["GenUI", "StockDisplayDemo"]'
---

<Image
src='/blogs/llm-and-rsc/cover.png'
alt='Speed Insights'
width={1080}
height={540}
className='grayscale'
priority
/>
import cover from './cover.png';
import { GenUI } from './gen-ui';
import { StockDisplayDemo } from './stock-display';

<Image src={cover} alt='cover image' className='grayscale' priority />

> I know the title is a bit creepy, but bear with me till the end, and I'll convince you that the title is actually true.
Expand Down
Loading

1 comment on commit e2d85a0

@vercel
Copy link

@vercel vercel bot commented on e2d85a0 Dec 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.