Skip to content

feat: add provider logo overlays to workflow template thumbnails#8365

Merged
christian-byrne merged 19 commits intomainfrom
templates/composite-logos
Feb 1, 2026
Merged

feat: add provider logo overlays to workflow template thumbnails#8365
christian-byrne merged 19 commits intomainfrom
templates/composite-logos

Conversation

@christian-byrne
Copy link
Contributor

@christian-byrne christian-byrne commented Jan 28, 2026

Summary

Add support for overlaying provider logos on workflow template thumbnails at runtime.

Changes

  • What:
    • Add LogoInfo interface and logos field to TemplateInfo type
    • Create LogoOverlay.vue component for rendering positioned logos
    • Fetch logo index from templates/index_logo.json in store
    • Add getLogoUrl helper to useTemplateWorkflows composable
    • Integrate LogoOverlay into WorkflowTemplateSelectorDialog

Review Focus

  • Logo positioning uses Tailwind classes (e.g. absolute bottom-2 right-2)
  • Supports multiple logos per template with configurable size/opacity
  • Gracefully handles missing logos (returns empty string, renders nothing)
  • Templates must explicitly declare logos - no magic inference from models

Dependencies

Requires separate PR in workflow_templates repo to:

  1. Update index.schema.json with logos definition
  2. Add logos field to templates in index.json

Screenshots (if applicable)

image

┆Issue is synchronized with this Notion page by Unito

- Add LogoInfo interface and logos field to TemplateInfo type
- Create LogoOverlay.vue component for rendering positioned logos
- Fetch logo index from templates/index_logo.json in store
- Add getLogoUrl helper to useTemplateWorkflows composable
- Integrate LogoOverlay into WorkflowTemplateSelectorDialog

Supports multiple logos per template with configurable:
- Position (Tailwind classes)
- Size (sm/md/lg)
- Opacity (0-1)

Templates can declare logos explicitly. Logo assets are fetched
from the workflow_templates repo (templates/logo/*.png).

Amp-Thread-ID: https://ampcode.com/threads/T-019c03a1-9f05-70bd-b0a3-2848e54e04af
Co-authored-by: Amp <amp@ampcode.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 28, 2026

📝 Walkthrough

Walkthrough

This PR introduces a logo overlay feature for workflow templates. It adds a new LogoOverlay component to display provider logos on template cards, integrates logo management into the template store with URL resolution, and defines necessary types and schemas to support logo data throughout the system.

Changes

Cohort / File(s) Summary
Logo Overlay Component
src/components/templates/thumbnails/LogoOverlay.vue, src/components/templates/thumbnails/LogoOverlay.test.ts, src/components/custom/widget/WorkflowTemplateSelectorDialog.vue
Introduces LogoOverlay component that renders overlaid logo pills for multiple providers with error handling and visibility management based on failed images. Comprehensive test coverage includes rendering behavior, URL filtering, stacking with gaps, localization, and error handling. Integration into template selector dialog to display logos within template cards.
Logo Management & Types
src/platform/workflow/templates/repositories/workflowTemplatesStore.ts, src/platform/workflow/templates/types/template.ts, src/platform/workflow/templates/schemas/templateSchema.ts
Adds logo index state and public getLogoUrl() API to resolve provider logo paths from a logo index JSON file with safety validation. Introduces LogoInfo interface with provider, label, gap, position, and opacity fields. Adds logos array to TemplateInfo. Includes Zod schema and type inference for logo index validation.
Localization
src/locales/en/main.json
Adds new localization string "logoProviderSeparator" under templates section for separating multiple logo providers in UI labels.

Sequence Diagram

sequenceDiagram
    participant TS as Template Selector
    participant Store as Templates Store
    participant HTTP as HTTP Client
    participant LO as LogoOverlay
    participant IMG as Image Load

    TS->>Store: loadWorkflowTemplates()
    Store->>HTTP: GET /templates/index_logo.json
    HTTP-->>Store: logoIndex data
    Store->>Store: validate with zLogoIndex
    Store-->>TS: templates with logos[]

    TS->>TS: render template cards
    TS->>LO: pass logos[] + getLogoUrl
    
    LO->>LO: compute validLogos (resolve URLs)
    LO->>LO: render logo pills

    LO->>IMG: load provider image
    IMG-->>LO: onImageError
    LO->>LO: update failedLogos set
    LO->>LO: hasAllFailed checks visibility
    LO-->>TS: render UI with overlay
Loading

Suggested reviewers

  • comfyui-wiki
  • Yorha4D
  • KarryCharon
  • shinshin86
  • PabloWiedemann
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch templates/composite-logos

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.

@github-actions
Copy link

github-actions bot commented Jan 28, 2026

🎨 Storybook Build Status

Build completed successfully!

⏰ Completed at: 02/01/2026, 01:39:13 AM UTC

🔗 Links


🎉 Your Storybook is ready for review!

@github-actions
Copy link

github-actions bot commented Jan 28, 2026

🎭 Playwright Tests: ⚠️ Passed with flaky tests

Results: 503 passed, 0 failed, 2 flaky, 8 skipped (Total: 513)

❌ Failed Tests

📊 Browser Reports
  • chromium: View Report (✅ 491 / ❌ 0 / ⚠️ 2 / ⏭️ 8)
  • chromium-2x: View Report (✅ 2 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • chromium-0.5x: View Report (✅ 1 / ❌ 0 / ⚠️ 0 / ⏭️ 0)
  • mobile-chrome: View Report (✅ 9 / ❌ 0 / ⚠️ 0 / ⏭️ 0)

@github-actions
Copy link

github-actions bot commented Jan 28, 2026

Bundle Size Report

Summary

  • Raw size: 22.2 MB baseline 22.2 MB — 🔴 +5.28 kB
  • Gzip: 4.61 MB baseline 4.61 MB — 🔴 +1.27 kB
  • Brotli: 3.43 MB baseline 3.43 MB — 🔴 +845 B
  • Bundles: 175 current • 175 baseline • 86 added / 86 removed

Category Glance
Graph Workspace 🔴 +4.23 kB (978 kB) · Data & Services 🔴 +976 B (2.71 MB) · Other 🔴 +73 B (7.12 MB) · Vendor & Third-Party ⚪ 0 B (10.7 MB) · Panels & Settings ⚪ 0 B (471 kB) · Views & Navigation ⚪ 0 B (80.7 kB) · + 5 more

Per-category breakdown
App Entry Points — 26 kB (baseline 26 kB) • ⚪ 0 B

Main entry bundles and manifests

File Before After Δ Raw Δ Gzip Δ Brotli
assets/index-CsfTyeN5.js (removed) 26 kB 🟢 -26 kB 🟢 -7.5 kB 🟢 -6.59 kB
assets/index-O6RHP__Q.js (new) 26 kB 🔴 +26 kB 🔴 +7.5 kB 🔴 +6.62 kB

Status: 1 added / 1 removed

Graph Workspace — 978 kB (baseline 974 kB) • 🔴 +4.23 kB

Graph editor runtime, canvas, workflow orchestration

File Before After Δ Raw Δ Gzip Δ Brotli
assets/GraphView-CR-QLtpo.js (new) 978 kB 🔴 +978 kB 🔴 +198 kB 🔴 +149 kB
assets/GraphView-D-87gY60.js (removed) 974 kB 🟢 -974 kB 🟢 -197 kB 🟢 -148 kB

Status: 1 added / 1 removed

Views & Navigation — 80.7 kB (baseline 80.7 kB) • ⚪ 0 B

Top-level views, pages, and routed surfaces

File Before After Δ Raw Δ Gzip Δ Brotli
assets/CloudSurveyView-4ZEGwzk5.js (removed) 17.1 kB 🟢 -17.1 kB 🟢 -3.6 kB 🟢 -3.05 kB
assets/CloudSurveyView-DKiCM6W8.js (new) 17.1 kB 🔴 +17.1 kB 🔴 +3.61 kB 🔴 +3.05 kB
assets/CloudLoginView-BRbIj2SC.js (new) 11.8 kB 🔴 +11.8 kB 🔴 +3.09 kB 🔴 +2.73 kB
assets/CloudLoginView-CaY0u00G.js (removed) 11.8 kB 🟢 -11.8 kB 🟢 -3.09 kB 🟢 -2.72 kB
assets/UserCheckView-Dl_scB-S.js (removed) 10.5 kB 🟢 -10.5 kB 🟢 -2.44 kB 🟢 -2.13 kB
assets/UserCheckView-DX2ZA664.js (new) 10.5 kB 🔴 +10.5 kB 🔴 +2.45 kB 🔴 +2.13 kB
assets/CloudLayoutView-4CKU5gB8.js (new) 8.54 kB 🔴 +8.54 kB 🔴 +2.24 kB 🔴 +1.96 kB
assets/CloudLayoutView-CpfjE_ZG.js (removed) 8.54 kB 🟢 -8.54 kB 🟢 -2.24 kB 🟢 -1.96 kB
assets/CloudSignupView-Dl2XDUgi.js (new) 8.18 kB 🔴 +8.18 kB 🔴 +2.33 kB 🔴 +2.02 kB
assets/CloudSignupView-DqGkRrXv.js (removed) 8.18 kB 🟢 -8.18 kB 🟢 -2.33 kB 🟢 -2.02 kB
assets/CloudForgotPasswordView-BpXVMnPc.js (removed) 6.26 kB 🟢 -6.26 kB 🟢 -1.93 kB 🟢 -1.69 kB
assets/CloudForgotPasswordView-Cmpfqjp5.js (new) 6.26 kB 🔴 +6.26 kB 🔴 +1.93 kB 🔴 +1.69 kB
assets/UserSelectView-DTdXyyl8.js (new) 5.28 kB 🔴 +5.28 kB 🔴 +1.76 kB 🔴 +1.58 kB
assets/UserSelectView-uW60Fxkr.js (removed) 5.28 kB 🟢 -5.28 kB 🟢 -1.76 kB 🟢 -1.58 kB
assets/CloudSubscriptionRedirectView-DMYKN9Wj.js (removed) 5.27 kB 🟢 -5.27 kB 🟢 -1.73 kB 🟢 -1.54 kB
assets/CloudSubscriptionRedirectView-pptq5uKn.js (new) 5.27 kB 🔴 +5.27 kB 🔴 +1.73 kB 🔴 +1.54 kB
assets/CloudAuthTimeoutView-C2JqiG1E.js (new) 5.24 kB 🔴 +5.24 kB 🔴 +1.71 kB 🔴 +1.48 kB
assets/CloudAuthTimeoutView-DdeERRDa.js (removed) 5.24 kB 🟢 -5.24 kB 🟢 -1.7 kB 🟢 -1.49 kB
assets/CloudSorryContactSupportView-Ckn0CJgp.js 1.97 kB 1.97 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/layout-BnPgRWUn.js 500 B 500 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 9 added / 9 removed

Panels & Settings — 471 kB (baseline 471 kB) • ⚪ 0 B

Configuration panels, inspectors, and settings screens

File Before After Δ Raw Δ Gzip Δ Brotli
assets/WorkspacePanel-B94RbMEk.js (removed) 29.8 kB 🟢 -29.8 kB 🟢 -5.89 kB 🟢 -5.14 kB
assets/WorkspacePanel-DAh48rOQ.js (new) 29.8 kB 🔴 +29.8 kB 🔴 +5.89 kB 🔴 +5.14 kB
assets/LegacyCreditsPanel-B1twbdTs.js (removed) 23.8 kB 🟢 -23.8 kB 🟢 -5.94 kB 🟢 -5.22 kB
assets/LegacyCreditsPanel-BZp32DN7.js (new) 23.8 kB 🔴 +23.8 kB 🔴 +5.94 kB 🔴 +5.22 kB
assets/SubscriptionPanel-nPxZKTLi.js (removed) 21 kB 🟢 -21 kB 🟢 -5.04 kB 🟢 -4.45 kB
assets/SubscriptionPanel-xpssq9B5.js (new) 21 kB 🔴 +21 kB 🔴 +5.04 kB 🔴 +4.46 kB
assets/KeybindingPanel-BK5ifqmZ.js (removed) 14.3 kB 🟢 -14.3 kB 🟢 -3.77 kB 🟢 -3.35 kB
assets/KeybindingPanel-Dcqx1def.js (new) 14.3 kB 🔴 +14.3 kB 🔴 +3.77 kB 🔴 +3.35 kB
assets/AboutPanel-C5iLAKjW.js (new) 10.8 kB 🔴 +10.8 kB 🔴 +2.68 kB 🔴 +2.42 kB
assets/AboutPanel-DP70w3cp.js (removed) 10.8 kB 🟢 -10.8 kB 🟢 -2.68 kB 🟢 -2.42 kB
assets/ExtensionPanel-Bf8umkLp.js (new) 10.2 kB 🔴 +10.2 kB 🔴 +2.71 kB 🔴 +2.4 kB
assets/ExtensionPanel-D9bVmqYh.js (removed) 10.2 kB 🟢 -10.2 kB 🟢 -2.71 kB 🟢 -2.4 kB
assets/ServerConfigPanel-C6LaeXqL.js (removed) 7.23 kB 🟢 -7.23 kB 🟢 -2.17 kB 🟢 -1.94 kB
assets/ServerConfigPanel-DxmPmEiT.js (new) 7.23 kB 🔴 +7.23 kB 🔴 +2.17 kB 🔴 +1.94 kB
assets/UserPanel-CQJ5463e.js (new) 6.58 kB 🔴 +6.58 kB 🔴 +1.91 kB 🔴 +1.67 kB
assets/UserPanel-ON1IVxxR.js (removed) 6.58 kB 🟢 -6.58 kB 🟢 -1.91 kB 🟢 -1.67 kB
assets/refreshRemoteConfig-CgHyH33j.js (removed) 1.31 kB 🟢 -1.31 kB 🟢 -571 B 🟢 -496 B
assets/refreshRemoteConfig-raka8GpS.js (new) 1.31 kB 🔴 +1.31 kB 🔴 +570 B 🔴 +504 B
assets/config-C3FKkhIK.js (new) 1.15 kB 🔴 +1.15 kB 🔴 +604 B 🔴 +519 B
assets/config-C3FT_p6v.js (removed) 1.15 kB 🟢 -1.15 kB 🟢 -604 B 🟢 -531 B
assets/cloudRemoteConfig-BzeVDJpc.js (new) 1.11 kB 🔴 +1.11 kB 🔴 +511 B 🔴 +438 B
assets/cloudRemoteConfig-DpHl5Iab.js (removed) 1.11 kB 🟢 -1.11 kB 🟢 -509 B 🟢 -450 B
assets/refreshRemoteConfig-DcLy1Mhp.js (removed) 169 B 🟢 -169 B 🟢 -108 B 🟢 -106 B
assets/refreshRemoteConfig-hwcaf95R.js (new) 169 B 🔴 +169 B 🔴 +108 B 🔴 +106 B
assets/remoteConfig-B0mlVvm7.js 788 B 788 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings--kdIt6Ri.js 30.4 kB 30.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-Bz57yvlp.js 25.8 kB 25.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CDJne0Sg.js 31.2 kB 31.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CmfKjjkA.js 26.4 kB 26.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-crWL6KAZ.js 39.4 kB 39.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-CYbRky-T.js 29.4 kB 29.4 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-D_kNbI7_.js 35.2 kB 35.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-Dn1HqM1j.js 32.9 kB 32.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-EPgYkg8b.js 29.6 kB 29.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-ShWh746R.js 32 kB 32 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/settings-slBzDG7F.js 30.2 kB 30.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 12 added / 12 removed

User & Accounts — 3.94 kB (baseline 3.94 kB) • ⚪ 0 B

Authentication, profile, and account management bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/auth-BLqx0ipS.js (new) 3.54 kB 🔴 +3.54 kB 🔴 +1.24 kB 🔴 +1.07 kB
assets/auth-C-ffnsbd.js (removed) 3.54 kB 🟢 -3.54 kB 🟢 -1.24 kB 🟢 -1.07 kB
assets/firebaseAuthStore-_RF9WUXq.js (removed) 217 B 🟢 -217 B 🟢 -136 B 🟢 -119 B
assets/firebaseAuthStore-BEfpaAAj.js (new) 217 B 🔴 +217 B 🔴 +136 B 🔴 +118 B
assets/auth-BzjqVA8-.js (removed) 178 B 🟢 -178 B 🟢 -140 B 🟢 -128 B
assets/auth-CbFpcsZh.js (new) 178 B 🔴 +178 B 🔴 +141 B 🔴 +132 B

Status: 3 added / 3 removed

Editors & Dialogs — 2.89 kB (baseline 2.89 kB) • ⚪ 0 B

Modals, dialogs, drawers, and in-app editors

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useSubscriptionDialog-C_5uAmda.js (new) 2.71 kB 🔴 +2.71 kB 🔴 +1.29 kB 🔴 +1.14 kB
assets/useSubscriptionDialog-DkEb81cQ.js (removed) 2.71 kB 🟢 -2.71 kB 🟢 -1.29 kB 🟢 -1.14 kB
assets/useSubscriptionDialog-B7c_IVhM.js (removed) 179 B 🟢 -179 B 🟢 -110 B 🟢 -101 B
assets/useSubscriptionDialog-CAvBf1iy.js (new) 179 B 🔴 +179 B 🔴 +110 B 🔴 +100 B

Status: 2 added / 2 removed

UI Components — 33.7 kB (baseline 33.7 kB) • ⚪ 0 B

Reusable component library chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/ComfyQueueButton-C4dPwtEx.js (new) 9.52 kB 🔴 +9.52 kB 🔴 +2.69 kB 🔴 +2.41 kB
assets/ComfyQueueButton-smNgTd-U.js (removed) 9.52 kB 🟢 -9.52 kB 🟢 -2.69 kB 🟢 -2.41 kB
assets/SubscribeButton-CKW07m6u.js (removed) 4.63 kB 🟢 -4.63 kB 🟢 -1.57 kB 🟢 -1.39 kB
assets/SubscribeButton-ii1bfk0h.js (new) 4.63 kB 🔴 +4.63 kB 🔴 +1.57 kB 🔴 +1.39 kB
assets/CloudBadge-CWMuZNt-.js (new) 1.85 kB 🔴 +1.85 kB 🔴 +719 B 🔴 +643 B
assets/CloudBadge-WASw0ss4.js (removed) 1.85 kB 🟢 -1.85 kB 🟢 -717 B 🟢 -642 B
assets/cloudFeedbackTopbarButton-Bj45HgDg.js (new) 1.24 kB 🔴 +1.24 kB 🔴 +676 B 🔴 +572 B
assets/cloudFeedbackTopbarButton-el6HtuOh.js (removed) 1.24 kB 🟢 -1.24 kB 🟢 -674 B 🟢 -572 B
assets/ComfyQueueButton-CaHPgde3.js (new) 181 B 🔴 +181 B 🔴 +118 B 🔴 +120 B
assets/ComfyQueueButton-CBPnd6Gw.js (removed) 181 B 🟢 -181 B 🟢 -118 B 🟢 -107 B
assets/Button-DbRyW27H.js 3.82 kB 3.82 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/TopbarBadge-Cob4Egm4.js 8.36 kB 8.36 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/UserAvatar-D80lITos.js 1.73 kB 1.73 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetButton-CfA1JDV_.js 2.41 kB 2.41 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 5 added / 5 removed

Data & Services — 2.71 MB (baseline 2.71 MB) • 🔴 +976 B

Stores, services, APIs, and repositories

File Before After Δ Raw Δ Gzip Δ Brotli
assets/dialogService-CvsVhZC0.js (new) 2.01 MB 🔴 +2.01 MB 🔴 +425 kB 🔴 +324 kB
assets/dialogService-CHsxM5k7.js (removed) 2.01 MB 🟢 -2.01 MB 🟢 -425 kB 🟢 -324 kB
assets/api-CFS9PUas.js (new) 675 kB 🔴 +675 kB 🔴 +149 kB 🔴 +118 kB
assets/api-DhlIks9k.js (removed) 675 kB 🟢 -675 kB 🟢 -149 kB 🟢 -119 kB
assets/releaseStore-BijHSKKG.js (removed) 8.91 kB 🟢 -8.91 kB 🟢 -2.4 kB 🟢 -2.12 kB
assets/releaseStore-DQ8X6mtX.js (new) 8.91 kB 🔴 +8.91 kB 🔴 +2.4 kB 🔴 +2.12 kB
assets/keybindingService-CxCVsF2-.js (removed) 6.74 kB 🟢 -6.74 kB 🟢 -1.76 kB 🟢 -1.53 kB
assets/keybindingService-fkiAXewL.js (new) 6.74 kB 🔴 +6.74 kB 🔴 +1.76 kB 🔴 +1.53 kB
assets/bootstrapStore-DNZfEzua.js (removed) 2.69 kB 🟢 -2.69 kB 🟢 -1.03 kB 🟢 -958 B
assets/bootstrapStore-Oiix1e0b.js (new) 2.69 kB 🔴 +2.69 kB 🔴 +1.03 kB 🔴 +969 B
assets/userStore-Be9IYItI.js (new) 2.16 kB 🔴 +2.16 kB 🔴 +810 B 🔴 +725 B
assets/userStore-ViL0RYhl.js (removed) 2.16 kB 🟢 -2.16 kB 🟢 -810 B 🟢 -724 B
assets/audioService-BWGC0NYp.js (removed) 2.03 kB 🟢 -2.03 kB 🟢 -928 B 🟢 -814 B
assets/audioService-DedouwPN.js (new) 2.03 kB 🔴 +2.03 kB 🔴 +927 B 🔴 +815 B
assets/releaseStore-De6OZO0L.js (new) 140 B 🔴 +140 B 🔴 +106 B 🔴 +108 B
assets/releaseStore-De9psQNm.js (removed) 140 B 🟢 -140 B 🟢 -106 B 🟢 -107 B
assets/serverConfigStore-B4PsmGgu.js 2.64 kB 2.64 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 8 added / 8 removed

Utilities & Hooks — 25.3 kB (baseline 25.3 kB) • ⚪ 0 B

Helpers, composables, and utility bundles

File Before After Δ Raw Δ Gzip Δ Brotli
assets/useErrorHandling-D_KDDzZI.js (new) 5.21 kB 🔴 +5.21 kB 🔴 +1.54 kB 🔴 +1.34 kB
assets/useErrorHandling-POIDvAvH.js (removed) 5.21 kB 🟢 -5.21 kB 🟢 -1.54 kB 🟢 -1.34 kB
assets/useWorkspaceUI-BEltmjim.js (removed) 3.42 kB 🟢 -3.42 kB 🟢 -974 B 🟢 -835 B
assets/useWorkspaceUI-BjMTYeb1.js (new) 3.42 kB 🔴 +3.42 kB 🔴 +975 B 🔴 +844 B
assets/useSubscriptionActions-C_C7mY7U.js (removed) 2.22 kB 🟢 -2.22 kB 🟢 -870 B 🟢 -763 B
assets/useSubscriptionActions-g351hhUS.js (new) 2.22 kB 🔴 +2.22 kB 🔴 +870 B 🔴 +764 B
assets/subscriptionCheckoutUtil-CQmCT0m6.js (new) 2.03 kB 🔴 +2.03 kB 🔴 +873 B 🔴 +770 B
assets/subscriptionCheckoutUtil-ocQWXcoB.js (removed) 2.03 kB 🟢 -2.03 kB 🟢 -871 B 🟢 -768 B
assets/useSubscriptionCredits-BEYhyujV.js (new) 1.39 kB 🔴 +1.39 kB 🔴 +598 B 🔴 +527 B
assets/useSubscriptionCredits-DaYMaP9E.js (removed) 1.39 kB 🟢 -1.39 kB 🟢 -599 B 🟢 -525 B
assets/audioUtils-BWZTzW0b.js (new) 970 B 🔴 +970 B 🔴 +548 B 🔴 +459 B
assets/audioUtils-HZ_Y9Cud.js (removed) 970 B 🟢 -970 B 🟢 -549 B 🟢 -483 B
assets/useCurrentUser-Crwm2sO9.js (new) 145 B 🔴 +145 B 🔴 +114 B 🔴 +107 B
assets/useCurrentUser-CrzQ98mS.js (removed) 145 B 🟢 -145 B 🟢 -114 B 🟢 -104 B
assets/_plugin-vue_export-helper-DuK_Fly3.js 467 B 467 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/colorUtil-DfMUHmsF.js 7.2 kB 7.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/markdownRendererUtil-DM9z_tTX.js 1.78 kB 1.78 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/tailwindUtil-BWBAZ7f9.js 488 B 488 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 7 added / 7 removed

Vendor & Third-Party — 10.7 MB (baseline 10.7 MB) • ⚪ 0 B

External libraries and shared vendor chunks

File Before After Δ Raw Δ Gzip Δ Brotli
assets/vendor-chart-DHGfk3hn.js 408 kB 408 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-other-B3TsI6ya.js 4.1 MB 4.1 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-primevue-4Jj8eU28.js 3.04 MB 3.04 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-reka-ui-aCG649nF.js 263 kB 263 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-three-CERwhPwK.js 1.83 MB 1.83 MB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-tiptap-BxrEVL6s.js 650 kB 650 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-vue-Dwii0E-t.js 13.6 kB 13.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/vendor-xterm-IX6P8SWv.js 398 kB 398 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
Other — 7.12 MB (baseline 7.12 MB) • 🔴 +73 B

Bundles that do not match a named category

File Before After Δ Raw Δ Gzip Δ Brotli
assets/i18n-DC0FK4TL.js (new) 501 kB 🔴 +501 kB 🔴 +96.7 kB 🔴 +72 kB
assets/i18n-C5cFroQV.js (removed) 501 kB 🟢 -501 kB 🟢 -96.7 kB 🟢 -72 kB
assets/core-BlDAFxRw.js (new) 97.8 kB 🔴 +97.8 kB 🔴 +23.4 kB 🔴 +20.1 kB
assets/core-E85XJMZI.js (removed) 97.8 kB 🟢 -97.8 kB 🟢 -23.4 kB 🟢 -20.1 kB
assets/groupNode-9EpIMpoJ.js (new) 74.7 kB 🔴 +74.7 kB 🔴 +18.1 kB 🔴 +15.9 kB
assets/groupNode-BhZCiM2M.js (removed) 74.7 kB 🟢 -74.7 kB 🟢 -18.1 kB 🟢 -15.9 kB
assets/WidgetSelect-D48wbJUv.js (new) 52.2 kB 🔴 +52.2 kB 🔴 +11.5 kB 🔴 +10 kB
assets/WidgetSelect-DWWr0r4C.js (removed) 52.2 kB 🟢 -52.2 kB 🟢 -11.5 kB 🟢 -10 kB
assets/Load3DControls-CHan40q1.js (removed) 35.9 kB 🟢 -35.9 kB 🟢 -5.87 kB 🟢 -5.09 kB
assets/Load3DControls-DLZ46O7u.js (new) 35.9 kB 🔴 +35.9 kB 🔴 +5.87 kB 🔴 +5.08 kB
assets/SubscriptionRequiredDialogContent-BYI0syd1.js (new) 28.7 kB 🔴 +28.7 kB 🔴 +6.79 kB 🔴 +5.92 kB
assets/SubscriptionRequiredDialogContent-OFm2J5KW.js (removed) 28.7 kB 🟢 -28.7 kB 🟢 -6.79 kB 🟢 -5.91 kB
assets/CurrentUserPopoverWorkspace-CL2i_ia8.js (new) 22.2 kB 🔴 +22.2 kB 🔴 +4.99 kB 🔴 +4.43 kB
assets/CurrentUserPopoverWorkspace-Hk46O7G8.js (removed) 22.2 kB 🟢 -22.2 kB 🟢 -4.99 kB 🟢 -4.42 kB
assets/Load3D-BcIbq9J7.js (new) 19.2 kB 🔴 +19.2 kB 🔴 +4.38 kB 🔴 +3.85 kB
assets/Load3D-juqWp5Gj.js (removed) 19.2 kB 🟢 -19.2 kB 🟢 -4.38 kB 🟢 -3.84 kB
assets/WidgetInputNumber-cinVFKu3.js (removed) 18.3 kB 🟢 -18.3 kB 🟢 -4.52 kB 🟢 -4.02 kB
assets/WidgetInputNumber-wXT8k5rJ.js (new) 18.3 kB 🔴 +18.3 kB 🔴 +4.52 kB 🔴 +4.02 kB
assets/WidgetRecordAudio-Bn8tA5ac.js (removed) 18.3 kB 🟢 -18.3 kB 🟢 -4.97 kB 🟢 -4.44 kB
assets/WidgetRecordAudio-CDtj8pHb.js (new) 18.3 kB 🔴 +18.3 kB 🔴 +4.97 kB 🔴 +4.44 kB
assets/SubscriptionPanelContentWorkspace-5UOt30jv.js (removed) 18.2 kB 🟢 -18.2 kB 🟢 -4.47 kB 🟢 -3.9 kB
assets/SubscriptionPanelContentWorkspace-Cl4AOLOi.js (new) 18.2 kB 🔴 +18.2 kB 🔴 +4.47 kB 🔴 +3.9 kB
assets/WidgetImageCrop-BdnRP3kN.js (new) 17.1 kB 🔴 +17.1 kB 🔴 +4.14 kB 🔴 +3.63 kB
assets/WidgetImageCrop-CBiHXCsA.js (removed) 17.1 kB 🟢 -17.1 kB 🟢 -4.14 kB 🟢 -3.63 kB
assets/PanelTemplate-B8Sd03kt.js (removed) 16.2 kB 🟢 -16.2 kB 🟢 -5.45 kB 🟢 -4.8 kB
assets/PanelTemplate-QMK17And.js (new) 16.2 kB 🔴 +16.2 kB 🔴 +5.46 kB 🔴 +4.8 kB
assets/AudioPreviewPlayer-6VQuJTRB.js (new) 10.8 kB 🔴 +10.8 kB 🔴 +2.97 kB 🔴 +2.66 kB
assets/AudioPreviewPlayer-RLzsG_d4.js (removed) 10.8 kB 🟢 -10.8 kB 🟢 -2.97 kB 🟢 -2.66 kB
assets/nodeTemplates-0qJcH_x6.js (removed) 9.45 kB 🟢 -9.45 kB 🟢 -3.16 kB 🟢 -2.8 kB
assets/nodeTemplates-szw2fqO8.js (new) 9.45 kB 🔴 +9.45 kB 🔴 +3.16 kB 🔴 +2.79 kB
assets/InviteMemberDialogContent-BBU2m9qT.js (new) 8.36 kB 🔴 +8.36 kB 🔴 +2.5 kB 🔴 +2.17 kB
assets/InviteMemberDialogContent-DAzWE9xc.js (removed) 8.36 kB 🟢 -8.36 kB 🟢 -2.51 kB 🟢 -2.17 kB
assets/WidgetWithControl-CszkMXbN.js (removed) 8.07 kB 🟢 -8.07 kB 🟢 -2.68 kB 🟢 -2.42 kB
assets/WidgetWithControl-DFAU20ab.js (new) 8.07 kB 🔴 +8.07 kB 🔴 +2.68 kB 🔴 +2.41 kB
assets/CreateWorkspaceDialogContent-C_jPPPr2.js (new) 5.93 kB 🔴 +5.93 kB 🔴 +1.92 kB 🔴 +1.68 kB
assets/CreateWorkspaceDialogContent-CK7EQ8RS.js (removed) 5.93 kB 🟢 -5.93 kB 🟢 -1.93 kB 🟢 -1.68 kB
assets/EditWorkspaceDialogContent-BhExkCSt.js (removed) 5.7 kB 🟢 -5.7 kB 🟢 -1.88 kB 🟢 -1.64 kB
assets/EditWorkspaceDialogContent-wycGGwFh.js (new) 5.7 kB 🔴 +5.7 kB 🔴 +1.88 kB 🔴 +1.64 kB
assets/ValueControlPopover-B6AnNPZW.js (new) 5.17 kB 🔴 +5.17 kB 🔴 +1.69 kB 🔴 +1.5 kB
assets/ValueControlPopover-BlTgv6Qg.js (removed) 5.17 kB 🟢 -5.17 kB 🟢 -1.69 kB 🟢 -1.5 kB
assets/DeleteWorkspaceDialogContent-aLwDphZ7.js (removed) 4.59 kB 🟢 -4.59 kB 🟢 -1.56 kB 🟢 -1.35 kB
assets/DeleteWorkspaceDialogContent-Rqss9XTU.js (new) 4.59 kB 🔴 +4.59 kB 🔴 +1.56 kB 🔴 +1.35 kB
assets/LeaveWorkspaceDialogContent-Co2VJ0Mb.js (removed) 4.41 kB 🟢 -4.41 kB 🟢 -1.5 kB 🟢 -1.31 kB
assets/LeaveWorkspaceDialogContent-DkRwwAVD.js (new) 4.41 kB 🔴 +4.41 kB 🔴 +1.5 kB 🔴 +1.31 kB
assets/RemoveMemberDialogContent-BRBjgCZ4.js (new) 4.38 kB 🔴 +4.38 kB 🔴 +1.45 kB 🔴 +1.27 kB
assets/RemoveMemberDialogContent-Cxr_Y70S.js (removed) 4.38 kB 🟢 -4.38 kB 🟢 -1.45 kB 🟢 -1.27 kB
assets/RevokeInviteDialogContent-CPC0RZ1V.js (removed) 4.29 kB 🟢 -4.29 kB 🟢 -1.47 kB 🟢 -1.29 kB
assets/RevokeInviteDialogContent-D4aa7j03.js (new) 4.29 kB 🔴 +4.29 kB 🔴 +1.47 kB 🔴 +1.29 kB
assets/GlobalToast-78qyVR4N.js (new) 3.05 kB 🔴 +3.05 kB 🔴 +1.1 kB 🔴 +940 B
assets/GlobalToast-Ct23BpX3.js (removed) 3.05 kB 🟢 -3.05 kB 🟢 -1.1 kB 🟢 -944 B
assets/SubscribeToRun-BxeyGYf7.js (new) 2.96 kB 🔴 +2.96 kB 🔴 +1.16 kB 🔴 +1.02 kB
assets/SubscribeToRun-YFHZZiCl.js (removed) 2.96 kB 🟢 -2.96 kB 🟢 -1.16 kB 🟢 -1.02 kB
assets/cloudSessionCookie-B0QSBxf2.js (removed) 2.94 kB 🟢 -2.94 kB 🟢 -936 B 🟢 -807 B
assets/cloudSessionCookie-D-KlTyuC.js (new) 2.94 kB 🔴 +2.94 kB 🔴 +934 B 🔴 +810 B
assets/BaseViewTemplate-B39YS7YG.js (removed) 2.42 kB 🟢 -2.42 kB 🟢 -1.05 kB 🟢 -945 B
assets/BaseViewTemplate-CLMmFit9.js (new) 2.42 kB 🔴 +2.42 kB 🔴 +1.04 kB 🔴 +943 B
assets/CloudRunButtonWrapper-D74YAw6b.js (removed) 1.79 kB 🟢 -1.79 kB 🟢 -646 B 🟢 -562 B
assets/CloudRunButtonWrapper-ltiSZ2t6.js (new) 1.79 kB 🔴 +1.79 kB 🔴 +644 B 🔴 +596 B
assets/cloudBadges-CrN1Vrz6.js (new) 1.08 kB 🔴 +1.08 kB 🔴 +537 B 🔴 +480 B
assets/cloudBadges-pUt7sb4r.js (removed) 1.08 kB 🟢 -1.08 kB 🟢 -533 B 🟢 -476 B
assets/graphHasMissingNodes-BNJdZHvx.js (new) 1.06 kB 🔴 +1.06 kB 🔴 +463 B 🔴 +409 B
assets/graphHasMissingNodes-D_SZ3HBl.js (removed) 1.06 kB 🟢 -1.06 kB 🟢 -462 B 🟢 -421 B
assets/cloudSubscription-B35BzChY.js (removed) 976 B 🟢 -976 B 🟢 -468 B 🟢 -401 B
assets/cloudSubscription-Cfsw38Nb.js (new) 976 B 🔴 +976 B 🔴 +465 B 🔴 +402 B
assets/nightlyBadges-Bgt62z0o.js (removed) 595 B 🟢 -595 B 🟢 -356 B 🟢 -309 B
assets/nightlyBadges-DrERhCjE.js (new) 595 B 🔴 +595 B 🔴 +355 B 🔴 +308 B
assets/SubscriptionPanelContentWorkspace-0LSO1sX-.js (new) 266 B 🔴 +266 B 🔴 +136 B 🔴 +127 B
assets/SubscriptionPanelContentWorkspace-DfY4JJCA.js (removed) 266 B 🟢 -266 B 🟢 -136 B 🟢 -128 B
assets/i18n-C3IdN_fW.js (new) 188 B 🔴 +188 B 🔴 +152 B 🔴 +127 B
assets/i18n-DxfmwtyY.js (removed) 188 B 🟢 -188 B 🟢 -151 B 🟢 -129 B
assets/WidgetInputNumber-Ca96ks3_.js (removed) 186 B 🟢 -186 B 🟢 -119 B 🟢 -117 B
assets/WidgetInputNumber-COfTBLTH.js (new) 186 B 🔴 +186 B 🔴 +119 B 🔴 +121 B
assets/WidgetLegacy-BviiqWWp.js (removed) 164 B 🟢 -164 B 🟢 -125 B 🟢 -109 B
assets/WidgetLegacy-Dd-amktM.js (new) 164 B 🔴 +164 B 🔴 +125 B 🔴 +111 B
assets/Load3D-RQkUG_OU.js (new) 131 B 🔴 +131 B 🔴 +107 B 🔴 +106 B
assets/Load3D-sox763KC.js (removed) 131 B 🟢 -131 B 🟢 -107 B 🟢 -109 B
assets/auto-DWs2ctGL.js 1.73 kB 1.73 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-2Ummrt4M.js 18.8 kB 18.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-8WuluAqM.js 19.3 kB 19.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BViLP6Ia.js 17.8 kB 17.8 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-BWPBsR-j.js 20.6 kB 20.6 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-ByXor5xN.js 18 kB 18 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-C5-8fNtq.js 17.9 kB 17.9 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CTC-eRiE.js 18.5 kB 18.5 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-CwopaVr4.js 17.2 kB 17.2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-gY5a0Gsv.js 18 kB 18 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-mFAeWi-p.js 19.3 kB 19.3 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/commands-tMuFl0J5.js 17 kB 17 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/LazyImage-CEFt1pNt.js 14.1 kB 14.1 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BbU3jvmz.js 113 kB 113 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BNS3riuS.js 131 kB 131 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-BrtCV7Bk.js 151 kB 151 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-C4U1m7i3.js 126 kB 126 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-Ch4KooEl.js 145 kB 145 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DfTcOVNP.js 113 kB 113 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DyJ_W2qZ.js 175 kB 175 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-DyOi1LHY.js 133 kB 133 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-SUJPWsXI.js 156 kB 156 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-w5Cua0MA.js 127 kB 127 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/main-wwqSj12G.js 129 kB 129 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Media3DTop-DGffIyse.js 2.38 kB 2.38 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaAudioTop-ISx56tjc.js 2 kB 2 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaImageTop-BwZR_RlC.js 2.34 kB 2.34 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/MediaVideoTop-CQptuwWY.js 2.82 kB 2.82 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/mixpanel.module-DLR992B1.js 143 B 143 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BAXY47oa.js 418 kB 418 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BeUwYCWI.js 378 kB 378 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BIg3fLCY.js 417 kB 417 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BIq1C8FK.js 387 kB 387 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-Bj0ivJ27.js 346 kB 346 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BnbbHFi8.js 374 kB 374 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-BoHz7Ee8.js 454 kB 454 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-C2En48mu.js 374 kB 374 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-CO7SpDOn.js 367 kB 367 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-DcIT7mAs.js 371 kB 371 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/nodeDefs-DjHtovWB.js 343 kB 343 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/OBJLoader2WorkerModule-DTMpvldF.js 109 kB 109 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/previousFullPath-DZ4Ggh4M.js 838 B 838 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/rolldown-runtime-cVp-94Rc.js 1.96 kB 1.96 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/Slider-C87scEAV.js 4.21 kB 4.21 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widget-BJiJuR5i.js 518 B 518 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetBoundingBox-CUtab2CB.js 4.71 kB 4.71 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetBoundingBox-D79nBMxa.js 186 B 186 B ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetChart-dhHvUOFA.js 2.79 kB 2.79 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetColorPicker-Zaz1Nr7i.js 3.71 kB 3.71 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetGalleria-BqahYEoy.js 4.57 kB 4.57 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetImageCompare-D9rnJ7Ml.js 3.79 kB 3.79 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetInputText-C8mogiaC.js 2.58 kB 2.58 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetLayoutField-Boxd1MvX.js 2.7 kB 2.7 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetMarkdown-34YdaCsh.js 3.49 kB 3.49 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetPropFilter-C63n39Js.js 1.31 kB 1.31 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetTextarea-DZ6NZx0W.js 3.87 kB 3.87 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/WidgetToggleSwitch-CCjTCwYf.js 3.26 kB 3.26 kB ⚪ 0 B ⚪ 0 B ⚪ 0 B
assets/widgetTypes-KPj-zM0O.js 573 B 573 B ⚪ 0 B ⚪ 0 B ⚪ 0 B

Status: 38 added / 38 removed

@christian-byrne christian-byrne marked this pull request as ready for review January 28, 2026 08:41
@dosubot dosubot bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jan 28, 2026
Copy link
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.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@src/components/templates/thumbnails/LogoOverlay.test.ts`:
- Around line 41-88: Update the tests in LogoOverlay.test.ts to avoid asserting
Tailwind classes and inline styles: instead of checking container.classes() or
img.classes() and container.attributes('style'), assert semantic attributes or
behavior (e.g., check for data-position, data-size, data-opacity or the rendered
alt/src and any layout/interaction effects). Specifically, modify the
mountOverlay usage and subsequent assertions (the tests that call mountOverlay
and query wrapper.find('div') and wrapper.find('img')) to expect data-position,
data-size, and data-opacity attributes (or other behavior-driven outputs)
produced by the LogoOverlay component; if those attributes don't exist, add them
in the LogoOverlay implementation so tests can assert stable, semantic
attributes rather than Tailwind classes or inline style strings.

In `@src/components/templates/thumbnails/LogoOverlay.vue`:
- Around line 11-23: Update LogoOverlay.vue to respect the LogoInfo contract by
using logo.size to set the img dimensions, honoring logo.opacity with default 1,
and defaulting the overlay position to top-left when logo.position is missing:
bind the image size via :style or explicit width/height using logo.size
(fallback to the component/test default), keep :style="{ opacity: logo.opacity
?? 1 }" for opacity, and ensure the container CSS classes reflect top-left
alignment unless logo.position specifies another value; adjust any uses of
onImageError and the container class string accordingly so size, opacity, and
position are applied consistently (also apply the same fixes in the other block
referenced at lines 37-57).
- Around line 3-4: Replace the unstable index key on the v-for in
LogoOverlay.vue (v-for="(logo, index) in validLogos") with a stable identifier
from each logo object—e.g. use :key="logo.provider" or :key="logo.id" (prefer an
immutable unique id if available); update any code that constructs validLogos to
guarantee the chosen field exists and is unique so Vue can track logo items
reliably instead of reusing DOM by index.

In `@src/platform/workflow/templates/repositories/workflowTemplatesStore.ts`:
- Around line 506-520: The logo index may contain untrusted paths; update
fetchLogoIndex/getLogoUrl to validate entries from logoIndex (the
logoIndex.value lookup used by getLogoUrl) before composing a file URL: ensure
the resolved logoPath is a simple relative filename or allowed subpath (reject
any segments containing ".." or leading "/" ), and enforce an allowed filename
pattern/extension (e.g., only png|svg|jpg|jpeg and safe characters) or a
whitelist of expected prefixes; if validation fails, return an empty string (or
skip the entry) instead of calling api.fileURL. Use the existing functions
fetchLogoIndex and getLogoUrl and the logoIndex variable to locate and apply
this validation.

Comment on lines +11 to +23
class="flex items-center gap-1.5 rounded-full bg-black/20 px-2 py-1"
:style="{ opacity: logo.opacity ?? 1 }"
>
<img
:src="logo.url"
:alt="logo.provider"
class="h-5 w-5 rounded-[50%]"
draggable="false"
@error="onImageError(logo.provider)"
/>
<span class="text-sm font-medium text-white">
{{ logo.provider }}
</span>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Honor size/opacity defaults and align default position.

size is currently ignored, default opacity is 1, and the default position is top-left; this diverges from the LogoInfo contract/tests and will break expected rendering.

🛠️ Proposed fix
 const {
   logos,
   getLogoUrl,
-  defaultPosition = 'top-2 left-2'
+  defaultPosition = 'bottom-2 right-2'
 } = defineProps<{
   logos: LogoInfo[]
   getLogoUrl: (provider: string) => string
   defaultPosition?: string
 }>()
 
+function getLogoSizeClass(size?: 'sm' | 'md' | 'lg') {
+  switch (size) {
+    case 'sm':
+      return 'h-6 w-6'
+    case 'lg':
+      return 'h-12 w-12'
+    default:
+      return 'h-8 w-8'
+  }
+}
+
 const failedLogos = ref(new Set<string>())
-      :style="{ opacity: logo.opacity ?? 1 }"
+      :style="{ opacity: logo.opacity ?? 0.9 }"
-        class="h-5 w-5 rounded-[50%]"
+        :class="cn('rounded-full', getLogoSizeClass(logo.size))"

Also applies to: 37-57

🤖 Prompt for AI Agents
In `@src/components/templates/thumbnails/LogoOverlay.vue` around lines 11 - 23,
Update LogoOverlay.vue to respect the LogoInfo contract by using logo.size to
set the img dimensions, honoring logo.opacity with default 1, and defaulting the
overlay position to top-left when logo.position is missing: bind the image size
via :style or explicit width/height using logo.size (fallback to the
component/test default), keep :style="{ opacity: logo.opacity ?? 1 }" for
opacity, and ensure the container CSS classes reflect top-left alignment unless
logo.position specifies another value; adjust any uses of onImageError and the
container class string accordingly so size, opacity, and position are applied
consistently (also apply the same fixes in the other block referenced at lines
37-57).

Subagent 5 and others added 3 commits January 28, 2026 21:43
Replace unstable index-based key with logo.provider for reliable
DOM tracking when logo order changes.

Amp-Thread-ID: https://ampcode.com/threads/T-019c083e-8ba0-7699-a5ff-63fd03e24391
Co-authored-by: Amp <amp@ampcode.com>
Guard against path traversal and unexpected file types by
validating logo paths start with 'logo/', have allowed image
extensions, and contain no '..' or leading '/' segments.

Amp-Thread-ID: https://ampcode.com/threads/T-019c083e-8ba0-7699-a5ff-63fd03e24391
Co-authored-by: Amp <amp@ampcode.com>
Remove tests that assert Tailwind utility classes and inline styles.
Focus on semantic attributes (src, alt, draggable) and behavioral
outputs (filtering, rendering counts) per testing guidelines.

Amp-Thread-ID: https://ampcode.com/threads/T-019c083e-8ba0-7699-a5ff-63fd03e24391
Co-authored-by: Amp <amp@ampcode.com>
@coderabbitai coderabbitai bot requested a review from Yorha4D January 29, 2026 05:46
Copy link
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.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/components/templates/thumbnails/LogoOverlay.test.ts`:
- Line 8: Replace the helper function expression mockGetLogoUrl with a function
declaration; locate the constant mockGetLogoUrl in LogoOverlay.test (the pure
helper used to return `/logos/${provider}.png`) and refactor it to a named
function declaration (function mockGetLogoUrl(provider: string) { ... }) so it
follows the repository guideline preferring declarations for pure helpers.
- Around line 65-72: The test currently couples to Tailwind by using the CSS
selector '[class*="absolute"]'; change it to assert structural/behavioral output
instead: update the test using mountOverlay to query by a stable marker (e.g.,
data-testid or the logo child component) and assert the count/unique keys, for
example use wrapper.findAll('[data-testid="logo-container"]') or
wrapper.findAllComponents(LogoComponent) and expect length 2, and/or verify that
each rendered item's key/prop contains the provider value (check vnode.props.key
or props.provider) instead of relying on the "absolute" class.

@comfyui-wiki
Copy link
Member

Seems the size currently isn't working, but I think we might not need size, since it's always fixed.

image

logo size

image

Style updates:

<div class="pointer-events-none absolute z-10 top-2 right-2">
<div 
- class="flex items-center gap-1.5 rounded-full bg-black/20 px-2 py-1"
+ class="flex items-center gap-1.5 rounded-full bg-black/20 pr-2"
"
 style="opacity: 0.85;">
<img src="/templates/logo/stability.png" alt="Stability" 
-  class="h-5 w-5  rounded-[50%]" 
+ class="h-6 w-6  rounded-[50%]" 
 rounded-[50%]" 
 draggable="false"><span class="text-sm font-medium text-white">Stability</span></div></div>

Multiple logos support

The status of multiple providers does not seem very good.
image

So I'm wondering if it's possible to change it to like this

logos: 
{
"label": "WaveSpeed & Hunyuan",
"gap": "5px" # optional, should support  negative numbers as well
"position": "" # Optional, maybe we should remove it to unify all logo overlays` position
"provider": ["wavespeed", "hunyuan"]
}
image
  • Each logo has a unified 2px border width
  • Use the gap to control the space

Not sure if we need to support the border setting. When there are multiple logos, a border makes it easier to distinguish them. Need advice here
image

Myestery
Myestery previously approved these changes Jan 29, 2026
Copy link
Contributor

@Myestery Myestery left a comment

Choose a reason for hiding this comment

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

Valid suggestions from rabbit around the size but I guess there's no need for it at the moment

- Update LogoInfo to accept provider as string | string[] for stacked logos
- Add label and gap fields for custom text and overlap control
- Redesign LogoOverlay with overlapping circular logos (white border, -6px gap)
- Apply style updates: h-6 w-6 size, pr-2 padding, 0.85 default opacity
- Add path validation in getLogoUrl to prevent directory traversal
- Expand tests for stacked logos, custom labels, and styling

Amp-Thread-ID: https://ampcode.com/threads/T-019c0ca3-c517-7310-9b34-6d21a20ca7e2
Co-authored-by: Amp <amp@ampcode.com>
Copy link
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.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/components/templates/thumbnails/LogoOverlay.test.ts`:
- Around line 128-146: Tests in LogoOverlay.test.ts are asserting Tailwind
utility classes (selectors '.rounded-full' and classes
'border-2'/'border-white') which couples tests to styling; update tests (which
use mountOverlay) to assert behavior/semantics instead: add semantic data
attributes in the component (e.g., data-testid="logo-pill" on the pill and
data-testid="logo-img" on the image) or expose a prop-driven flag, then change
the tests to find by those attributes (e.g.,
wrapper.find('[data-testid="logo-pill"]') and
wrapper.find('[data-testid="logo-img"]') ) and assert on relevant
attributes/inline style values (opacity via attributes('style') or presence of a
visible border via computed style string) instead of checking Tailwind class
names '.rounded-full', 'border-2', or 'border-white'; keep mountOverlay
unchanged except for rendering these data attributes.

In `@src/platform/workflow/templates/repositories/workflowTemplatesStore.ts`:
- Around line 507-517: The fetchLogoIndex function returns response.data without
validating its shape; update axios.get to use a typed response (e.g.,
axios.get<LogoIndex>) and add runtime validation of the returned payload before
returning (use an existing schema validator or add a lightweight guard that
checks required keys/types for LogoIndex) so malformed JSON is rejected and {}
is returned or an error is handled; reference fetchLogoIndex, axios.get,
LogoIndex and the content-type check to locate where to add the typed generic
and validator.

- Add data-testid attributes (logo-pill, logo-img) to decouple tests from styling
- Add typed axios.get<LogoIndex> and runtime validation for fetchLogoIndex

Amp-Thread-ID: https://ampcode.com/threads/T-019c1215-0fc3-752a-aa20-514c5c4804aa
Co-authored-by: Amp <amp@ampcode.com>
Copy link
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.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/components/templates/thumbnails/LogoOverlay.test.ts`:
- Around line 7-147: Add tests exercising the onImageError/hasAllFailed logic in
LogoOverlay: use the existing mountOverlay helper to mount LogoOverlay, trigger
an 'error' event on img elements to simulate failed loads, and assert the pill
(data-testid="logo-pill") visibility (isVisible or v-show) — one test where all
provider images error and the pill becomes hidden, and one test where only some
stacked provider images error and the pill remains visible; reference the
onImageError/hasAllFailed behavior in LogoOverlay and the mountOverlay helper to
locate where to add these new specs.

In `@src/components/templates/thumbnails/LogoOverlay.vue`:
- Around line 14-16: Replace the inline style marginLeft: '2px' on the div with
the Tailwind spacing class by removing :style and adding ml-0.5 to the existing
class list on the div with class "flex items-center" in LogoOverlay.vue; ensure
the element's attributes become class="flex items-center ml-0.5" (or equivalent
merged classes) and remove the :style binding.

- Use Tailwind ml-0.5 instead of inline marginLeft style
- Add error handling test coverage for onImageError/hasAllFailed

Amp-Thread-ID: https://ampcode.com/threads/T-019c1215-0fc3-752a-aa20-514c5c4804aa
Co-authored-by: Amp <amp@ampcode.com>
Copy link
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.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@src/components/templates/thumbnails/LogoOverlay.test.ts`:
- Around line 13-20: The test helper mountOverlay should type its props
parameter as Partial<ComponentProps<typeof LogoOverlay>> to keep it aligned with
the actual component props; update the signature of mountOverlay to accept
props: Partial<ComponentProps<typeof LogoOverlay>> (and import ComponentProps
from 'vue' if not already imported) so TypeScript will validate test prop shapes
and prevent drift as LogoOverlay's props evolve.
- Line 1: ESLint flags the import of `@vue/test-utils` as unresolved in
LogoOverlay.test.ts (the `import { mount } from '@vue/test-utils'` line);
install the correct package (e.g., add `@vue/test-utils` to devDependencies for
the project's Vue version) and ensure your import resolver is configured (update
ESLint settings such as import/resolver in .eslintrc or tsconfig/paths so the
workspace resolver recognizes node_modules and any path aliases); after
installing, run the provided verification script to confirm package.json entries
include "@vue/test-utils" and that import/resolver or tsconfig alias settings
are present.

In `@src/components/templates/thumbnails/LogoOverlay.vue`:
- Around line 74-92: The label in the computed validLogos uses a hard-coded
separator (" & ") which bypasses localization; update the code in the validLogos
computed (where label is assigned for each ValidatedLogo) to format providers
using Intl.ListFormat with the current locale instead of string-joining with " &
" so user-facing provider names respect locale-specific conjunctions; locate the
label assignment in the validLogos computed that currently uses logo.label ??
validProviders.join(' & ') and replace the join with a localized formatting call
(using Intl.ListFormat or a locale-aware helper) so labels fall back to
logo.label but otherwise use the localized provider list.

@@ -0,0 +1,168 @@
import { mount } from '@vue/test-utils'
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Resolve the ESLint no-unresolved error for @vue/test-utils.

ESLint reports import-x/no-unresolved; ensure the dependency is installed and the resolver is configured for the workspace.

#!/bin/bash
set -euo pipefail

# Check package.json files for `@vue/test-utils` dependency
fd package.json -t f -E node_modules -E dist -E build | while read -r f; do
  echo "== $f =="
  rg -n '"@vue/test-utils"' "$f" || true
done

# Check eslint resolver configuration
rg -n "import/resolver|alias|tsconfig" .eslintrc* package.json
🧰 Tools
🪛 ESLint

[error] 1-1: Unable to resolve path to module '@vue/test-utils'.

(import-x/no-unresolved)

🤖 Prompt for AI Agents
In `@src/components/templates/thumbnails/LogoOverlay.test.ts` at line 1, ESLint
flags the import of `@vue/test-utils` as unresolved in LogoOverlay.test.ts (the
`import { mount } from '@vue/test-utils'` line); install the correct package
(e.g., add `@vue/test-utils` to devDependencies for the project's Vue version) and
ensure your import resolver is configured (update ESLint settings such as
import/resolver in .eslintrc or tsconfig/paths so the workspace resolver
recognizes node_modules and any path aliases); after installing, run the
provided verification script to confirm package.json entries include
"@vue/test-utils" and that import/resolver or tsconfig alias settings are
present.

…helper

- Use Intl.ListFormat for locale-aware provider name conjunction
- Type mountOverlay helper with Partial<ComponentProps<typeof LogoOverlay>>
- Update test to expect 'and' (English locale) instead of '&'

Amp-Thread-ID: https://ampcode.com/threads/T-019c1614-d5f6-74f3-bfff-431a70f89040
Co-authored-by: Amp <amp@ampcode.com>
Copy link
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.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@src/components/templates/thumbnails/LogoOverlay.test.ts`:
- Around line 135-172: Replace brittle inline-style assertions in
LogoOverlay.test.ts: update the "hides logo pill when all provider images fail
to load" and "keeps logo visible when only some images fail in stacked logos"
tests to use behavioral checks (e.g., use pill.isVisible() or
expect(pill.exists()).toBe(false/true)) instead of inspecting style strings;
change the "applies default opacity" and "applies custom opacity" tests to
assert a semantic signal emitted by the component (e.g., data-opacity attribute
or a computed class) rather than "style" — reference mountOverlay,
[data-testid="logo-pill"], and [data-testid="logo-img"] to locate the tests; and
remove the redundant "logos have border styling for stacking visibility" test
entirely since it does not assert meaningful behavior.

In `@src/components/templates/thumbnails/LogoOverlay.vue`:
- Around line 87-108: The computed validLogos currently builds objects with keys
based only on providers which can collide; update the key generation inside the
validLogos computed (where result.push is called) to include layout/identity
attributes (e.g., position, label, gap and/or opacity) or a stable id from
LogoInfo so each entry is unique and stable across renders; ensure the key
construction uses validProviders.join('-') plus those attributes (and still
falls back to `logo-${index}`) so Vue won't reuse DOM for distinct logos.
- Around line 45-55: The fallback hard-coded " & " in formatProviderList should
be localized: import and call useI18n() inside the same scope as
formatProviderList to get t() and the locale, use new Intl.ListFormat(locale,
...) as before, and in the catch return
providers.join(t('thumbnails.andSeparator')); then add the key
"thumbnails.andSeparator": " & " to your main locale JSON so the separator is
provided via vue-i18n.

christian-byrne and others added 3 commits January 31, 2026 16:14
- Create templateSchema.ts with zLogoIndex schema
- Replace manual isValidLogoIndex() with zod safeParse
- Re-export LogoIndex type from schema for consistency

Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019c1614-d5f6-74f3-bfff-431a70f89040
- Use api.fetchApi() instead of raw axios for fetchLogoIndex
- Localize fallback separator via vue-i18n
- Include layout attributes in logo keys to avoid collisions
- Remove style-based tests (change detectors)
- Keep behavioral error handling test

Amp-Thread-ID: https://ampcode.com/threads/T-019c16c9-30a5-7024-9c89-aa58b490d37c
Co-authored-by: Amp <amp@ampcode.com>
@christian-byrne christian-byrne requested a review from a team as a code owner February 1, 2026 01:37
@coderabbitai coderabbitai bot requested a review from PabloWiedemann February 1, 2026 01:38
@christian-byrne christian-byrne merged commit 1bbbcfe into main Feb 1, 2026
28 checks passed
@christian-byrne christian-byrne deleted the templates/composite-logos branch February 1, 2026 03:18
christian-byrne added a commit to Comfy-Org/workflow_templates that referenced this pull request Feb 1, 2026
- Update index.schema.json with logos field and logoInfo definition
- Convert index_logo.json to key-value format for frontend compatibility
- Add example logos field to 4 templates (OpenAI, Stability, Google, WaveSpeed)

Depends on: Comfy-Org/ComfyUI_frontend#8365
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:templates size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants