Files
malkuthro-ComfyUI-Koolook/docs/maintainers/curated-sidebar.md
T
malkuthroandClaude Opus 4.7 a6a31c8086 feat(sidebar): Tools row + starter preset replaces curated_defaults (#72)
* 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>
2026-05-05 17:18:15 +02:00

4.3 KiB
Raw Blame History

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

  1. 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…".
  2. In the Tools row (between Snapshot and the search field), click the ↓ button → full snapshot JSON copied to clipboard.
  3. Open web/starter_preset.json in your editor, paste over the contents, save.
  4. git commit ... && git push. Does not trigger publish — only pyproject.toml changes merged to main do.

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):

  1. The libraryPath field in <comfyui-userdata>/koolook-settings.json (set via Snapshot → Settings dialog),
  2. The KFORGELABS_PRESETS env var (deployment / facility config),
  3. 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/file endpoint 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 > 0 early-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 a pyproject.toml change merged to main does. See releasing.md.