mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-14 01:36:14 +00:00
cb6accaca5c5ac7829ccb35b9c9ff68fc052d966
7877 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
cb6accaca5 | [automated] Apply ESLint and Oxfmt fixes | ||
|
|
f1df30f24f |
refactor(website): fix model pages architecture and design token violations
Architecture:
- Replace 1585-line hand-coded models.ts with generated-models.json (207 models,
auto-generated by running pnpm generate:models) + 40-line model-metadata.ts for
editorial overrides (docsUrl, blogUrl, featured) + slim 65-line models.ts that
merges both. No more manually maintained data file.
- Remove 830 per-model translation keys from translations.ts — displayName is now
a plain string from the generator, not a TranslationKey
- models.ts no longer imports TranslationKey; displayName/description are strings
- Add generate:models script to website package.json
Design token fixes (pattern-compliance violations):
- Replace text-[var(--color-primary-comfy-yellow)] with text-primary-comfy-yellow
- Replace text-white/70 with text-primary-comfy-canvas/70 (matches existing components)
- Replace invented --color-accent/--color-text-secondary with real tokens
- Fix h1 text from text-white to text-primary-comfy-canvas (matches HeroSection pattern)
i18n fixes:
- Add models.hero.tutorialCta, models.hero.blogLink, models.whatIs.heading,
models.whatIs.tutorialLink keys
- Use t() for all button labels and UI strings in ModelHeroSection.vue
- partner_nodes added to dirLabel in index.astro
Other:
- H1 now reads "{displayName} in ComfyUI" (FE-421 spec)
- Remove description prop from hero (redundant with What-is section)
- Fix GH Actions discovery: m.slug field now matches generator output
- Update add-model-page skill to document new 3-file architecture
|
||
|
|
dd0816af3d | [automated] Apply ESLint and Oxfmt fixes | ||
|
|
f22efbb986 |
fix(website): address review comments on model pages PR
- Fix missing comma in translations.ts (broke build/oxfmt parse) - Fix partner node huggingFaceUrl: use empty string instead of HF homepage - Add rel="noopener noreferrer" to external anchor tags - Remove client:load from ModelHeroSection (presentational, no JS needed) - Fix GH Actions workflow: rename .yml→.yaml, bump to @v6 actions (pinact exempt), pin pnpm action to SHA, fix m.slug→m.suggestedSlug in discovery comparison - Rewrite add-model-page skill to be repo-agnostic (no Glary-Bot references, no hardcoded paths/system assumptions) |
||
|
|
aaf0ceac9f |
feat(website): add SEO model pages infrastructure
- 103-model registry (100 local + 3 partner nodes) in models.ts with docsUrl/blogUrl fields - Dynamic [slug].astro route with SoftwareApplication + BreadcrumbList + FAQPage JSON-LD - ModelHeroSection.vue with partner node support and docs/tutorial CTAs - "What is X?" section on every model page targeting AI Overviews / PAA - generate-models.ts parser with API_PROVIDER_MAP for 30+ partner node providers - Auto-discovery GH Actions workflow (weekly, opens issue on new models) - add-model-page Glary-Bot skill for non-dev Slack-driven PRs - Index page listing all 103 models Closes FE-421 |
||
|
|
5e3266e0c2 |
test: add e2e tests for node replacement flows (#11242)
## Summary Add Playwright e2e tests for the node replacement feature (swap nodes UI in the errors tab). ## Changes - **What**: 6 e2e test cases across two describe blocks covering single and multi-type node replacement flows. Tests verify swap nodes group visibility, in-place replacement, widget value preservation, Replace All across multiple types, output connection preservation, and success toast display. Includes typed mock data for `/api/node_replacements` and two workflow fixture files with fake missing node types mapped to real core nodes. ## Review Focus - Mock setup pattern in `setupNodeReplacement` — enables feature flag via `page.evaluate` and routes the API endpoint - Workflow fixture design — uses fake node types (E2E_OldSampler, E2E_OldUpscaler) that map to real registered types (KSampler, ImageScaleBy) - Assertion coverage for link preservation after replacement ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11242-test-add-e2e-tests-for-node-replacement-flows-3426d73d3650811e87d7f0d96fd66433) by [Unito](https://www.unito.io) --------- Co-authored-by: Connor Byrne <c.byrne@comfy.org> |
||
|
|
b5b502755f |
fix(load3d): parse [output]/[input]/[temp] annotation when loading (#11805)
## Summary The Vue node model picker mixes output assets into the dropdown with a trailing ' [output]' suffix on the value. Forwarding that string to loadModel as a literal filename under the configured input folder caused a 404 and the model never rendered. Strip the trailing folder annotation per call and use the matching folder so picking an output asset loads correctly while plain values keep the configured folder. Output assets stored under a subfolder (e.g. 3d/) were exposed in the Vue node dropdown as just '<filename> [output]', so selection produced an /api/view URL with empty subfolder and a 404. Read the subfolder from the asset's OutputAssetMetadata and prefix it onto the annotated path so the downstream load handler can split it back out and target the correct folder. ## Screenshots (if applicable) https://github.com/user-attachments/assets/463d1071-efdc-46a4-b101-8e1c012d19c7 ┆Issue is synchronized with this [Notion page](https://app.notion.com/p/PR-11805-fix-load3d-parse-output-input-temp-annotation-when-loading-3536d73d365081a8ac9cf75d14ae29e6) by [Unito](https://www.unito.io) |
||
|
|
5fbcea6b27 |
test: add test for workflow delete confirmation (#11780)
## Summary Adds tests for the `Comfy.Workflow.ConfirmDelete` setting ## Changes - **What**: - ensures dialog does/doesnt appear based on the setting ┆Issue is synchronized with this [Notion page](https://app.notion.com/p/PR-11780-test-add-test-for-workflow-delete-confirmation-3526d73d36508134a3cdf0e908b95919) by [Unito](https://www.unito.io) Co-authored-by: Christian Byrne <cbyrne@comfy.org> |
||
|
|
ac36dc47a4 |
docs: Weekly Documentation Update (#11465)
## Summary Fixed two minor documentation inaccuracies found during comprehensive documentation audit: - Corrected outdated "Lodash" reference to "Utility Functions" in unit testing guide - Updated package manager command from `npx` to `pnpm dlx` in Playwright skill documentation ## Changes Made ### Documentation Fixes #### docs/testing/unit-testing.md:150 - **Before**: `## Mocking Lodash Functions` - **After**: `## Mocking Utility Functions` - **Reason**: The section describes mocking `es-toolkit/compat` functions, not Lodash. The project uses es-toolkit as stated in AGENTS.md line 158 and docs/guidance/typescript.md line 60. #### .claude/skills/writing-playwright-tests/SKILL.md:117 - **Before**: `npx playwright show-trace trace.zip` - **After**: `pnpm dlx playwright show-trace trace.zip` - **Reason**: Project standardizes on pnpm, explicitly avoiding npx per AGENTS.md line 42: "use `pnpx` or `pnpm dlx` — never `npx`" ## Audit Summary Comprehensive audit verified accuracy of: - ✅ Core documentation (CLAUDE.md, AGENTS.md, README.md) - ✅ All docs/**/*.md files (40+ files including ADRs, testing guides, architecture docs) - ✅ All README files throughout repository (21 files) - ✅ All .claude/commands/*.md files (8 files) - ✅ Code examples and API references - ✅ File structure references (verified src/router.ts, src/i18n.ts, src/main.ts, config files exist) - ✅ Package dependencies (es-toolkit ^1.39.9 confirmed) - ✅ Script commands (pnpm test:unit, pnpm test:browser:local, etc.) - ✅ External resource links - ✅ ADR index and dates All other documentation remains accurate and up-to-date as of 2026-05-04. ## Review Notes This PR contains only two trivial corrections to terminology/commands. No functional changes, no code changes, no breaking changes. The documentation audit found the codebase documentation to be in excellent condition overall. Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com> |
||
|
|
aef71852f0 |
feat: add demo pages with Arcade embeds at /demos/{slug} (#11436)
*PR Created by the Glary-Bot Agent*
---
## Summary
Adds a demo pages system to the website that embeds Arcade interactive
walkthroughs at `comfy.org/demos/{slug}`. These pages will be linked
from welcome/lifecycle emails via Customer.io.
- Adds `/demos/image-to-video` and `/demos/workflow-templates` as the
first two demos
- Follows the existing `customers/[slug].astro` pattern exactly
(config-driven `getStaticPaths()`)
- Full SEO: OG/Twitter cards, HowTo + LearningResource + BreadcrumbList
JSON-LD schemas
- GEO: AI crawler directives in robots.txt, crawlable transcript
alongside iframe
- A11y: iframe title, sr-only transcript, aria-expanded toggle, noscript
fallback
- Email optimization: 1200x630 OG images, SSG pre-rendered, preconnect
to Arcade CDN
- Full zh-CN localization
- Library index stub at /demos for future expansion
- Automatic sitemap inclusion
## Architecture
Adding a new demo = adding one object to `src/config/demos.ts`.
## Note
OG images are tiny placeholders — replace with real 1200x630 screenshots
before go-live.
## Screenshots


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11436-feat-add-demo-pages-with-Arcade-embeds-at-demos-slug-3486d73d365081abbd72e02bf497a43a)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com>
|
||
|
|
94b570a177 |
test: rename misnamed Mixpanel test and cover the actual provider class (#11749)
## Summary The existing \`MixpanelTelemetryProvider.test.ts\` was misnamed: it only tested \`getExecutionContext\` from \`../../utils/getExecutionContext\`, never the provider class itself — provider coverage sat at **0%** despite a 239-line test file living next to it. This PR: 1. **Renames** the existing test file to \`src/platform/telemetry/utils/getExecutionContext.test.ts\` (co-located with the source it actually tests). Updates its relative import to \`./getExecutionContext\`. 2. **Adds** a fresh \`src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.test.ts\` covering the provider class. Lifts provider coverage from **0% → 81.1%** lines (functions 73.5%, branches 88.5%). ## Test Coverage (new tests) Constructor / initialization: - Without \`mixpanel_token\`, warns and disables itself; subsequent \`trackXxx\` calls are no-ops. - With \`mixpanel_token\`, dynamically imports mixpanel-browser, calls \`init\`, and after \`loaded()\` fires identifies users via \`onUserResolved\`. Queueing semantics: - Events fired before \`loaded()\` are queued and flushed in order once Mixpanel reports ready. Filtering: - Events listed in the default \`disabledEvents\` set (e.g. \`workflow_opened\`) are suppressed. Direct dispatchers (parameterized \`it.each\`): - 16 \`trackXxx\` methods covered: signup/auth/login, subscription lifecycle, credit topup events, template lifecycle, workflow imported/saved, default-view, enter-linear, share-flow, execution success/error. - \`trackApiCreditTopupButtonPurchaseClicked\` payload includes \`credit_amount\`. - \`trackEmailVerification\` dispatches the matching \`USER_EMAIL_VERIFY_*\` event for each stage. - \`trackSubscription\` maps \`'modal_opened'\` and \`'subscribe_clicked'\` to their distinct events. - \`trackRunButton\` populates \`RunButtonProperties\` from the execution context. - \`trackWorkflowExecution\` consumes the latest \`trigger_source\` from \`trackRunButton\`, then resets it to \`'unknown'\`. Survey: - On \`'submitted'\`, normalized properties are written to \`Mixpanel.people\`. - On \`'opened'\`, \`Mixpanel.people\` is not touched. Topup delegation: - \`startTopupTracking\`, \`clearTopupTracking\`, \`checkForCompletedTopup\` all forward to the \`topupTracker\` utility. ## Testing \`\`\`bash pnpm vitest run src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.test.ts pnpm vitest run src/platform/telemetry/utils/getExecutionContext.test.ts \`\`\` ┆Issue is synchronized with this [Notion page](https://app.notion.com/p/PR-11749-test-rename-misnamed-Mixpanel-test-and-cover-the-actual-provider-class-3516d73d365081609c54f34bd2d8b00d) by [Unito](https://www.unito.io) --------- Co-authored-by: Christian Byrne <cbyrne@comfy.org> |
||
|
|
846412af17 |
[chore] Update Ingest API types from cloud@758732f (#11479)
## Automated Ingest API Type Update This PR updates the Ingest API TypeScript types and Zod schemas from the latest cloud OpenAPI specification. - Cloud commit: 758732f - Generated using @hey-api/openapi-ts with Zod plugin These types cover cloud-only endpoints (workspaces, billing, secrets, assets, tasks, etc.). Overlapping endpoints shared with the local ComfyUI Python backend are excluded. --------- Co-authored-by: skishore23 <178779+skishore23@users.noreply.github.com> Co-authored-by: GitHub Action <action@github.com> |
||
|
|
aa2169e108 |
test: reset queue history cap in browser tests (#11773)
## Summary - Reset `Comfy.Queue.MaxHistoryItems` in the shared browser-test `comfyPage` setup so worker-persisted queue settings cannot leak between tests. - Keep the queue settings spec focused on asserting the setting behavior without local cleanup scaffolding. ## Validation - `PLAYWRIGHT_LOCAL=1 PLAYWRIGHT_TEST_URL=http://127.0.0.1:65419 PLAYWRIGHT_SETUP_API_URL=http://127.0.0.1:65400 TEST_COMFYUI_DIR=/Users/ben/.codex/comfyui-preview-env/runtime/worktrees/fe-500-maxhistoryitems pnpm exec playwright test browser_tests/tests/queue/queueSettings.spec.ts --project=chromium --workers=1` - `pnpm exec eslint browser_tests/tests/queue/queueSettings.spec.ts browser_tests/fixtures/ComfyPage.ts` - `pnpm exec oxlint browser_tests/tests/queue/queueSettings.spec.ts browser_tests/fixtures/ComfyPage.ts` - `pnpm typecheck:browser` - `git diff --check` - commit hook: staged oxfmt, oxlint, eslint, `pnpm typecheck`, `pnpm typecheck:browser` Linear: FE-500v1.44.16 |
||
|
|
cc24d1411a |
1.44.16 (#11813)
Patch version increment to 1.44.16 **Base branch:** `main` --------- Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com> Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Alexander Brown <drjkl@comfy.org> |
||
|
|
c2abbeda80 |
Fix core node detection for missing nodes (#11809)
Nodes in the 'essentials' category do not have type 'core'. The check has been updated to instead use the dedicated `isCoreNode` prop. No tests currently. The existing tests for this code section all mock out the relevant code path and properly writing a test for this would take far more time than I can allocate right now. ┆Issue is synchronized with this [Notion page](https://app.notion.com/p/PR-11809-Fix-core-node-detection-for-missing-nodes-3536d73d3650815aabb2deb54c4ecec4) by [Unito](https://www.unito.io) |
||
|
|
56ac3762a0 |
fix: catch angle-bracket Error assertions (#11909)
## Summary Extends the new unsafe Error assertion lint rule from #11845 to also reject angle-bracket assertions. ## Changes - **What**: Adds a `TSTypeAssertion` selector alongside the existing `TSAsExpression` selector and broadens the lint message to cover Error type assertions generally. ## Review Focus This is stacked on #11845 and only addresses the lint-rule bypass for `<Error>value` syntax. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11909-fix-catch-angle-bracket-Error-assertions-3566d73d365081f58ecfecfa2e948c33) by [Unito](https://www.unito.io) --------- Co-authored-by: bymyself <cbyrne@comfy.org> |
||
|
|
f70285dcb2 |
fix(website): point Install via GitHub buttons to install docs anchor (#11852)
*PR Created by the Glary-Bot Agent* --- ## Summary Updates the "Install via GitHub" CTA buttons on the `/download` page to deep-link to the install instructions section of the ComfyUI README (`#installing`) instead of the repo root, so users land directly on setup steps. ## Changes - `apps/website/src/config/routes.ts`: add `externalLinks.githubInstall = 'https://github.com/Comfy-Org/ComfyUI#installing'` (separate from `externalLinks.github`, which is still used by the navbar/footer/star badge for the generic repo link). - `apps/website/src/components/product/local/HeroSection.vue`: switch the secondary CTA next to "Download Local" from `externalLinks.github` to `externalLinks.githubInstall`. - `apps/website/src/components/product/local/EcoSystemSection.vue`: same swap on the ecosystem-section CTA. The platform-aware `Download Local` button (Windows/macOS installers via `useDownloadUrl`) and the generic GitHub social/repo links elsewhere on the site are unchanged. ## Verification - `pnpm --filter @comfyorg/website typecheck` — 0 errors - `pnpm --filter @comfyorg/website test:unit` — 23/23 passing - `pnpm exec eslint` on changed files — clean - `pnpm exec oxfmt --check` — clean - Manual via `pnpm dev` + Playwright DOM assertion on `/download`: - Hero "INSTALL FROM GITHUB" → `https://github.com/Comfy-Org/ComfyUI#installing` ✓ - EcoSystem "INSTALL FROM GITHUB" → `https://github.com/Comfy-Org/ComfyUI#installing` ✓ - Other "GitHub" links (nav, footer, star badge) → unchanged at `https://github.com/Comfy-Org/ComfyUI` ✓ Per request from #website-and-docs: the local download surfaces should at least link to the ComfyUI install instructions on GitHub. Companion change to comfy-org/website#227. ## Screenshots  ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11852-fix-website-point-Install-via-GitHub-buttons-to-install-docs-anchor-3546d73d365081fe8370cd675ae8f896) by [Unito](https://www.unito.io) --------- Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> |
||
|
|
6762c08134 |
feat(website): add payment success and failed pages (#11855)
*PR Created by the Glary-Bot Agent* --- ## Summary Recreate the two payment status pages that were never migrated from Framer (they weren't in the sitemap, so were missed). The Stripe checkout flow in `comfy-api` redirects to `https://www.comfy.org/payment/{success,failed}` after a checkout session, so users currently hit a 404 on completion or cancel. ## Changes - **What**: New static Astro pages at `/payment/success`, `/payment/failed` and their `/zh-CN/` variants, sharing a `PaymentStatusSection.vue` component built from the existing `BrandButton` / `SectionLabel` primitives. Translation keys live in `src/i18n/translations.ts` for both locales. Pages are `noindex` and explicitly excluded from the generated sitemap. Adds a Playwright e2e spec covering both pages in both locales. - **Dependencies**: none ## Review Focus - **URL slug**: matches production Stripe config (`STRIPE_CANCEL_URL=…/payment/failed` in `comfy-api/run-service-{prod,staging}.yaml`), not `/payment/failure`. - **Primary CTA target**: links to `externalLinks.apiKeys` (`platform.comfy.org/profile/api-keys`) — the platform root is just a redirect, so this avoids a hop. - **Locale-aware secondary CTA**: derived from `getRoutes(locale)` so future i18n/route changes flow through the existing helper. - **Stale fallback** (out of scope): `comfy-api/gateways/stripe/stripe.go:159` has an unrelated stale fallback pointing at `/payments/` (plural) that's overridden by the env config in production. Worth fixing in a follow-up. ## Screenshots EN success / failed and zh-CN success / failed at desktop widths. Mobile viewport stacks the CTA buttons vertically (verified locally). ## Screenshots     ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11855-feat-website-add-payment-success-and-failed-pages-3556d73d3650819f8f45d8ecf27cb264) by [Unito](https://www.unito.io) --------- Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> |
||
|
|
211c49f538 |
docs(skill): improve backport-management with tiered triage, path pre-filter, and public-API conflict review (#11868)
*PR Created by the Glary-Bot Agent* --- Synthesizes lessons from the recent `v1.43.16` backport session (PRs #11856–#11862) into the `.claude/skills/backport-management/` skill. **Documentation only — no code, no workflow, no automation changes.** ## What's new ### `SKILL.md` - **Quick Start** expanded from 7 to 12 steps, surfacing the pre-filter and target-file-existence check that should run BEFORE per-PR triage - **New gotcha**: *Cherry-Picked Tests Can Reference Files Added By Earlier Unbackported PRs* — drop the test, document why - **New gotcha**: *Backport-Only Compatibility Shims* — when a refactor-style fix's mechanism relies on changes that aren't on the older branch, a literal cherry-pick can recreate the bug for extensions still using the old contract. Real example: #11541 + `LGraphNode.vue` `handleDrop` - **New section**: *Path Pre-Filter* under Auto-Skip Categories — auto-skip PRs touching only `apps/website/`, `browser_tests/`, `.github/`, `packages/design-system/`, generated types, `.claude/`, `docs/`, or `*.stories.ts`. Removes 30–50% of candidates without reading their bodies ### `reference/analysis.md` - **New subsection**: *Verify Target File Existence* — `git cat-file -e` before cherry-pick to skip PRs targeting features the branch doesn't ship, faster than letting cherry-pick fail with modify/delete - **New section**: *Tiered Triage* — **Tier 1** (core editor must-haves), **Tier 2** (cloud-distribution only), **Tier 3** (skip) before per-PR Y/N. Surfaces release-engineering decisions a flat MUST/SHOULD list obscures ### `reference/discovery.md` - Reconciliation workflow combining Slack bot list + git gap, subtracting already-backported PRs (extracted via `Backport of #` grep on the branch) - Clarifies that no single source is authoritative ### `reference/execution.md` - **New Step 0**: *Test-Then-Resolve Pre-Pass* — moved the dry-run loop to the top of the workflow so you classify clean vs conflict before triggering automation - **New inline guard**: *Public-API conflict review* in the manual cherry-pick loop — consult oracle BEFORE pushing if resolution touches LiteGraph callbacks, `node.*` methods, or extension-API surfaces - **Per-PR validation block** (typecheck + targeted unit tests + ESLint + oxfmt) before push, in addition to wave verification - **Three new lessons learned** (19–21) covering the above - **New PR Body Template** for manual cherry-picks — non-negotiable conflict-resolution section so reviewers don't have to re-derive resolution logic from the diff six months later ## Why 1. **Path pre-filtering** caught 35 of 61 candidates as `skip` before any per-PR analysis was needed during the `v1.43.16` session (`apps/website/`, CI, tests, design-system). The previous flat MUST/SHOULD/SKIP rubric meant reading every PR. 2. **Oracle review on PR #11856** (#11541 backport) caught a regression in `LGraphNode.vue:823` where the upstream PR's removal of the legacy `handled === true` sync-return path would silently break custom nodes still using the old `onDragDrop` contract — recreating the very duplicate-node bug the PR was fixing. The skill had no guidance for this class of issue. 3. **Two separate backports** (#11180, #11541) hit the same modify/delete conflict pattern: a test file added on `main` by an earlier unbackported PR. The skill's *Conflict Triage* table covered modify/delete generally but didn't surface this specific anti-pattern of smuggling in test scaffolding without its prerequisites. 4. **Discovery sources** — the skill assumed Slack bot + git gap as inputs but didn't show how to reconcile them with already-backported PRs, leading to potential double-cherry-picking. ## Verification - No code, no workflow, no automation changes — skill documentation only - `git diff --check` clean - All four edited files render as valid markdown - Cross-references between SKILL.md and `reference/*.md` files validated by line-count check ## Out of scope (intentionally not changed) - The `pr-backport.yaml` GitHub Action — the skill describes this but doesn't own it - The Slack bot — described as *Source 1*, not modified - The PR title convention `[backport TARGET] ...` — kept as-is (CodeRabbit's auto-skip filter relies on it) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11868-docs-skill-improve-backport-management-with-tiered-triage-path-pre-filter-and-public-3556d73d3650814faec3df795567bee3) by [Unito](https://www.unito.io) --------- Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> Co-authored-by: GitHub Action <action@github.com> |
||
|
|
b83602fd23 |
feat: hide Google SSO button in embedded webviews (#10699)
Hide the Google SSO login/signup button when the app runs inside an embedded webview (Android WebView, iOS WKWebView, social app in-app browsers), where Google blocks OAuth with a `403 disallowed_useragent` error. Fixes #7017 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-10699-feat-hide-Google-SSO-button-in-embedded-webviews-3326d73d365081048e35d9d678fe1a2f) by [Unito](https://www.unito.io) --------- Co-authored-by: Benjamin Lu <benjaminlu1107@gmail.com> |
||
|
|
aee2e6e6dd |
test: add e2e tests for nested SubgraphNode input target resolution (#11405)
*PR Created by the Glary-Bot Agent* --- ## Summary - Adds four Playwright tests targeting `resolveSubgraphInputTarget` lines 20-31 — the `inputNode.isSubgraphNode()` branch where the target widget is a PromotedWidgetView - These lines had 0% e2e coverage because no existing test loaded a multi-level nested subgraph with VueNodes enabled - Tests use the existing `subgraph-nested-promotion.json` workflow (node 5 → Sub 0 → node 6 → Sub 1), which has outer SubgraphNode inputs connecting to an inner SubgraphNode ## Test cases | Test | Coverage target | Mechanism | |---|---|---| | Nested SubgraphNode promoted widgets render without resolution failures | Lines 20-31 (via VueNodes rendering) | Console warning collection + widget count assertion | | Subgraph input resolves through inner SubgraphNode with PromotedWidgetView | Lines 20-31 (graph structure verification) | `page.evaluate` walks link chain, asserts `isSubgraphNode() === true` and `isPromotedWidgetView === true` | | Promoted widgets from inner SubgraphNode carry correct source identity | Lines 24-31 (source identity) | Asserts widgets with `sourceNodeId === '6'` have correct `sourceWidgetName` | | Serialize and reload preserves nested promoted widget resolution | Lines 20-31 (persistence) | `serializeAndReload()` + polled widget count comparison | ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11405-test-add-e2e-tests-for-nested-SubgraphNode-input-target-resolution-3476d73d365081ab932edc8a01c55c40) by [Unito](https://www.unito.io) --------- Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> Co-authored-by: Alexander Brown <drjkl@comfy.org> Co-authored-by: Connor Byrne <c.byrne@comfy.org> |
||
|
|
2a3b692c0b |
Repair: re-add bug-dump-ingest skill (#11460) — GitHub squash-commit incident recovery, step 2 of 2 (#11630)
*PR Created by the Glary-Bot Agent* --- ## Step 2 of 2 — GitHub squash-commit incident recovery for #11460 This is the companion to #11629. After #11629 (the revert) merges, this PR re-applies the original PR #11460 contents on top of the post-revert `main`, restoring the intended state of the codebase. ### ⚠️ Sequencing — must merge after #11629 Until #11629 is merged, this PR's diff against `main` is empty (because `main` currently still contains the squashed bug-dump-ingest commit that #11629 will revert). After #11629 is merged into `main`, GitHub will recompute the diff and this PR will show a clean re-add of the same 5 `.claude/skills/bug-dump-ingest/` files. ### Verification The branch was constructed by: 1. Branching from `glary/revert-pr-11460` (the revert branch in #11629). 2. `git checkout FETCH_HEAD -- .claude/skills/bug-dump-ingest/` from `refs/pull/11460/head` to restore the exact files. 3. Committing them as a single squash-style commit. I verified that all 5 file blobs are byte-for-byte identical to the original squash commit `559922eaa5c129767c22275c206c6877931ac15c` by comparing git object SHAs: | File | Object SHA | |---|---| | `.claude/skills/bug-dump-ingest/SKILL.md` | `413737835fa1c996291019483effdd39e6da33e5` | | `.claude/skills/bug-dump-ingest/reference/examples.md` | `4fc54a4f14b1359de63f558acca0de48c1b65c57` | | `.claude/skills/bug-dump-ingest/reference/linear-api.md` | `57986740df2ee02c19b81059f0f1e00e54c2a042` | | `.claude/skills/bug-dump-ingest/reference/schema.md` | `84db1a5818c04ee53a94167092ec76dd814992d4` | | `.claude/skills/bug-dump-ingest/reference/verify-commands.md` | `a2c99a43a030ccc3769692d3c09be74132645bb4` | ### Notes - One commit on `refs/pull/11460/head` (an automated lint commit `76ca1598e`) modified `src/renderer/extensions/vueNodes/widgets/components/WidgetChart.test.ts` to remove an `eslint-disable` directive. That change was **not** in the original squash commit on `main` (verified via `git show --stat`), and the directive has separately been removed from `main` by an unrelated commit (#11550), so re-applying that change would now be a no-op. This repair PR therefore intentionally restores **only the 5 bug-dump-ingest files**, matching the original squash commit exactly. - Branch name is `glary/repair-pr-11460` (the `glary/` prefix is required by the tooling; otherwise equivalent to GitHub's suggested `repair-pr-11460`). Refs: #11460, #11629 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11630-Repair-re-add-bug-dump-ingest-skill-11460-GitHub-squash-commit-incident-recovery--34d6d73d365081acbd54c19316561fa9) by [Unito](https://www.unito.io) --------- Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> |
||
|
|
dac3396de8 |
test: add selection paste, rename, and batch rename browser tests (#11367)
*PR Created by the Glary-Bot Agent* --- ## Summary Adds `browser_tests/tests/selectionPasteRename.spec.ts` covering the untested `pasteSelection()` and `renameSelection()` paths in `useSelectionOperations.ts`. ### Coverage gaps filled - `pasteSelection()` — copy → paste creates new nodes - `renameSelection()` single node path — opens title editor - `renameSelection()` batch path — prompt dialog with sequential naming - Empty selection → toast warning ### References - Follows patterns from `selectionToolboxMoreActions.spec.ts` (More Options menu, `selectNodeWithPan`) - Follows `browser_tests/AGENTS.md` directory structure - Follows `browser_tests/FLAKE_PREVENTION_RULES.md` assertion patterns ### Verification - TypeScript: clean - ESLint: clean - oxlint: clean - oxfmt: formatted ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11367-test-add-selection-paste-rename-and-batch-rename-browser-tests-3466d73d3650812194a4d8bfbed3dee7) by [Unito](https://www.unito.io) --------- Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> Co-authored-by: Amp <amp@ampcode.com> |
||
|
|
d253d87c92 |
Revert "feat: add bug-dump-ingest skill (#11460)" — GitHub squash-commit incident recovery (#11629)
*PR Created by the Glary-Bot Agent* --- ## Step 1 of 2 — GitHub squash-commit incident recovery for #11460 GitHub flagged the squash commit for #11460 (`559922eaa5c129767c22275c206c6877931ac15c`) as affected by the squash-commit incident that produced non-deterministic merges. This PR is **step 1 of 2** in the recovery procedure GitHub asked us to follow. ### What this PR does Reverts `559922eaa5c129767c22275c206c6877931ac15c` (the affected squash commit for #11460, "feat: add bug-dump-ingest skill") on top of current `main`. ### Diff 5 files removed, all under `.claude/skills/bug-dump-ingest/`: - `.claude/skills/bug-dump-ingest/SKILL.md` - `.claude/skills/bug-dump-ingest/reference/examples.md` - `.claude/skills/bug-dump-ingest/reference/linear-api.md` - `.claude/skills/bug-dump-ingest/reference/schema.md` - `.claude/skills/bug-dump-ingest/reference/verify-commands.md` `git revert` applied cleanly with no conflicts. ### Recovery procedure Per GitHub's instructions: 1. **This PR (step 1)** — Revert the affected squash commit. Removes both the original changes and any unintended changes that the incident may have introduced. 2. **Next PR (step 2)** — Re-apply the original PR's changes from `refs/pull/11460/head`, rebased onto post-revert `main`. Will be opened as a separate "repair" PR. ### Review notes - This is a pure revert; please confirm the diff is exactly the inverse of #11460. - After this PR is merged, the companion repair PR will land the original changes back on `main` from a clean source ref, restoring the intended state of the codebase. - Branch name is `glary/revert-pr-11460` (the `glary/` prefix is required by the tool that opened this PR — it's otherwise equivalent to GitHub's suggested `revert-pr-11460`). - Code review: Oracle reviewed and found 0 issues (critical/warning/suggestion all 0). Ready to merge. Refs: #11460 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11629-Revert-feat-add-bug-dump-ingest-skill-11460-GitHub-squash-commit-incident-recove-34d6d73d3650810f9ed3f6068e4f1511) by [Unito](https://www.unito.io) Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> |
||
|
|
4033dde983 |
refactor(website): replace UseCaseSection scroll override with hover on desktop (#11696)
## Summary
Per product feedback, scroll-jacking the page to step through
'Industries that create with ComfyUI' categories feels bad on desktop.
This PR removes the desktop scroll override and switches to hover-driven
imagery on lg+, while preserving the existing pin/scrub interaction on
mobile/touch breakpoints.
## Changes
- **What**:
- Gate `usePinScrub` setup to `(max-width: 1023px)` so the pin/scrub
only runs on touch breakpoints; desktop never engages it.
- Wire `@mouseenter` and `@focus` on each category button to update the
active category on desktop. Click still works on both modes via the
existing `scrollToIndex` (which falls through to a direct ref set when
no ScrollTrigger instance is present).
- Pass the same `(max-width: 1023px)` to `useParallax` via its existing
`mediaQuery` option so parallax doesn't run against the no-longer-pinned
section on desktop.
- Apply the section's `lg:h-[calc(100vh+60px)]` unconditionally on lg+
since pin no longer drives it; mobile height is still managed
dynamically by `usePinScrub`'s `cacheLayout`.
- **Breaking**: None.
- **Dependencies**: None.
## Review Focus
- Mobile path inside `usePinScrub.onMounted` is byte-identical to main —
only the early-return condition gained one extra clause
(`!window.matchMedia('(max-width: 1023px)').matches`), which mobile
evaluates to `false` so it falls through to the existing setup.
- `onCategoryHover` early-returns when `isEnabled` is true, making it a
no-op on mobile (where pin is engaged), so a tap doesn't accidentally
fight the scrub.
- `@focus` is wired alongside `@mouseenter` so keyboard tab navigation
also previews the imagery.
- The previous Lenis-on-macOS workaround from this branch is reverted —
it was only needed because the scroll override existed.
## Screenshots (if applicable)
N/A — interaction change. Test on desktop (≥1024px) by hovering category
labels — imagery should swap with no scroll-jacking. Test on mobile
(<1024px) by scrolling the section; pin/scrub should engage as before.
---------
Co-authored-by: Marwan Ahmed <marwan@Marwans-MacBook-Pro.local>
Co-authored-by: GitHub Action <action@github.com>
Co-authored-by: Alexander Brown <drjkl@comfy.org>
|
||
|
|
61a444ed99 |
test: combine duplicated undo/redo and settings dialog E2E tests with test.step (#11835)
## Summary Refactor E2E tests added in #11210 that repeated full prior-test bodies as setup, combining duplicate pairs into single tests with named `test.step()` blocks. ## Changes - **What**: In [`browser_tests/tests/keyboardShortcutActions.spec.ts`](../blob/batch-dispatch/cr-11556/browser_tests/tests/keyboardShortcutActions.spec.ts): - Merge `Ctrl+Z undoes` + `Ctrl+Shift+Z redoes` → single test with two `test.step()` blocks. - Merge `Ctrl+, opens settings dialog` + `Escape closes settings dialog` → single test with two `test.step()` blocks. - **What**: In [`browser_tests/tests/topbarMenuCommands.spec.ts`](../blob/batch-dispatch/cr-11556/browser_tests/tests/topbarMenuCommands.spec.ts): - Merge `Edit > Undo` + `Edit > Redo` → single test with two `test.step()` blocks. The redo step now reuses the post-undo state from its preceding step instead of re-creating and re-undoing the node, removing the duplicated setup the reviewer flagged. ## Review Focus - Naming of combined tests and `test.step()` labels. - Note: per @AustinMroz's [comment thread](https://github.com/Comfy-Org/ComfyUI_frontend/pull/11210#discussion_r3113526265), location 2 in the issue refers to the `Escape closes settings dialog` test (which duplicated the `Ctrl+,` test body), not the `Delete` test (which has unique logic). Treated accordingly. Fixes #11556 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11835-test-combine-duplicated-undo-redo-and-settings-dialog-E2E-tests-with-test-step-3546d73d365081689df3c56bfbb6f4e4) by [Unito](https://www.unito.io) |
||
|
|
385a1d421d |
[chore] Update Comfy Registry API types from comfy-api@84a4468 (#11910)
## Automated API Type Update This PR updates the Comfy Registry API types from the latest comfy-api OpenAPI specification. - API commit: 84a4468 - Generated on: 2026-05-04T15:45:35Z These types are automatically generated using openapi-typescript. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11910-chore-Update-Comfy-Registry-API-types-from-comfy-api-84a4468-3566d73d365081ef8771cb77b5de6119) by [Unito](https://www.unito.io) Co-authored-by: bigcat88 <13381981+bigcat88@users.noreply.github.com> |
||
|
|
341fef46a9 |
refactor: replace unsafe as Error assertions with type guards (#11845)
## Summary Replaces all 7 production `as Error` type assertions with proper `instanceof Error` narrowing or a new `toError()` helper, and adds an ESLint rule to prevent new ones. First slice of #11429 (the `as Error` category — 9 total occurrences, 7 production + 2 in a test file left untouched). ## Changes - **What**: - New `src/utils/errorUtil.ts` exporting `toError(value: unknown): Error` and `getErrorMessage(value: unknown): string | undefined`. `toError` returns the value unchanged if already an `Error`, otherwise wraps it (handles strings, `undefined`, JSON-serializable objects, and circular refs via `String()` fallback). - Refactored 7 production call sites: - `src/services/gateway/registrySearchGateway.ts` — `toError(error)` for `lastError` assignment in fallback loop - `src/platform/cloud/onboarding/auth.ts` (×2) — `toError(error)` for `captureApiError` Sentry calls - `src/renderer/extensions/vueNodes/widgets/composables/audio/useAudioRecorder.ts` — `toError(err)` before forwarding to `options.onError` - `src/extensions/core/load3d/LoaderManager.ts` — replaced `error as Error & { response?: ... }` cast inside `isNotFoundError` with `'response' in error` + nested narrowing - `apps/desktop-ui/src/stores/maintenanceTaskStore.ts` — inline `error instanceof Error ? error.message : String(error)` - `apps/desktop-ui/src/components/maintenance/TaskListPanel.vue` — inline `error instanceof Error ? error.message : undefined` - New ESLint rule (`no-restricted-syntax` block named `comfy/no-unsafe-error-assertion`) banning `TSAsExpression TSTypeReference[typeName.name='Error']` in `src/**` and `apps/*/src/**`, with test files (`*.test.ts`, `*.spec.ts`) excluded. - 12 unit tests for the new helpers in `src/utils/errorUtil.test.ts`. - **Breaking**: none - **Dependencies**: none ## Review Focus - The lint rule is scoped to non-test source files. Test files retain freedom to use `as Error` for fixture construction; only 2 occurrences exist (in `teamWorkspaceStore.test.ts` and `errorDialog.spec.ts`) and they're intentional. - `toError` is duplicated as inline `instanceof` narrowing in `apps/desktop-ui/` rather than imported, since the desktop-ui workspace doesn't share `@/utils/` with the main app and adding a path mapping for one helper felt heavier than two inline guards. - Remaining `as`-on-DOM categories (HTMLElement ×133, HTMLInputElement ×55, HTMLCanvasElement ×36, KeyboardEvent ×7, Element ×3, MouseEvent ×2, Event ×2) are intentionally left for follow-up PRs to keep this one reviewable. Refs #11429 ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11845-refactor-replace-unsafe-as-Error-assertions-with-type-guards-3546d73d36508137a015c4f9e8708f23) by [Unito](https://www.unito.io) |
||
|
|
24b548aebc |
fix: route footer Support link to Zendesk help center (#11904)
*PR Created by the Glary-Bot Agent* --- ## Summary The "Support" link in the marketing site footer (Contact column) was reusing the Discord external link. Update it to point at the Zendesk help center at `https://support.comfy.org/hc/en-us`, as requested in the `#website-and-docs` Slack thread. ## Changes - `apps/website/src/config/routes.ts` — add `support` entry to `externalLinks` pointing at `https://support.comfy.org/hc/en-us`. - `apps/website/src/components/common/SiteFooter.vue` — use `externalLinks.support` for the Contact > Support entry instead of `externalLinks.discord`. ## Verification - `pnpm format` and `pnpm exec eslint` clean on both files. - `pnpm typecheck` passes. - Verified locally with `pnpm dev` (Astro on `localhost:4321`); the rendered footer Support link now resolves to `https://support.comfy.org/hc/en-us` (screenshot below). ## Notes Reviewer flagged that `/hc/en-us` forces English and bypasses Zendesk locale negotiation. The exact URL was explicitly requested by the user in the Slack thread, so it is preserved here. Switching to a locale-neutral `https://support.comfy.org/` can be done as a follow-up if desired. ## Screenshots  ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11904-fix-route-footer-Support-link-to-Zendesk-help-center-3566d73d36508189abcff34ae766d3c4) by [Unito](https://www.unito.io) Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> |
||
|
|
6ea278da30 |
[chore] Update Comfy Registry API types from comfy-api@9ec8c25 (#11906)
## Automated API Type Update This PR updates the Comfy Registry API types from the latest comfy-api OpenAPI specification. - API commit: 9ec8c25 - Generated on: 2026-05-04T15:11:04Z These types are automatically generated using openapi-typescript. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11906-chore-Update-Comfy-Registry-API-types-from-comfy-api-9ec8c25-3566d73d365081e394a6c13c0e30499b) by [Unito](https://www.unito.io) Co-authored-by: coderfromthenorth93 <213232275+coderfromthenorth93@users.noreply.github.com> |
||
|
|
560e53c68f |
fix: remove coming soon badge from parallel job execution (#11819)
*PR Created by the Glary-Bot Agent* --- Removes the "coming soon" badge from the Parallel Job Execution feature card on the cloud pricing page (`comfy.org/cloud/pricing`). ## Changes - `apps/website/src/components/pricing/WhatsIncludedSection.vue`: drop `isComingSoon: true` from feature11 so it renders with the standard check icon and no badge. The `isComingSoon` mechanism (clock icon + yellow badge) is preserved in the component for future use on other features. ## Note The FAQ copy elsewhere on the site (`cloud.faq.9.a`) still references "one active job at a time" and "parallel runs soon". That copy will be updated separately. ## Verification - `pnpm typecheck` (website): 0 errors - `pnpm lint`: clean (1 pre-existing warning unrelated to this change) - `pnpm format:check`: clean - `pnpm test:unit` (website): 20 passed - Visual check via Playwright on local dev server (see screenshot) ## Screenshots  ┆Issue is synchronized with this [Notion page](https://app.notion.com/p/PR-11819-fix-remove-coming-soon-badge-from-parallel-job-execution-3546d73d365081d19060f976095d03ac) by [Unito](https://www.unito.io) --------- Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> |
||
|
|
1999b7fba0 |
fix: remove (beta) from cloud.faq.3.a (#11905)
*PR Created by the Glary-Bot Agent* --- ## Summary Remove `(beta)` from the `cloud.faq.3.a` translation entry in both English and Simplified Chinese (`zh-CN`), since Comfy Cloud is no longer in beta. ## Changes `apps/website/src/i18n/translations.ts`: - en: `Comfy Cloud (beta) has zero setup...` → `Comfy Cloud has zero setup...` - zh-CN: `Comfy Cloud(测试版)无需任何设置...` → `Comfy Cloud 无需任何设置...` ## Verification - Pre-commit hooks (oxfmt, oxlint, eslint, typecheck, typecheck:website) all passed - Code review (oracle): 0 issues, ready to merge - Manual verification via Playwright on `/cloud` and `/zh-CN/cloud` — FAQ item 3 renders updated copy in both locales (screenshots attached) ## Screenshots   ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11905-fix-remove-beta-from-cloud-faq-3-a-3566d73d36508150997bcf2c89826091) by [Unito](https://www.unito.io) Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> |
||
|
|
285421a87c |
feat: add queue progress overlay feature survey (#11560)
*PR Created by the Glary-Bot Agent* --- ## Summary Registers a new nightly feature survey for the Queue Progress Overlay using the existing feature-survey registry (same pattern as the merged node-search survey, PRs #8175/#8355/#9934). - New registry entry `queue-progress-overlay` → Typeform `HZ5saxry`, threshold **16**, 5s display delay. - `trackFeatureUsed()` wired at the major user-initiated handlers inside the overlay so the survey triggers regardless of panel location (floating-right v1 or docked-left v2). - Run button and other ActionBar items that the overlay pops over from are deliberately **not** tracked — tracking is scoped to interactions that originate inside the job panel / queue progress overlay itself. ## Tracked interactions Both variants share most sub-components, so tracking is instrumented once at each logical surface: - **`QueueProgressOverlay.vue`** (v1 container): `viewAllJobs`, `interruptAll`, `cancelQueuedWorkflows`, `onClearHistoryFromMenu`, `toggleAssetsSidebar`, `onCancelItem`, `onDeleteItem`, `inspectJobAsset` - **`QueueOverlayExpanded.vue`**: job tab switches - **`JobHistorySidebarTab.vue`** (v2 docked): job tab switches, `clearQueuedWorkflows`, `onClearHistory`, `onCancelItem`, `onDeleteItem`, `onViewItem` - **`JobFilterActions.vue`** (shared): workflow filter + sort mode selections - **`JobHistoryActionsMenu.vue`** (shared): docked-history toggle + run-progress-bar toggle Deliberately **not tracked** to keep the signal clean: - Hover handlers (ambient preview behaviour) - Search-box keystrokes (debounced typing) - Context menu open and menu-item dispatch — menu actions either bubble through already-tracked terminal handlers (e.g. inspect-asset → `onViewItem`) or are secondary operations (copy-id, open-workflow, download). Avoids double-counting per code review feedback. ## How it works (inherits from existing infrastructure) 1. `surveyRegistry.ts` drives `NightlySurveyController` → `NightlySurveyPopover`, which handles the Typeform embed. 2. Eligibility already gated on `isNightly && !isCloud && !isDesktop`, once-per-user, 4-day global cooldown across all surveys, and opt-out. 3. Typeform response routing to #C0ALLT6Q3SQ is handled on the Typeform side. ## Verification - `pnpm typecheck` ✅ - `pnpm lint` ✅ (no new warnings) - `pnpm knip` ✅ - `pnpm test:unit` on `src/components/queue`, `src/components/sidebar/tabs/JobHistorySidebarTab`, `src/platform/surveys` → **123/123 passing** - Pre-commit hooks (stylelint, oxfmt, oxlint, eslint, typecheck) all pass - Manual: dev server + backend boot cleanly, app loads without new runtime errors, `localStorage['Comfy.FeatureUsage']` layout verified to match what `useFeatureUsageTracker` writes ## Notes - Survey key `queue-progress-overlay` covers both v1 (floating-right) and v2 (docked-sidebar) per product guidance: _"This should trigger regardless of the location of the panel (docked from left or floating on right)."_ Both surfaces are the same product feature — the survey is intentionally scoped to the whole job-panel experience. ## Screenshots  ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11560-feat-add-queue-progress-overlay-feature-survey-34b6d73d3650819a9a50fd67fd9b5941) by [Unito](https://www.unito.io) --------- Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> |
||
|
|
5523df1aea |
fix(website): unstretch See all case studies button (#11854)
*PR Created by the Glary-Bot Agent* --- ## Summary The "See all case studies" button on the homepage `CaseStudySpotlightSection` was rendering oddly stretched because it had `class="flex-1 text-center"` while being the sole child of a `flex-row` container — it expanded to fill the entire content column (~592px) instead of sizing to its label. This drops `flex-1`/`text-center` and adds `items-start` to the wrapper so the button sizes to its content and is left-aligned, matching the proportions of every other outline `BrandButton` on the site (Hero, UseCase, customer detail, etc.). ## Changes - `apps/website/src/components/home/CaseStudySpotlightSection.vue`: remove `flex-1 text-center` from the `BrandButton` and align the row's items to the start. `BrandButton` already centers its label internally via `inline-flex … justify-center`, so dropping `text-center` is a no-op visually. ## Before / After - Desktop before: button width = 592px (stretched across the column) - Desktop after: button width = 223px (natural) - Mobile: 1-column layout, now consistently left-aligned ## Review Focus Whether the fix should also live on the `BrandButton` component itself (e.g. a global `max-width`) instead of at the call site. I went with the instance-level fix because every other CTA in the website intentionally uses bare `BrandButton` and lets the content size it; only this one had `flex-1`. A blanket `max-width` would risk changing Hero/MobileMenu buttons that explicitly opt into `w-full lg:w-auto lg:min-w-60`. ## Screenshots    ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11854-fix-website-unstretch-See-all-case-studies-button-3556d73d365081abb3bbe9dbc51cbc07) by [Unito](https://www.unito.io) --------- Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> |
||
|
|
65876c635d |
feat(website): add responsive media tooling for marketing assets (#11869)
*PR Created by the Glary-Bot Agent*
---
## Summary
Adds the building blocks for a responsive media system on
`apps/website`, motivated by the gallery video blurriness raised in
Slack. Three independent pieces:
1. **`<SiteVideo>` Vue component + URL helper** — emits a `<video>` with
multiple `<source>` tags, designed to pair with assets named
`${name}-${width}.${format}` on `media.comfy.org`.
2. **`scripts/process-videos.sh`** — local-developer `ffmpeg` helper
that produces VP9/WebM + H.264/MP4 variants and a poster JPG. Not wired
into CI; the team uploads to `media.comfy.org` out-of-band.
3. **Marketing image conventions** — shared `MARKETING_FORMATS` /
`MARKETING_WIDTHS` constants and a README documenting how to render
local marketing images via Astro's built-in `<Picture>` from
`astro:assets`.
This PR is **infrastructure only** — no existing pages are modified.
Adoption (e.g. converting `HeroSection`, gallery videos) is a follow-up.
The new files are added to knip's ignore list with the existing "pending
stacked PR" pattern.
## Why this shape
- **No custom `<Picture>` wrapper.** Astro 5 already ships a
`ResponsiveImage` component (name conflict), and Astro's
`LocalImageProps | RemoteImageProps` discriminated union does not
survive a thin wrapper without unsafe `as` casts. Shared constants give
the consistency benefit at lower cost.
- **No CI media-upload step.** The `Release: Website` workflow currently
only refreshes the Ashby snapshot; wiring GCS uploads into it would
require new secrets and team coordination beyond this PR's scope. The
script runs locally and outputs are uploaded to `media.comfy.org` the
same way as today.
- **Single resolution per `<video>`.** `<source media="...">` inside
`<video>` is unreliable across browsers (Safari ignores it). The script
generates multiple widths so callers can pick one per page; JS-based
selection can be layered on later if metrics demand it.
## What's verified
- `pnpm --filter @comfyorg/website test:unit` — 30 pass (7 new for
`buildVideoSources` / `videoKey`)
- `pnpm --filter @comfyorg/website typecheck` — clean
- `pnpm --filter @comfyorg/website build` — 41 pages built clean
- `pnpm knip` — exit 0
- `oxfmt --check` and `oxlint` clean on all changed files
- `bash -n` on `process-videos.sh` clean; usage and missing-deps paths
exercised manually
- Manual: home page and `/gallery` rendered via `astro dev` — both
unchanged with zero console errors (screenshots attached)
## Review feedback addressed
After Oracle review, three follow-up commits land:
- **`SiteVideo` reactivity** — `sources` is now `computed`; the
`<video>` is keyed on the joined source URLs so it remounts when the
source set changes (browsers don't reload on `<source>` mutation).
- **`SiteVideo` accessibility** — `aria-hidden="true"` only when truly
decorative (no `alt` and no `controls`).
- **Shell script robustness** — probes duration with `ffprobe` and falls
back to `t=0` for clips shorter than 1s; enables `nocaseglob` so
`CLIP.MP4` is picked up.
- **Docs** — clarifies when to use `<SiteVideo>` (lightweight
multi-source) vs `<VideoPlayer>` (captions, controls, scrubber).
## Out of scope (follow-ups)
- Converting existing pages (`HeroSection`, customer detail heros,
gallery) to use the new components. Most current images are CDN-hosted
and migrating them is a separate decision.
- Re-encoding the gallery videos at a higher source width to actually
fix the blurriness — that requires the team to run `process-videos.sh`
against the source clips and re-upload.
- Combining `<SiteVideo>`'s multi-source support with `<VideoPlayer>`'s
rich chrome.
## Screenshots


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11869-feat-website-add-responsive-media-tooling-for-marketing-assets-3556d73d3650818899c7f9ed3204c9a5)
by [Unito](https://www.unito.io)
---------
Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com>
|
||
|
|
04918360eb |
Use hash lookup for missing asset detection (#11873)
## Summary
Use exact BLAKE3 hash lookups first for missing model/media detection,
and add a separate public-inclusive input asset cache so public input
assets are considered missing-detection candidates without changing the
user-only input assets shown in the UI.
## Changes
- **What**:
- Added `assetService.checkAssetHash()` for `HEAD
/api/assets/hash/{hash}` status-only existence checks.
- Added strict BLAKE3 hash helpers so only `blake3:<64 hex>` media
values and raw 64-hex BLAKE3 model metadata are sent to the hash
endpoint.
- Updated missing media detection to group BLAKE3 candidates by hash,
resolve them through the hash endpoint, and fall back to the legacy
asset list path for invalid/unverifiable/non-hash values.
- Updated missing model detection to use hash lookup for BLAKE3-backed
asset-supported candidates before falling back to the existing node-type
asset matching path.
- Added `assetService.getInputAssetsIncludingPublic()` backed by a
dedicated cache that fetches input assets with `include_public=true` for
missing media fallback checks.
- Kept `assetsStore.inputAssets` user-only for widget/UI display, while
invalidating the public-inclusive missing-detection cache when input
assets may change.
- Added abort handling for paginated asset fetches and shared
public-input cache callers so one aborted caller does not cancel the
shared fetch for other callers.
- Added regression coverage for hash lookup, fallback behavior, abort
paths, public input fallback detection, and cache invalidation.
- **Dependencies**: None.
- **Change size**:
- Production code: 4 files, 400 insertions, 24 deletions, net +376.
- Test code: 4 files, 806 insertions, 59 deletions, net +747.
- Total: 8 files, 1206 insertions, 83 deletions, net +1123.
## Review Focus
- The public-inclusive input asset cache is intentionally separate from
`assetsStore.inputAssets`. The existing store data is user-only and
drives the asset widgets/sidebar, so using it for missing input
detection misses public assets. Making that store public-inclusive would
change UI data semantics; this PR instead keeps the UI dataset unchanged
and adds a missing-detection-specific cache in `assetService`.
- Hash lookup is only used when the workflow exposes a valid BLAKE3
hash. Filename-like values and invalid hash values still use the legacy
fallback path.
- Missing model detection keeps the existing fallback behavior for
non-hash candidates and for hash checks that are invalid or fail
transiently.
- Async model download cache refresh behavior is left unchanged; this PR
avoids coupling model download completion to input asset cache
invalidation.
- No browser/e2e test was added because this changes the missing asset
detection data path, not UI interaction or rendering. The behavioral
coverage is in unit tests for the asset service and the missing
media/model scanners.
## Follow-up Items
- Fix `assetsStore.updateAssetTags()` partial-failure recovery. If
`removeAssetTags()` succeeds and `addAssetTags()` fails, the local model
asset cache can roll back to tags that the backend has already removed;
this should be handled in a focused model asset cache PR.
- Consider extracting shared hash-verification flow used by missing
media and missing model scans after this behavior stabilizes.
- Consider adding a concurrency cap or short-lived request cache for
large workflows with many unique hash lookups.
- Consider splitting `assetService.ts` further, e.g. hash helpers, abort
utilities, and the public-inclusive input asset cache.
- Consider tightening the asset hash service API shape so callers do not
directly depend on HTTP-oriented statuses such as `invalid`.
- Consider adding broader mutation-path coverage for public-inclusive
input cache invalidation once the cache has more consumers.
Linear: FE-534
## Screenshots (if applicable)
Before <false positive / missing image / public asset>
https://github.com/user-attachments/assets/db7ce2a9-b169-4fae-bf9f-98bb93d3ee6d
After
https://github.com/user-attachments/assets/29af9f9e-b536-4fcd-a426-3add40bcb165
┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11873-Use-hash-lookup-for-missing-asset-detection-3556d73d36508165babafb16614be0d8)
by [Unito](https://www.unito.io)
|
||
|
|
af70d88860 |
fix: keep finished badge fully opaque in ProgressToastItem (#11542)
## Summary - fix **[slack](https://comfy-organization.slack.com/archives/C0A4XMHANP3/p1776801170742579)** - Move `opacity-50` off the row container onto the asset-name column only, so the contrast badge (white pill, dark label) is not dimmed to gray-on-gray when a download completes. - Matches the Figma intent that the `FINISHED` badge stands out — designer spec uses `base/foreground` for pill, `base/background` for text, which is unreadable when the parent is 50% opacity. <img width="560" height="269" alt="Screenshot 2026-04-23 at 2 46 17 PM" src="https://github.com/user-attachments/assets/fb84aa57-c348-4a86-9a65-9342c12400e1" /> <img width="764" height="332" alt="Screenshot 2026-04-23 at 2 46 41 PM" src="https://github.com/user-attachments/assets/ecbe6a5f-c2e8-4427-9c1d-f8f123009d2e" /> ## Before / After  ## Repro Cloud → trigger a model download → wait for completion → the `FINISHED` badge is the same tone as the toast surface (see Slack thread screenshots). ## Test plan - [ ] Complete a model download in cloud and confirm the `FINISHED` badge is clearly legible in both themes. - [ ] File name + subtitle still appear dimmed to signal the row is completed. - [ ] Running / failed / pending states unchanged. - Fixes [FE-237](https://linear.app/comfyorg/issue/FE-237/fix-honeytoast-badge-text-color-for-finished-job-matches-background) |
||
|
|
c955309b26 |
[chore] Update Comfy Registry API types from comfy-api@911406c (#11518)
## Automated API Type Update This PR updates the Comfy Registry API types from the latest comfy-api OpenAPI specification. - API commit: 911406c - Generated on: 2026-04-17T16:10:40Z These types are automatically generated using openapi-typescript. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11518-chore-Update-Comfy-Registry-API-types-from-comfy-api-911406c-3496d73d36508146a1e2e1ee90640fa4) by [Unito](https://www.unito.io) Co-authored-by: coderfromthenorth93 <213232275+coderfromthenorth93@users.noreply.github.com> Co-authored-by: Alexander Brown <drjkl@comfy.org> |
||
|
|
7abd9d12c8 |
chore(website): refresh Ashby roles snapshot (#11851)
Automated refresh of `apps/website/src/data/ashby-roles.snapshot.json` from the Ashby job board API. **Flow:** 1. `Release: Website` workflow ran (manual trigger). 2. This PR opens with the regenerated snapshot. 3. `CI: Vercel Website Preview` deploys a preview for review. 4. Merging to `main` triggers the production Vercel deploy. The snapshot fallback in `apps/website/src/utils/ashby.ts` remains intact: builds without `WEBSITE_ASHBY_API_KEY` continue to use the committed snapshot. Triggered by workflow run `25260868155`. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11851-chore-website-refresh-Ashby-roles-snapshot-3546d73d365081579f98f13f7b58e611) by [Unito](https://www.unito.io) Co-authored-by: christian-byrne <72887196+christian-byrne@users.noreply.github.com> |
||
|
|
dd9cb42fa1 |
feat: add Run your first workflow button to home hero (#11848)
## Summary Add an outline-style `BrandButton` to the right side of the home page hero section linking to the workflows page. ## Changes - **What**: - Added a `Run your first workflow` outline button below the subtitle in `apps/website/src/components/home/HeroSection.vue`, linking to `externalLinks.workflows`. Mirrors the button pattern from `product/local/HeroSection.vue`. - Added `hero.runFirstWorkflow` i18n entry (en + zh-CN) in `apps/website/src/i18n/translations.ts`. ## Review Focus - Confirmed alignment with design spec. <img width="1505" height="776" alt="image" src="https://github.com/user-attachments/assets/215e667d-1827-447b-99b8-eba8cb5ec7e3" /> <img width="335" height="700" alt="image" src="https://github.com/user-attachments/assets/aeac0876-74c3-4e12-a4b3-203f9e541bc2" /> ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11848-feat-add-Run-your-first-workflow-button-to-home-hero-3546d73d365081358d54eddfda71111e) by [Unito](https://www.unito.io) Co-authored-by: Amp <amp@ampcode.com> |
||
|
|
ccd19d8695 |
test: add metadata parser coverage (#11307)
## Summary Adds tests for metadata parsers ## Changes - **What**: - add test file generation script - identified & fixed bug in webp exif parsing over-reading - identified & fix bug in mp3/ogg parser where it would read from a fixed position instead of relative, causing incorrect reads throwing RangeError - added catch in latent + json parsing to resolve errors ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11307-test-add-metadata-parser-coverage-3446d73d36508108ac36dddcec0a54d4) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com> |
||
|
|
809fba7b36 |
feat: add Groove Jones customer story (#11849)
## Summary Add a new customer story for Groove Jones — Crocs x NFL FOOH holiday campaign for Dick's Sporting Goods, delivered with Comfy. ## Changes - **What**: - New entry in [`apps/website/src/config/customerStories.ts`](https://github.com/Comfy-Org/ComfyUI_frontend/blob/feat/groove-jones-customer-story/apps/website/src/config/customerStories.ts) registering slug `groove-jones` with cover image hosted on `media.comfy.org/website/customers/groove-jones/`. - Added `customers.story.groove-jones.{category,title,body}` and `customers.detail.groove-jones.topic-1` … `topic-10` translations (en + zh-CN) in [`apps/website/src/i18n/translations.ts`](https://github.com/Comfy-Org/ComfyUI_frontend/blob/feat/groove-jones-customer-story/apps/website/src/i18n/translations.ts). 10 sections matching design sidebar: INTRO, THE OUTPUT, THE PROBLEM, HOW COMFY SOLVED THE PROBLEM, BRAND-TRAINED LORAS, MULTI-MODEL ORCHESTRATION, THE PIPELINE, VERSION CONTROL, FINISHING IN NUKE, THE TAKEAWAY. - Includes 2 pull quotes (Doug Hogan, Dale Carman), 1 final blockquote + author card, and 3 inline images. - Routes `/customers/groove-jones` and `/zh-CN/customers/groove-jones` are auto-generated by `[slug].astro`. ## Review Focus - Contributors author card uses `TBD` placeholder names/roles — to be filled in. - No `readMoreHref` set yet (no public blog post URL). - All 4 images uploaded to `gs://comfy-org-videos/website/customers/groove-jones/` and served via `media.comfy.org`. <img width="1000" height="535" alt="Kapture 2026-05-02 at 23 17 04" src="https://github.com/user-attachments/assets/28654d24-0d49-4303-82ac-b6923cd6bc93" /> ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11849-feat-add-Groove-Jones-customer-story-3546d73d36508128a64bd6809ad77447) by [Unito](https://www.unito.io) Co-authored-by: Amp <amp@ampcode.com> |
||
|
|
df2ae6f2d0 |
fix(load3d): dispose THREE.Points GPU resources in clearModel() (#11836)
Fixes #11345 ## Summary `clearModel()` in `SceneModelManager` only traversed and disposed `THREE.Mesh` instances, leaving `THREE.Points` objects (created by `handlePLYModeSwitch()` for point-cloud mode) leaking GPU geometry and material memory on repeated point-cloud loads/clears. ## Changes - `SceneModelManager.ts`: extend the dispose traversal in `clearModel()` to also handle `THREE.Points`, mirroring the pattern already used by `removeAllMainModelsFromScene()`. - `SceneModelManager.test.ts`: add regression test verifying `geometry.dispose()` and `material.dispose()` are called for `THREE.Points` children on `clearModel()`. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11836-fix-load3d-dispose-THREE-Points-GPU-resources-in-clearModel-3546d73d365081718338e824bc3e737d) by [Unito](https://www.unito.io) |
||
|
|
3c7781190a |
feat(website): add llms.txt for GEO discovery by AI search agents (#11830)
## Summary Adds `/llms.txt` at the apex following the [llms.txt standard](https://llmstxt.org) — a curated, link-based markdown file that tells LLM-based search agents (ChatGPT search, Perplexity, Claude search, Google AI Overviews, etc.) what's most important on the site. It complements `robots.txt` (crawler permissions) and `sitemap-index.xml` (URL inventory) by giving AI agents a short, prose-friendly index they can ingest into a context window. ## What's in the file 28 links across 6 sections: - **Product** (6) — homepage, Local download, Cloud, Cloud pricing, API, Enterprise - **Workflows and Gallery** (2) — gallery + community workflows site - **Customers and Case Studies** (5) — customers index + 4 named studios (Series Entertainment, Moment Factory, Ubisoft Chord, Open Story Movement) - **Developers and Documentation** (4) — docs.comfy.org, ComfyUI repo, Comfy-Org GitHub org, registry.comfy.org - **Company** (6) — about, careers, contact, blog, privacy, terms - **Optional** (5) — `zh-CN` locale variant, long-form enterprise case studies, blog posts (de-prioritized per spec — agents can skip if context-limited) The intro paragraph names the four product surfaces (Local, Cloud, API, Enterprise), the named customers, and the use-case industries (VFX & animation, advertising, gaming, eCommerce/fashion) — so an agent that ingests only the prose still gets the elevator pitch. ## Verification - All 28 URLs verified live (`HTTP 200`) before commit. - File is plain markdown — no build step. Astro/Vercel will serve it from `apps/website/public/llms.txt` exactly as it serves `robots.txt` (which lives in the same directory and ships at `https://comfy.org/robots.txt`). - Will verify on the Vercel preview deploy after this PR opens that `curl -sI https://<preview>/llms.txt` returns `200` with a sensible `content-type`. (`robots.txt` currently serves as `text/plain; charset=utf-8` — `.txt` will likely do the same; that's fine for AI agents.) ## Decisions - **No `llms-full.txt` yet.** That variant inlines full prose of key pages and requires curating substantive content. Deferred to a follow-up — the marketing-site pages are mostly Vue-rendered hero/feature blocks rather than long-form prose, so a meaningful `llms-full.txt` would need either dedicated copy or a build step that flattens i18n strings + section text. Tracking separately. - **No comment line in `robots.txt`.** I considered adding a `# AI agents: see /llms.txt` comment above the `Sitemap:` directive, but decided against it: (a) the convention is to probe the well-known path `/llms.txt` directly, not to discover it via robots.txt; (b) `robots.txt` was just polished in #11823 with a deliberate compact design and adding a non-standard comment would muddy that; (c) zero implementations I checked actually parse robots.txt for llms.txt hints. Easy to add later if needed. ## Context Third of three follow-ups from the SEO/GEO sweep on 2026-05-02: 1. ~~Comfy-Router: add `X-Content-Type-Options: nosniff` to apex security headers~~ (separate PR on `Comfy-Org/comfy-router`) 2. ~~Cloudflare: enable "Always Use HTTPS"~~ (dashboard toggle, no PR) 3. **This PR** — add `llms.txt` for GEO discovery ## Testing - [x] All linked URLs return 200 - [x] File parses as valid markdown - [ ] Preview deploy serves `/llms.txt` (will verify once preview is up) ┆Issue is synchronized with this [Notion page](https://app.notion.com/p/PR-11830-feat-website-add-llms-txt-for-GEO-discovery-by-AI-search-agents-3546d73d365081a98c6bfc5301699f64) by [Unito](https://www.unito.io) |
||
|
|
167a1e6a0c |
fix(website): override X-Robots-Tag to index,follow on production deployment (#11831)
## P0 SEO fix — entire marketing site is currently `noindex` A deep-audit sweep on **2026-05-02** confirmed that every page on `comfy.org` (home, `/about`, `/pricing`, `/customers`, `/careers`, …) is being served with: ``` x-robots-tag: noindex ``` This hides the entire marketing site from Google and other search engines. ### Root cause `comfy.org` reaches the Astro marketing site via a Cloudflare Worker reverse proxy ([`comfy-router`](https://github.com/Comfy-Org/comfy-router)) that does: ```js fetch('https://website-frontend-comfyui.vercel.app/...') ``` Per Vercel's KB article [Avoiding duplicate-content with vercel.app URLs](https://vercel.com/kb/guide/avoiding-duplicate-content-with-vercel-app-urls): > By default, Vercel adds an `X-Robots-Tag: noindex` HTTP header to all deployments hosted on `vercel.app` URLs. […] This header tells search engines like Google not to index these deployment URLs. Because `website-frontend-comfyui.vercel.app` is **not** registered as a Production custom domain on the Vercel project, Vercel applies that header — and our Worker faithfully forwards it back to `comfy.org` clients (and Googlebot). ### Fix Vercel's documented workaround for proxied `*.vercel.app` setups is to override the header via `vercel.json` ([blog post by Dan Denney](https://www.dandenney.com/posts/front-end-dev/fixing-x-robots-nofollow-with-vercel/)): ```json "headers": [ { "source": "/(.*)", "has": [ { "type": "host", "value": "website-frontend-comfyui.vercel.app" } ], "headers": [ { "key": "X-Robots-Tag", "value": "index, follow" } ] } ] ``` ### Why the `has` host filter Critical scoping detail: without the `has` filter, the override would also apply to PR-preview deployments at `comfy-website-preview-pr-N.vercel.app`. We want previews to **stay** `noindex` to avoid duplicate-content competition with production. The filter pins the override to the production deployment hostname only. The hostname matches `WEBSITE_ORIGIN` in `comfy-router/src/index.js`: ```js const WEBSITE_ORIGIN = 'https://website-frontend-comfyui.vercel.app'; ``` ### Defense in depth A parallel PR on `comfy-router` (TBD) will also strip `X-Robots-Tag: noindex` at the Worker layer, so the public `comfy.org` response is correct even if a future Vercel project change re-introduces the upstream header. ### Verification (after merge + Vercel production deploy) ```bash # Production should no longer be noindex curl -sI https://comfy.org/ | grep -i x-robots-tag curl -sI https://comfy.org/about | grep -i x-robots-tag curl -sI https://comfy.org/pricing | grep -i x-robots-tag # Expect: empty output, OR "x-robots-tag: index, follow" # Direct Vercel production hostname curl -sI https://website-frontend-comfyui.vercel.app/ | grep -i x-robots-tag # Expect: "x-robots-tag: index, follow" # Preview deploys must stay noindex (proves the host filter works) curl -sI https://comfy-website-preview-pr-<N>.vercel.app/ | grep -i x-robots-tag # Expect: "x-robots-tag: noindex" ``` ### Pre-merge state (for the record) ``` $ curl -sI https://comfy.org/ | grep -iE 'x-robots-tag|x-served-by' x-served-by: vercel-website x-robots-tag: noindex ``` ### Scope Minimum delta — only `apps/website/vercel.json`. No other files touched. ┆Issue is synchronized with this [Notion page](https://app.notion.com/p/PR-11831-fix-website-override-X-Robots-Tag-to-index-follow-on-production-deployment-3546d73d365081489b62e6633d25dfe5) by [Unito](https://www.unito.io) --------- Co-authored-by: Christian Byrne <christian@comfy.org> Co-authored-by: GitHub Action <action@github.com> |
||
|
|
e4e1546458 |
test: add queue notification banners lifecycle browser tests (#11366)
*PR Created by the Glary-Bot Agent* --- ## Summary - Adds `browser_tests/tests/queueNotificationBanners.spec.ts` covering `useQueueNotificationBanners` composable E2E behavior - Adds `data-testid="queue-notification-banner"` to `QueueNotificationBannerHost.vue` for stable test targeting - Registers the new test ID in `TestIds.queue.notificationBanner` ### Test coverage added (7 tests) | Group | Tests | Behavior | |---|---|---| | Queuing lifecycle | 4 | `promptQueueing` → banner appears, `promptQueued` upgrades to queued, batch plural text, requestId mismatch doesn't upgrade | | Auto-dismiss | 1 | Banner disappears after 4s timeout | | FIFO queue | 1 | Second notification shows after first auto-dismisses | | Direct queued | 1 | `promptQueued` without prior `promptQueueing` shows banner directly | ### Approach Tests dispatch `promptQueueing`/`promptQueued` custom events directly via `window.app.api.dispatchCustomEvent()` inside `page.evaluate()`, matching how `app.ts` triggers these events during real queue operations. This avoids needing a running execution pipeline while exercising the full composable → component → DOM rendering chain. ### Verification - TypeScript: zero errors - ESLint: clean - oxlint: clean - oxfmt: formatted - Playwright execution requires running ComfyUI backend (not available in sandbox) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11366-test-add-queue-notification-banners-lifecycle-browser-tests-3466d73d36508172a7ffd3fe3b4fd925) by [Unito](https://www.unito.io) --------- Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> Co-authored-by: Amp <amp@ampcode.com> |
||
|
|
c1954028d1 |
feat(ci): add Release:Website workflow to refresh Ashby snapshot (#11829)
## Summary
Adds a unified manual-trigger release flow for the `apps/website`
package
(careers/marketing site at comfy.org), mirroring how main-app releases
work.
**User-facing flow:**
```
workflow_dispatch ──► fresh Ashby pull ──► auto-PR with snapshot bump
│
▼
existing CI / Vercel preview deploy
│
▼
human merges ──► auto prod deploy
```
The careers data on comfy.org comes from Ashby and is fetched at build
time by
`apps/website/src/utils/ashby.ts`. Without `WEBSITE_ASHBY_API_KEY`, the
build
falls back to a committed snapshot at
`apps/website/src/data/ashby-roles.snapshot.json`. That snapshot has
been
going stale because no CI workflow was passing the API key. This PR
fixes
both: a manual refresh workflow + day-to-day secrets wiring.
## Files
**Added**
- `.github/actions/ashby-pull/action.yaml` — composite action that runs
`pnpm --filter @comfyorg/website ashby:refresh-snapshot` with the Ashby
secrets piped in. Uses the existing `setup-frontend` composite for
pnpm/Node setup.
- `.github/workflows/release-website.yaml` — `workflow_dispatch`-only
release workflow. Checks out `main`, refreshes the snapshot via the
composite action, opens a PR labelled `Release:Website` via
`peter-evans/create-pull-request@c0f553fe…` (the same SHA pin used by
`release-version-bump.yaml`).
**Modified**
- `.github/workflows/ci-website-build.yaml` — adds
`WEBSITE_ASHBY_API_KEY`
and `WEBSITE_ASHBY_JOB_BOARD_NAME` env to the `Build website` step.
- `.github/workflows/ci-vercel-website-preview.yaml` — adds the same env
to both `vercel build` steps (preview + production).
## Snapshot fallback preserved
`apps/website/src/utils/ashby.ts` keeps using the committed snapshot
when
the API key is absent (e.g. fork PRs, secret rotation). Verified
locally:
```
$ pnpm --filter @comfyorg/website ashby:refresh-snapshot
Snapshot refresh aborted. Outcome: stale; reason: missing WEBSITE_ASHBY_API_KEY...
```
The release workflow surfaces this as a job failure, which is the
desired
behavior for a manual release trigger.
## Validation
- `yamllint --config-file .yamllint` on all changed YAML — clean
- `./scripts/cicd/check-yaml.sh` — clean
- `pinact run --check` on new files — clean (matches `.pinact.yaml`
policy)
- `pnpm install --frozen-lockfile` — works with `.nvmrc` Node 24
- Husky pre-commit hooks (eslint + typecheck + lint-staged) passed
## Caveats
- **Cannot fully end-to-end test until merged.** `workflow_dispatch`
workflows only run from branches that exist on `main`. The first
manual run can only happen after this PR lands. The pieces that
*can* be tested pre-merge — yamllint, pinact pin validation, and
the existing `CI: Website Build` / `CI: Vercel Website Preview`
workflows now picking up the secret — will run on this PR.
- **`Release:Website` label needs to be created** in the repo before
the auto-PR step will successfully apply it.
`peter-evans/create-pull-request`
will warn but not fail if the label doesn't exist. Suggested color:
`#4f6ef5` (matches `cloud/*` family in `release-branch-create.yaml`).
- The release workflow uses `secrets.PR_GH_TOKEN` (matching
`release-version-bump.yaml`) so the auto-PR can be authored by a
PAT and trigger downstream CI workflows. Without `PR_GH_TOKEN` it
will fall back behavior is up to GitHub Actions defaults — confirm
the secret exists before the first run.
## Context
Came out of work on `comfy-router#22` + `ComfyUI_frontend#11823`
(comfy.org/countdown subpage / website refresh). Discovered the
8+-day-stale snapshot while auditing the website build path.
┆Issue is synchronized with this [Notion
page](https://app.notion.com/p/PR-11829-feat-ci-add-Release-Website-workflow-to-refresh-Ashby-snapshot-3546d73d3650811eb300d8bcb593c652)
by [Unito](https://www.unito.io)
|
||
|
|
5cad2c952b |
refactor+test: extract useSubscriptionCheckout composable, rewrite tests (#11396)
## Summary Adds 20 component tests for `SubscriptionRequiredDialogContentWorkspace.vue` covering: - **Initial rendering**: pricing table display, close/back button visibility, out_of_credits reason message - **Close button**: calls onClose callback - **Subscribe click flow**: pricing→preview transitions (new subscription & upgrade), error toasts for disallowed/missing/failed previews, monthly billing cycle - **Back button**: returns from preview to pricing step - **Add credit card**: handles subscribed status (success toast + close), needs_payment_method (opens Stripe URL), error state - **Confirm transition**: success path with close emit, error toast on failure - **Resubscribe**: success path with toast + close, error toast on failure ## Testing ```bash pnpm test:unit -- src/platform/workspace/components/SubscriptionRequiredDialogContentWorkspace.test.ts ``` All 20 tests pass. Quality gates (typecheck, lint, format, knip) pass. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11396-test-add-component-tests-for-SubscriptionRequiredDialogContentWorkspace-3476d73d36508156a218dcb67a2a334e) by [Unito](https://www.unito.io) |
||
|
|
e356addeb6 |
feat: add model links for default workflow (#11308)
We now support detecting the missing models when loading the workflow. But the default workflow didn't include an embedded model link, so users don't know where to download the model or which one to use. Users will see an error when loading the default workflow every time, so I updated it to include the model link. Before <img width="1920" height="1050" alt="image" src="https://github.com/user-attachments/assets/08774480-78ae-41b4-85bd-64b431079ec1" /> After <img width="1920" height="1050" alt="image" src="https://github.com/user-attachments/assets/dcec5a02-94ad-416f-9881-d761f4137fbd" /> ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11308-feat-add-model-links-for-default-workflow-3446d73d365081188978e1d313c38ffe) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com> |
||
|
|
e831daae59 |
feat(website): point robots.txt at /sitemap-index.xml + AI crawler rules (#11823)
## Summary Once [comfy-router#22](https://github.com/Comfy-Org/comfy-router/pull/22) ships, `comfy.org/sitemap-index.xml` will return a unified index aggregating both the website (38 URLs) and workflow-templates sitemaps. This PR: 1. Reverts `Sitemap:` back to `/sitemap-index.xml` (was `/sitemap-0.xml` in #11802 as a workaround for the 404). 2. Adds explicit allow records for 21 search and AI/LLM crawlers (GPTBot, ChatGPT-User, OAI-SearchBot, Google-Extended, ClaudeBot, Claude-Web, anthropic-ai, PerplexityBot, Perplexity-User, Applebot-Extended, Bytespider, Amazonbot, CCBot, Meta-ExternalAgent, Meta-ExternalFetcher, Diffbot, etc.). 3. Adds `Disallow:` for `/_astro/`, `/_website/`, `/_vercel/` — Vercel build artifacts that aren't useful to crawl. ## Why granular UAs Stacked `User-agent:` records (per [RFC 9309 §2.2](https://datatracker.ietf.org/doc/html/rfc9309#section-2.2)) share one rule block. Listing each bot explicitly: - Signals intent to AI bots that look for their UA in robots.txt before crawling more aggressively. - Surfaces our crawl policy clearly to anyone inspecting the file. - Lets us add per-bot Disallows in future without restructuring. ## Merge order ⚠️ **Do NOT merge until comfy-router#22 is deployed to production.** Until then, `/sitemap-index.xml` returns 404 and this PR would re-break the issue PR #11802 patched. Verification: ```bash curl -sI https://comfy.org/sitemap-index.xml # expect: HTTP/2 200, x-served-by: worker-sitemap-index ``` Once that returns 200, this is safe to merge. ## Verification (after merge + deploy) ```bash # robots.txt is served and points at the unified index curl -s https://comfy.org/robots.txt | grep '^Sitemap:' # → Sitemap: https://comfy.org/sitemap-index.xml # Each AI crawler can fetch it for ua in 'GPTBot/1.0' 'ClaudeBot/1.0' 'PerplexityBot/1.0' 'Google-Extended' 'Applebot-Extended'; do curl -s -o /dev/null -w "$ua → %{http_code}\n" -A "$ua" https://comfy.org/robots.txt done # Sitemap is reachable from robots.txt SITEMAP=$(curl -s https://comfy.org/robots.txt | awk -F': ' '/^Sitemap:/ {print $2}') curl -s "$SITEMAP" | xmllint --noout - && echo "valid XML" ``` ## Linear / closes - Closes FE-437 (AI crawler rules) - Updates FE-432 — the robots.txt change in #11802 was a workaround that's no longer needed once #22 ships ┆Issue is synchronized with this [Notion page](https://app.notion.com/p/PR-11823-feat-website-point-robots-txt-at-sitemap-index-xml-AI-crawler-rules-3546d73d3650811dbceedd06c00db444) by [Unito](https://www.unito.io) |