-
Notifications
You must be signed in to change notification settings - Fork 12
Cs 9803 migrate field configuration showcases #3811
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…Field adn override the base spec edit/isolated template (remove example section too )
Preview deployments |
Host Test Results 1 files ± 0 1 suites ±0 1h 35m 44s ⏱️ + 5m 39s For more details on these errors, see this check. Results for commit 3ff3f13. ± Comparison against base commit b2f9b85. This pull request removes 1 and adds 217 tests. Note that renamed tests count towards both.♻️ This comment has been updated with latest results. |
|
|
||
| static isolated = | ||
| FieldSpecIsolatedTemplate as unknown as typeof Spec.isolated; | ||
| static edit = FieldSpecEditTemplate as unknown as typeof Spec.edit; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TypeScript can't verify the compatibility directly. I use this double type assertion (as unknown as typeof Spec.isolated) to tell TypeScript the template is compatible with the expected type
| "attributes": { | ||
| "ref": { | ||
| "name": "AudioFieldSpec", | ||
| "module": "http://localhost:4201/catalog/field-spec/audio-field-spec" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why are the refs absolulte? How is this gonna work in live environment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 'readMe content sourced from proxy mock', | ||
| ); | ||
| }); | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this test work? I thought we had to copy over files for host test that depend on catalog now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ya ,it work but sometimes it flaky in the host test, i wil investigate this
| const title = this.getSpecTitle(declaration, codeRef.name); | ||
| const specType = new SpecTypeGuesser(declaration).type; | ||
|
|
||
| const specClassToUse = await getSpecClassFromDeclaration( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets just call this specKlass as before
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will to rename this to ResolvedSpecKlass because this function also passes SpecKlass as an argument.
| relativeTo, | ||
| codeRefOpts, | ||
| codeRefOpts: metaCodeRefOpts, | ||
| customFieldDefinitions, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is my research.
When creating a Spec, the ref.module field (a CodeRef in attributes) was stored as an absolute URL (e.g., "http://localhost:4200/catalog-realm/blog-app") instead of a relative URL (e.g., "../blog-app/blog-app").
Root Cause:
In file-serializer.ts, processAttributes used codeRefOpts, which lacks:
- allowRelative: true
- maybeRelativeURL function
Without these, codeRefAdjustments couldn't convert absolute URLs to relative ones during serialization.
Solution:
Changed processAttributes to use metaCodeRefOpts instead of codeRefOpts. metaCodeRefOpts includes:
allowRelative: true — enables relative URL conversion
maybeRelativeURL — converts absolute URLs to relative when realmURL is available
Here is the demo after i made this changes:
Screen.Recording.2026-01-09.at.5.59.09.PM.mov
eb05214 to
292e6c3
Compare
| */ | ||
| async function getSpecClassFromDeclaration( | ||
| codeRef: ResolvedCodeRef, | ||
| fallbackSpecClass: typeof BaseDef, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wouldnt this be a typeof CardDef--Specs are Cards not fields
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed with it, the issue has been addressed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR migrates field configuration showcases from a single centralized field-showcase component to individual field spec subclasses with reusable templates. The changes introduce two new template components (FieldSpecIsolatedTemplate and FieldSpecEditTemplate) that provide the Field Configuration Playground functionality while removing the dependency on the large field-showcase file.
Key Changes
- Created reusable
FieldSpecIsolatedTemplateandFieldSpecEditTemplatecomponents for field spec subclasses - Implemented 20+ individual field spec files (AudioFieldSpec, ColorFieldSpec, DateFieldSpec, etc.) with proper configurations
- Enhanced
create-specscommand to automatically use spec subclasses when available - Removed the monolithic
field-showcase.gtsfile (~4000 lines) and its instance data
Reviewed changes
Copilot reviewed 70 out of 71 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
field-spec/components/field-spec-isolated-template.gts |
New reusable isolated template component for field specs with Field Configuration Playground |
field-spec/components/field-spec-edit-template.gts |
New reusable edit template component for field specs with Generate README button |
utils/is-own-field.ts |
Utility to filter inherited fields from own fields in field specs |
field-spec/*-field-spec.gts |
20+ new field spec files with field configurations and custom templates |
commands/create-specs.ts |
Enhanced to automatically detect and use spec subclasses |
tests/integration/commands/create-spec-test.gts |
Added tests for custom templates in subclassed specs |
runtime-common/file-serializer.ts |
Variable rename for clarity |
fields-preview/field-showcase.gts |
Deleted 4000-line monolithic showcase file |
| Various JSON files | New spec instances and supporting image data |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| import type { BaseDef } from 'https://cardstack.com/base/card-api'; | ||
|
|
||
| // When checking ColorFieldSpec: | ||
| // ✅ Returns: 'standard', 'wheel', 'sliderRgb', etc. (directly on ColorFieldSpec) | ||
| // ❌ Does NOT return: 'readMe', 'ref', 'title' (from Spec.prototype - inherited) | ||
| // ❌ Does NOT return: 'id' (from CardDef.prototype - inherited) | ||
| export function isOwnField(card: typeof BaseDef, fieldName: string): boolean { | ||
| return Object.keys(Object.getOwnPropertyDescriptors(card.prototype)).includes( | ||
| fieldName, | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a dupe of the schema-editor.ts's isOwnFields() function. instead of duplicating, please create function in runtime-common that can be shared by these two
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great catch. Thanks for the review and suggestion. I’ve created a shared isOwnField utility in runtime-common

Migrate field specs from field-showcase to individual subclass specs
This is the first pass to migrate fields from field-showcase to each subclass spec.
This change:
FieldSpecIsolatedTemplate / FieldSpecEditTemplate include the Field Configuration Playground (dynamic fields) and hide the example section, which differs from the Base Spec template.te and FieldSpecEditTemplate include the Field Configuration Playground (dynamic fields) and hide the example section, which differs from the Base Spec template.
Demo:
Screen.Recording.2026-01-08.at.6.21.03.PM.mov
Follow-up task:
https://linear.app/cardstack/issue/CS-9974/base-spec-isolatededit-and-subclass-spec-isolatededit-templates-have
In the catalog, we override the Subclass Spec isolated/edit template to display the Field Configuration Playground (dynamic fields / hide the example section). However, most of the remaining code is the same as
the Base Spec template.
We discussed whether we should move the shared isolatedTemplate and editTemplate components into the Base Spec (so both base spec and subclass spec can reuse it), or introduce a shared implementation that both Base and Subclass specs can reference. ** Currently all subclass spec is located under catalog-realms **