feat: add feature UI components with useQuery hooks

- navigation: SiteHeader component + useHeader hook
- blog: ArticleCard, ArticleList, ArticleDetail + useArticleList,
  useArticleBySlug hooks
- marketing-pages: PageHero, PageContent + usePageBySlug,
  useSiteSettings hooks
- App pages now thin server wrappers that prefetch + hydrate;
  feature components own their data fetching via useSuspenseQuery
This commit is contained in:
danijel-lf
2026-05-26 14:12:29 +02:00
parent 3ce71447b3
commit a28de6884c
20 changed files with 320 additions and 62 deletions

View File

@@ -1,31 +1,37 @@
import { dehydrate, HydrationBoundary } from "@tanstack/react-query";
import { appRouter } from "@repo/core-api";
import { getQueryClient } from "@repo/core-trpc";
import { PageContent } from "@repo/marketing-pages/ui";
import { bindAll } from "../../server/bind-production";
export default async function AboutPage() {
await bindAll();
const caller = appRouter.createCaller({});
const queryClient = getQueryClient();
const page = await caller.marketingPages.pageBySlug({ slug: "about" });
queryClient.setQueryData(
["marketingPages", "pageBySlug", { input: { slug: "about" } }],
page,
);
if (!page) {
return (
<main>
<h1>About</h1>
<p>This page hasn't been published yet.</p>
<main className="mx-auto max-w-3xl px-6 py-8">
<h1 className="text-3xl font-bold text-foreground">About</h1>
<p className="mt-2 text-muted-foreground">
This page hasn&apos;t been published yet.
</p>
</main>
);
}
return (
<main>
<article>
<header>
<h1>{page.hero.heading}</h1>
{page.hero.subheading ? <p>{page.hero.subheading}</p> : null}
</header>
<pre style={{ whiteSpace: "pre-wrap" }}>
{JSON.stringify(page.layout, null, 2)}
</pre>
</article>
</main>
<HydrationBoundary state={dehydrate(queryClient)}>
<main className="px-6 py-8">
<PageContent slug="about" />
</main>
</HydrationBoundary>
);
}