Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/sim/app/(landing)/blog/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Metadata } from 'next'
import { notFound } from 'next/navigation'
import { getAllPostMeta, getPostBySlug, getRelatedPosts } from '@/lib/blog/registry'
import { BLOG_SECTION, buildPostGraphJsonLd, buildPostMetadata } from '@/lib/blog/seo'
import { getBaseUrl } from '@/lib/core/utils/urls'
Expand All @@ -18,6 +19,7 @@ export async function generateMetadata({
}): Promise<Metadata> {
const { slug } = await params
const post = await getPostBySlug(slug)
if (!post) return {}
return buildPostMetadata(post)
}

Expand All @@ -26,6 +28,7 @@ export const revalidate = 86400
export default async function Page({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params
const post = await getPostBySlug(slug)
if (!post) notFound()
const related = await getRelatedPosts(slug, 3)

return (
Expand Down
9 changes: 6 additions & 3 deletions apps/sim/app/(landing)/blog/authors/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Metadata } from 'next'
import { notFound } from 'next/navigation'
import { getAllPostMeta } from '@/lib/blog/registry'
import { BLOG_SECTION, buildAuthorGraphJsonLd, buildAuthorMetadata } from '@/lib/blog/seo'
import { ContentAuthorPage } from '@/app/(landing)/components'
Expand All @@ -13,22 +14,24 @@ export async function generateMetadata({
const { id } = await params
const posts = (await getAllPostMeta()).filter((p) => p.authors.some((a) => a.id === id))
const author = posts[0]?.authors.find((a) => a.id === id)
if (!author) return {}
return buildAuthorMetadata(id, author)
}

export default async function AuthorPage({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params
const posts = (await getAllPostMeta()).filter((p) => p.authors.some((a) => a.id === id))
const author = posts[0]?.authors.find((a) => a.id === id)
if (!author) notFound()

return (
<ContentAuthorPage
basePath={BLOG_SECTION.basePath}
sectionName={BLOG_SECTION.name}
authorName={author?.name}
authorAvatarUrl={author?.avatarUrl}
authorName={author.name}
authorAvatarUrl={author.avatarUrl}
posts={posts}
graphJsonLd={author ? buildAuthorGraphJsonLd(author) : undefined}
graphJsonLd={buildAuthorGraphJsonLd(author)}
/>
)
}
26 changes: 26 additions & 0 deletions apps/sim/app/(landing)/blog/authors/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ChipLink } from '@sim/emcn'
import type { Metadata } from 'next'

export const metadata: Metadata = {
title: 'Page Not Found',
robots: { index: false, follow: true },
}

export default function BlogAuthorNotFound() {
return (
<main
id='main-content'
className='mx-auto flex min-h-[60vh] w-full max-w-[1460px] flex-col items-center justify-center gap-3 px-20 py-24 text-center max-sm:px-5 max-lg:px-8'
>
<h1 className='text-balance text-[40px] text-[var(--text-primary)] leading-[110%] tracking-[-0.02em]'>
Author not found
</h1>
<p className='text-[var(--text-muted)] text-lg'>
The author you&apos;re looking for doesn&apos;t exist or has been moved.
</p>
<ChipLink variant='primary' href='/blog' className='mt-3'>
Browse blog
</ChipLink>
</main>
)
}
26 changes: 26 additions & 0 deletions apps/sim/app/(landing)/blog/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ChipLink } from '@sim/emcn'
import type { Metadata } from 'next'

export const metadata: Metadata = {
title: 'Page Not Found',
robots: { index: false, follow: true },
}

export default function BlogNotFound() {
return (
<main
id='main-content'
className='mx-auto flex min-h-[60vh] w-full max-w-[1460px] flex-col items-center justify-center gap-3 px-20 py-24 text-center max-sm:px-5 max-lg:px-8'
>
<h1 className='text-balance text-[40px] text-[var(--text-primary)] leading-[110%] tracking-[-0.02em]'>
Post not found
</h1>
<p className='text-[var(--text-muted)] text-lg'>
The post you&apos;re looking for doesn&apos;t exist or has been moved.
</p>
<ChipLink variant='primary' href='/blog' className='mt-3'>
Browse blog
</ChipLink>
</main>
)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ChipLink } from '@sim/emcn'
import Image from 'next/image'
import Link from 'next/link'
import type { ContentMeta } from '@/lib/content/schema'
Expand All @@ -9,9 +8,9 @@ import { JsonLd } from '@/app/(landing)/components/json-ld'
interface ContentAuthorPageProps {
/** Route base path, e.g. `/blog` or `/library`. */
basePath: string
/** Section label used in the not-found fallback, e.g. "Blog" or "Library". */
/** Section label used in the back link, e.g. "Blog" or "Library". */
sectionName: string
authorName?: string
authorName: string
authorAvatarUrl?: string
/** Posts already filtered down to this author. */
posts: ContentMeta[]
Expand All @@ -32,22 +31,6 @@ export function ContentAuthorPage({
posts,
graphJsonLd,
}: ContentAuthorPageProps) {
if (!authorName) {
return (
<section className='mx-auto flex min-h-[60vh] w-full max-w-[1460px] flex-col items-center justify-center gap-3 px-20 py-24 text-center max-sm:px-5 max-lg:px-8'>
<h1 className='text-balance text-[40px] text-[var(--text-primary)] leading-[110%] tracking-[-0.02em]'>
Author not found
</h1>
<p className='text-[var(--text-muted)] text-lg'>
The author you&apos;re looking for doesn&apos;t exist or has been moved.
</p>
<ChipLink variant='primary' href={basePath} className='mt-3'>
Browse {sectionName}
</ChipLink>
</section>
)
}

return (
<>
<section className='bg-[var(--bg)]'>
Expand Down
3 changes: 3 additions & 0 deletions apps/sim/app/(landing)/library/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Metadata } from 'next'
import { notFound } from 'next/navigation'
import { getBaseUrl } from '@/lib/core/utils/urls'
import { getAllPostMeta, getPostBySlug, getRelatedPosts } from '@/lib/library/registry'
import { buildPostGraphJsonLd, buildPostMetadata, LIBRARY_SECTION } from '@/lib/library/seo'
Expand All @@ -18,6 +19,7 @@ export async function generateMetadata({
}): Promise<Metadata> {
const { slug } = await params
const post = await getPostBySlug(slug)
if (!post) return {}
return buildPostMetadata(post)
}

Expand All @@ -26,6 +28,7 @@ export const revalidate = 86400
export default async function Page({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params
const post = await getPostBySlug(slug)
if (!post) notFound()
const related = await getRelatedPosts(slug, 3)

return (
Expand Down
9 changes: 6 additions & 3 deletions apps/sim/app/(landing)/library/authors/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Metadata } from 'next'
import { notFound } from 'next/navigation'
import { getAllPostMeta } from '@/lib/library/registry'
import { buildAuthorGraphJsonLd, buildAuthorMetadata, LIBRARY_SECTION } from '@/lib/library/seo'
import { ContentAuthorPage } from '@/app/(landing)/components'
Expand All @@ -13,22 +14,24 @@ export async function generateMetadata({
const { id } = await params
const posts = (await getAllPostMeta()).filter((p) => p.authors.some((a) => a.id === id))
const author = posts[0]?.authors.find((a) => a.id === id)
if (!author) return {}
return buildAuthorMetadata(id, author)
}

export default async function AuthorPage({ params }: { params: Promise<{ id: string }> }) {
const { id } = await params
const posts = (await getAllPostMeta()).filter((p) => p.authors.some((a) => a.id === id))
const author = posts[0]?.authors.find((a) => a.id === id)
if (!author) notFound()

return (
<ContentAuthorPage
basePath={LIBRARY_SECTION.basePath}
sectionName={LIBRARY_SECTION.name}
authorName={author?.name}
authorAvatarUrl={author?.avatarUrl}
authorName={author.name}
authorAvatarUrl={author.avatarUrl}
posts={posts}
graphJsonLd={author ? buildAuthorGraphJsonLd(author) : undefined}
graphJsonLd={buildAuthorGraphJsonLd(author)}
/>
)
}
26 changes: 26 additions & 0 deletions apps/sim/app/(landing)/library/authors/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ChipLink } from '@sim/emcn'
import type { Metadata } from 'next'

export const metadata: Metadata = {
title: 'Page Not Found',
robots: { index: false, follow: true },
}

export default function LibraryAuthorNotFound() {
return (
<main
id='main-content'
className='mx-auto flex min-h-[60vh] w-full max-w-[1460px] flex-col items-center justify-center gap-3 px-20 py-24 text-center max-sm:px-5 max-lg:px-8'
>
<h1 className='text-balance text-[40px] text-[var(--text-primary)] leading-[110%] tracking-[-0.02em]'>
Author not found
</h1>
<p className='text-[var(--text-muted)] text-lg'>
The author you&apos;re looking for doesn&apos;t exist or has been moved.
</p>
<ChipLink variant='primary' href='/library' className='mt-3'>
Browse library
</ChipLink>
</main>
)
}
26 changes: 26 additions & 0 deletions apps/sim/app/(landing)/library/not-found.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ChipLink } from '@sim/emcn'
import type { Metadata } from 'next'

export const metadata: Metadata = {
title: 'Page Not Found',
robots: { index: false, follow: true },
}

export default function LibraryNotFound() {
return (
<main
id='main-content'
className='mx-auto flex min-h-[60vh] w-full max-w-[1460px] flex-col items-center justify-center gap-3 px-20 py-24 text-center max-sm:px-5 max-lg:px-8'
>
<h1 className='text-balance text-[40px] text-[var(--text-primary)] leading-[110%] tracking-[-0.02em]'>
Post not found
</h1>
<p className='text-[var(--text-muted)] text-lg'>
The post you&apos;re looking for doesn&apos;t exist or has been moved.
</p>
<ChipLink variant='primary' href='/library' className='mt-3'>
Browse library
</ChipLink>
</main>
)
}
6 changes: 3 additions & 3 deletions apps/sim/lib/content/registry-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export interface ContentRegistryConfig {

export interface ContentRegistry {
getAllPostMeta: () => Promise<ContentMeta[]>
getPostBySlug: (slug: string) => Promise<ContentPost>
getPostBySlug: (slug: string) => Promise<ContentPost | null>
getAllTags: () => Promise<TagWithCount[]>
getRelatedPosts: (slug: string, limit?: number) => Promise<ContentMeta[]>
getNavPosts: () => Promise<Pick<ContentMeta, 'slug' | 'title' | 'ogImage'>[]>
Expand Down Expand Up @@ -225,10 +225,10 @@ export function createContentRegistry(config: ContentRegistryConfig): ContentReg
}
}

async function getPostBySlug(slug: string): Promise<ContentPost> {
async function getPostBySlug(slug: string): Promise<ContentPost | null> {
const meta = await scanFrontmatters()
const found = meta.find((m) => m.slug === slug)
if (!found) throw new Error(`Post not found: ${slug}`)
if (!found) return null
const mdxPath = path.join(contentDir, slug, 'index.mdx')
const raw = await fs.readFile(mdxPath, 'utf-8')
const { content, data } = matter(raw)
Expand Down
Loading