Every bundle the CMS writes — upload, clone, sync, repair and the pet / effect / figure importers — now lands as `<classname>.hab`, the extension this deployment's renderer asks for. `.hab` and `.nitro` are the same container, so an upload of either extension is accepted. Resolution goes through one module, src/lib/furni/bundle-file.ts, so nothing has to know the extension twice. Every existence check probes `.hab` first and falls back to `.nitro`: the on-disk asset set is still predominantly `.nitro`, and without the fallback Studio would report every imported item as missing and the cleanup scan would classify 18k live bundles as fake leftovers. Downloads are unchanged — Habbo's CDN and every configured clone source still serve `.nitro`, so the conversion happens on write, not on request. Deliberately unchanged: the staged-attachment store in furni-attachment.ts keys on a UUID and never reaches the client, so renaming it would break in-flight recovery jobs. Adds scripts/migrate-nitro-to-hab.ts to rename the existing asset set. It refuses to run without --dry-run or --yes, never overwrites an existing .hab, never deletes, and is idempotent. Note: renderer-config.json lives outside this repo and was patched to .hab separately; that file is served with a 30-day max-age, so returning clients need a cms-client cache purge to pick the change up.
Catalog Studio code map
studio-client.tsx composes the workspace, selection and actions. Keep reusable data handling outside its render tree.
Client responsibilities
studio-filters.ts: pure filtering and sorting of the loaded furniture list; never mutates the input array.use-studio-translations.ts: language selection, persisted defaults and translation requests.use-furniture-jobs.ts: queue submission, retry identity, polling and completion notifications.furniture-jobs.tsx: job history and retry controls.use-furniture-inspection.ts: cancellable inspection requests and explicit rechecks.furniture-inspector.tsx: local component status, source comparison and repair controls.import-review.tsx: import review, actionable review groups and attachment confirmation.import-recommendation.ts: completion, conflict and verification recommendations from inspected component evidence.studio-types.ts: shared client data types.
Server responsibilities
src/lib/services/furniture-inspection.ts: reads SQL, catalog offers, furnidata and asset presence.src/lib/furni/studio-inspection.ts: shared validation, comparison and completeness classification.src/lib/services/furniture-repair.ts: preflight, preservation options and post-repair verification.src/lib/services/furni-job-worker.ts: durable queued work and per-item results.
Keep client modules free of filesystem/database imports. Background refreshes must not reset open editors or unsaved input. Completion status must come from verification, not optimistic UI flags.
Detail navigation keeps the mounted workspace state and restores the list scroll position and originating control on close. Escape closes an open detail before clearing selection. Furniture responses must belong to the latest list request; source changes invalidate pending detail, review and delete state. Selection is never persisted outside the mounted workspace.