feat: unified storybook + PR preview pipeline#35
Conversation
Root-level .storybook/ config needs these packages directly available, not just hoisted from individual packages.
Pulls stories from base-ui, ai-ui, and editors into a single build. Merges Vite configs: @omniview/base-ui alias for cross-package imports, monaco-editor optimizations, and STORYBOOK_BASE env var for PR previews.
Superset of all package previews: theme/density/motion controls, ThemeProvider decorator, base-ui CSS, and Monaco worker setup. Editors stories now gain density/motion controls they previously lacked.
Root 'pnpm storybook' now launches all packages. Per-package scripts available as storybook:base, storybook:ai, storybook:editors.
Replaces GitHub Pages deployment with S3 sync + CloudFront invalidation. Deploys unified storybook (all packages) to storybook.omniview.dev.
Builds unified storybook with path prefix, deploys to S3, posts preview URL as a comment on the PR. Skips forks, uses concurrency groups to prevent race conditions.
Event-driven cleanup on PR close + weekly cron safety net. Cron lists all pr-* prefixes, checks PR status via GitHub API, deletes stale ones.
📝 WalkthroughWalkthroughSwitches Storybook production deployment from GitHub Pages to AWS S3 + CloudFront, adds PR preview deployment and automated cleanup workflows, and updates Storybook/Vite configuration, dependencies, and preview UI settings. Changes
Sequence Diagram(s)sequenceDiagram
participant GH as GitHub Actions
participant Repo as Repository (actions)
participant AWS as AWS (STS → S3/CloudFront)
participant GitHubAPI as GitHub API
rect rgba(135,206,250,0.5)
GH->>Repo: checkout, install, build Storybook (base path set)
GH->>AWS: assume role (configure-aws-credentials)
GH->>AWS: aws s3 sync storybook-static/ -> s3://bucket/pr-<num>/ or /main/
GH->>AWS: aws cloudfront create-invalidation --paths "/*" or "/pr-<num>/*"
end
rect rgba(144,238,144,0.5)
GH->>GitHubAPI: post/update PR comment with preview URL (for PR previews)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
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. Comment |
|
Storybook Preview Updated: ba742cc |
There was a problem hiding this comment.
Actionable comments posted: 6
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/deploy-storybook.yml:
- Around line 6-9: The workflow path filter under the paths key is missing
package.json so changes to scripts/devDependencies can bypass Storybook deploy;
update the paths array used in the deploy-storybook.yml workflow to include the
root and package-level package.json (e.g., add 'package.json' and/or
'packages/**/package.json') so that any edits to package.json will trigger the
Storybook deploy; ensure the added entries align with existing patterns like
'packages/**' and '.storybook/**'.
In @.github/workflows/pr-storybook-cleanup.yml:
- Around line 71-75: The current check uses state=$(gh api
"repos/$REPO/pulls/$pr_num" --jq '.state' 2>/dev/null || echo "unknown") and
then deletes if [ "$state" != "open" ], which causes deletions on transient
failures; change the logic to only remove the S3 preview when state is exactly
"closed" and skip/log for "unknown" or other states. Update the conditional
around the aws s3 rm call (referencing the state variable, the gh api lookup,
and the prefix/aws s3 rm invocation) so it performs deletion only when
state=="closed" and otherwise echoes a skip message without deleting.
- Around line 18-26: The cleanup-pr job runs on all pull_request events and
tries to assume AWS credentials for forks that lack secrets; add the same fork
guard used in deploy-preview by adding the conditional if:
github.event.pull_request.head.repo.full_name == github.repository to the job
definition so the job (the block that includes uses:
aws-actions/configure-aws-credentials@v4 and env: PR_NUMBER) only runs for
non-fork PRs and will not attempt to access secrets for forked repositories.
In @.github/workflows/pr-storybook-preview.yml:
- Around line 6-9: The workflow's paths filter omits the root package manifest
so changes to scripts or deps won't trigger the job; update the workflow's paths
array (the "paths:" list in the YAML) to include "package.json" (and optionally
"packages/**/package.json" if you want package-level manifest changes to also
trigger) so storybook preview builds run when package manifests change.
- Around line 58-67: The workflow currently uses
peter-evans/create-or-update-comment@v4 with a now-unsupported comment-tag,
causing new comments each run; update the job to first run
peter-evans/find-comment@v4 to locate the existing "storybook-preview" comment
(use the same body marker or search term) and pass the returned comment id into
create-or-update-comment@v4 via its comment-id input (keep issue-number: ${{
env.PR_NUMBER }} and the body content, and include _Updated: ${{ github.sha
}}_), so the existing PR comment is updated instead of creating duplicates.
In @.storybook/main.ts:
- Around line 49-53: The current merge of config.resolve.alias always treats
aliases as an object which breaks when Vite provides an array; update the logic
in .storybook/main.ts to detect Array.isArray(config.resolve.alias) and handle
both shapes: if it's an array, push or unshift a { find: '@omniview/base-ui',
replacement: path.resolve(__dirname, '../packages/base-ui/src/index.ts') } entry
(preserving intended order), and if it's an object (or undefined) merge by
spreading into config.resolve.alias as before; ensure you still set
config.resolve = config.resolve ?? {} and only mutate config.resolve.alias in
the matching branch so existing array entries keep their numeric order and
object entries keep their properties.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 56ec5a46-9b9f-4884-9e2e-40ab42334759
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (6)
.github/workflows/deploy-storybook.yml.github/workflows/pr-storybook-cleanup.yml.github/workflows/pr-storybook-preview.yml.storybook/main.ts.storybook/preview.tsxpackage.json
| paths: | ||
| - 'packages/**' | ||
| - '.storybook/**' | ||
| - 'pnpm-lock.yaml' |
There was a problem hiding this comment.
Include package.json in the deploy triggers.
Production deploy now depends on the root Storybook scripts and devDependencies. Without package.json in this path filter, script-only changes there can merge to main without ever rebuilding or redeploying Storybook.
Suggested fix
paths:
- 'packages/**'
- '.storybook/**'
+ - 'package.json'
- 'pnpm-lock.yaml'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| paths: | |
| - 'packages/**' | |
| - '.storybook/**' | |
| - 'pnpm-lock.yaml' | |
| paths: | |
| - 'packages/**' | |
| - '.storybook/**' | |
| - 'package.json' | |
| - 'pnpm-lock.yaml' |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/deploy-storybook.yml around lines 6 - 9, The workflow path
filter under the paths key is missing package.json so changes to
scripts/devDependencies can bypass Storybook deploy; update the paths array used
in the deploy-storybook.yml workflow to include the root and package-level
package.json (e.g., add 'package.json' and/or 'packages/**/package.json') so
that any edits to package.json will trigger the Storybook deploy; ensure the
added entries align with existing patterns like 'packages/**' and
'.storybook/**'.
| if: github.event_name == 'pull_request' | ||
| runs-on: ubuntu-latest | ||
| env: | ||
| PR_NUMBER: ${{ github.event.pull_request.number }} | ||
| steps: | ||
| - uses: aws-actions/configure-aws-credentials@v4 | ||
| with: | ||
| role-to-assume: ${{ secrets.AWS_ROLE_ARN }} | ||
| aws-region: us-east-2 |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find .github/workflows -name "*.yml" -o -name "*.yaml" | head -20Repository: omniviewdev/ui
Length of output: 213
🏁 Script executed:
cat -n .github/workflows/pr-storybook-cleanup.ymlRepository: omniviewdev/ui
Length of output: 3061
🏁 Script executed:
cat -n .github/workflows/pr-storybook-preview.ymlRepository: omniviewdev/ui
Length of output: 2396
Mirror the fork guard from deploy-preview in cleanup-pr.
.github/workflows/pr-storybook-preview.yml already uses if: github.event.pull_request.head.repo.full_name == github.repository (line 23) to skip forks, since fork PRs do not receive repository secrets. The cleanup-pr job currently runs on all pull request events and will attempt AWS credential setup even though fork PRs cannot access secrets.AWS_ROLE_ARN, causing the job to fail unnecessarily.
Suggested fix
cleanup-pr:
- if: github.event_name == 'pull_request'
+ if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if: github.event_name == 'pull_request' | |
| runs-on: ubuntu-latest | |
| env: | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| steps: | |
| - uses: aws-actions/configure-aws-credentials@v4 | |
| with: | |
| role-to-assume: ${{ secrets.AWS_ROLE_ARN }} | |
| aws-region: us-east-2 | |
| if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository | |
| runs-on: ubuntu-latest | |
| env: | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| steps: | |
| - uses: aws-actions/configure-aws-credentials@v4 | |
| with: | |
| role-to-assume: ${{ secrets.AWS_ROLE_ARN }} | |
| aws-region: us-east-2 |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/pr-storybook-cleanup.yml around lines 18 - 26, The
cleanup-pr job runs on all pull_request events and tries to assume AWS
credentials for forks that lack secrets; add the same fork guard used in
deploy-preview by adding the conditional if:
github.event.pull_request.head.repo.full_name == github.repository to the job
definition so the job (the block that includes uses:
aws-actions/configure-aws-credentials@v4 and env: PR_NUMBER) only runs for
non-fork PRs and will not attempt to access secrets for forked repositories.
| state=$(gh api "repos/$REPO/pulls/$pr_num" --jq '.state' 2>/dev/null || echo "unknown") | ||
|
|
||
| if [ "$state" != "open" ]; then | ||
| echo "Cleaning up $prefix (PR #$pr_num is $state)" | ||
| aws s3 rm "s3://$BUCKET/$prefix" --recursive |
There was a problem hiding this comment.
Do not delete previews when the PR-state lookup fails.
gh api ... || echo "unknown" currently falls into the deletion branch. A transient GitHub API/auth failure would therefore purge previews for still-open PRs. Only delete on an explicit closed state, and skip/log anything else.
Suggested fix
- state=$(gh api "repos/$REPO/pulls/$pr_num" --jq '.state' 2>/dev/null || echo "unknown")
-
- if [ "$state" != "open" ]; then
- echo "Cleaning up $prefix (PR #$pr_num is $state)"
- aws s3 rm "s3://$BUCKET/$prefix" --recursive
- else
- echo "Keeping $prefix (PR #$pr_num is still open)"
- fi
+ state=$(gh api "repos/$REPO/pulls/$pr_num" --jq '.state' 2>/dev/null || true)
+
+ if [ "$state" = "open" ]; then
+ echo "Keeping $prefix (PR #$pr_num is still open)"
+ elif [ "$state" = "closed" ]; then
+ echo "Cleaning up $prefix (PR #$pr_num is closed)"
+ aws s3 rm "s3://$BUCKET/$prefix" --recursive
+ else
+ echo "Skipping $prefix (could not determine PR #$pr_num state)"
+ fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| state=$(gh api "repos/$REPO/pulls/$pr_num" --jq '.state' 2>/dev/null || echo "unknown") | |
| if [ "$state" != "open" ]; then | |
| echo "Cleaning up $prefix (PR #$pr_num is $state)" | |
| aws s3 rm "s3://$BUCKET/$prefix" --recursive | |
| state=$(gh api "repos/$REPO/pulls/$pr_num" --jq '.state' 2>/dev/null || true) | |
| if [ "$state" = "open" ]; then | |
| echo "Keeping $prefix (PR #$pr_num is still open)" | |
| elif [ "$state" = "closed" ]; then | |
| echo "Cleaning up $prefix (PR #$pr_num is closed)" | |
| aws s3 rm "s3://$BUCKET/$prefix" --recursive | |
| else | |
| echo "Skipping $prefix (could not determine PR #$pr_num state)" | |
| fi |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/pr-storybook-cleanup.yml around lines 71 - 75, The current
check uses state=$(gh api "repos/$REPO/pulls/$pr_num" --jq '.state' 2>/dev/null
|| echo "unknown") and then deletes if [ "$state" != "open" ], which causes
deletions on transient failures; change the logic to only remove the S3 preview
when state is exactly "closed" and skip/log for "unknown" or other states.
Update the conditional around the aws s3 rm call (referencing the state
variable, the gh api lookup, and the prefix/aws s3 rm invocation) so it performs
deletion only when state=="closed" and otherwise echoes a skip message without
deleting.
| paths: | ||
| - 'packages/**' | ||
| - '.storybook/**' | ||
| - 'pnpm-lock.yaml' |
There was a problem hiding this comment.
Add package.json to the trigger paths.
This workflow now builds via the root pnpm build-storybook, and the Storybook CLI/addon versions plus scripts live in the root manifest. A script-only or dependency-only change in package.json will currently skip preview generation entirely.
Suggested fix
paths:
- 'packages/**'
- '.storybook/**'
+ - 'package.json'
- 'pnpm-lock.yaml'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| paths: | |
| - 'packages/**' | |
| - '.storybook/**' | |
| - 'pnpm-lock.yaml' | |
| paths: | |
| - 'packages/**' | |
| - '.storybook/**' | |
| - 'package.json' | |
| - 'pnpm-lock.yaml' |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/pr-storybook-preview.yml around lines 6 - 9, The
workflow's paths filter omits the root package manifest so changes to scripts or
deps won't trigger the job; update the workflow's paths array (the "paths:" list
in the YAML) to include "package.json" (and optionally
"packages/**/package.json" if you want package-level manifest changes to also
trigger) so storybook preview builds run when package manifests change.
| - name: Post or update PR comment | ||
| uses: peter-evans/create-or-update-comment@v4 | ||
| with: | ||
| issue-number: ${{ env.PR_NUMBER }} | ||
| body: | | ||
| **Storybook Preview** | ||
| https://storybook-preview.omniview.dev/pr-${{ env.PR_NUMBER }}/ | ||
|
|
||
| _Updated: ${{ github.sha }}_ | ||
| comment-tag: storybook-preview |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
peter-evans/create-or-update-comment v4 comment-tag parameter
💡 Result:
The peter-evans/create-or-update-comment GitHub Action in version 4 (v4) does not have a 'comment-tag' input parameter. The official action.yml and documentation list inputs such as token, repository, issue-number, comment-id, body, body-path, body-file (deprecated), edit-mode, append-separator, reactions, and reactions-edit-mode, but no 'comment-tag'. A feature request to add 'comment-tag' support for create-or-update functionality exists in issue #429 (opened Aug 2025), with a related commit pushed but the PR/issue still open as of Jan 2026, indicating it is not yet implemented in any released version, including v4. The latest release is v5.0.0 (Oct 2025). To update or find comments, use the companion peter-evans/find-comment action with parameters like body-includes or comment-author to locate the comment-id, then pass it to create-or-update-comment.
Citations:
- 1: feat: add comment-tag support for create-or-update functionality peter-evans/create-or-update-comment#429
- 2: https://github.com/peter-evans/create-or-update-comment
- 3: Create works but update doesn't? peter-evans/create-or-update-comment#364
- 4: https://github.com/peter-evans/create-or-update-comment/blob/main/action.yml
- 5: Bump peter-evans/create-or-update-comment from 3.0.0 to 4.0.0 github/docs#31363
🌐 Web query:
peter-evans/create-or-update-comment v4 comment-id update pattern
💡 Result:
To update an existing comment using peter-evans/create-or-update-comment@v4 with a known comment-id, use the comment-id input along with the new body (and optionally edit-mode and reactions). Example workflow step from official documentation and user examples: - name: Update comment uses: peter-evans/create-or-update-comment@v4 with: comment-id: 557858210 # Replace with actual comment ID body: | Edit: Some additional info reactions: eyes edit-mode: replace # Optional: 'replace' or 'append' (default 'append') Key points for v4 (behavior unchanged from v5, per official repo and issues): - comment-id: Required for update. The numeric ID of the comment (e.g., from previous creation step output ${{ steps.create.outputs.comment-id }} or peter-evans/find-comment). - Without comment-id, it creates a new comment using issue-number. - edit-mode: replace fully replaces the body; append adds to it. - Obtain comment-id typically via: 1. Output from prior create-or-update-comment step (give it an id: stepname). 2. peter-evans/find-comment@v3 action, searching by author/body. Example full pattern to find-or-create-update: - name: Find Comment uses: peter-evans/find-comment@v3 id: fc with: issue-number: ${{ github.event.pull_request.number }} body-includes: "unique marker text" - name: Create or update comment uses: peter-evans/create-or-update-comment@v4 with: comment-id: ${{ steps.fc.outputs.comment-id }} issue-number: ${{ github.event.pull_request.number }} body: | Updated content edit-mode: replace If no comment found, comment-id is empty string; action creates new. Note: Current latest is v5 (Oct 2025), but v4 works identically for this. Requires permissions: { issues: write, pull-requests: write } or equivalent token.
Citations:
- 1: https://github.com/peter-evans/create-or-update-comment
- 2: Create works but update doesn't? peter-evans/create-or-update-comment#364
- 3: https://cicube.io/workflow-hub/peter-evans-create-or-update-comment/
- 4: https://github.com/marketplace/actions/create-or-update-comment
- 5: Bump peter-evans/create-or-update-comment from 1 to 4 prisma/web#5906
🌐 Web query:
peter-evans/find-comment v4 GitHub Action
💡 Result:
peter-evans/find-comment@v4 is a GitHub Action that finds a comment in an issue or pull request and outputs its details like ID, body, author, and creation date. Usage example: - name: Find Comment uses: peter-evans/find-comment@v4 id: fc with: issue-number: 1 body-includes: search string Key inputs: - token: GITHUB_TOKEN (default) - repository: github.repository (default) - issue-number: Required, number of issue/PR - comment-author: Filter by author - body-includes: String to search in body - body-regex: Regex to match body - direction: first or last (default: first) - nth: 0-indexed position (default: 0) Outputs (empty if not found): - comment-id - comment-node-id - comment-body - comment-author - comment-created-at Latest release: v4.0.0 on 2025-10-01. Runs on Node 24 (requires runner v2.327.1+ for self-hosted). MIT licensed. Repository last updated 2026-03-06.
Citations:
- 1: https://github.com/peter-evans/find-comment
- 2: https://github.com/marketplace/actions/find-comment
- 3: https://github.com/peter-evans/find-comment/blob/main/action.yml
- 4: https://github.com/peter-evans/find-comment/releases
Use comment-id to update the preview comment; comment-tag is ignored here.
The create-or-update-comment@v4 action does not support comment-tag as an input parameter. Without comment-id, the action will create a new comment on each synchronize run instead of updating the existing one. Use peter-evans/find-comment@v4 to locate the existing comment and pass its ID to the action for proper updates.
Suggested fix
+ - name: Find existing preview comment
+ id: preview_comment
+ uses: peter-evans/find-comment@v4
+ with:
+ issue-number: ${{ env.PR_NUMBER }}
+ comment-author: github-actions[bot]
+ body-includes: '<!-- storybook-preview -->'
+
- name: Post or update PR comment
uses: peter-evans/create-or-update-comment@v4
with:
+ comment-id: ${{ steps.preview_comment.outputs.comment-id }}
issue-number: ${{ env.PR_NUMBER }}
body: |
+ <!-- storybook-preview -->
**Storybook Preview**
https://storybook-preview.omniview.dev/pr-${{ env.PR_NUMBER }}/
_Updated: ${{ github.sha }}_
- comment-tag: storybook-preview
+ edit-mode: replace📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - name: Post or update PR comment | |
| uses: peter-evans/create-or-update-comment@v4 | |
| with: | |
| issue-number: ${{ env.PR_NUMBER }} | |
| body: | | |
| **Storybook Preview** | |
| https://storybook-preview.omniview.dev/pr-${{ env.PR_NUMBER }}/ | |
| _Updated: ${{ github.sha }}_ | |
| comment-tag: storybook-preview | |
| - name: Find existing preview comment | |
| id: preview_comment | |
| uses: peter-evans/find-comment@v4 | |
| with: | |
| issue-number: ${{ env.PR_NUMBER }} | |
| comment-author: github-actions[bot] | |
| body-includes: '<!-- storybook-preview -->' | |
| - name: Post or update PR comment | |
| uses: peter-evans/create-or-update-comment@v4 | |
| with: | |
| comment-id: ${{ steps.preview_comment.outputs.comment-id }} | |
| issue-number: ${{ env.PR_NUMBER }} | |
| body: | | |
| <!-- storybook-preview --> | |
| **Storybook Preview** | |
| https://storybook-preview.omniview.dev/pr-${{ env.PR_NUMBER }}/ | |
| _Updated: ${{ github.sha }}_ | |
| edit-mode: replace |
🧰 Tools
🪛 actionlint (1.7.11)
[error] 67-67: input "comment-tag" is not defined in action "peter-evans/create-or-update-comment@v4". available inputs are "append-separator", "body", "body-file", "body-path", "comment-id", "edit-mode", "issue-number", "reactions", "reactions-edit-mode", "repository", "token"
(action)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/pr-storybook-preview.yml around lines 58 - 67, The
workflow currently uses peter-evans/create-or-update-comment@v4 with a
now-unsupported comment-tag, causing new comments each run; update the job to
first run peter-evans/find-comment@v4 to locate the existing "storybook-preview"
comment (use the same body marker or search term) and pass the returned comment
id into create-or-update-comment@v4 via its comment-id input (keep issue-number:
${{ env.PR_NUMBER }} and the body content, and include _Updated: ${{ github.sha
}}_), so the existing PR comment is updated instead of creating duplicates.
| config.resolve = config.resolve ?? {}; | ||
| config.resolve.alias = { | ||
| ...config.resolve.alias, | ||
| '@omniview/base-ui': path.resolve(__dirname, '../packages/base-ui/src/index.ts'), | ||
| }; |
There was a problem hiding this comment.
🧩 Analysis chain
🌐 Web query:
Vite resolve.alias object array format documentation
💡 Result:
Vite's resolve.alias configuration supports two formats: an object (Record) or an array of objects. The array format is Array<{ find: string | RegExp, replacement: string }>. This is passed to @rollup/plugin-alias as its entries option. The order of entries matters, with earlier rules applied first. Use absolute paths for file system aliases. ### Object Format (Record) resolve: { alias: { utils: '../../../utils', 'batman-1.0.0': './joker-1.5.0' } } ### Array Format resolve: { alias: [ { find: 'utils', replacement: '../../../utils' }, { find: 'batman-1.0.0', replacement: './joker-1.5.0' } ] } When find is a RegExp, replacement supports patterns like
Citations:
🏁 Script executed:
# Find and read the .storybook/main.ts file
find . -path "./.storybook/main.ts" -type fRepository: omniviewdev/ui
Length of output: 78
🏁 Script executed:
# Get more context around lines 49-53 in .storybook/main.ts
if [ -f ".storybook/main.ts" ]; then
echo "=== Full context of viteFinal function ==="
cat -n ".storybook/main.ts" | head -80
fiRepository: omniviewdev/ui
Length of output: 3122
🏁 Script executed:
# Search for other uses of resolve.alias in the codebase
rg "resolve\.alias" --type ts --type js -B 2 -A 2Repository: omniviewdev/ui
Length of output: 40
🏁 Script executed:
# Check Storybook version and configuration
if [ -f "package.json" ]; then
echo "=== Storybook/Vite versions ==="
cat package.json | grep -E '"@storybook|vite"' | head -20
fiRepository: omniviewdev/ui
Length of output: 248
🏁 Script executed:
# Check if there are any tests for the viteFinal hook
find . -path ./node_modules -prune -o -name "*.test.*" -o -name "*.spec.*" | grep -i storybookRepository: omniviewdev/ui
Length of output: 40
🏁 Script executed:
# Search for how Storybook might configure resolve.alias in this project
rg "config\.resolve" --type ts --type js -B 3 -A 3 | head -50Repository: omniviewdev/ui
Length of output: 40
Handle both Vite alias shapes before merging.
Vite allows resolve.alias to be either an object or an array of { find, replacement } entries, and array order is significant. Spreading config.resolve.alias into an object only works for the object form; if Storybook/Vite hands you an array here, the existing aliases are converted into numeric keys and resolution breaks. (Vite documentation)
Suggested fix
// --- Alias: resolve `@omniview/base-ui` to source (from ai-ui config) ---
config.resolve = config.resolve ?? {};
- config.resolve.alias = {
- ...config.resolve.alias,
- '@omniview/base-ui': path.resolve(__dirname, '../packages/base-ui/src/index.ts'),
- };
+ if (Array.isArray(config.resolve.alias)) {
+ config.resolve.alias.unshift({
+ find: '@omniview/base-ui',
+ replacement: path.resolve(__dirname, '../packages/base-ui/src/index.ts'),
+ });
+ } else {
+ config.resolve.alias = {
+ ...(config.resolve.alias ?? {}),
+ '@omniview/base-ui': path.resolve(__dirname, '../packages/base-ui/src/index.ts'),
+ };
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| config.resolve = config.resolve ?? {}; | |
| config.resolve.alias = { | |
| ...config.resolve.alias, | |
| '@omniview/base-ui': path.resolve(__dirname, '../packages/base-ui/src/index.ts'), | |
| }; | |
| config.resolve = config.resolve ?? {}; | |
| if (Array.isArray(config.resolve.alias)) { | |
| config.resolve.alias.unshift({ | |
| find: '@omniview/base-ui', | |
| replacement: path.resolve(__dirname, '../packages/base-ui/src/index.ts'), | |
| }); | |
| } else { | |
| config.resolve.alias = { | |
| ...(config.resolve.alias ?? {}), | |
| '@omniview/base-ui': path.resolve(__dirname, '../packages/base-ui/src/index.ts'), | |
| }; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.storybook/main.ts around lines 49 - 53, The current merge of
config.resolve.alias always treats aliases as an object which breaks when Vite
provides an array; update the logic in .storybook/main.ts to detect
Array.isArray(config.resolve.alias) and handle both shapes: if it's an array,
push or unshift a { find: '@omniview/base-ui', replacement:
path.resolve(__dirname, '../packages/base-ui/src/index.ts') } entry (preserving
intended order), and if it's an object (or undefined) merge by spreading into
config.resolve.alias as before; ensure you still set config.resolve =
config.resolve ?? {} and only mutate config.resolve.alias in the matching branch
so existing array entries keep their numeric order and object entries keep their
properties.
The root .storybook/ config needs react, react-dom, and @vitejs/plugin-react directly available. Without these, the storybook build produces "React is not defined" errors.
|
Storybook Preview Updated: 955dbea |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@package.json`:
- Around line 51-53: package.json pins the dependency eslint-plugin-react-hooks
at ^5.2.0 which is incompatible with React 19.2 features; update the dependency
entry for "eslint-plugin-react-hooks" to a v6+ range (e.g. ^6.0.0 or latest
6.x), run the package manager to update the lockfile (npm/yarn/pnpm install) and
verify linting (run eslint) so the new rules for useEffectEvent and React
Compiler are enforced; ensure there are no breaking rule changes by addressing
any new lint errors reported by eslint.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: e7a45cbc-c728-4f5c-939b-6c302332622e
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (1)
package.json
| "react": "^19.0.0", | ||
| "react-dom": "^19.0.0", | ||
| "storybook": "^10.2.15", |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "Manifest versions:"
jq -r '
.devDependencies.react,
.devDependencies["react-dom"],
.devDependencies["eslint-plugin-react-hooks"]
' package.json
echo
echo "Resolved lockfile entries (if pnpm lock exists):"
LOCKFILE=$(fd '^pnpm-lock.yaml$' | head -n1 || true)
if [ -n "${LOCKFILE:-}" ]; then
rg -n '^( {2})?(react|react-dom|eslint-plugin-react-hooks)@' "$LOCKFILE" -n
else
echo "pnpm-lock.yaml not found"
fiRepository: omniviewdev/ui
Length of output: 353
🌐 Web query:
eslint-plugin-react-hooks v6 React 19 compatibility release notes
💡 Result:
eslint-plugin-react-hooks v6 is fully compatible with React 19. It was released as part of the React 19.2 announcement on 2025-10-01, with the first official stable version being 6.1.0 (after an accidental 6.0.0 release was deprecated). The plugin now defaults to flat config support for ESLint 9+ in the 'recommended' preset (use 'recommended-legacy' for older configs). It includes core rules like rules-of-hooks and exhaustive-deps, plus opt-in React Compiler rules via 'recommended-latest'. Key changes in v6 (from CHANGELOG): - Breaking: Flat config is now default 'recommended'; legacy moved to 'recommended-legacy'. - Requires Node.js 18+. - Added support for additionalEffectHooks setting. - Handles React.useEffect in rules-of-hooks. - Added recommended-latest configs with React Compiler rules (e.g., purity, immutability, set-state-in-effect). React 19.2 blog explicitly recommends upgrading to eslint-plugin-react-hooks v6 (or latest) for compatibility with new features like useEffectEvent, which requires the updated linter to exclude effect events from dependency arrays. Current latest version is 7.0.1 (as of 2026-03-18), which builds on v6 with further refinements like slimmed presets and all compiler rules enabled by default in recommended-latest.
Citations:
- 1: https://github.com/facebook/react/blob/master/packages/eslint-plugin-react-hooks/CHANGELOG.md
- 2: https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/CHANGELOG.md
- 3: https://react.dev/blog/2025/10/01/react-19-2
- 4: https://letsreact.org/how-to-use-eslint-plugin-react-hooks-v6-in-react-19-2
- 5: https://www.npmjs.com/package/eslint-plugin-react-hooks
- 6: https://www.reddit.com/r/reactjs/comments/1ocab09/eslint_6_or_7_react_192/
- 7: https://react.dev/reference/eslint-plugin-react-hooks
- 8: Upgrade
eslint-plugin-react-hooksinto v6 vercel/next.js#84484
Upgrade eslint-plugin-react-hooks to v6+ for React 19.2 compatibility
React 19.2 introduced new features (useEffectEvent, React Compiler rules) that require eslint-plugin-react-hooks v6 or later. Current manifest pins eslint-plugin-react-hooks@^5.2.0, which resolves to v5.2.0 in the lockfile while react and react-dom resolve to 19.2.4, causing the linter to miss validation rules for React 19.2+ features.
Proposed fix
- "eslint-plugin-react-hooks": "^5.2.0",
+ "eslint-plugin-react-hooks": "^6.0.0",🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@package.json` around lines 51 - 53, package.json pins the dependency
eslint-plugin-react-hooks at ^5.2.0 which is incompatible with React 19.2
features; update the dependency entry for "eslint-plugin-react-hooks" to a v6+
range (e.g. ^6.0.0 or latest 6.x), run the package manager to update the
lockfile (npm/yarn/pnpm install) and verify linting (run eslint) so the new
rules for useEffectEvent and React Compiler are enforced; ensure there are no
breaking rule changes by addressing any new lint errors reported by eslint.
- Add .npmrc with shamefully-hoist=true so root storybook can resolve all workspace package dependencies - Explicitly inject @vitejs/plugin-react in viteFinal when missing (pnpm workspace hoisting can lose it from @storybook/react-vite) - Add obsidian, carbon, void themes to toolbar in all storybook previews (root, base-ui, ai-ui, editors)
|
Storybook Preview Updated: e662359 |
Merging this PR will degrade performance by 16.89%
Performance Changes
Comparing Footnotes
|
Summary
pnpm storybooknow launches the full component catalog; per-package scripts still availablestorybook.omniview.devon push to mainstorybook-preview.omniview.dev/pr-<number>/with bot commentInfrastructure
S3 + CloudFront infrastructure provisioned via
tf-infra-registry(PR #1, merged). GitHub secrets/variables configured.Test plan
pnpm storybooklocally — verify all three packages renderstorybook.omniview.devdeploysSummary by CodeRabbit
New Features
Bug Fixes
Chores