Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
217 changes: 36 additions & 181 deletions commands/boxel-create-card.md

Large diffs are not rendered by default.

66 changes: 19 additions & 47 deletions commands/boxel-create-instance.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,63 +20,35 @@ boxel:

## Read

1. `skills/boxel/SKILL.md` (focus: `references/data-management.md`)
2. `skills/boxel-create-edit-cards/SKILL.md`
3. `skills/source-code-editing/SKILL.md` (if going via SEARCH/REPLACE)
1. `skills/boxel/SKILL.md` — cardinal rules 13-14 (external URLs in `links.self`, `linksToMany` indexed keys) plus `references/data-management.md` for the full JSON:API instance shapes (`containsMany` arrays, empty links, `adoptsFrom`).
2. `skills/boxel/references/card-references.md` — how every `links.self` resolves (`./` / `../` / absolute; bare paths throw). Also `references/core-concept.md` "Relationship path resolution" and "`adoptsFrom.module` — URL of the .gts, NOT including the export name".
3. `skills/boxel/references/base-field-catalog.md` — DateField vs DateTimeField value contract; the image URL/ImageDef pair pattern.
4. `skills/boxel-patterns/patterns/theme-first-workflow/README.md` — theme linking via `relationships["cardInfo.theme"]`, absolute URLs for nested folders, and why Theme cards omit the self-theme relationship.
5. `skills/boxel-create-edit-cards/SKILL.md` — choosing the host-command combination.
6. `skills/source-code-editing/SKILL.md` (if going via SEARCH/REPLACE).

## Procedure

1. Decide the tool: `write-text-file` (new instance, simple shape), `patch-fields` (existing instance, surgical), `patchCardInstance` (existing instance, full replace), or SEARCH/REPLACE (large or structural).
2. Compose the JSON. Use `"data"` envelope, `"type": "card"`, `"meta.adoptsFrom"`, `"attributes"`, `"relationships"`.
3. For empty `linksTo`/`linksToMany` use `"self": null`, NEVER `[]`.
4. Save to `<RealmURL>/<CardType>/<slug>.json`.

## Instance shape — JSON:API correctness rules

- **`adoptsFrom.module` is the URL of the .gts, NOT including the export name.** Use `"module": "https://cardstack.com/base/brand-guide"`, `"name": "default"` — never `"module": "https://cardstack.com/base/brand-guide/default"` (that treats the export name as a URL path and returns 404).
- **Every `links.self` MUST start with `./`, `../`, or `http`.** Bare paths like `"BrandGuide/foo"` are treated as npm-style package specifiers and fail with `Cannot resolve bare package specifier`. Use `"./BrandGuide/foo"` for root-level instances, `"../BrandGuide/foo"` for subfolder instances, or absolute URLs for cross-realm references. See `boxel/references/core-concept.md` "Relationship path resolution."
- **`linksToMany` uses INDEXED KEYS, not an array.** Each linked item is its own top-level relationship key:
```json
"relationships": {
"materials.0": { "links": { "self": "../Material/white-oak" } },
"materials.1": { "links": { "self": "../Material/walnut" } }
}
```
NEVER `"materials": { "links": { "self": ["a", "b"] } }` — the host rejects the instance as "not a card resource document" and it never loads.
- **`containsMany` is an ARRAY in attributes.** `"attributes": { "cabinets": [ {...}, {...} ] }` — opposite of `linksToMany`. Easy to mix up.
- **Date fields match their schema type.** `DateField` ↔ `"YYYY-MM-DD"` (no `T`). `DateTimeField` ↔ `"YYYY-MM-DDTHH:MM:SS.sssZ"` (with `T` and `Z`). Mismatch passes lint, crashes at render with `RangeError: Invalid time value`.
- **Image URLs go in the paired `*URL` field, NEVER in a `linksTo` relationship's `links.self`.** Putting an external URL there bricks the realm (Postgres NULL-byte rejection rolls back the whole indexing batch). See Cardinal Rule in CLAUDE.md.
2. Compose the JSON: `"data"` envelope, `"type": "card"`, `meta.adoptsFrom` (module + name), `attributes`, `relationships` — shapes per the Read list above.
3. Include `attributes.cardInfo` unless there's a specific reason not to (it's the user's edit surface); set `relationships["cardInfo.theme"]` when this instance should carry its own theme. Theme instances themselves omit that relationship.
4. Match date string formats to the schema's field type (DateField vs DateTimeField); put external image URLs in the paired `*URL` attribute, never in a relationship.
5. Save to `<RealmURL>/<CardType>/<slug>.json`.

## Done Criteria (self-verify)

- [ ] `"data"` envelope at top level.
- [ ] `"meta.adoptsFrom"` has both `module` and `name`. Module URL does NOT include `/default` or any export-name suffix.
- [ ] Every `links.self` value starts with `./`, `../`, or `http`. No bare paths.
- [ ] `linksToMany` uses indexed-key shape (`"field.0"`, `"field.1"`), NOT array in `links.self`.
- [ ] `containsMany` is an array in `attributes.<field>`.
- [ ] Empty relationships use `"self": null`.
- [ ] `attributes` is an object, NEVER a JSON-string.
- [ ] `relationships` is a sibling of `attributes`, not nested inside it.
- [ ] Include `attributes.cardInfo` (the four-key object: `name`, `summary`, `cardThumbnailURL`, `notes`; nulls fine) UNLESS the CardDef has a meaningful computed `cardTheme` AND there's no name/summary the user might want to edit. When in doubt, include it — it's cheap and gives the user an edit surface.
- [ ] **Per-instance theme override.** If you want THIS instance to override whatever `cardTheme` would otherwise compute, set `relationships["cardInfo.theme"]` with the dotted key. For CardDefs that use the default `cardTheme` pass-through, this is also the only way to install a theme at all. For CardDefs that override `cardTheme` (e.g. Task inherits from Project), it's optional.
- [ ] Exception for Theme card instances themselves: they include `attributes.cardInfo` but OMIT `relationships["cardInfo.theme"]` entirely (no circular self-link).
- [ ] Date string formats match the schema's field type (DateField vs DateTimeField).
- [ ] Image URLs are in `attributes.<heroImageURL>`, NOT in `relationships.<heroImage>.links.self`.
- [ ] `"data"` envelope; `meta.adoptsFrom` has `module` (no export-name suffix) + `name`.
- [ ] Every `links.self` starts with `./`, `../`, or `http` (see `card-references.md`).
- [ ] `linksToMany` uses indexed keys, `containsMany` is an array in attributes, empty links use `"self": null` (cardinal rule 14 + `data-management.md`).
- [ ] `attributes` is an object (never a JSON string); `relationships` is its sibling, not nested inside it.
- [ ] `attributes.cardInfo` present; theme linkage decided per `theme-first-workflow`; no self-theme on Theme instances.
- [ ] Date values match field type; image URLs in the `*URL` attribute (cardinal rule 13 + `base-field-catalog.md`).

## Verification after push

`npx boxel file lint` does NOT confirm the instance is indexed. Run:

```sh
npx boxel search --realm <url> \
--query "{\"filter\":{\"type\":{\"module\":\"<absolute-module-url>\",\"name\":\"<ClassName>\"}}}" \
--json | python3 -c "import json,sys;raw=sys.stdin.read();s=raw.find('[');e=raw.rfind(']')+1;print(len(json.loads(raw[s:e])))"
```

Count must match the number of `<ClassName>` instances you intended to push. If short, look for: bare `links.self` path, malformed `linksToMany` array, wrong `adoptsFrom.module` URL.
`npx boxel file lint` does NOT confirm the instance is indexed. Run the typed-search count gate from `skills/boxel-environment/references/indexing-operations.md`: `npx boxel search` filtered on the CardDef's absolute module URL must return the number of instances you pushed. If short, look for: bare `links.self` path, malformed `linksToMany` array, wrong `adoptsFrom.module` URL.

## Failure Recovery

- "Error: attributes is a string" → `attributes` must be an object literal, not a stringified JSON.
- "Error: relationships inside attributes" → move `relationships` to be a sibling at the top level of `data`.
- See `skills/boxel-environment/references/common-errors.md` for the full error catalogue.
- "attributes is a string" / "relationships inside attributes" → see `skills/boxel-environment/references/common-errors.md` for the full error catalogue with fixes.
- Instance never loads ("not a card resource document") → `linksToMany` array shape; use indexed keys.
14 changes: 3 additions & 11 deletions commands/boxel-design-card.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: boxel-design-card
description: Improve a card's visual design — colors, typography, mood, asset direction, theme tokens.
description: Workflow to improve an EXISTING card's visual design end-to-end — Theme check, design discovery, tokenization. Routes into boxel-design (visual decisions) and boxel-ui-guidelines (template implementation); use this for the procedure, those skills for the rules.
boxel:
kind: skill
---
Expand Down Expand Up @@ -35,15 +35,7 @@ boxel:

2. Run the design discovery process from `boxel-design`: mood, audience, references, distinctive angle. Use those to inform the Theme card's `visualDNA` + `cssVariables`.

3. Link `cardInfo.theme` on every relevant instance:
```json
"relationships": {
"cardInfo.theme": {
"links": { "self": "../Theme/<name>" }
}
}
```
The relationship key has a literal dot — `"cardInfo.theme"`, not nested.
3. Link `cardInfo.theme` on every relevant instance — the relationship key has a literal dot (`"cardInfo.theme"`, not nested). Exact JSON shape: `theme-first-workflow/README.md`.

4. Update templates' `<style scoped>` blocks to reference only theme tokens (`var(--background)`, `var(--card)`, `var(--primary)`, `var(--font-sans)`, etc.). Strip any hard-coded colors.

Expand All @@ -59,4 +51,4 @@ boxel:

- "Looks the same after edit" → check that the instance has `cardInfo.theme` set; without it, the Theme's CSS variables aren't injected.
- "Theme card not applying" → confirm the linked Theme exists at the URL in `cardInfo.theme.links.self`; confirm `cssVariables` includes `:root { ... }` selectors.
- "Style changes work locally but not after sync" → the realm needs to re-index the Theme card after `cssVariables` updates. Use `/boxel-debug-runtime` or `npx boxel realm cancel-indexing` + manual re-trigger.
- "Style changes work locally but not after sync" → the realm needs to re-index the Theme card after `cssVariables` updates. Touch the Theme file (`npx boxel file touch`) or use `/boxel-debug-runtime`. Do **not** reach for `cancel-indexing` — slow indexing is not stuck indexing (see `boxel-environment/references/indexing-operations.md`).
50 changes: 9 additions & 41 deletions commands/boxel-develop-theme.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,58 +23,26 @@ boxel:

## Read

1. `skills/boxel-theme-development/SKILL.md`.
1. `skills/boxel-theme-development/SKILL.md` — THE workflow (classify → choose card type → gather → map → build → validate). This command follows it end to end.
2. `skills/boxel-theme-development/references/shadcn-boxel-token-mapping.md` before assigning semantic token values.
3. `skills/boxel-theme-development/references/design-md-adapter.md` if DESIGN.md, brand-guide prose, or token conversion is involved.
4. `skills/boxel/references/theme-design-system.md`.
5. `skills/boxel-patterns/patterns/theme-first-workflow/README.md`.
5. `skills/boxel-patterns/patterns/theme-first-workflow/README.md` — how consumers link themes.
6. `skills/boxel-design/SKILL.md` when visual direction must be invented or improved.
7. `skills/boxel-ui-guidelines/references/use-boxel-design-tokens-for-theming.md` when checking downstream template token usage.
8. `skills/source-code-editing/SKILL.md` before `.gts` edits.

## Procedure

1. **Identify the source of truth.**
- Boxel built-in feature: use `https://cardstack.com/base/Theme/boxel-brand-guide`.
- User/custom realm: use the user's brand/design source.
- Existing theme patch: preserve the current theme subclass unless there is a clear reason to upgrade.

2. **Choose the artifact type.**
- Token-only -> `StructuredTheme`.
- Visual DNA and inspirations -> `StyleReference`.
- Full style system prose -> `DetailedStyleReference`.
- Logo/mark/brand governance -> `BrandGuide`.

3. **Map source material.**
- For DESIGN.md: map YAML tokens and markdown sections through `design-md-adapter.md`.
- For generic brand guides: extract exact tokens, then prose rules; do not leave critical values only in prose.
- For logos/marks: use `markUsage`; do not inline data URLs or image bytes.
- For shadcn-style tokens: keep surface/foreground pairs intact, keep `--primary` out of ordinary text roles, and normalize Boxel `spacing` through the `--spacing * 4` runtime rule.

4. **Write or patch the card.**
- Preserve structured fields: `rootVariables`, `darkModeVariables`, `typography`, `brandColorPalette`, `functionalPalette`, and `markUsage`.
- Include `attributes.cardInfo`.
- Omit `relationships["cardInfo.theme"]` on Theme cards.
- Keep font imports in `cssImports`.

5. **Link consumers if requested.**
- Non-Theme instances can link through `relationships["cardInfo.theme"]`.
- CardDefs can compute `cardTheme` from a parent/default when that is the cleaner model.
- Prefer absolute Theme URLs for nested folders until relative paths are verified.

6. **Validate.**
- If a DESIGN.md file is involved and the CLI is available, run `npx @google/design.md lint DESIGN.md`.
- If `.gts` files changed, run `npx boxel file lint` before push and `npx boxel lint` after push.
- Preview the Theme/BrandGuide and at least one consuming card.
- Check buttons, inputs, dropdowns, tooltips, pills, and card containers for token-pair contrast and spacing scale.
1. **Classify the job and identify the source of truth** (SKILL.md step 1): create / convert / audit / patch. Boxel built-in feature work uses the Boxel Brand Guide; existing theme patches preserve the current subclass unless there's a clear reason to upgrade.
2. **Choose the narrowest correct card type** (SKILL.md step 2): token-only → `StructuredTheme`; visual DNA/inspirations → `StyleReference`; full style-system prose → `DetailedStyleReference`; logo/mark/brand governance → `BrandGuide`.
3. **Map source material** per SKILL.md step 4, routing through `design-md-adapter.md` (DESIGN.md/brand prose) and `shadcn-boxel-token-mapping.md` (semantic pairs, spacing normalization) as applicable.
4. **Build or patch the card** per SKILL.md step 5 (preserve structured fields, `cardInfo`, no self-theme relationship, fonts in `cssImports`).
5. **Link consumers if requested** per `theme-first-workflow` — `relationships["cardInfo.theme"]` on instances, or a computed `cardTheme` on the CardDef when inheritance is the cleaner model.
6. **Validate** per SKILL.md step 6, including the `.gts` lint gate from `boxel/references/lint-workflow.md` when card code changed, and preview the theme plus at least one consuming card.

## Done Criteria

- [ ] The chosen Theme subclass matches the source material.
- [ ] Exact token values are captured in structured fields, not prose only.
- [ ] Style/brand rationale is captured in `visualDNA` or DetailedStyleReference markdown fields.
- [ ] Logo/mark material, if any, is captured in `markUsage`.
- [ ] Theme JSON has `attributes.cardInfo` and no self-theme relationship.
- [ ] All items in the Done Criteria of `boxel-theme-development/SKILL.md` pass.
- [ ] Consuming instances or CardDefs have a clear theme linkage strategy.
- [ ] Shadcn/Boxel semantic pairs are complete; `--primary` is not used as ordinary text; `spacing` is normalized for Boxel.
- [ ] Relevant lint/preview checks were run, or the reason they could not run is stated.
Loading