spb/autoscholar
Public
1import { listTopics } from "@autoscholar/core";2import type { Metadata } from "next";3import Link from "next/link";4import { EmptyState } from "@/components/EmptyState";5import { db } from "@/lib/server/db";67export const dynamic = "force-dynamic";8export const metadata: Metadata = {9 title: "Topics",10 description: "Browse AutoScholar working papers by scientific discipline and subfield.",11 alternates: { canonical: "/topics" },12};1314export default async function TopicsPage() {15 const topics = await listTopics(db());16 const roots = topics.filter((t) => !t.parentId);17 return (18 <div className="container-x section-tight space-y-8">19 <header className="max-w-2xl">20 <p className="eyebrow">Browse</p>21 <h1 className="title-1 mt-2">Scientific disciplines</h1>22 <p className="muted mt-2 text-sm leading-relaxed">23 Every legitimate academic discipline is in scope. Methodology follows the question: econometrics is24 never imposed on a proof, and a literature review never pretends to be an experiment.25 </p>26 </header>27 {roots.length === 0 ? (28 <EmptyState title="Topics have not been configured yet." />29 ) : (30 <ul className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">31 {roots.map((t) => {32 const children = topics.filter((c) => c.parentId === t.id);33 return (34 <li key={t.id} className="surface card-link relative p-5">35 <Link href={`/topics/${t.slug}`} className="title-3 no-underline hover:underline">36 {t.name}37 </Link>38 <p className="mono-id mt-1">39 {t.paperCount} {t.paperCount === 1 ? "paper" : "papers"}40 </p>41 {t.description && <p className="muted mt-2 text-sm">{t.description}</p>}42 {children.length > 0 && (43 <ul className="mt-3 flex flex-wrap gap-1.5">44 {children.map((c) => (45 <li key={c.id}>46 <Link47 href={`/topics/${c.slug}`}48 className="chip no-underline"49 style={{ minHeight: "1.75rem" }}50 >51 {c.name}52 </Link>53 </li>54 ))}55 </ul>56 )}57 </li>58 );59 })}60 </ul>61 )}62 </div>63 );64}65