Skip to content

Add Chromatic CI + fix Storybook production build#2168

Merged
rolfheij-sil merged 6 commits intoai/mainfrom
ai/workflow/chromatic-ci-rolf-04-01-2026
Apr 15, 2026
Merged

Add Chromatic CI + fix Storybook production build#2168
rolfheij-sil merged 6 commits intoai/mainfrom
ai/workflow/chromatic-ci-rolf-04-01-2026

Conversation

@rolfheij-sil
Copy link
Copy Markdown
Contributor

@rolfheij-sil rolfheij-sil commented Apr 1, 2026

Summary

  • Chromatic CI workflow: Adds .github/workflows/chromatic.yml that publishes Storybook to Chromatic for UX team review, gated by a storybook-review PR label
  • Storybook build fix: Filters out conflicting webpack plugins (HtmlWebpackPlugin, BundleAnalyzerPlugin) from the merged Electron renderer config, fixing storybook build failure with Storybook 9

Details

Chromatic workflow

  • Triggers on PRs to ai/main when storybook-review label is present (labeled + synchronize events)
  • Only snapshots extension stories (extensions/src/**/*.stories.tsx) via onlyStoryFiles — tested locally: 4 snapshots out of 355 stories
  • Uses TurboSnap (onlyChanged) for further savings on subsequent builds
  • exitZeroOnChanges: true so visual changes don't fail CI
  • Requires CHROMATIC_PROJECT_TOKEN repo secret (already configured)

Storybook build fix

  • Root cause: Storybook 9's WebpackInjectMockerRuntimePlugin hooks into every HtmlWebpackPlugin instance. The merged Electron renderer config brought in a second HtmlWebpackPlugin, causing mocker-runtime-injected.js to be emitted twice.
  • Fix: Selectively filter out HtmlWebpackPlugin and BundleAnalyzerPlugin from the renderer config. Also strip optimization and cache which Storybook manages itself.
  • This also fixes the publish-docs.yml workflow's Storybook build.

Test plan

  • npx storybook build succeeds (was failing before)
  • npx chromatic --only-story-files="extensions/src/**/*.stories.tsx" publishes successfully with 4 snapshots
  • Verify npm run storybook (dev mode) still works
  • Add storybook-review label to a test PR to confirm the GitHub Action triggers

🤖 Generated with Claude Code


This change is Reviewable

devin-ai-integration[bot]

This comment was marked as resolved.

@rolfheij-sil rolfheij-sil changed the title ci: add Chromatic workflow for Storybook visual review Add Chromatic CI + fix Storybook production build Apr 1, 2026
devin-ai-integration[bot]

This comment was marked as resolved.

@rolfheij-sil
Copy link
Copy Markdown
Contributor Author

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

rolfheij-sil and others added 5 commits April 10, 2026 12:46
Publishes Storybook to Chromatic when the `storybook-review` label is
present on a PR targeting ai/main. Uses TurboSnap (onlyChanged) and
limits snapshots to extension stories only. Visual changes don't fail
the CI check (exitZeroOnChanges).

Setup steps mirror the existing publish-docs.yml workflow.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Filter out HtmlWebpackPlugin and BundleAnalyzerPlugin from the merged
Electron renderer webpack config. Storybook 9's WebpackInjectMockerRuntimePlugin
hooks into every HtmlWebpackPlugin instance, causing mocker-runtime-injected.js
to be emitted twice when the renderer's HtmlWebpackPlugin is merged in.

Also strip optimization and cache configs that Storybook manages itself.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
github.ref returns a ref string (refs/heads/branch-name), not a commit
SHA. Use github.sha for correct baseline detection if the trigger were
ever expanded beyond pull_request events.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Read glob pattern from .chromatic-story-filter if present, falling
back to all extension stories. This lets the porting workflow target
only the feature's stories, saving Chromatic snapshot quota.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Pin chromaui/action@latest to @v16 for supply-chain safety,
  consistent with all other pinned actions in the repo
- Remove resolved TODO "Make this work in production mode" since
  this PR fixes exactly that
- Remove misleading "will not affect anything" comment on the
  production config branch
- Replace vague "Remove configs that break stuff" with an accurate
  explanation of what is stripped and why

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@rolfheij-sil rolfheij-sil force-pushed the ai/workflow/chromatic-ci-rolf-04-01-2026 branch from 677cd9e to 9b979bd Compare April 10, 2026 10:47
…ings

Add explanation comments above eslint-disable directives in .storybook/main.ts
and e2e-tests/fixtures/papi-live.fixture.ts. Remove unused `err` catch binding.
Extract hardcoded webpack plugin names to array constant. These pre-date the
require-disable-comment rule but surfaced after rebase onto ai/main.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Copy Markdown
Member

@lyonsil lyonsil left a comment

Choose a reason for hiding this comment

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

:lgtm:

I wish there was a GitHub setting for "always squash all commits from AI before merging" 😄

@lyonsil partially reviewed 3 files and made 1 comment.
Reviewable status: 2 of 3 files reviewed, all discussions resolved.

@rolfheij-sil rolfheij-sil merged commit 65698cb into ai/main Apr 15, 2026
7 of 8 checks passed
@rolfheij-sil rolfheij-sil deleted the ai/workflow/chromatic-ci-rolf-04-01-2026 branch April 15, 2026 14:52
rolfheij-sil added a commit that referenced this pull request Apr 16, 2026
Captures the agreed-upon design for a one-PR change that fixes the core
Storybook production build (by applying the plugin-filter fix from PR #2168),
decouples PBR stories from the core Storybook, and publishes the result to
GitHub Pages alongside the existing platform-bible-react Storybook.
katherinejensen00 pushed a commit that referenced this pull request Apr 18, 2026
* ci: add Chromatic workflow for Storybook visual review

Publishes Storybook to Chromatic when the `storybook-review` label is
present on a PR targeting ai/main. Uses TurboSnap (onlyChanged) and
limits snapshots to extension stories only. Visual changes don't fail
the CI check (exitZeroOnChanges).

Setup steps mirror the existing publish-docs.yml workflow.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix Storybook production build failure with Storybook 9

Filter out HtmlWebpackPlugin and BundleAnalyzerPlugin from the merged
Electron renderer webpack config. Storybook 9's WebpackInjectMockerRuntimePlugin
hooks into every HtmlWebpackPlugin instance, causing mocker-runtime-injected.js
to be emitted twice when the renderer's HtmlWebpackPlugin is merged in.

Also strip optimization and cache configs that Storybook manages itself.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: use github.sha instead of github.ref for CHROMATIC_SHA fallback

github.ref returns a ref string (refs/heads/branch-name), not a commit
SHA. Use github.sha for correct baseline detection if the trigger were
ever expanded beyond pull_request events.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Use feature-specific story filter for Chromatic snapshots

Read glob pattern from .chromatic-story-filter if present, falling
back to all extension stories. This lets the porting workflow target
only the feature's stories, saving Chromatic snapshot quota.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Pin chromaui/action to v16 and clean up stale Storybook comments

- Pin chromaui/action@latest to @v16 for supply-chain safety,
  consistent with all other pinned actions in the repo
- Remove resolved TODO "Make this work in production mode" since
  this PR fixes exactly that
- Remove misleading "will not affect anything" comment on the
  production config branch
- Replace vague "Remove configs that break stuff" with an accurate
  explanation of what is stripped and why

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix ESLint errors: require-disable-comment, unused var, hardcoded strings

Add explanation comments above eslint-disable directives in .storybook/main.ts
and e2e-tests/fixtures/papi-live.fixture.ts. Remove unused `err` catch binding.
Extract hardcoded webpack plugin names to array constant. These pre-date the
require-disable-comment rule but surfaced after rebase onto ai/main.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
rolfheij-sil added a commit that referenced this pull request Apr 20, 2026
* docs: add design spec for publishing paranext-core Storybook

Captures the agreed-upon design for a one-PR change that fixes the core
Storybook production build (by applying the plugin-filter fix from PR #2168),
decouples PBR stories from the core Storybook, and publishes the result to
GitHub Pages alongside the existing platform-bible-react Storybook.

* docs: add implementation plan for publishing paranext-core Storybook

Five tasks covering the storybook production build fix, PBR decoupling,
the CI step in publish-docs.yml, the landing-page card, and the PR.
Each task is broken into bite-sized steps with exact code, commands,
and expected outputs, ready for subagent-driven or inline execution.

* fix(storybook): filter conflicting plugins from merged renderer config

Storybook 9's WebpackInjectMockerRuntimePlugin hooks into every
HtmlWebpackPlugin instance. The merged Electron renderer config brought
in a second HtmlWebpackPlugin, causing mocker-runtime-injected.js to be
emitted twice and the production build to fail.

Filter out HtmlWebpackPlugin and BundleAnalyzerPlugin from the renderer
config, and strip optimization + cache which Storybook manages itself.

Applies the .storybook/main.ts hunk from paranext-core#2168 (merged to
ai/main) onto main so publish-docs can build the core Storybook.

* refactor(storybook): decouple platform-bible-react stories from core Storybook

Remove the platform-bible-react stories glob and the platform-bible-react
staticDirs entry. PBR has its own Storybook that is published to
/platform-bible-react-storybook/; core Storybook should only host core
and extension stories so the two publications don't duplicate content.

Keep both webpack aliases ('platform-bible-react' -> PBR source,
'@' -> lib/platform-bible-react/src) so core and extension stories that
import PBR by bare specifier continue to resolve to source during dev.

* ci(publish-docs): build and deploy paranext-core Storybook

Adds a build step that outputs the core Storybook to
docs-for-pages/paranext-core-storybook/, deployed alongside the
existing platform-bible-react Storybook to GitHub Pages.

* docs: add paranext-core Storybook card to GitHub Pages landing

Fourth resource card linking to /paranext-core-storybook/ — the
Storybook produced by the new publish-docs build step. Matches the
styling of the existing platform-bible-react Design System link.
katherinejensen00 pushed a commit that referenced this pull request Apr 20, 2026
* ci: add Chromatic workflow for Storybook visual review

Publishes Storybook to Chromatic when the `storybook-review` label is
present on a PR targeting ai/main. Uses TurboSnap (onlyChanged) and
limits snapshots to extension stories only. Visual changes don't fail
the CI check (exitZeroOnChanges).

Setup steps mirror the existing publish-docs.yml workflow.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix Storybook production build failure with Storybook 9

Filter out HtmlWebpackPlugin and BundleAnalyzerPlugin from the merged
Electron renderer webpack config. Storybook 9's WebpackInjectMockerRuntimePlugin
hooks into every HtmlWebpackPlugin instance, causing mocker-runtime-injected.js
to be emitted twice when the renderer's HtmlWebpackPlugin is merged in.

Also strip optimization and cache configs that Storybook manages itself.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: use github.sha instead of github.ref for CHROMATIC_SHA fallback

github.ref returns a ref string (refs/heads/branch-name), not a commit
SHA. Use github.sha for correct baseline detection if the trigger were
ever expanded beyond pull_request events.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Use feature-specific story filter for Chromatic snapshots

Read glob pattern from .chromatic-story-filter if present, falling
back to all extension stories. This lets the porting workflow target
only the feature's stories, saving Chromatic snapshot quota.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Pin chromaui/action to v16 and clean up stale Storybook comments

- Pin chromaui/action@latest to @v16 for supply-chain safety,
  consistent with all other pinned actions in the repo
- Remove resolved TODO "Make this work in production mode" since
  this PR fixes exactly that
- Remove misleading "will not affect anything" comment on the
  production config branch
- Replace vague "Remove configs that break stuff" with an accurate
  explanation of what is stripped and why

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix ESLint errors: require-disable-comment, unused var, hardcoded strings

Add explanation comments above eslint-disable directives in .storybook/main.ts
and e2e-tests/fixtures/papi-live.fixture.ts. Remove unused `err` catch binding.
Extract hardcoded webpack plugin names to array constant. These pre-date the
require-disable-comment rule but surfaced after rebase onto ai/main.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
katherinejensen00 pushed a commit that referenced this pull request Apr 20, 2026
* docs: add design spec for publishing paranext-core Storybook

Captures the agreed-upon design for a one-PR change that fixes the core
Storybook production build (by applying the plugin-filter fix from PR #2168),
decouples PBR stories from the core Storybook, and publishes the result to
GitHub Pages alongside the existing platform-bible-react Storybook.

* docs: add implementation plan for publishing paranext-core Storybook

Five tasks covering the storybook production build fix, PBR decoupling,
the CI step in publish-docs.yml, the landing-page card, and the PR.
Each task is broken into bite-sized steps with exact code, commands,
and expected outputs, ready for subagent-driven or inline execution.

* fix(storybook): filter conflicting plugins from merged renderer config

Storybook 9's WebpackInjectMockerRuntimePlugin hooks into every
HtmlWebpackPlugin instance. The merged Electron renderer config brought
in a second HtmlWebpackPlugin, causing mocker-runtime-injected.js to be
emitted twice and the production build to fail.

Filter out HtmlWebpackPlugin and BundleAnalyzerPlugin from the renderer
config, and strip optimization + cache which Storybook manages itself.

Applies the .storybook/main.ts hunk from paranext-core#2168 (merged to
ai/main) onto main so publish-docs can build the core Storybook.

* refactor(storybook): decouple platform-bible-react stories from core Storybook

Remove the platform-bible-react stories glob and the platform-bible-react
staticDirs entry. PBR has its own Storybook that is published to
/platform-bible-react-storybook/; core Storybook should only host core
and extension stories so the two publications don't duplicate content.

Keep both webpack aliases ('platform-bible-react' -> PBR source,
'@' -> lib/platform-bible-react/src) so core and extension stories that
import PBR by bare specifier continue to resolve to source during dev.

* ci(publish-docs): build and deploy paranext-core Storybook

Adds a build step that outputs the core Storybook to
docs-for-pages/paranext-core-storybook/, deployed alongside the
existing platform-bible-react Storybook to GitHub Pages.

* docs: add paranext-core Storybook card to GitHub Pages landing

Fourth resource card linking to /paranext-core-storybook/ — the
Storybook produced by the new publish-docs build step. Matches the
styling of the existing platform-bible-react Design System link.
katherinejensen00 pushed a commit that referenced this pull request Apr 20, 2026
* ci: add Chromatic workflow for Storybook visual review

Publishes Storybook to Chromatic when the `storybook-review` label is
present on a PR targeting ai/main. Uses TurboSnap (onlyChanged) and
limits snapshots to extension stories only. Visual changes don't fail
the CI check (exitZeroOnChanges).

Setup steps mirror the existing publish-docs.yml workflow.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix Storybook production build failure with Storybook 9

Filter out HtmlWebpackPlugin and BundleAnalyzerPlugin from the merged
Electron renderer webpack config. Storybook 9's WebpackInjectMockerRuntimePlugin
hooks into every HtmlWebpackPlugin instance, causing mocker-runtime-injected.js
to be emitted twice when the renderer's HtmlWebpackPlugin is merged in.

Also strip optimization and cache configs that Storybook manages itself.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: use github.sha instead of github.ref for CHROMATIC_SHA fallback

github.ref returns a ref string (refs/heads/branch-name), not a commit
SHA. Use github.sha for correct baseline detection if the trigger were
ever expanded beyond pull_request events.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Use feature-specific story filter for Chromatic snapshots

Read glob pattern from .chromatic-story-filter if present, falling
back to all extension stories. This lets the porting workflow target
only the feature's stories, saving Chromatic snapshot quota.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Pin chromaui/action to v16 and clean up stale Storybook comments

- Pin chromaui/action@latest to @v16 for supply-chain safety,
  consistent with all other pinned actions in the repo
- Remove resolved TODO "Make this work in production mode" since
  this PR fixes exactly that
- Remove misleading "will not affect anything" comment on the
  production config branch
- Replace vague "Remove configs that break stuff" with an accurate
  explanation of what is stripped and why

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix ESLint errors: require-disable-comment, unused var, hardcoded strings

Add explanation comments above eslint-disable directives in .storybook/main.ts
and e2e-tests/fixtures/papi-live.fixture.ts. Remove unused `err` catch binding.
Extract hardcoded webpack plugin names to array constant. These pre-date the
require-disable-comment rule but surfaced after rebase onto ai/main.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
rolfheij-sil added a commit that referenced this pull request Apr 22, 2026
* ci: add Chromatic workflow for Storybook visual review

Publishes Storybook to Chromatic when the `storybook-review` label is
present on a PR targeting ai/main. Uses TurboSnap (onlyChanged) and
limits snapshots to extension stories only. Visual changes don't fail
the CI check (exitZeroOnChanges).

Setup steps mirror the existing publish-docs.yml workflow.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix Storybook production build failure with Storybook 9

Filter out HtmlWebpackPlugin and BundleAnalyzerPlugin from the merged
Electron renderer webpack config. Storybook 9's WebpackInjectMockerRuntimePlugin
hooks into every HtmlWebpackPlugin instance, causing mocker-runtime-injected.js
to be emitted twice when the renderer's HtmlWebpackPlugin is merged in.

Also strip optimization and cache configs that Storybook manages itself.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: use github.sha instead of github.ref for CHROMATIC_SHA fallback

github.ref returns a ref string (refs/heads/branch-name), not a commit
SHA. Use github.sha for correct baseline detection if the trigger were
ever expanded beyond pull_request events.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Use feature-specific story filter for Chromatic snapshots

Read glob pattern from .chromatic-story-filter if present, falling
back to all extension stories. This lets the porting workflow target
only the feature's stories, saving Chromatic snapshot quota.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Pin chromaui/action to v16 and clean up stale Storybook comments

- Pin chromaui/action@latest to @v16 for supply-chain safety,
  consistent with all other pinned actions in the repo
- Remove resolved TODO "Make this work in production mode" since
  this PR fixes exactly that
- Remove misleading "will not affect anything" comment on the
  production config branch
- Replace vague "Remove configs that break stuff" with an accurate
  explanation of what is stripped and why

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix ESLint errors: require-disable-comment, unused var, hardcoded strings

Add explanation comments above eslint-disable directives in .storybook/main.ts
and e2e-tests/fixtures/papi-live.fixture.ts. Remove unused `err` catch binding.
Extract hardcoded webpack plugin names to array constant. These pre-date the
require-disable-comment rule but surfaced after rebase onto ai/main.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
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