import Link from "next/link"; import { listDocuments } from "@mcpedia/core"; import { SECTIONS } from "@mcpedia/config/sections"; export const dynamic = "force-dynamic"; /** * Build a hierarchical folder tree from a flat list of document paths. * Each tree node is either a folder (has children) or a leaf doc. */ interface TreeNode { name: string; slug: string; title: string; children: TreeNode[]; isLeaf: boolean; } function buildFolderTree(paths: string[], section: string): TreeNode[] { const tree: TreeNode[] = []; const base = `${section}/`; const addPath = (cleanPath: string) => { const parts = cleanPath.split("/"); let current = tree; let currentPath = section; for (let i = 0; i < parts.length; i++) { const part = parts[i]; const isLeaf = i === parts.length - 1; currentPath = `${currentPath}/${part}`; let node = current.find((n) => n.name === part); if (!node) { node = { name: part, slug: currentPath, title: "", children: [], isLeaf: false, }; current.push(node); } if (isLeaf) { node.isLeaf = true; node.title = part .split(/[-_]/) .map((w) => w.charAt(0).toUpperCase() + w.slice(1)) .join(" "); } else if (!node.title) { node.title = part .split(/[-_]/) .map((w) => w.charAt(0).toUpperCase() + w.slice(1)) .join(" "); } current = node.children; } }; for (const docPath of paths) { const rel = docPath.startsWith(base) ? docPath.slice(base.length) : docPath; const cleanPath = rel.replace(/\.md$/, ""); addPath(cleanPath); } return tree; } function renderTree(nodes: TreeNode[], pathname: string) { return ( ); } interface SectionTreeProps { section: string; docPaths: string[]; pathname: string; } function SectionTree({ section, docPaths, pathname }: SectionTreeProps) { const tree = buildFolderTree(docPaths.filter((p) => p.startsWith(`${section}/`)), section); const sectionInfo = SECTIONS.find((s) => s.id === section); if (!sectionInfo) return null; return (
{sectionInfo.icon}

{sectionInfo.label}

{tree.length > 0 ? ( renderTree(tree, pathname) ) : (

No documents

)}
); } export default async function HomePage() { const all = await listDocuments(); const docPaths = all.map((d) => d.path); const recent = [...all] .sort( (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(), ) .slice(0, 6); return ( <> {/* Hero */}

MCPedia

A content-first knowledge base for humans and AI agents. Browse the hierarchical folder structure below, search all documents, or connect via the MCP server.

Browse Documents Search
{/* Hierarchical Folder Tree */}

Browse by section

{SECTIONS.map((s) => { const sectionDocs = all.filter((d) => d.section === s.id); return (
{s.icon} View all ({sectionDocs.length})

{s.label}

{s.desc}

{/* Inline folder tree */}
); })}
{/* Recent Documents */} {recent.length > 0 && (

Recently updated

View all →
{recent.map((d) => { const sInfo = SECTIONS.find((s) => s.id === d.section); return (
{sInfo?.icon || "📄"}

{d.title}

{d.tags.slice(0, 3).map((t) => ( #{t} ))}
); })}
)} {/* MCP info */}

AI agents

MCP server at{" "} mcp.asepharyana.my.id/mcp . All tools available via Streamable HTTP transport.

MCP spec →
); }