Skip to content

Commit 7bc9e10

Browse files
committed
add blog
1 parent f90770a commit 7bc9e10

File tree

8 files changed

+238
-153
lines changed

8 files changed

+238
-153
lines changed

apps/site/app/blog/[slug]/page.tsx

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { blog } from '@/.source/server';
2+
import { notFound } from 'next/navigation';
3+
import { HomeLayout } from 'fumadocs-ui/layouts/home';
4+
import { Logo } from '../../components/Logo';
5+
import defaultMdxComponents from 'fumadocs-ui/mdx';
6+
7+
export default async function BlogPost({
8+
params,
9+
}: {
10+
params: Promise<{ slug: string }>;
11+
}) {
12+
const { slug } = await params;
13+
const post = blog.find((post: any) => post.slug === slug);
14+
15+
if (!post) notFound();
16+
17+
const MDX = post.data.body;
18+
19+
return (
20+
<HomeLayout
21+
nav={{ title: <Logo />, url: '/' }}
22+
links={[
23+
{
24+
text: 'Documentation',
25+
url: '/docs',
26+
active: 'nested-url',
27+
},
28+
{
29+
text: 'Blog',
30+
url: '/blog',
31+
active: 'nested-url',
32+
},
33+
]}
34+
>
35+
<article className="container mx-auto max-w-3xl px-6 py-12">
36+
<header className="mb-12 text-center">
37+
<div className="mb-4 text-sm text-fd-muted-foreground">
38+
<time>{new Date(post.data.date).toLocaleDateString()}</time>
39+
{post.data.author && <span>{post.data.author}</span>}
40+
</div>
41+
<h1 className="text-4xl font-bold leading-tight md:text-5xl">
42+
{post.data.title}
43+
</h1>
44+
{post.data.description && (
45+
<p className="mt-6 text-xl text-fd-muted-foreground">
46+
{post.data.description}
47+
</p>
48+
)}
49+
</header>
50+
51+
<div className="prose prose-zinc dark:prose-invert max-w-none">
52+
<MDX components={defaultMdxComponents} />
53+
</div>
54+
</article>
55+
</HomeLayout>
56+
);
57+
}
58+
59+
export function generateStaticParams() {
60+
return blog.map((post) => ({
61+
slug: post.slug,
62+
}));
63+
}
64+
65+
export async function generateMetadata({
66+
params
67+
}: {
68+
params: Promise<{ slug: string }>
69+
}) {
70+
const { slug } = await params;
71+
const post = blog.find((post) => post.slug === slug);
72+
if (!post) return;
73+
return {
74+
title: post.data.title,
75+
description: post.data.description,
76+
};
77+
}

apps/site/app/blog/page.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { blog } from '@/.source/server';
2+
import Link from 'next/link';
3+
import { HomeLayout } from 'fumadocs-ui/layouts/home';
4+
import { Logo } from '../components/Logo';
5+
6+
export default function BlogIndex() {
7+
const posts = [...blog].sort(
8+
(a, b) => new Date(b.data.date).getTime() - new Date(a.data.date).getTime()
9+
);
10+
11+
return (
12+
<HomeLayout
13+
nav={{ title: <Logo />, url: '/' }}
14+
links={[
15+
{
16+
text: 'Documentation',
17+
url: '/docs',
18+
active: 'nested-url',
19+
},
20+
{
21+
text: 'Blog',
22+
url: '/blog',
23+
active: 'nested-url',
24+
},
25+
]}
26+
>
27+
<main className="container mx-auto max-w-4xl px-6 py-12">
28+
<h1 className="mb-8 text-4xl font-bold">Latest Updates</h1>
29+
<div className="grid gap-6">
30+
{posts.map((post) => (
31+
<Link
32+
key={post.url}
33+
href={`/blog/${post.slug}`}
34+
className="flex flex-col gap-2 rounded-lg border p-6 transition-colors hover:bg-fd-accent/50"
35+
>
36+
<h2 className="text-2xl font-bold">{post.data.title}</h2>
37+
<div className="flex gap-2 text-sm text-fd-muted-foreground">
38+
<time>{new Date(post.data.date).toLocaleDateString()}</time>
39+
{post.data.author && <span>{post.data.author}</span>}
40+
</div>
41+
{post.data.description && (
42+
<p className="text-fd-muted-foreground">{post.data.description}</p>
43+
)}
44+
</Link>
45+
))}
46+
</div>
47+
</main>
48+
</HomeLayout>
49+
);
50+
}

apps/site/app/docs/layout.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,22 @@ import { Logo } from '../components/Logo';
55

66
export default function Layout({ children }: { children: ReactNode }) {
77
return (
8-
<DocsLayout tree={source.pageTree} nav={{ title: <Logo /> }}>
8+
<DocsLayout
9+
tree={source.pageTree}
10+
nav={{ title: <Logo />, url: '/' }}
11+
links={[
12+
{
13+
text: 'Documentation',
14+
url: '/docs',
15+
active: 'nested-url',
16+
},
17+
{
18+
text: 'Blog',
19+
url: '/blog',
20+
active: 'nested-url',
21+
},
22+
]}
23+
>
924
{children}
1025
</DocsLayout>
1126
);

apps/site/app/page.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ export default function HomePage() {
1616
url: '/docs',
1717
active: 'nested-url',
1818
},
19+
{
20+
text: 'Blog',
21+
url: '/blog',
22+
active: 'nested-url',
23+
},
1924
]}
2025
>
2126
{/* Hero Section */}

apps/site/content/blog/welcome.mdx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
title: Welcome to Object UI Blog
3+
date: 2024-03-20
4+
description: We are excited to announce the launch of our new blog!
5+
author: Object UI Team
6+
---
7+
8+
# Hello World
9+
10+
This is the first post on the Object UI blog. Here we will share updates about:
11+
- New features
12+
- Release notes
13+
- Tutorials and guides
14+
- Community showcases
15+
16+
Stay tuned for more!
17+
18+
## Code Example
19+
20+
```tsx
21+
import { SchemaRenderer } from '@object-ui/react';
22+
23+
export const App = () => (
24+
<SchemaRenderer schema={{ type: 'button', props: { children: 'Click Me' } }} />
25+
);
26+
```

apps/site/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
"fumadocs-ui": "^16.4.7",
1616
"next": "^16.1.4",
1717
"react": "19.2.3",
18-
"react-dom": "19.2.3"
18+
"react-dom": "19.2.3",
19+
"zod": "^3.22.4"
1920
},
2021
"devDependencies": {
2122
"@tailwindcss/postcss": "^4.1.18",

apps/site/source.config.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
1-
import { defineConfig, defineDocs } from 'fumadocs-mdx/config';
1+
import { defineConfig, defineDocs, defineCollections } from 'fumadocs-mdx/config';
2+
import { z } from 'zod';
23

34
export const { docs, meta } = defineDocs({
45
dir: '../../docs',
56
root: '../../docs',
67
files: ['**/*.{md,mdx}', '!**/node_modules/**'],
78
});
89

10+
export const blog = defineCollections({
11+
dir: 'content/blog',
12+
schema: z.object({
13+
title: z.string(),
14+
description: z.string().optional(),
15+
date: z.string().date().or(z.date()).map((d) => new Date(d).toISOString()),
16+
author: z.string().optional(),
17+
}),
18+
type: 'doc',
19+
});
20+
921
export default defineConfig();

0 commit comments

Comments
 (0)