# Catalogue and demos data

> Fields and shapes in catalogue.ts, catalogue.i18n.ts, and demos.ts: tell ids, copy locales, and demo HTML payloads used by site components.

- 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`
- `website/src/components/SlopEntry.astro`
- `website/src/components/T.astro`
- `website/src/styles/demos.css`

---

---
title: "Catalogue and demos data"
description: "Fields and shapes in catalogue.ts, catalogue.i18n.ts, and demos.ts: tell ids, copy locales, and demo HTML payloads used by site components."
---

`website/src/data/catalogue.ts` defines the field-guide tell records (`Entry`, `GROUPS`, `Bi`) that `SlopEntry.astro` renders. Japanese and Korean copy attach from `catalogue.i18n.ts` by entry `id`. Optional before/after HTML lives in `demos.ts` under the same key family, styled in `styles/demos.css` under `.demo-<id>`.

## Data files

:::files
website/src/data/
  catalogue.ts        # Entry types, GROUPS, rawEntries (en + zh copy)
  catalogue.i18n.ts   # ja/ko partials keyed by entry id
  demos.ts            # before/after HTML strings keyed by demo id
website/src/styles/
  demos.css           # .ba-stage + .demo-<id> scopes
website/src/components/
  SlopEntry.astro     # Entry → page article
  T.astro             # Bi/locale spans (en/zh/ja/ko)
  BeforeAfter.astro   # consumes entry.demo id
:::

| File | Export / surface | Role |
|------|------------------|------|
| `catalogue.ts` | `Group`, `Bi`, `Entry`, `GROUPS`, `rawEntries` | Single source of tell ids, tiers, groups, en/zh copy, `detect[]`, optional `demo` |
| `catalogue.i18n.ts` | `EntryI18n`, `i18n` | Optional `ja` / `ko` strings for `title` \| `what` \| `why` \| `fix` |
| `demos.ts` | `demos` | Plain-HTML `before` / `after` payloads per demo id |
| `demos.css` | `.ba-stage`, `.demo-<id>` | Shared primitives + per-demo styles; generic class names do not leak site-wide |

Catalogue header comments state this catalogue is the website source of truth and the spec the kill-ai-slop skill enforces. Demos replaced earlier screenshot annotations so comparisons stay rebuilt HTML rather than pinned images.

## Locale model

| Locale | Where defined | Required? |
|--------|---------------|-----------|
| `en` | `catalogue.ts` (`Bi.en`, `GROUPS`) | Yes — source of truth |
| `zh` | `catalogue.ts` inline (`Bi.zh`) | Yes on `Bi` |
| `ja` | `catalogue.i18n.ts` (optional fields) | No — fallback to English |
| `ko` | `catalogue.i18n.ts` (optional fields) | No — fallback to English |

`T.astro` renders four spans (`data-t="en|zh|ja|ko"`). Only `en` is required on props; `zh` / `ja` / `ko` use `?? en` when missing. Active language is selected via `<html data-lang>` (global CSS), not by omitting spans.

i18n file comments: partial translations are safe; voice must stay terse and non-slop in every language (no punchy triads, no “not just X, it’s Y”, no exclamation).

## Types

### `Group`

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

### `Bi` (localized string)

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

### `Entry`

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

### `EntryI18n` / `i18n`

```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>;
```

### `demos`

```ts
export const demos: Record<string, { before: string; after: string }>;
```

## Entry fields

Source records use `const rawEntries: Omit<Entry, "n">[]`. Comments state display numbers are assigned by array position so inserts renumber automatically (`n` is not hand-edited on each object).

<ParamField body="id" type="string" required>
Stable slug used as article `id`, hash deep-link (`#${entry.id}`), and key into `i18n`.
</ParamField>

<ParamField body="n" type="number" required>
1-based-style display index after position mapping. `SlopEntry` shows `String(entry.n).padStart(2, "0")`.
</ParamField>

<ParamField body="tier" type="1 | 2" required>
`1` classic slop; `2` evolved slop. CSS class `t${entry.tier}` on the group tag; tier `2` uses inverted ink/paper styling (`.tag.group.t2`).
</ParamField>

<ParamField body="group" type="Group" required>
Category key into `GROUPS`. Rendered as the uppercase group tag via `<T {...GROUPS[entry.group]} />`.
</ParamField>

<ParamField body="title" type="Bi" required>
Tell name in the entry heading.
</ParamField>

<ParamField body="what" type="Bi" required>
One-line description of the tell.
</ParamField>

<ParamField body="why" type="Bi" required>
Why the pattern reads as machine-made.
</ParamField>

<ParamField body="fix" type="Bi" required>
Clean remediation guidance shown under “The fix”.
</ParamField>

<ParamField body="detect" type="string[]" required>
Code-level signal chips (also skill heuristics). Each string renders as a mono `<code>` list item.
</ParamField>

<ParamField body="demo" type="string" optional>
Key into `demos` / `demos.css` / `BeforeAfter`. When set, `SlopEntry` mounts `<BeforeAfter id={entry.demo} />`.
</ParamField>

### Tiers (catalogue comments)

| Tier | Label | Meaning |
|------|--------|---------|
| `1` | classic | Tells most people already recognise |
| `2` | evolved | Newer defaults that already read as templated (“friendly-AI-app” look) |

### `GROUPS` labels

| Key | en | zh | ja | ko |
|-----|----|----|----|-----|
| `color` | Color | 配色 | カラー | 색상 |
| `type` | Type | 字体 | 書体 | 타이포 |
| `copy` | Copy | 文案 | コピー | 카피 |
| `component` | Components | 组件 | コンポーネント | 컴포넌트 |
| `layout` | Layout | 版式 | レイアウト | 레이아웃 |
| `evolved` | Evolved slop | 进化型 slop | 進化型 slop | 진화형 slop |

## How `SlopEntry` consumes an entry

| UI region | Source |
|-----------|--------|
| `article.id`, permalink `#id` | `entry.id` |
| Zero-padded number | `entry.n` |
| Group tag + tier class | `GROUPS[entry.group]`, `entry.tier` |
| Title / what | `entry.title`, `entry.what` |
| Before/after demo | `entry.demo` → `BeforeAfter` when truthy |
| Why / fix notes | `entry.why`, `entry.fix` |
| Code signals | `entry.detect[]` as `<code>` chips |

Static section labels (“Why it’s slop”, “The fix”, “Code signals”) are hardcoded multilingual props on `T`, not catalogue fields.

## Demo payloads

Each `demos[id]` is two HTML string fragments:

| Field | Content rules (file header) |
|-------|-----------------------------|
| `before` | Rebuilds the slop tell in plain HTML |
| `after` | Clean counterpart; same rules the site and skill enforce: one accent, no gradient chrome, hierarchy from scale + space, mono for code only, no decorative emoji/badges |

Demo copy is illustrative, short, and neutral. Styles:

- Shared under `.ba-stage` (`h5`, `.ey`, `.sub`, buttons, etc.)
- Per-demo under `.demo-<id>` so generic class names (`card`, `btn`, `sem`) do not leak into the rest of the site
- “Before” panes intentionally reproduce slop; “after” panes obey site rules

Example shape (`indigo-violet-gradient`):

```ts
"indigo-violet-gradient": {
  before: `
    <div class="card slop-grad">
      <p class="ey">✨ AI-POWERED</p>
      <h5>Deploys on git push</h5>
      <p class="sub">Connect a repo; every commit to main ships.</p>
      <button class="btn grad">Get started →</button>
    </div>`,
  after: `
    <div class="card clean">
      <p class="ey">Continuous deploy</p>
      <h5>Deploys on git push</h5>
      <p class="sub">Connect a repo; every commit to main ships.</p>
      <button class="btn solid">Get started</button>
    </div>`,
},
```

## Key inventory (from data exports)

Ids are the join keys across catalogue, i18n, and demos. Alignment is by string equality; `demo` may equal `id` or be omitted.

### Catalogue `rawEntries` ids present in source fragment

| `id` | `tier` | `group` | `demo` (when present) |
|------|--------|---------|------------------------|
| `indigo-violet-gradient` | `1` | `color` | `indigo-violet-gradient` |
| `gradient-text` | `1` | `color` | `gradient-text` |
| `warm-cozy-palette` | `1` | `color` | `warm-cozy-palette` |
| `default-semantic-palette` | `1` | `color` | `default-semantic-palette` |
| `mono-hue-alert` | `1` | `color` | (not shown in truncated fragment) |

The array continues after `mono-hue-alert` in the full file; only these objects appear in the supplied catalogue fragment.

### Example `detect` chips (color group)

| `id` | `detect` values |
|------|-----------------|
| `indigo-violet-gradient` | `from-indigo-500 to-purple-500`, `#6366f1 → #a855f7`, `bg-gradient-to-r via-purple`, `shadow-purple-500/50` |
| `gradient-text` | `bg-clip-text text-transparent`, `background-clip: text`, `-webkit-text-fill-color: transparent` |
| `warm-cozy-palette` | `amber-50 / stone-100 / orange-400`, `bg-[#fdf6ec] text-amber-900`, `border-amber-200` |
| `default-semantic-palette` | `bg-blue-50 / bg-amber-50 / bg-green-50 together`, `-50 bg + -600 text semantic set`, `default info/warn/success/error hues` |

### `i18n` keys present

`indigo-violet-gradient`, `gradient-text`, `warm-cozy-palette`, `default-semantic-palette`, `serif-emphasis`, `serif-body-misuse`, `decorative-text-lines`, `highlighted-keywords`, `ai-copy-tics`, `emoji-everywhere`, `status-dot-glow`, `left-border-callout` (file continues past this key in full source).

Each key holds optional `ja` / `ko` objects with any of `title`, `what`, `why`, `fix`.

### `demos` keys present

| Demo id | Notes |
|---------|--------|
| `status-dot-glow` | Glowing live dot → flat status + label |
| `indigo-violet-gradient` | Gradient CTA card → solid card |
| `gradient-text` | Clipped gradient head → solid head |
| `warm-cozy-palette` | Amber cozy card → neutral card |
| `default-semantic-palette` | Rainbow chips → neutral chips + small dots |
| `serif-emphasis` | Mixed serif italic → single-voice bold |
| `serif-body-misuse` | Display-serif panel → sans panel |
| `decorative-text-lines` | `s` / `u` / `mark` ornament → plain claim |
| `highlighted-keywords` | Multi-span keyword paint → concrete paragraph |
| `ai-copy-tics` | Triads / “not just” copy → concrete copy |
| `emoji-everywhere` | Emoji list → numeric/plain list |
| `left-border-callout` | Colored left-bar cards → plain list |
| `pastel-icon-tiles` | Pastel icon feature tiles → measured feature list |
| `over-rounded-glass` | Glassmorphism plan card → flat card (payload truncated in evidence) |

### Cross-file join sketch

```text
rawEntries[i].id  ──►  i18n[id].{ja,ko}.{title,what,why,fix}
       │
       └── demo?  ──►  demos[demo].{before,after}
                       styles .demo-<demo>  (+ shared .ba-stage)
       │
       └── detect[] ──► mono chips in SlopEntry (+ skill heuristics)
```

<Note>
`demo` is optional. `mono-hue-alert` appears in `rawEntries` without a confirmed `demo` in the catalogue fragment; demos and i18n maps can include keys for tells whose full catalogue objects live later in the file (e.g. `serif-emphasis`, `status-dot-glow`).
</Note>

## Constraints

| Rule | Detail |
|------|--------|
| English authority | `Bi.en` / `T` `en` prop is required; missing locales fall back to English |
| zh location | Chinese copy lives in `catalogue.ts`, not `catalogue.i18n.ts` |
| ja/ko location | Isolated reviewable block in `catalogue.i18n.ts` |
| Numbering | Do not hardcode permanent numbers; position in `rawEntries` drives `n` |
| Demo/CSS lockstep | New demo needs `demos[id]`, `.demo-<id>` rules, and matching `entry.demo` |
| After-pane rules | One accent; no gradient chrome; hierarchy via scale + space; mono for code only; no decorative emoji/badges |
| CSS isolation | Scope under `.ba-stage` or `.demo-<id>` only |
| Copy voice (all locales) | Terse, plain, specific — site must not commit the slop it catalogues |
| `T` styling | `T` emits bare spans only; parent owns element + classes (no `as` / `class` on `T`) |

## Verification signals

When editing these files, confirm:

1. Every `entry.demo` string exists as a key in `demos` (and has `.demo-<id>` styles when that demo uses custom CSS).
2. `i18n` keys match real `entry.id` values (orphans only waste bytes; missing keys silently fall back to English).
3. Each `Bi` has both `en` and `zh`; optional `ja`/`ko` either complete the four fields you care about or omit them intentionally.
4. `detect` strings are short enough for mono chips and useful as skill/scanner heuristics.
5. `group` is one of the six `Group` keys and has a `GROUPS` label.
6. `tier` is only `1` or `2`.
7. On the field guide, the entry renders title/what/why/fix for each `data-lang`, demo panes when `demo` is set, and code-signal chips from `detect`.

## Related pages

<CardGroup>
  <Card title="Catalogue model" href="/catalogue-model">
    How catalogue.ts is the single source of truth and how demos and i18n attach.
  </Card>
  <Card title="Extend the catalogue" href="/extend-catalogue">
    Add or update a tell: entry, i18n, HTML demo, skill alignment.
  </Card>
  <Card title="Slop taxonomy" href="/slop-taxonomy">
    Categories, named signals, shared language with the skill.
  </Card>
  <Card title="Detection patterns" href="/detection-patterns">
    How `detect` strings and scanner rules map back to tell 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">
    How entries and demos render on the Astro index.
  </Card>
  <Card title="Design tokens" href="/design-tokens">
    Site self-constraints that “after” panes should obey.
  </Card>
</CardGroup>
