# Phase 14 — Hierarchical Folder Structure > User: "gk ada bedanya, maksud saya inginnya itu bisa yg bertingkat seperti github yg memiliki folder dalam folder" > Context: after the full dynamic-custom-fields overhaul (Phase 13), the user > wants document URLs/content organized in **nested folders** like GitHub — > `writeups/ctf/defcon-quals-2024/pwn-100/...` with subfolders under subfolders, > not just one level deep. ## Problem The current URL scheme is `/
/` where `slug` can contain `/` (e.g. `writeups/ctf/defcon-quals-2024/pwn-100-ret2win-alignment` → `/writeups/ctf/defcon-quals-2024/pwn-100-ret2win-alignment`). This works for **files** but there are no **folder-level index pages** — navigating to `/writeups/ctf/defcon-quals-2024/` returns 404 because Next.js catch-all `[section]/[...slug]/page.tsx` requires at least one slug segment beyond the section, and the sidebar only shows flat doc titles (no folder tree). GitHub's model: `github.com/org/repo/tree/main/path/to/folder/file` — every folder has an index page (`/path/to/folder/`) listing its contents. ## Solution ### 1. Folder Index Pages **Create `apps/web/app/[section]/[...slug]/folder.tsx`** (or a parallel route). Actually — cleaner approach per Next.js App Router: the catch-all `[section]/[...slug]/page.tsx` handles both. Add logic: if the slug resolves to an actual markdown file → doc page (existing behavior). If the slug resolves to a **directory** (folder of docs) → render a folder index listing all docs whose `path` starts with that prefix. **Mechanism:** - Call `listDocuments()` to get all docs. - The incoming URL path is `{section}/{...slug}`. - Build the "folder prefix" = `${section}/${slug.join("/")}/` (with trailing `/`, or just `${section}/${slug.join("/")}` if no slug segments). - Filter docs whose `doc.path` starts with that prefix. - If exactly one doc matches AND its path === prefix (trimmed .md) → it's a doc page (existing). If zero or multiple match and they all start with the prefix → it's a folder index. - Edge: a folder with exactly one doc whose path matches exactly — still a doc page. A folder is when there are docs at `prefix/sub/...`. **Better heuristic:** A slug path is a "folder" if there exist docs whose `path` is `prefix/deep/...` (i.e., the slug is a parent of other doc paths, not a leaf itself). A slug is a "leaf doc" if `path === prefix + ".md"`. ### 2. Sidebar Tree **Update `Sidebar.tsx`:** - `listDocuments()` already returns all docs with their full `slug` and `path`. - Build a **tree** from the flat list: split each slug by `/`, create nested folder nodes. - Render nested `