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="space-y-8">19 <header>20 <p className="eyebrow">Browse</p>21 <h1 className="serif mt-1 text-3xl font-semibold">Scientific disciplines</h1>22 <p className="muted mt-2 max-w-2xl text-sm">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 p-4">35 <Link36 href={`/topics/${t.slug}`}37 className="serif text-lg font-semibold no-underline hover:underline"38 >39 {t.name}40 </Link>41 <p className="subtle mt-1 font-mono text-xs">42 {t.paperCount} {t.paperCount === 1 ? "paper" : "papers"}43 </p>44 {t.description && <p className="muted mt-2 text-sm">{t.description}</p>}45 {children.length > 0 && (46 <ul className="mt-3 flex flex-wrap gap-1.5">47 {children.map((c) => (48 <li key={c.id}>49 <Link href={`/topics/${c.slug}`} className="badge no-underline">50 {c.name}51 </Link>52 </li>53 ))}54 </ul>55 )}56 </li>57 );58 })}59 </ul>60 )}61 </div>62 );63}64