# Catalogue model

> How catalogue.ts is the single source of truth for tells, how demos and i18n attach, and boundaries between site data and skill references.

- Repository: yetone/kill-ai-slop
- GitHub: https://github.com/yetone/kill-ai-slop
- Human docs: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb
- Complete Markdown: https://grok-wiki.com/public/docs/yetone-kill-ai-slop-c0d8c9670cbb/llms-full.txt

## Source Files

- `website/src/data/catalogue.ts`
- `website/src/data/catalogue.i18n.ts`
- `website/src/data/demos.ts`
- `skill/references/taxonomy.md`
- `website/src/components/SlopEntry.astro`

---

---
title: "Catalogue model"
description: "How catalogue.ts is the single source of truth for tells, how demos and i18n attach, and boundaries between site data and skill references."
---

`website/src/data/catalogue.ts` defines the field-guide tell list: stable `id`s, display order `n`, tier, group, localized `title` / `what` / `why` / `fix`, code-level `detect` chips, and an optional `demo` key. The file header states it is the single source of truth for the website and the spec the kill-ai-slop skill enforces. Japanese and Korean copy attach from `catalogue.i18n.ts`; before→after HTML lives in `demos.ts` and is rendered by `SlopEntry.astro` via `BeforeAfter`.

## Role in the repo

| Artifact | Path | Owns |
| --- | --- | --- |
| Catalogue entries | `website/src/data/catalogue.ts` | Tell identity, order, tiers, groups, EN/ZH copy, `detect` strings, `demo` key |
| JA/KO strings | `website/src/data/catalogue.i18n.ts` | Optional `title` / `what` / `why` / `fix` per `id` for `ja` and `ko` |
| Demo HTML | `website/src/data/demos.ts` | Plain-HTML `before` / `after` payloads keyed by demo id |
| Demo styles | `styles/demos.css` (scoped under `.demo-<id>`) | Visual treatment for each demo pane |
| Entry UI | `website/src/components/SlopEntry.astro` | Renders one `Entry`: group tag, localized fields, demo, detect chips |
| Skill taxonomy prose | `skill/references/taxonomy.md` | Agent-facing narrative of the same tell set (what / why / fix) |
| Skill detection / fixes | `detection.md`, `fixes.md` (referenced from taxonomy) | Detection patterns and code patches for the skill workflow |

```mermaid
flowchart TB
  subgraph site["Field guide site"]
    CAT["catalogue.ts\nEntry[], GROUPS, Bi"]
    I18N["catalogue.i18n.ts\nja / ko by id"]
    DEM["demos.ts\nbefore / after HTML"]
    CSS["demos.css\n.demo-id scopes"]
    SE["SlopEntry.astro"]
    T["T.astro locale layer"]
    BA["BeforeAfter"]
    CAT -->|"merge ja/ko into Bi"| SE
    I18N --> CAT
    CAT -->|"entry.demo key"| BA
    DEM --> BA
    CSS --> BA
    SE --> T
    SE --> BA
  end

  subgraph skill["Agent skill references"]
    TAX["taxonomy.md\n23 tells, tiers, categories"]
    DET["detection.md"]
    FIX["fixes.md"]
    TAX --> DET
    TAX --> FIX
  end

  CAT -.->|"shared tell language / enforce as spec"| TAX
  CAT -->|"detect[] as mono chips + skill heuristics"| DET
```

The dashed link is alignment, not a TypeScript import. Site components import from `../data/catalogue`; skill agents read markdown under `skill/references/`. Keep ids, meaning, and remediation language in sync across both surfaces.

## Entry shape

`Entry` and related types in `catalogue.ts`:

| Field | Type | Required | Role |
| --- | --- | --- | --- |
| `id` | `string` | yes | Stable slug; article `id` / deep-link hash (`#${entry.id}`) |
| `n` | `number` | yes | Display number; assigned from array position (inserting renumbers the rest) |
| `tier` | `1 \| 2` | yes | `1` classic, `2` evolved |
| `group` | `Group` | yes | Category key into `GROUPS` |
| `title` | `Bi` | yes | Short name |
| `what` | `Bi` | yes | One line: what the tell is |
| `why` | `Bi` | yes | Why it reads as machine-made |
| `fix` | `Bi` | yes | Clean alternative |
| `detect` | `string[]` | yes | Code-level signals (UI mono chips + skill heuristics) |
| `demo` | `string` | no | Key into demos data / `demos.css` / `BeforeAfter` |

```ts
export type Group = "color" | "type" | "copy" | "component" | "layout" | "evolved";

export interface Bi {
  en: string;
  zh: string;
  ja?: string;
  ko?: string;
}

export interface Entry {
  id: string;
  n: number;
  tier: 1 | 2;
  group: Group;
  title: Bi;
  what: Bi;
  why: Bi;
  fix: Bi;
  detect: string[];
  demo?: string;
}
```

`rawEntries` is typed as `Omit<Entry, "n">[]`. Comments state numbering is by position so inserts renumber automatically. `GROUPS` is a `Record<Group, Bi>` used for the category tag on each entry.

### Tiers and groups

| Concept | Values | Meaning in catalogue header / UI |
| --- | --- | --- |
| Tier 1 | `tier: 1` | Classic slop — tells most people already recognise |
| Tier 2 | `tier: 2` | Evolved slop — newer defaults that already read as templated |
| Groups | `color`, `type`, `copy`, `component`, `layout`, `evolved` | EN labels: Color, Type, Copy, Components, Layout, Evolved slop (plus ZH/JA/KO in `GROUPS`) |

`SlopEntry` styles the group tag with `t${entry.tier}` (e.g. `tag group t2` for evolved emphasis).

### Localized strings (`Bi`)

- English is the source of truth and always present.
- Chinese (`zh`) is authored inline on each entry in `catalogue.ts`.
- Japanese and Korean are optional on `Bi` and are merged in from `catalogue.i18n.ts`.
- Missing locales fall back to English at the `<T>` layer; partial translations are safe.

`catalogue.i18n.ts` exports:

```ts
type Field = "title" | "what" | "why" | "fix";
type LangText = Partial<Record<Field, string>>;

export interface EntryI18n {
  ja?: LangText;
  ko?: LangText;
}

export const i18n: Record<string, EntryI18n> = { /* keyed by entry id */ };
```

Voice rule in that file: match English — terse, plain, specific; no punchy triads, no “not just X, it’s Y”, no exclamation. Site copy must not commit the slop patterns the catalogue documents.

## How demos attach

1. Catalogue entry sets `demo` to a string key (usually the same slug as `id`, e.g. `"indigo-violet-gradient"`).
2. `demos.ts` exports `demos: Record<string, { before: string; after: string }>` with plain HTML for each key.
3. Styles live under `.demo-<id>` in `styles/demos.css`.
4. `SlopEntry` renders `{entry.demo && <BeforeAfter id={entry.demo} />}`.

Demo contract (from `demos.ts` header):

- Rebuild the tell in HTML (`before`) and the clean counterpart (`after`).
- Keep illustrative copy short and neutral.
- `after` panes follow the same rules the site and skill enforce: one accent, no gradient chrome, hierarchy from scale + space, mono for code only, no decorative emoji/badges.

Earlier drafts used annotated screenshots of a reference product; those were removed in favour of live HTML demos so comparisons stay precise and do not drift.

### Example wire-up

Catalogue fragment:

```ts
{
  id: "indigo-violet-gradient",
  tier: 1,
  group: "color",
  title: { zh: "蓝紫渐变", en: "The indigo→violet gradient" },
  // what, why, fix...
  detect: [
    "from-indigo-500 to-purple-500",
    "#6366f1 → #a855f7",
    "bg-gradient-to-r via-purple",
    "shadow-purple-500/50",
  ],
  demo: "indigo-violet-gradient",
}
```

Matching demo key in `demos.ts`:

```ts
"indigo-violet-gradient": {
  before: `/* card with gradient chrome, decorative emoji */`,
  after: `/* solid surfaces, plain label, solid button */`,
}
```

If `demo` is omitted, `SlopEntry` still renders text fields and detect chips; only the evidence pane is skipped.

## How the site consumes an entry

`SlopEntry.astro` props: `{ entry: Entry }`.

| UI region | Data |
| --- | --- |
| Permalink number | `String(entry.n).padStart(2, "0")`; `href={`#${entry.id}`}`; click copies shareable `#id` URL |
| Group tag | `<T {...GROUPS[entry.group]} />` with class `t${entry.tier}` |
| Title / what | `<T {...entry.title} />`, `<T {...entry.what} />` |
| Demo | `BeforeAfter` when `entry.demo` is set |
| Why / fix | Localized section labels + `<T {...entry.why} />` / `fix` |
| Code signals | `entry.detect.map` → `<code>` chips |

Article root: `<article class="entry" id={entry.id}>`. Deep links land on the tell; sticky-nav offset is handled globally (`html { scroll-padding-top }`), not inside the entry.

## Skill boundary: catalogue vs references

`skill/references/taxonomy.md` opens with **23 tells, in two tiers** (Classic / Evolved). For each tell it covers what it is, why it reads as machine-made, and the fix. Detection patterns live in `detection.md`; code patches in `fixes.md`.

Shared rule across taxonomy and catalogue framing: **slop is the absence of a decision**. A tell is only slop when it is a default nobody chose; the same element, chosen and defended, is fine.

| Concern | Site catalogue | Skill references |
| --- | --- | --- |
| Authoritative structured data for the Astro field guide | Yes (`catalogue.ts`) | No |
| Multilingual field-guide UI copy | Yes (`Bi` + i18n) | Taxonomy is prose (EN in the evidence) |
| Live before/after demos | Yes (`demos.ts` + CSS) | No |
| Agent scan / triage narrative | Spec alignment via comments + `detect` heuristics | Yes (`taxonomy.md`) |
| Machine-oriented detection rules | `detect[]` chips (shared language) | Full patterns in `detection.md` |
| Remediation patches | `fix` prose on the entry | Playbook in `fixes.md` |

Do not treat `catalogue.ts` as runtime input for the standalone scanner unless another surface imports it. Treat it as the website SSOT and the human/agent-aligned **spec** that skill docs must match. When adding or renaming a tell, update catalogue identity first, then demos, i18n, and skill taxonomy / detection / fix references so ids and meaning stay one language.

### Id ↔ taxonomy alignment (examples)

Stable catalogue ids are slug identifiers; taxonomy.md uses numbered titles. Align by meaning, not by inventing a runtime bridge:

| Catalogue `id` (examples from data) | Taxonomy title (examples) |
| --- | --- |
| `indigo-violet-gradient` | 01 · Indigo→violet gradient |
| `gradient-text` | 02 · Gradient headline text |
| `warm-cozy-palette` | 03 · Warm "cozy" palette |
| `default-semantic-palette` | 04 · The default semantic palette |
| `mono-hue-alert` | 05 · The one-hue status box |
| `atmosphere-gradient` | 06 · Gradients as atmosphere |
| `serif-emphasis` | 07 · Serif-italic on one word |
| `emoji-everywhere` | 12 · Emoji everywhere |
| `status-dot-glow` | 13 · The glowing status dot |
| `left-border-callout` | 14 · Rounded card, colored left border |

Full id inventory, complete `detect` lists, and full demo HTML shapes belong on the data reference page; this page defines the model and attachment rules only.

## Constraints and verification

| Constraint | Signal |
| --- | --- |
| English always present on every `Bi` field | Required `en` / `zh` on type; EN is fallback |
| JA/KO optional and partial-safe | `Partial` fields; missing → EN at `<T>` |
| `demo` key must exist in `demos` when set | Runtime: `BeforeAfter` lookup by id; missing key fails the evidence pane |
| Demo styles scoped by id | `.demo-<id>` in `demos.css` |
| Numbering is positional | Insert/reorder `rawEntries` renumbers `n` |
| Site copy must not be slop | i18n header voice rules; demo `after` rules |
| Skill docs stay in the same language | Parallel update of taxonomy / detection / fixes |

<Check>
After a catalogue change: confirm `id` uniqueness, `demo` key match, i18n key match, and that taxonomy/detection/fix text still describe the same tell.
</Check>

## Related pages

<CardGroup>
  <Card title="Slop taxonomy" href="/slop-taxonomy">
    Categories, named signals, and how field guide and skill share taxonomy language.
  </Card>
  <Card title="Catalogue and demos data" href="/catalogue-data-reference">
    Field-level shapes for catalogue.ts, catalogue.i18n.ts, and demos.ts.
  </Card>
  <Card title="Extend the catalogue" href="/extend-catalogue">
    Add or update a tell across catalogue, i18n, demo, and skill references.
  </Card>
  <Card title="Detection patterns" href="/detection-patterns">
    Code-level signals and how findings map back to taxonomy ids.
  </Card>
  <Card title="Remediation playbook" href="/fixes-playbook">
    Per-tell clean fixes and before/after outcomes.
  </Card>
  <Card title="Run the field guide site" href="/run-field-guide-site">
    Local Astro preview and how entries/demos render on the index.
  </Card>
</CardGroup>
