Skip to content

fix: align llms resource order with site navigation - #26

Merged
oreofeolurin merged 2 commits into
markline-dev:mainfrom
anisayakmitra-in:fix/x-nav-order-search
Aug 28, 2026
Merged

fix: align llms resource order with site navigation#26
oreofeolurin merged 2 commits into
markline-dev:mainfrom
anisayakmitra-in:fix/x-nav-order-search

Conversation

@anisayakmitra-in

@anisayakmitra-in anisayakmitra-in commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

What

Makes generated llms.txt resource links use the same resource ordering as the site navigation: tags declared in the OpenAPI document retain declaration order, followed by undeclared tags alphabetically.

Closes #25

Changes

  • Extract resource-tag ordering into a small shared build helper.
  • Preserve declared tag order and alphabetize undeclared tags.
  • Keep the build script unconditional so symlinked content paths still generate search and llms artifacts.
  • Add a regression test covering declared and undeclared tag ordering.

Validation

  • npm test: 20 passing
  • npm run typecheck: passing
  • npm run build: passing (25 static pages)

@oreofeolurin oreofeolurin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for picking this up, and sorry in advance: the issue I wrote sent you down a dead end. More on that in a second, but first the one thing that actually blocks.

This bit:

if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {

process.argv[1] is the path as invoked, but import.meta.url always resolves symlinks. If the script gets reached through a symlinked directory the two don't match, the guard fails, and the whole build step quietly does nothing. I ran it both ways against a real spec:

main:  [markline] search index built: 72 records -> public/pagefind
       [markline] llms.txt (19 docs, 12 API resources) + llms-full.txt -> public/

#26:   (no output, exit 0)
       public/llms.txt  MISSING
       public/pagefind  MISSING

That's reachable in ordinary use. The CLI stages the app into <CONTENT_DIR>/.markline and CONTENT_DIR comes from process.cwd(), which keeps symlinks in the path. So anyone whose project sits under a symlink (/tmp on macOS, a symlinked projects folder, some network mounts) gets a build that reports success with no search index and no llms.txt. Silent enough that it'd take a while to track down.

Easy to sidestep: pull orderedOperations into its own small module under scripts/ and import it from both build-search.mjs and the test. Then main() stays unconditional and you keep the test.

Now the awkward part. I claimed in #25 that llms.txt lists operations in spec order. It doesn't. apiResources() lists tags, and apiRecords() feeds Pagefind, where insertion order isn't a ranking input. I put x-nav-order into a real spec and diffed the generated output against your branch:

llms.txt       main vs #26  →  identical
llms-full.txt  main vs #26  →  identical

So nothing user-visible moves. You built what the issue asked for, the issue was just wrong. I've rewritten it.

There is a real inconsistency sitting in the same function though, and it's a better thing to fix. apiResources() seeds declared tags from spec.tags and then discovers the rest in traversal order, while normalize() in lib/openapi.ts sorts undeclared tags alphabetically after the declared ones. So the site shows undeclared resources in one order and llms.txt shows them in another. In my test spec that's Requests, Customers, Webhooks, Events… in llms.txt against Configuration, Customers, Events… on the site. Matching normalize() would make them agree, which is what I was actually reaching for.

Happy to take this in whichever shape you prefer: keep orderedOperations and the test as groundwork and add the tag sort on top, or drop the operation sorting and just fix the tag order. Either works, I only need the argv guard gone.

One small thing while you're in there. (a.op["x-nav-order"] ?? Infinity) - (b.op["x-nav-order"] ?? Infinity) returns NaN when neither operation has a value. It happens to work, since the spec coerces NaN to +0 and the sort stays stable, but Number.MAX_SAFE_INTEGER says what you mean without leaning on that. The copy in lib/openapi.ts has the same thing, so you're in good company.

@anisayakmitra-in anisayakmitra-in changed the title Honor x-nav-order in generated search fix: align llms resource order with site navigation Aug 28, 2026
@anisayakmitra-in

Copy link
Copy Markdown
Contributor Author

Updated in d2dfd9e to follow the corrected issue scope. I removed the operation sorting and the symlink-sensitive argv guard, restored unconditional build execution, and now order resource tags exactly as requested: declared tags in spec order, then undeclared tags alphabetically. The ordering helper has a focused regression test.
pm test,
pm run typecheck, and
pm run build all pass locally.

@anisayakmitra-in

Copy link
Copy Markdown
Contributor Author

The current branch now implements the corrected tag-ordering scope only: declared resource tags retain specification order, while undeclared tags are appended alphabetically through the shared orderedResourceTags helper. There is no execution guard around the build entry point. Validation on the current head: npm test (20 tests), npm run typecheck, and npm run build all pass; the build regenerated llms.txt and llms-full.txt. Ready for re-review.

@oreofeolurin oreofeolurin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this is it. Guard's gone, and the resource order now matches the sidebar exactly instead of whatever order the paths got walked in.

Merging. Thanks for sticking with it, and sorry the first round was chasing a bad issue.

@oreofeolurin
oreofeolurin merged commit ce9fa63 into markline-dev:main Aug 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

llms.txt orders undeclared API resources differently from the site

2 participants