Phase C: Split monolithic modules, consolidate duplicates - #709
Merged
Conversation
Framework package mistakenly committed into the catalog realm. Not a catalog listing, and not imported by any catalog file — the only references elsewhere were an unrelated CSS var name coincidentally containing "boxel-surface" and doc comments noting other components were "ported from"/"styled after" it while staying self-contained.
blog-app.gts (2477 lines) was one giant class per section (BlogAdminData, BlogAppTemplate, BlogSiteView, IsolatedPortal) plus the BlogApp CardDef itself. Extracted the four component classes into components/admin-view.gts, admin-template.gts, site-view.gts, and isolated-portal.gts. blog-app.gts now only holds the CardDef. No Spec update needed — BlogApp's own Spec still points at ./blog-app, and none of the internal components are Spec-referenced.
GradeField, QuestionField, LetterGradeField, and isGradeConsistent were defined inline in homework-grader.gts (3032 lines) ahead of the giant HomeworkIsolated/HomeworkFitted component classes, with zero dependency on their instance state. Moved them to fields.gts; the two big component classes are untouched. Updated the 3 Specs (GradeField, QuestionField, LetterGradeField) whose ref.module pointed at ../homework-grader to ../fields.
tsp.gts (11452 lines) had a block of ~14 standalone pure functions sitting between the two giant Isolated/Fitted component classes: HTML/string builders, geometry cloning + numeric clamping, and generic async/loading helpers (including a PDF-to-PNG renderer). Grouped into utils/html-builders.gts, utils/geometry.gts, and utils/async-helpers.gts respectively. Neither component class body was touched.
virtual-piano.gts (5414 lines) had keyboard-mapping, notation-parsing, and audio-frequency helpers defined at module scope ahead of the giant IsolatedVirtualPiano class, with no dependency on its instance state. Split into utils/keyboard-helpers.gts, utils/notation-helpers.gts, and utils/audio-helpers.gts. Also dropped a stale comment header left orphaned by the earlier diffLabel/diffClass extraction.
PlayingCardField, StatsField, and normalizeStatistics were defined inline in blackjack.gts (2552 lines) ahead of the giant IsolatedTemplate/FittedTemplate/Blackjack classes, with no dependency on their instance state. Moved to fields.gts. Fixes a regression caught by Copilot-style verification: the move initially dropped StringField/NumberField imports that Blackjack's own CardDef fields still needed, which broke card rendering with "X is not defined". Restored both imports.
DrumKitField, DrumKitCard, BeatPatternField, BeatPatternCard were defined inline in beat-maker.gts (2984 lines) ahead of the giant BeatMakerIsolated/BeatMakerCard classes, with no dependency on their instance state. Moved to fields.gts. Updated 12 pre-existing card instances (6 DrumKitCard + 6 BeatPatternCard) whose adoptsFrom.module still pointed at ../beat-maker post-move. Also fixed 5 Specs whose ref.module had a stale, unrelated broken path left over from a prior submission-folder rename (../beat-maker-studio-<hash>/beat-maker/beat-maker) — 4 now point at ../fields, BeatMakerCard's own Spec at ../beat-maker.
components/generator.gts (2373 lines) had two pure template helpers (versionLabel, friendlyError) defined at module scope alongside the AiImageGeneratorIsolated/AiImageGeneratorEmbedded classes, with no dependency on their instance state. Moved to utils/generator-helpers.gts.
…kens 19dee3-virtual-try-on-application/46f065-popover/ was a fully orphaned copy of the Popover component/utils — virtual-try-on-app.gts already imports the canonical @cardstack/catalog/46f065-popover/popover alias, so nothing referenced the local copy. Before deleting it, ported one real feature it had gained that the canonical version lacked: --bx-popover-* custom-property names in the portal's no-theme-scope fallback bridge, so popover-only knobs set directly on an anchor with no linked theme (not just theme-scoped knobs) still carry across the portal boundary.
Staging Submissions PreviewThis PR's content is pushed to the staging submissions realm: https://realms-staging.stack.cards/submissions/ Changed folders:
Updated at 2026-09-06 07:45:18 UTC for commit |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase C of the Master Catalog Refactor: audit catalog listings for monolithic files and duplicate code, split/consolidate at low risk.
Fixes: CS-12776
Part of: CS-12782 Master Catalog Refactor
Approach: these giant files are one Isolated/Fitted component class holding
@trackedstate, not naturally-separable pieces — so the low-risk extraction only pulls out standalone pure functions / FieldDef classes that already sit outside the component's instance state, leaving the component class bodies untouched.Split (5 originally-identified monoliths):
components/admin-view.gts,admin-template.gts,site-view.gts,isolated-portal.gtsGradeField/QuestionField/LetterGradeField/isGradeConsistent→fields.gts; 3 Specs updatedutils/html-builders.gts,utils/geometry.gts,utils/async-helpers.gtsutils/keyboard-helpers.gts,utils/notation-helpers.gts,utils/audio-helpers.gtsSplit (4 additional monoliths found during the full-catalog audit):
PlayingCardField/StatsField/normalizeStatistics→fields.gtsDrumKitField/DrumKitCard/BeatPatternField/BeatPatternCard→fields.gts; fixed 12 card instances + 5 Specs whose module paths needed updating (one Spec set had a pre-existing, unrelated broken path from an old submission-folder rename)versionLabel/friendlyError→utils/generator-helpers.gtsConsolidated:
boxel-surface+boxel-surface-demo— a framework package mistakenly committed into the catalog realm, not a listing, not imported anywhere (separate commit, already merged)19dee3-virtual-try-on-application/46f065-popover/(nothing imported it — the listing already used the canonical@cardstack/catalog/46f065-popover/popoveralias); ported one real feature the dead copy had gained (--bx-popover-*fallback tokens) into the canonical file firstBugs caught and fixed during verification (none of these would have been caught by lint alone):
StringField/NumberFieldimports still needed by theBlackjackCardDef itself → runtime "X is not defined"adoptsFrom.moduleat../beat-makerafter the classes moved to../fieldsAudited, no action needed: the remaining 21 listings (Tier List, Wine Bottle, Wine Cellar, Stepper, Survey, Mortgage Calculator, 15 field listings) — no stale Specs, no broken imports, no orphaned files. Wine Bottle/Wine Cellar's byte-identical
wine-bottle.gtsis an intentional self-contained copy, confirmed in sync.Follow-ups filed on CS-12776, not in this PR's scope:
image-source-editor.gtsUI has drifted between the canonicalfields/image-sourceand older embedded copies in Virtual Try-On + Tier List (both work, just an outdated design — needs a deliberate backport with browser QA)6a076d-ai-image-generator/Spec/generating-overlay.jsonis a pre-existing orphaned Spec pointing at a file that doesn't exist41e20f-wedding-table-seating-planner'sArrangeSeatsCommandSpec has a redundant.gtsextension in its module path (harmless, resolves fine, just inconsistent)Test plan
.gtsfiles)ref.modulepointing at the new location🤖 Generated with Claude Code