Skip to content

Core: Storybook failed to load iframe.html when publishing#33896

Merged
valentinpalkovic merged 2 commits into
storybookjs:nextfrom
danielalanbates:fix/issue-33848
Mar 3, 2026
Merged

Core: Storybook failed to load iframe.html when publishing#33896
valentinpalkovic merged 2 commits into
storybookjs:nextfrom
danielalanbates:fix/issue-33848

Conversation

@danielalanbates
Copy link
Copy Markdown

@danielalanbates danielalanbates commented Feb 21, 2026

Fixes #33848

Summary

This PR fixes: [Bug]: Storybook failed to load iframe.html when publishing

Changes

code/core/src/manager-api/modules/url.ts    |  3 +-
 code/core/src/manager-api/tests/url.test.js | 45 +++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+), 1 deletion(-)

Testing

Please review the changes carefully. The fix was verified against the existing test suite.


This PR was created with the assistance of Claude Sonnet 4.6 by Anthropic | effort: low. Happy to make any adjustments!

Summary by CodeRabbit

  • Bug Fixes

    • Improved preview URL resolution for applications hosted in subdirectories, ensuring correct URL construction in various hosting configurations.
  • Tests

    • Added test coverage for subpath hosting scenarios, including cases with and without trailing slashes and index.html files.

…subpath

When Storybook is hosted at a subpath without a trailing slash (e.g.
`/design-system`), the previous regex `/\/[^/]*$/` would strip the
entire last path segment and replace it with `/`, losing the subpath
prefix and producing `/iframe.html` instead of `/design-system/iframe.html`.

Fix: only strip the last segment if it looks like an HTML file (ends in
`.html`), then ensure a trailing slash before appending `iframe.html`.
This correctly handles all cases:
- `/`                    → `/iframe.html`
- `/index.html`          → `/iframe.html`
- `/design-system`       → `/design-system/iframe.html`
- `/design-system/`      → `/design-system/iframe.html`
- `/design-system/index.html` → `/design-system/iframe.html`

Fixes storybookjs#33848
@dosubot
Copy link
Copy Markdown

dosubot Bot commented Feb 21, 2026

Related Documentation

Checked 0 published document(s) in 1 knowledge base(s). No updates required.

How did I do? Any feedback?  Join Discord

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 21, 2026

📝 Walkthrough

Walkthrough

Modified URL construction logic in manager-api to conditionally strip only HTML-suffixed path segments before appending iframe.html when no explicit PREVIEW_URL is configured. Added test coverage for subpath hosting scenarios.

Changes

Cohort / File(s) Summary
URL Base Path Handling
code/core/src/manager-api/modules/url.ts
Updated previewBase URL construction to selectively remove last path segment only if it ends with .html, then ensure trailing slash before appending iframe.html.
Test Coverage
code/core/src/manager-api/tests/url.test.js
Added three test cases validating getStoryHrefs behavior for subpath hosting: without trailing slash, with trailing slash, and with index.html in pathname.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • storybookjs/storybook#33686: Modifies URL base-path handling in the same url.ts file to improve last path segment stripping logic.
  • storybookjs/storybook#33647: Addresses similar previewBase/previewHref construction issues when handling index.html path segments in the same module.
✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
code/core/src/manager-api/modules/url.ts (1)

255-258: LGTM — fix is correct; consider an inline comment for the regex chain.

The two-step regex is correct for all cases:

  • replace(/\/[^/]*\.html$/, '') removes the trailing .html path segment (e.g., index.html) only when present.
  • replace(/\/?$/, '/') normalises the result to always end with exactly one slash before iframe.html is appended.

Optionally, a brief comment would help future readers understand the intent without having to trace through the regexes:

💬 Suggested comment
  const previewBase = refId
    ? refs[refId].url + '/iframe.html'
    : global.PREVIEW_URL ||
+       // Strip trailing .html segment (e.g. index.html), ensure trailing slash, then append iframe.html
        `${managerBase.replace(/\/[^/]*\.html$/, '').replace(/\/?$/, '/')}iframe.html`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/core/src/manager-api/modules/url.ts` around lines 255 - 258, Add a brief
inline comment next to the previewBase assignment explaining the two-step regex
on managerBase: note that replace(/\/[^/]*\.html$/, '') strips a trailing .html
segment (e.g., index.html) if present and replace(/\/?$/, '/') normalizes the
URL to end with exactly one slash before appending 'iframe.html'; place this
comment alongside the previewBase declaration (referencing previewBase,
managerBase, refId, refs) so future readers immediately understand the intent
without parsing the regexes.
code/core/src/manager-api/tests/url.test.js (1)

490-533: Three new tests correctly cover the bug scenarios — consider adding subpath + absolute-URL coverage.

The three added tests map cleanly to the three deployment configurations mentioned in the issue (no trailing slash, trailing slash, index.html) and their assertions are correct against the updated regex logic.

One gap: the existing 'supports returning absolute URLs using the base option' test (lines 421–438) only exercises pathname: '/'. The same base: 'origin' / base: 'network' path through the code now also runs the regex chain, so a subpath variant would guard against regressions when both options are combined.

✅ Suggested additional test
it('correctly links with base option when hosted at a subpath', () => {
  const { api, state } = initURL({
    store,
    provider: { channel: new EventEmitter() },
    state: { location: { pathname: '/design-system/', search: '' } },
    navigate: vi.fn(),
    fullAPI: { getCurrentStoryData: () => ({ id: 'test--story' }) },
  });
  store.setState(state);

  const origin = api.getStoryHrefs('test--story', { base: 'origin' });
  expect(origin.previewHref).toContain('http://localhost:6006/design-system/iframe.html');

  const network = api.getStoryHrefs('test--story', { base: 'network' });
  expect(network.previewHref).toContain('http://192.168.1.1:6006/design-system/iframe.html');
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@code/core/src/manager-api/tests/url.test.js` around lines 490 - 533, Add a
new test (or extend the existing "supports returning absolute URLs using the
base option" test) that exercises api.getStoryHrefs with base: 'origin' and
base: 'network' while the initURL state uses a subpath (e.g.
state.location.pathname = '/design-system/' or '/design-system') so the regex
logic for trimming/keeping subpaths runs for absolute URLs; use initURL and
api.getStoryHrefs('test--story', { base: 'origin' }) / ({ base: 'network' }) and
assert that previewHref contains the absolute origin/network host plus the
subpath + '/iframe.html' (e.g. contains
'http://localhost:6006/design-system/iframe.html') to guard against regressions
in getStoryHrefs.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@code/core/src/manager-api/modules/url.ts`:
- Around line 255-258: Add a brief inline comment next to the previewBase
assignment explaining the two-step regex on managerBase: note that
replace(/\/[^/]*\.html$/, '') strips a trailing .html segment (e.g., index.html)
if present and replace(/\/?$/, '/') normalizes the URL to end with exactly one
slash before appending 'iframe.html'; place this comment alongside the
previewBase declaration (referencing previewBase, managerBase, refId, refs) so
future readers immediately understand the intent without parsing the regexes.

In `@code/core/src/manager-api/tests/url.test.js`:
- Around line 490-533: Add a new test (or extend the existing "supports
returning absolute URLs using the base option" test) that exercises
api.getStoryHrefs with base: 'origin' and base: 'network' while the initURL
state uses a subpath (e.g. state.location.pathname = '/design-system/' or
'/design-system') so the regex logic for trimming/keeping subpaths runs for
absolute URLs; use initURL and api.getStoryHrefs('test--story', { base: 'origin'
}) / ({ base: 'network' }) and assert that previewHref contains the absolute
origin/network host plus the subpath + '/iframe.html' (e.g. contains
'http://localhost:6006/design-system/iframe.html') to guard against regressions
in getStoryHrefs.

@valentinpalkovic valentinpalkovic changed the title Fix #33848: [Bug]: Storybook failed to load iframe.html when publishing Core: Storybook failed to load iframe.html when publishing Feb 23, 2026
@valentinpalkovic valentinpalkovic moved this to Empathy Queue (prioritized) in Core Team Projects Feb 23, 2026
@storybook-app-bot
Copy link
Copy Markdown

storybook-app-bot Bot commented Feb 23, 2026

Package Benchmarks

Commit: 601bd11, ran on 25 February 2026 at 15:23:10 UTC

No significant changes detected, all good. 👏

@valentinpalkovic valentinpalkovic moved this from Empathy Queue (prioritized) to In Progress in Core Team Projects Feb 25, 2026
@valentinpalkovic valentinpalkovic self-assigned this Feb 25, 2026
@valentinpalkovic valentinpalkovic added the patch:yes Bugfix & documentation PR that need to be picked to main branch label Mar 3, 2026
@valentinpalkovic valentinpalkovic merged commit 344ac52 into storybookjs:next Mar 3, 2026
116 of 119 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in Core Team Projects Mar 3, 2026
yannbf pushed a commit that referenced this pull request Mar 4, 2026
Core: Storybook failed to load iframe.html when publishing
(cherry picked from commit 344ac52)
@github-actions github-actions Bot added the patch:done Patch/release PRs already cherry-picked to main/release branch label Mar 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug ci:normal core patch:done Patch/release PRs already cherry-picked to main/release branch patch:yes Bugfix & documentation PR that need to be picked to main branch

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Bug]: Storybook failed to load iframe.html when publishing

2 participants