11import Link from "next/link" ;
22import { notFound } from "next/navigation" ;
3- import type { ComponentType } from "react" ;
43import { Container } from "@/components/ui/container" ;
54import { MonoLabel } from "@/components/ui/mono-label" ;
65import { Tag } from "@/components/ui/tag" ;
7- import {
8- getAdjacentResearchArticles ,
9- getAllResearchArticles ,
10- getResearchArticleBySlug ,
11- } from "@/lib/research" ;
12- import type { ResearchArticleMetadata } from "@/types" ;
6+ import { researchRepository } from "@/lib/research" ;
137
148// Prerenders every known article at build time — same as
159// /projects/[slug]. Deliberately NOT setting `dynamicParams = false` here:
@@ -21,7 +15,7 @@ import type { ResearchArticleMetadata } from "@/types";
2115// /projects/[slug]/page.tsx already does successfully in production — is
2216// the pattern actually proven to work on this stack.
2317export async function generateStaticParams ( ) {
24- const articles = await getAllResearchArticles ( ) ;
18+ const articles = await researchRepository . getPublishedArticles ( ) ;
2519 return articles . map ( ( article ) => ( { slug : article . slug } ) ) ;
2620}
2721
@@ -40,17 +34,15 @@ export default async function ResearchArticlePage(
4034) {
4135 const { slug } = await props . params ;
4236
43- const known = await getResearchArticleBySlug ( slug ) ;
44- if ( ! known ) notFound ( ) ;
37+ // The page asks the repository for an article and either gets a fully
38+ // renderable one back or doesn't — it never knows or cares whether that
39+ // meant a slug lookup in an array, a file import, or (eventually) a D1
40+ // query for a row with status = 'published'.
41+ const article = await researchRepository . getPublishedArticleBySlug ( slug ) ;
42+ if ( ! article ) notFound ( ) ;
4543
46- const { default : Article , metadata } = ( await import (
47- `@/content/research/${ slug } .mdx`
48- ) ) as {
49- default : ComponentType ;
50- metadata : ResearchArticleMetadata ;
51- } ;
52-
53- const { newer, older } = await getAdjacentResearchArticles ( slug ) ;
44+ const { Content } = article ;
45+ const { newer, older } = await researchRepository . getAdjacentPublishedArticles ( slug ) ;
5446
5547 return (
5648 < Container as = "main" className = "flex flex-1 flex-col gap-10 py-16" >
@@ -63,32 +55,32 @@ export default async function ResearchArticlePage(
6355
6456 < div className = "flex flex-col gap-3" >
6557 < MonoLabel className = "text-dim" >
66- RESEARCH / { metadata . category }
58+ RESEARCH / { article . category }
6759 </ MonoLabel >
6860 < div className = "flex flex-wrap items-center gap-3" >
6961 < MonoLabel className = "text-dim" >
70- { formatArticleDate ( metadata . date ) }
62+ { formatArticleDate ( article . publishedAt ) }
7163 </ MonoLabel >
7264 < span className = "text-dim" > ·</ span >
73- < MonoLabel className = "text-dim" > { metadata . readingMinutes } MIN READ</ MonoLabel >
65+ < MonoLabel className = "text-dim" > { article . readingMinutes } MIN READ</ MonoLabel >
7466 </ div >
7567 < h1 className = "text-3xl font-semibold tracking-tight sm:text-4xl" >
76- { metadata . title }
68+ { article . title }
7769 </ h1 >
78- < p className = "max-w-xl text-lg text-muted" > { metadata . description } </ p >
70+ < p className = "max-w-xl text-lg text-muted" > { article . description } </ p >
7971 </ div >
8072
8173 < div className = "flex flex-col gap-3 border-t border-border pt-8" >
8274 < MonoLabel > ARTICLE</ MonoLabel >
8375 < div className = "max-w-xl" >
84- < Article />
76+ < Content />
8577 </ div >
8678 </ div >
8779
8880 < div className = "flex flex-col gap-3 border-t border-border pt-8" >
8981 < MonoLabel > TAGS</ MonoLabel >
9082 < div className = "flex flex-wrap gap-2" >
91- { metadata . tags . map ( ( tag ) => (
83+ { article . tags . map ( ( tag ) => (
9284 < Tag key = { tag } > { tag } </ Tag >
9385 ) ) }
9486 </ div >
0 commit comments