feat(website): add brand portal page at /brand#13484
Conversation
Implement the Brand Portal page (FE-1217) from the Figma design: hero, logo system with downloadable assets, color palette, voice guidelines, trademark, and questions sections. Ships English and Simplified Chinese, reusing the shared Button, SectionHeader, and BaseLayout.
🌐 Website E2ETip All tests passed.
🔗 Website PreviewWebsite Preview: https://comfy-website-preview-pr-13484.vercel.app This commit: https://website-frontend-62jt1e72l-comfyui.vercel.app Last updated: 2026-07-08T18:30:14Z for |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a localized Brand Portal page at ChangesBrand Portal Page
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 6✅ Passed checks (6 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
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 |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/website/e2e/brand.spec.ts`:
- Around line 5-8: The brand asset URL literals in brand.spec.ts are duplicated
from the source of truth, so replace the local constants with imports from
affiliateBrandAssets.ts. Update the test to use the exported BRAND_ASSETS_ZIP
and BRAND_GUIDELINES_PDF symbols directly, keeping the spec aligned with the
shared data module and preventing drift if the URLs change.
In `@apps/website/src/data/affiliateBrandAssets.ts`:
- Around line 10-11: The shared brand asset constants are in a file named for
affiliate-specific assets, but they are also used by the general brand page.
Move BRAND_ASSETS_ZIP and BRAND_GUIDELINES_PDF into a more appropriately named
shared brand assets module, then update the imports in BrandHeroSection.vue,
BrandLogosSection.vue, and any other consumers to reference the new location.
Keep affiliate-only assets separate so the module name matches its actual
responsibility.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: a2edbf8b-f59e-4e49-ad18-848d519311ec
📒 Files selected for processing (13)
apps/website/e2e/brand.spec.tsapps/website/src/config/routes.tsapps/website/src/data/affiliateBrandAssets.tsapps/website/src/data/brandColors.tsapps/website/src/i18n/translations.tsapps/website/src/pages/brand.astroapps/website/src/pages/zh-CN/brand.astroapps/website/src/templates/brand/BrandColorSection.vueapps/website/src/templates/brand/BrandHeroSection.vueapps/website/src/templates/brand/BrandLogosSection.vueapps/website/src/templates/brand/BrandQuestionsSection.vueapps/website/src/templates/brand/BrandTrademarkSection.vueapps/website/src/templates/brand/BrandVoiceSection.vue
Move BRAND_ASSETS_ZIP and BRAND_GUIDELINES_PDF into a shared brandAssets module (out of affiliateBrandAssets) and import them in the e2e spec instead of duplicating literals. Baseline-align and resize the brand portal download-logos icon to match the design.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/website/src/templates/brand/BrandLogosSection.vue (1)
1-12: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winLogo grid still borrows the affiliate-only data source.
affiliateBrandAssets(and itsAffiliateBrandAssettype with a per-itemdownloadfield) is now consumed by this general Brand Portal section too, even though onlytitle/previeware used here — thedownloadfield per item goes unused since the section-level link usesBRAND_ASSETS_ZIPdirectly. This is the same cohesion smell previously flagged for the constants, just now surfacing on the shared array/type itself.Consider moving the four logo entries (title/preview) into
brandAssets.ts(or a new shared module) with a leaner type that doesn't carry the unuseddownloadfield, keepingaffiliateBrandAssets.tsfocused on its own page's needs.Also applies to: 34-56
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/website/src/templates/brand/BrandLogosSection.vue` around lines 1 - 12, The BrandLogosSection component is still importing affiliate-only brand data, so move the shared logo entries out of affiliateBrandAssets and into brandAssets.ts or a new shared module with a leaner type that only includes title and preview. Update BrandLogosSection to consume that shared source directly, keeping affiliateBrandAssets and its per-item download field limited to the affiliate page’s needs. Use the existing identifiers BrandLogosSection, affiliateBrandAssets, and BRAND_ASSETS_ZIP to locate the affected wiring.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@apps/website/src/templates/brand/BrandLogosSection.vue`:
- Around line 1-12: The BrandLogosSection component is still importing
affiliate-only brand data, so move the shared logo entries out of
affiliateBrandAssets and into brandAssets.ts or a new shared module with a
leaner type that only includes title and preview. Update BrandLogosSection to
consume that shared source directly, keeping affiliateBrandAssets and its
per-item download field limited to the affiliate page’s needs. Use the existing
identifiers BrandLogosSection, affiliateBrandAssets, and BRAND_ASSETS_ZIP to
locate the affected wiring.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 195a9fdc-76a9-4e93-b227-1e46612243bf
📒 Files selected for processing (5)
apps/website/e2e/brand.spec.tsapps/website/src/data/affiliateBrandAssets.tsapps/website/src/data/brandAssets.tsapps/website/src/templates/brand/BrandHeroSection.vueapps/website/src/templates/brand/BrandLogosSection.vue
Port the hero node field from the brand guidelines reference: 14 drifting yellow nodes with halo rings, linked by faint bezier curves, rendered on a canvas across the first viewport behind the content. Uses a VueUse rAF loop paused via IntersectionObserver when off screen, and honours reduced-motion by painting a single static frame.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/website/src/templates/brand/BrandBackground.vue`:
- Around line 20-21: The dpr value in BrandBackground.vue is only read once at
setup time, so it can become stale if the window moves between displays with
different pixel ratios. Update the logic around the dpr calculation to react to
devicePixelRatio changes during the component lifecycle, and make sure the
drawing code that uses dpr stays in sync by recalculating or re-running when the
ratio changes.
- Around line 32-37: The resize logic in BrandBackground.vue clears the canvas
by resetting width and height, but it never redraws the frame afterward, so the
canvas can stay blank when the RAF animation is paused. Update the resize()
function to always trigger a draw after resizing, and make sure this happens
regardless of whether the animation loop is running in the pause/resume flow
used by BrandBackground and its resize listener.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 56d24543-0bff-4695-8837-39b13c482a50
📒 Files selected for processing (3)
apps/website/src/pages/brand.astroapps/website/src/pages/zh-CN/brand.astroapps/website/src/templates/brand/BrandBackground.vue
resize() now recomputes dpr and redraws after resetting the canvas bitmap, so the node field stays visible after a window resize even while the RAF loop is paused (off screen or reduced-motion).
Add click-to-copy on all four swatch values, swap the Icon card to the ink square / yellow C (brand page only), route the contact links to the support site, match the stacked hero CTA widths on mobile, and remove the halo ring from the background nodes.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/website/src/templates/brand/BrandColorSection.vue`:
- Around line 58-70: The copy button in BrandColorSection uses a hardcoded
English aria-label and lacks screen-reader confirmation after copy. Update the
button’s accessible label to use the existing translations.ts t() helper with
locale instead of embedding “Copy”, and add an aria-live polite, visually hidden
message near the button that announces success when copy completes. Use the
existing copied/copiedId state and copyValue handler to wire the live feedback
without changing the visible UI.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 51556d3c-704a-45a5-9b72-6eca21d9cf53
📒 Files selected for processing (9)
apps/website/src/i18n/translations.tsapps/website/src/pages/brand.astroapps/website/src/pages/zh-CN/brand.astroapps/website/src/templates/brand/BrandBackground.vueapps/website/src/templates/brand/BrandColorSection.vueapps/website/src/templates/brand/BrandHeroSection.vueapps/website/src/templates/brand/BrandLogosSection.vueapps/website/src/templates/brand/BrandQuestionsSection.vueapps/website/src/templates/brand/BrandTrademarkSection.vue
Point the hero 'View brand guidelines' CTA at the Google Drive copy (shared to Comfy Org only) opened in a new tab, instead of the public media-bucket PDF, so Google enforces the comfy.org sign-in.
Use the ink app icon (comfyicon.svg) for the Icon card. Make swatches copyable: clicking the card copies the hex, clicking a value copies that value, with a 'Copied {value}' overlay that replaces the card content until it reverts.
Localize the copy aria-label and the 'Copied' overlay text via t(), and announce the copied value through a persistent visually-hidden aria-live region for screen readers.
Summary
Add the Brand Portal page at
/brand(and/zh-CN/brand), implementing the Figma design in English and Simplified Chinese.Changes
BaseLayout,Button, andSectionHeader; addsdata/brandColors.ts(palette with hex/rgb/hsl/cmyk) andtemplates/brand/sections. The hero "View brand guidelines" downloads the guidelines PDF; both "Download logos" actions download the brand-assets zip. Route registered inconfig/routes.ts; copy ini18n/translations.ts(en + zh-CN).Review Focus
media.comfy.orgwithContent-Disposition: attachmentso the buttons download rather than open inline./contactin the same tab (the Figma prototype annotation used a new tab).Implements FE-1217.
Screenshots
Desktop
Mobile
Test plan
pnpm --filter @comfyorg/website typecheckpnpm lintpnpm formate2e/brand.spec.ts(sections render; logo bundle and guidelines-PDF download links)