* fix(sidebar): merge preset HEAD route into GET handler PR #68 shipped koolook_routes.py with @routes.get + @routes.head on the same path. aiohttp's add_get auto-registers HEAD by default, so the explicit @routes.head collided with the auto-synthesized HEAD and crashed ComfyUI startup with "Added route will never be executed, method HEAD is already registered". Trying allow_head=False on the GET to opt out triggered a second crash: ComfyUI's server.py mirrors every PromptServer route into a parallel /api/... table via api_routes.route(method, path)(handler, **kwargs), and RouteTableDef.route's inner closure rejects unknown kwargs with TypeError. So no kwarg-based opt-out is viable. Drop the dedicated HEAD handler. Aiohttp's auto-HEAD-from-GET delivers HEAD probes to get_preset; we branch on request.method to skip the file read for HEAD — preserving the cheap-existence optimization the client's presetExists relies on for multi-MB JSON over Dropbox / iCloud / NFS-mounted libraries. CHANGELOG [Unreleased] updated to match. This bug never reached users — koolook_routes.py was added in #68 (post-v0.2.0) and was never published to Comfy Registry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(sidebar): Tools row + starter preset replaces curated_defaults Two coordinated UX changes for fresh-install distribution + admin ergonomics — designed together and shipped as one unit. 1. New "Tools" row sits between the Snapshot row and the search field. Moves the Export and "Install missing for picks" buttons up out of the Nodes row (admin/advanced operations don't belong in the everyday + Add toolbar). Adds a new "Drop placeholders onto canvas" button — the security_level=normal escape hatch for installing missing packs: instantiates one placeholder per missing pack on a fresh canvas tab so ComfyUI/Manager's standard "Install Missing Custom Nodes" detection takes over via Manager's UI flow (which uses different gates than our programmatic /customnode/install/ git_url call). Nodes row keeps only the everyday + button. 2. curated_defaults.json retired in favor of starter_preset.json. Fresh installs no longer get picks seeded directly into localStorage on first load. Instead the bundled web/starter_preset.json (full snapshot format — picks + workflows + tags + archive) is copied into the user's snapshot library directory as starter.json. The user opens Snapshot -> Load -> starter to apply in one click. Unifies fresh-install distribution with the per-user snapshot library (#68); maintainer flow becomes "build state in ComfyUI -> click the (down-arrow) Tools-row button -> paste over web/starter_preset.json -> commit." Existing users with non-empty picks are explicitly skipped by the new seeder, so their state is untouched. Removed: seedDefaultsIfNeeded, exportPicks, web/curated_defaults.json, SEEDED_KEY, DEFAULTS_URL. Added: seedStarterPresetIfNeeded, exportStarterPreset (snapshot.js), STARTER_SEEDED_KEY, STARTER_URL, STARTER_PRESET_FILENAME, discoverMissingPacks (installer.js), dropPlaceholdersForPacks (canvas_io.js), web/starter_preset.json. Docs: CLAUDE.md "Curated Nodes sidebar — distributed defaults" -> "Kforge Labs sidebar — starter preset distribution". docs/maintainers/curated-sidebar.md rewritten. CHANGELOG.md [Unreleased] updated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4.3 KiB
Kforge Labs sidebar starter preset — quick reference
The "Kforge Labs" sidebar tab (id koolook.curatedNodes); implementation in
web/koolook_sidebar.js.
What ships to fresh users
A single bundled snapshot file at web/starter_preset.json — same format the user-facing Snapshot library uses (picks + workflows + tags + archive). On first launch the seeder copies it into the user's snapshot library directory as starter.json. The user opens Snapshot → Load, sees one entry called starter, clicks → state populated.
Nothing seeds into localStorage directly anymore — replaced the legacy curated_defaults.json pick-only seed in 0.3.0.
Update the shipped starter preset
- In ComfyUI's Kforge Labs tab, customize the state you want fresh users to see — picks via
+/×/ right-click; workflows via the Workflows section; tags via right-click "Tags…". - In the Tools row (between Snapshot and the search field), click the ↓ button → full snapshot JSON copied to clipboard.
- Open
web/starter_preset.jsonin your editor, paste over the contents, save. git commit ... && git push. Does not trigger publish — onlypyproject.tomlchanges merged tomaindo.
Files & storage keys
| Where | What |
|---|---|
web/starter_preset.json (repo) |
Bundled starter preset, snapshot format |
web/koolook_sidebar.js (repo) |
Sidebar entry point |
web/sidebar/snapshot.js (repo) |
seedStarterPresetIfNeeded + exportStarterPreset |
<library-dir>/starter.json (per-install) |
The seeded preset on the user's disk |
localStorage["koolook.starter.seeded.v1"] |
"1" once the seed has been attempted on this browser |
localStorage["koolook.curated.userPicks.v1"] |
User's actual picks list (per-browser) |
localStorage["koolook.snapshot.currentPresetName.v1"] |
Last preset the user loaded/saved |
The library directory is configured by (in priority order):
- The
libraryPathfield in<comfyui-userdata>/koolook-settings.json(set via Snapshot → Settings dialog), - The
KFORGELABS_PRESETSenv var (deployment / facility config), - Default fallback
<comfyui-userdata>/koolook-presets/.
See koolook_routes.py for the resolution chain.
Reset (force re-seed)
In the browser DevTools console with ComfyUI open:
localStorage.removeItem("koolook.starter.seeded.v1");
localStorage.removeItem("koolook.curated.userPicks.v1");
// And delete <library-dir>/starter.json on disk (or via Snapshot → Load → × button)
location.reload();
The seeder bails when picks are non-empty (treats it as "existing user, don't re-seed"), so the picks deletion is necessary for the seed to fire.
Things that surprised us — keep in mind
- The seeder needs the snapshot library reachable. It calls the same
/koolook/presets/fileendpoint the Save dialog uses. If the library path is read-only, points at a non-existent directory, or the routes module isn't loaded, the seed silently retries on the next page load — no error toast for fresh users. See the console for[Koolook] starter seed: …messages. - Paste is manual. Browsers can't write to your filesystem. The ↓ button only copies to clipboard / falls back to a download. Nothing auto-updates
starter_preset.json. - Other users can't reach the repo. Their ↓ click only touches their own clipboard / library. Only you, with push access, can change the distributed starter.
- Seeding runs exactly once per browser. Existing users with picks already in localStorage are explicitly skipped (the
loadUserPicks().length > 0early-return) so a new starter doesn't disturb their state. To preview the fresh-install UX yourself, use the reset block above. - The seed populates the library, not the canvas. After seeding, the user still has empty picks until they explicitly Load the starter preset. This was the design choice for 0.3.0 — discoverable, opt-in, respects user agency. Pattern 1 (auto-apply on first run, identical to the old curated_defaults UX) was rejected because the source-of-state becomes invisible to the user.
- No publish on this kind of push. Edits under
web/never trigger the registry publish workflow; only apyproject.tomlchange merged tomaindoes. Seereleasing.md.