Skip to content

docs(nav): stop listing "index" in meta.json pages — it detaches the folder index from the tree - #13710

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-12352-meta-index-breadcrumb
Aug 31, 2026
Merged

docs(nav): stop listing "index" in meta.json pages — it detaches the folder index from the tree#13710
os-project-manager merged 1 commit into
mainfrom
claude/issue-12352-meta-index-breadcrumb

Conversation

@os-project-manager

@os-project-manager os-project-manager commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

Part of #12352

Removes "index" from the pages array of 16 of the 17 meta.json files under
content/docs that list it. Producer-side only: no consumer-side URL
reconstruction, in page.tsx or anywhere else.

Mechanism (fumadocs-core 16.14.4, buildFolder() in dist/loader-*.js)

A folder's index.mdx becomes that folder's tree index node only while the
folder's meta.json does not list "index" in pages. Listing it makes the
page an ordinary child and then deletes the folder's index:

if (indexPath) {
  if (excludedPaths.has(indexPath)) delete node.index;   // "index" was listed
  else excludedPaths.add(indexPath);
}

Two surfaces read that one node:

surface consumer with "index" listed
breadcrumb getBreadcrumbItems() links a folder crumb to item.index?.url ancestor has a name and no URL, so docsTrail() drops it
sidebar node.index ? SidebarFolderLink : SidebarFolderTrigger section header is inert text; the overview page sits below it as a child

Re-derived on current origin/main (not inherited from the card)

Measured by driving the real pinned fumadocs-core loader over content/docs
and applying both consumers to the resulting tree.

  • 17 of 35 meta.json files list "index" — unchanged from the card.
  • 172 short trails, and the per-top-folder breakdown matches the card's
    production-build numbers row for row (ai 8 · api 11 · automation 9 ·
    capabilities 10 · concepts 5 · data-modeling 17 · deployment 11 ·
    getting-started 8 · kernel 22 · permissions 20 · plugins 4 · protocol 24 ·
    releases 8 · ui 15).
  • Page count reads 404 where the card read 403 sitemap URLs; the extra one is
    /docs itself, whose trail was already complete. 404 = 232 + 172 against the
    card's 403 = 231 + 172, so the two harnesses agree exactly.

After: short trails 172 to 8. The remaining 8 are every page under
/docs/releases.

Per-file decisions — checked individually, not blanket-edited

"index" was the first pages entry in 15 files and the first entry after
the ---Start Here--- separator in getting-started. No file placed it between
other entries, so no entry's position depends on it. Each edit asserted, per
file, that pages had exactly one "index", that the resulting array equals the
original minus that one element, and that no other key changed.

content/docs/releases/meta.json is not touched: content/docs/releases/ is
fenced by AGENTS.md and by this card's dispatch. It still lists "index", which
is why this is Part of and not a closing reference — #12352 stays open for that
one file, and whether it should be swept in a dedicated docs-only PR is the
maintainer's call.

Sidebar — verified rendered, before and after

The ruling requires the sidebar, not only the JSON-LD. Captured from a running
dev server, with content/docs reverted to this branch's parent commit for the
"before" pass and restored from HEAD afterwards (git diff HEAD empty, blob
hashes back to the HEAD blobs).

/docs/getting-started/glossary, sidebar entries in document order:

-FOLDER-TRIGGER | Get Started | None
+FOLDER-LINK    | Get Started | /docs/getting-started
 separator      | Start Here  | None
-link           | What is ObjectStack? | /docs/getting-started
 link           | How AI Development Works | /docs/getting-started/how-ai-development-works

/docs/data-modeling/objects:

-FOLDER-TRIGGER | Data Modeling | None
-link           | Data Modeling | /docs/data-modeling
+FOLDER-LINK    | Data Modeling | /docs/data-modeling
 link           | Schema Design | /docs/data-modeling/schema-design

FOLDER-LINK | Reference | /docs/references renders identically in both passes —
a folder that never listed "index", i.e. the control.

Over the whole tree the delta is exactly 16 headers TRIGGER to LINK plus 16
index children leaving the child list, and nothing else
: every removed child's
URL is now its folder header's href (set equality, checked mechanically), and
no other line moved in either direction. SidebarFolderLink still renders the
collapse chevron, so no section loses collapsibility.

Six of the 16 removed a child whose label was identical to the section header
(Automation, What Can It Do?, Core Concepts, Data Modeling,
Kernel & Services, Permissions & Identity) — a duplicate row, now gone. The
other ten swap the page title for the folder title on the same link:

link sidebar label before after
/docs/getting-started What is ObjectStack? Get Started
/docs/ui UI Engine Views & Apps
/docs/plugins Plugin System Plugins & Packages
/docs/protocol/kernel Kernel: The System Protocol System Protocol
/docs/protocol Protocol Specification Protocol Spec
/docs/deployment Deployment Overview Deployment & Operations
/docs/kernel/runtime-services Runtime Service APIs Runtime Services
/docs/kernel/contracts Service Contracts Overview Service Contracts
/docs/ai AI Overview AI
/docs/api API Overview API & SDK

No folder is judged worse: the page stays in the sidebar at the same tree
position, one click away, and this is already how the 18 folders that never
listed "index" render (references, protocol/objectql, protocol/objectui,
…). /docs/getting-started is the widest label gap and is flagged for review
rather than decided here.

Breadcrumb — rendered BreadcrumbList, after

/docs/data-modeling/objects           ObjectStack > Documentation > Data Modeling(/docs/data-modeling) > Object Metadata
/docs/getting-started/glossary        ObjectStack > Documentation > Get Started(/docs/getting-started) > Glossary
/docs/protocol/objectql/query-syntax  ObjectStack > Documentation > Protocol Spec(/docs/protocol) > Data Protocol(/docs/protocol/objectql) > Query Syntax
/docs/releases/v17                    ObjectStack > Documentation > v17.0.0                              (still short — fenced folder)

The first is the card's own example, which shipped three crumbs with the section
missing. The third is the card's control: it was already linking
/docs/protocol/objectql and now also links /docs/protocol, because
content/docs/protocol/meta.json listed "index" too.

One comment-only edit outside content/

apps/docs/app/[lang]/docs/[[...slug]]/page.tsx carries a doc comment that
states this defect as live and quantifies it ("17 of the 35 …", "172 of 403 …").
Landing this would make that text false, so the paragraph is rewritten to the
post-fix state and to name the one folder still affected. No executable line
changes
— every changed line in that file starts with *, checked
mechanically. The ⛔ fence against reconstructing the URL consumer-side is kept
verbatim and is untouched.

Verification

At 1a5ba4fa4, the branch head:

  • The 43 gate families node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
    derives for this change set: 42 green, 1 NOT MEASURED. The exception is
    scripts/check-test-completeness.mjs, which grades a saved turbo run test
    log and exits 3 with PREREQUISITE NOT MET when the family names it with no
    argument — its own header says to record it as NOT MEASURED locally. Three
    gates first returned PREREQUISITE NOT MET for unbuilt workspace packages
    (@objectstack/formula, @objectstack/lint, packages/spec/json-schema) and
    one for a missing @objectstack/client-react build; all four were rebuilt and
    re-run green, and none of those first readings is reported as a result.
  • pnpm lint (eslint . --no-inline-config, whole repo, no narrowing) — clean.
  • pnpm --filter @objectstack/docs run typecheck
    (fumadocs-mdx && next typegen && tsc --noEmit) — clean.
  • node scripts/check-section-landing-index.mjs green, and by construction: that
    gate already filters 'index' out of the pages array it reads, so the
    landing-page index blocks are unaffected.

Every exit code was captured before any pipe.

Not in scope

The inbound-links work from the sibling card of the same sweep is untouched here.


Generated by Claude Code


Generated by Claude Code

…folder index (#12352)

Fumadocs attaches a folder's index.mdx as that folder's tree `index` node only
when the folder's meta.json does NOT list "index" in `pages`. Listing it makes
the page an ordinary child and leaves the folder node with a name and no url,
which degrades both surfaces built from that node: `getBreadcrumbItems()` drops
the un-linkable ancestor, and the sidebar renders an inert `SidebarFolderTrigger`
instead of a `SidebarFolderLink`.

Removes "index" from 16 of the 17 meta.json files that listed it.
content/docs/releases/ is fenced by AGENTS.md and is left untouched.

Measured on the real fumadocs-core 16.14.4 loader over content/docs:
short breadcrumb trails 172 -> 8 (the 8 are all under /docs/releases), and the
sidebar delta is exactly 16 folder headers TRIGGER -> LINK plus 16 index
children leaving the child list, with no other entry moved.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation tooling labels Aug 31, 2026
@os-project-manager
os-project-manager marked this pull request as ready for review August 31, 2026 08:33
@os-project-manager
os-project-manager added this pull request to the merge queue Aug 31, 2026
Merged via the queue into main with commit 787d757 Aug 31, 2026
37 of 38 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-12352-meta-index-breadcrumb branch August 31, 2026 08:51
os-project-manager added a commit that referenced this pull request Aug 31, 2026
…13711)

Fumadocs attaches a folder's index.mdx as that folder's tree `index` node only
when the folder's meta.json does NOT list "index" in `pages`. Listing it makes
the landing page an ordinary child and leaves the folder node with a name and
no url. In fumadocs-core 16.14.4 `buildFolder()`:

    if (indexPath) {
      if (excludedPaths.has(indexPath)) delete node.index;   // "index" was listed
      else excludedPaths.add(indexPath);
    }

`getBreadcrumbItems()` still emits that ancestor, but with `url: undefined`, and
`docsTrail()` in apps/docs drops any crumb without a url (Google requires `item`
on every BreadcrumbList entry but the last). The sidebar reads the same node as
`node.index ? SidebarFolderLink : SidebarFolderTrigger`.

Measured on the real loader over content/docs (405 pages), removing this one
line and changing nothing else:

  - short breadcrumb trails 8 -> 0; the 8 fixed are exactly the non-landing
    pages under /docs/releases (v9, v12..v17, implementation-status)
  - the Releases folder header goes TRIGGER -> LINK, indexUrl /docs/releases
  - /docs/releases stays in getPages() and source.getPage(['releases']) still
    resolves -- the landing page is not unlisted, it becomes the section link
  - 405 pages before and after; exactly one sidebar folder header flips and
    only the 9 /docs/releases trails change

This was the 17th and last meta.json still listing it; the other 16 were fixed
in #13710, which left this one alone because content/docs/releases/ is fenced
by AGENTS.md. This is the dedicated docs-only PR that fence names as the route.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pk26oZ12t5N1hwGW1m1MgC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants