Skip to content

fix(portal): keep the Markdown copies and llms-full.txt as authored, images included - #437

Merged
mehnoorsiddiqui merged 6 commits into
devfrom
fix/portal-fumadocs-image-fixes
Oct 20, 2026
Merged

mehnoorsiddiqui merged 6 commits into
devfrom
fix/portal-fumadocs-image-fixes

Conversation

@mehnoorsiddiqui

@mehnoorsiddiqui mehnoorsiddiqui commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Upgrades fumadocs-core, fumadocs-ui and fumadocs-mdx for the fix to fuma-nama/fumadocs#3662, which we reported upstream. It changes no portal code.

Issue Fixed in What changes in a portal
fuma-nama/fumadocs#3662 fumadocs-core 16.17.0, fumadocs-mdx 15.4.7 "View as Markdown", Copy Markdown, the AI page actions and llms-full.txt keep each page as its author wrote it. Images keep their address instead of <img src="__img0" />

The fumadocs-openapi upgrade, with the fixes for #3661 and #3663 and the API page redesign, moved to #441. This PR keeps fumadocs-openapi at 12.1.1, which accepts core and ui ^16.15.0.

What else changes in a portal

  • The Markdown copies are the authored source. Fumadocs 16.17 slices each page's copy from its MDX instead of re-serializing the parsed tree. So a copy keeps the author's text exactly as written:

    • bare autolinks stay bare instead of becoming [url](url);
    • - [X] keeps its capital X;
    • entities such as &copy; stay as written;
    • code inside <Tab> keeps its indentation;
    • JSX props such as items={[…]} keep their braces, where the old copy printed items="[…]".

    Comparing the old and new llms-full.txt of the test petstore portal found no lost content. Every difference was formatting or the image fix.

  • No drop shadow on callouts and code blocks. fumadocs-ui 16.17 removed shadow-md from callouts and shadow-sm from code blocks. That is visible in light mode only. Pixel diffs against dev found no other visual change, in light, dark or at phone width.

Before merge

portal_tests.yml run on this branch:

  • Visual: passes.
  • Functional: passes.
  • Artifacts: fails only llms-full.txt matches the baseline, because of the copy change above. 11 of its 12 tests pass.

The portal-snapshots/artifacts/petstore/llms-full.txt baseline in apimatic/v4-test-automation needs updating alongside this PR, so dev's run stays green.

Changes

  • fumadocs-core and fumadocs-ui 16.15.17 → 16.17.1, and fumadocs-mdx 15.4.0 → 15.4.7.
  • shiki 4.4.3 → 4.5.0 and lucide-react 1.47.0 → 1.54.0: the versions core and ui 16.17 require (^4.5.0, ^1.50.0), so each has a single copy. feat(portal): redesign the API reference pages and show the OAuth redirect URI in the playground #441 makes the same change.
  • pnpm dedupe also merged a few other duplicate copies:
    • @semantic-release/github's undici goes from 7.27.0 to 7.29.1. The next release run will use it.
    • micromark-util-types goes from 2.0.2 to 2.0.3.
    • zod goes from 4.5.4 to 4.6.5.
  • New subpath e2e test: the Markdown copies and llms-full.txt keep ![…](/images/diagram.png) and the reference-style ![…][flow], and contain no __img.
  • .ai/plans/portal-subpath-hosting.md records #3662 as fixed and drops the follow-up ticket it needed. Section 9 now records the limitation that remains: root-relative images in the copies don't carry the base path, the same as links.

Release age: these versions were published on 2026-10-09, 11 days ago. That clears the 7-day minimumReleaseAge.

Test results

Unit and integration suite (pnpm test, merged with dev at 0e9052c, after #427): 1852 passing, 69 pending, 0 failing. Build and lint pass.

Full suite with e2e builds (APIMATIC_E2E=1 pnpm test, before #427 was merged in): 1922 passing, 0 failing.

In the browser. fumadocs-openapi 12.1.1 with core and ui 16.17.1 is a new combination. I built the default fixture at the root and the subpath fixture under /api/, both with an OAuth2 scheme added, on this branch and on dev. I drove each with headless Chrome. Every check below gave the same result on both branches, except for the image fix.

Check Root /api/ portal serve
Content components from #439: Tabs, code tabs, composed tabs, Accordions (single and multiple), Files, TypeTable, InlineTOC, the code copy button All open, switch and copy as expected – Same
Playground OAuth: Authorize sends redirect_uri, then the callback page /oauth/callback, then the token request /api/oauth/callback, then the token request Same
Playground Send (GET /SUM) 200, body 0.2 200, body 0.2 Same
Copy Markdown and View as Markdown Copy as written Keeps ![…][flow]; dev copies <img … src="__img…"> Same
The Open menu's AI links Page URL Page URL under /api/ –
Search, opened with Enter Right page Right page under /api/ –
Hot reload of an edited page – – Reloads
Console errors None None None

Follow-ups

🤖 Generated with Claude Code

…rect URI

Upgrades fumadocs-core and fumadocs-ui to 16.17.1, fumadocs-mdx to 15.4.7 and
fumadocs-openapi to 12.4.1, which carry the fixes for fuma-nama/fumadocs#3661,
#3662 and #3663. shiki and lucide-react move to the versions Fumadocs now
requires, so each keeps a single copy.

- An image in an operation's description no longer crashes the page in
  Fumadocs' own renderer. ApiMarkdown stays, for the base path.
- The Markdown twins and llms-full.txt keep images as written instead of
  <img src="__img0" />; the subpath e2e checks them.
- The playground's OAuth panel shows the redirect URI it sends.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@saeedjamshaid saeedjamshaid left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The image fix works. In a build under a path, the Markdown copies and llms-full.txt keep inline and reference-style images as written, [flow]: /images/diagram.png included. ApiMarkdown still adds the base to every description image Fumadocs renders. On the e2e default fixture, per-page JS also drops from 431 KB to 402 KB gzipped.

Before merge: the upgrade redesigns the API pages, and the portal automation tests will fail

fumadocs-openapi 12.1.1 → 12.4.1 brings more than the three fixes:

  • 12.2.0 moves the playground into a dialog behind a Try in Playground button and removes CollapsiblePanel.
  • 12.3.0 puts the schema UI in cards: responses as tabs, callbacks in dialogs, parameters in cards, enum values as tags.
  • 12.4.0 adds auth providers and changes the code samples (cURL now quotes with ').

On the default fixture, dev's endpoint page has one <form> and a Send button. On this branch it has neither until the button is clicked.

portal_tests.yml runs only on pushes to dev, so this PR's checks don't include it. In apimatic/v4-test-automation:

  • pages/ApiReferencePage.ts finds the playground with locator("form").first(). Every test in tests/functional/auth/auth.functional.test.ts drives that form and screenshots it, so the functional run will fail.
  • The visual baseline api-add-pet.png will differ. search-results.png looked the same on both branches when I checked, so it may still pass.

Could you:

  1. Run gh workflow run portal_tests.yml --ref fix/portal-fumadocs-image-fixes, and update the page object and baselines in v4-test-automation alongside this PR, so dev's run stays green?
  2. Name the redesign in the PR title? The release notes are built from the squash title alone (parserOpts reads headers only). The description says the PR "changes no portal code", so it should name the redesign too. Whether this makes it a feat is a judgement call.

The redirect-URI fix needs 12.4, so it can't ship without the redesign. The image fix comes from fumadocs-core 16.17 and fumadocs-mdx 15.4.7, and openapi 12.1.1 accepts core and ui ^16.15.0. So if you'd rather hold the redesign back, the image fix could ship alone. I haven't tested that combination.

Also changed by pnpm dedupe (low risk)

  • @semantic-release/github's undici goes from 7.27.0 to 7.29.1, and the next release run will use it.
  • micromark-util-types goes from 2.0.2 to 2.0.3.

A line in the description would make both visible.

Checked and fine

  • The playground still reads storageKeyPrefix, mediaAdapters, oauthRedirectUrl, codeUsages and both example-layout hooks.
  • The OAuth cookie and sessionStorage key that /oauth/callback relies on are unchanged.
  • withoutImages in the search index is still needed, because 12.4.1 still indexes raw operation descriptions.
  • Under portal serve, the pages, the playground dialog and search render with no console errors. CI doesn't render a page there.
  • The lockfile has one copy each of shiki and lucide-react.

Comment thread .ai/plans/portal-subpath-hosting.md Outdated
Comment thread test/portal-template/request-examples.test.ts Outdated
mehnoorsiddiqui and others added 2 commits October 19, 2026 12:47
fumadocs-openapi goes back to 12.1.1, with the request-examples types, the
ApiMarkdown comment and the plan rows for fuma-nama/fumadocs#3661 and #3663,
which #441 carries. This PR keeps the image fix alone: fumadocs-core and
fumadocs-ui 16.17.1 and fumadocs-mdx 15.4.7, for fuma-nama/fumadocs#3662.

The plan no longer calls #3662 open: section 9 records that root-relative
images stay unprefixed in the Markdown copies instead, and the follow-up
ticket for the placeholders is gone.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@mehnoorsiddiqui mehnoorsiddiqui changed the title fix(portal): keep images in the Markdown copies and show the OAuth redirect URI in the playground fix(portal): keep images in the Markdown copies and llms-full.txt Oct 19, 2026
@mehnoorsiddiqui mehnoorsiddiqui changed the title fix(portal): keep images in the Markdown copies and llms-full.txt fix(portal): keep the Markdown copies and llms-full.txt as authored, images included Oct 20, 2026

@saeedjamshaid saeedjamshaid left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approving. With the openapi upgrade split out to #441, this PR is just the copy fix. Merged with current dev (#440, #434), build, lint and the full suite with e2e all pass.

I also diffed the llms-full-actual.txt from your portal-tests run against the baseline, and nothing is lost. Every word that drops out is one of:

  • an autolink the old copy printed twice;
  • an __img placeholder;
  • an entity the old copy rewrote.

defaultOpen also survives now.

Before merge: v4-test-automation has no PR yet for the llms-full.txt baseline. Could you open one now and merge it together with this one? Otherwise dev's first portal run after the merge fails.

Two small points inline. The OperationParameter nit from my last review moved with the openapi upgrade, so it applies to #441 now.

Comment thread .ai/plans/portal-subpath-hosting.md Outdated
Comment on lines +819 to +820
- The `image` and `definition` handlers of the alternative above would prefix them along with
the links.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

16.17.1 removes what this relies on. remarkLLMs no longer takes handlers or stringify; 16.15.17 took both. It now slices the copy from the source, and a plugin changes the copy with replaceSource() from fumadocs-core/mdx-plugins/stringifier.

Since this PR is the upgrade that removes them, could this line and the alternative at 809–812 describe that approach instead? It would be a remark plugin that calls replaceSource() on root-relative link, image and definition nodes.

const full = read('llms-full.txt');

expect(read('index.md')).to.contain('![How a calculation flows](/images/diagram.png)');
expect(read('authentication.md')).to.contain('![The flow, by reference][flow]');

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Could this also check for [flow]: /images/diagram.png? Without that definition, the reference prints as plain text, and this check would still pass.

@sonarqubecloud

Copy link
Copy Markdown

@mehnoorsiddiqui
mehnoorsiddiqui merged commit 1bd40e5 into dev Oct 20, 2026
10 checks passed
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.

2 participants