# Run the field guide site

> Develop and preview the multilingual Astro field guide: install, dev server, static build output, and how entries and demos render on the index.

- 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/astro.config.mjs`
- `website/src/pages/index.astro`
- `website/src/layouts/Base.astro`
- `website/src/components/SlopEntry.astro`
- `website/src/components/LangToggle.astro`
- `README.md`

---

---
title: "Run the field guide site"
description: "Develop and preview the multilingual Astro field guide: install, dev server, static build output, and how entries and demos render on the index."
---

The field guide lives under `website/` as a static Astro app: multilingual content (English, Chinese, Japanese, Korean), zero-JS-by-default, and a single-page index that renders the 23-tell catalogue from `website/src/data/catalogue.ts`. Live production is `https://killaislop.com`; local work is install → `npm run dev` → optional `npm run build` into `dist/`.

## Surface and layout

| Path | Role |
|------|------|
| `website/` | Astro field guide (multilingual, static) |
| `website/astro.config.mjs` | Site URL and lean build options |
| `website/src/pages/index.astro` | Index: hero, definition, catalogue section, principles data |
| `website/src/layouts/Base.astro` | Document shell, SEO, pre-paint prefs, Nav/Footer |
| `website/src/components/SlopEntry.astro` | One catalogue entry (copy, demo, signals) |
| `website/src/components/LangToggle.astro` | Language menu → `html[data-lang]` |
| `website/src/data/catalogue.ts` | Taxonomy / entry source of truth (shared with the skill) |
| `website/src/styles/tokens.css` | Design self-constraints (paper/ink, one accent) |

Repo split from the root README: `website/` is the guide; `skill/` is the agent skill and scanner (separate runtime).

## Prerequisites

- Node.js and npm available on the machine.
- Working tree that includes the `website/` package (clone of `yetone/kill-ai-slop` or equivalent).

No Astro integrations are configured. `astro.config.mjs` is intentionally dependency-light: `site` plus `build.inlineStylesheets: 'auto'` only.

## Install and run

<Steps>
  <Step title="Install website dependencies">
    From the repository root:

```bash
cd website
npm install
```

  </Step>
  <Step title="Start the dev server">
```bash
npm run dev
```

    Open **http://localhost:4321**. Success signal: the field guide index loads with the hero kicker, definition section, and catalogue heading for 23 tells.
  </Step>
  <Step title="Build static output (optional)">
```bash
npm run build
```

    Output goes to **`dist/`** (static files; deploy anywhere static hosting accepts).
  </Step>
</Steps>

<RequestExample>
```bash
cd website
npm install
npm run dev        # http://localhost:4321
npm run build      # → dist/
```
</RequestExample>

<Check>
Dev server on port **4321** and a populated **`dist/`** after build are the primary local success signals documented for the website.
</Check>

## Astro configuration

`website/astro.config.mjs`:

| Key | Value | Notes |
|-----|--------|--------|
| `site` | `https://killaislop.com` | Used for absolute canonical/OG URLs in `Base.astro` |
| `build.inlineStylesheets` | `'auto'` | Stylesheet inlining policy |
| Integrations | none | Comment in config: no integrations by design; keep the build artifact lean |

Canonical and Open Graph image URLs in the layout are built as `new URL(Astro.url.pathname, Astro.site)` and `new URL("/og.png", Astro.site)`.

## Index page structure

`website/src/pages/index.astro` wraps content in `Base` and imports `catalogue` plus `SlopEntry`. Documented sections on the index include:

| Anchor | Content |
|--------|---------|
| `#top` | Hero: multilingual kicker, title variants per language, lede, CTAs |
| `#what` | Definition of AI slop (`data-index="00"`) |
| `#catalogue` | Catalogue header (`data-index="01"`): 23 tells, before → after pairs in plain HTML |
| `#skill` | Linked from hero ghost CTA (“Get the cleanup skill”) |

Hero CTAs:

- Primary → `#catalogue` (“See the catalogue”)
- Ghost → `#skill` (“Get the cleanup skill”)

Frontmatter also defines a `principles` array (six multilingual `head` / `body` pairs: decide before decorate, one accent, hierarchy from scale/space, subtract first, specific beats loud, decoration must mean something). Those strings are co-located on the index page for the site’s anti-slop messaging.

Copy on the page is mostly rendered through the `<T>` component with `en` / `zh` / `ja` / `ko` props (hero title uses `data-t` spans for the four locales).

## How catalogue entries and demos render

Each tell is an `Entry` from `catalogue`. `SlopEntry` is the presentational unit:

```astro
<article class="entry" id={entry.id}>
  <!-- number, group tag, title, what -->
  {entry.demo && <BeforeAfter id={entry.demo} />}
  <!-- Why it's slop / The fix -->
  <!-- Code signals: entry.detect as <code> chips -->
</article>
```

### Entry chrome

| Element | Behavior |
|---------|----------|
| `id={entry.id}` | Deep-link target for `/#entry-id` |
| Number | `String(entry.n).padStart(2, "0")`; permalink control |
| Group tag | `<T {...GROUPS[entry.group]} />` with tier class `t${entry.tier}` (tier `2` is inverted ink-on-paper styling) |
| Title / what | `<T {...entry.title} />`, `<T {...entry.what} />` |
| Demo | If `entry.demo` is set, `<BeforeAfter id={entry.demo} />` |
| Why / fix | Multilingual labels + `entry.why` / `entry.fix` |
| Code signals | `entry.detect` list items as `<code>` |

Demos are plain-HTML rebuilds of the slop tell and the clean alternative (README: interactive before → after; catalogue lede: click to switch). They exist for commentary and education, not as live scrapes of third-party products.

### Permalink interaction

Clicking `a.num.permalink`:

1. `preventDefault`
2. `history.replaceState` to `#${id}` (no extra history entries)
3. Smooth-scrolls the entry into view
4. Copies `origin + pathname + #id` to the clipboard when available, then flashes a `copied` class (~1.4s) so the affordance shows `✓`

Sticky-nav offset for deep links is handled globally (`html { scroll-padding-top }`); entries do not double-offset themselves.

## Multilingual runtime

Languages supported in UI chrome and pre-paint resolution: **en**, **zh**, **ja**, **ko**.

### Pre-paint (`Base.astro` inline scripts)

| Storage key | Default / resolution | Effect |
|-------------|----------------------|--------|
| `kas-lang` | English default; if unset/invalid, map `navigator.language` prefix `zh`/`ja`/`ko`, else `en` | Sets `documentElement.dataset.lang` and `lang` (`en`, `zh-Hans`, `ja`, `ko`) |
| `kas-sound` | On unless stored `"off"` | `dataset.sound` = `on` \| `off` (avoids muted users hearing stray sweep sound) |
| `kas-theme` | Unset follows OS `@media`; only explicit `"light"` or `"dark"` stored | `dataset.theme` when set |

Language choice is the source of truth for `<T>` and global CSS selectors on `html[data-lang]`.

### Language menu (`LangToggle.astro`)

- Custom dropdown (not native `<select>`), labels: EN / 中文 / 日本語 / 한국어.
- On select: `localStorage.setItem("kas-lang", lang)`, then `apply(lang)` updates `data-lang`, `lang`, trigger label, and `aria-checked` on options.
- Reflects whatever the head pre-paint script already resolved (`apply(root.dataset.lang || "en")`).

Open Graph locales advertised: `en_US` plus alternates `zh_CN`, `ja_JP`, `ko_KR`.

## Document shell and deep links

`Base.astro` defaults:

| Prop | Default |
|------|---------|
| `title` | `Kill AI Slop — 杀死 AI slop` |
| `description` | Field-guide bilingual blurb (EN + ZH) |

Also sets: `color-scheme: light dark`, canonical URL, OG/Twitter large image (`/og.png`, 1200×630), favicon `/favicon.svg`, skip link to `#main`, `Nav` above `<main id="main">`, `Footer` after.

Deep-link landing script:

- On load, if `location.hash` is present, scrolls the matching element with `block: "start"` (instant, before smooth nav is enabled).
- Then, unless `prefers-reduced-motion: reduce`, adds class `nav-ready` so later in-page navigation can use smooth scrolling.

## Design constraints (site as rebuttal)

The site is intentionally not “slop”: paper + ink, **one** editorial accent (proofreader’s pen), hierarchy from scale and space, hairline rules; no gradients / emoji / glass / badges as the house style. Self-rules live in `website/src/styles/tokens.css`. Taxonomy and entry data live in `website/src/data/catalogue.ts` (shared language with the skill).

Astro comment in config: the build artifact should stay as lean as the aesthetic the site argues for.

## Verification checklist

| Check | Expected |
|-------|----------|
| `npm run dev` | Site at `http://localhost:4321` |
| Hero | Multilingual field-guide kicker; CTAs to catalogue and skill |
| `#catalogue` | Copy claims **23** tells, each a before → after HTML demo |
| Language menu | Switching updates chrome and persisted `kas-lang` without full reload flash (pre-paint + dropdown) |
| Entry permalink | URL hash updates; clipboard may receive shareable `#id` URL |
| `npm run build` | Static tree under `website/dist/` |

## Troubleshooting

| Symptom | What to check |
|---------|----------------|
| Wrong language on first paint | Clear or set `localStorage.kas-lang`; confirm browser language mapping only applies when no valid stored key |
| Flash of wrong theme | Only stored `light`/`dark` force theme; otherwise OS media query applies—ensure `kas-theme` is not stale |
| Hash link lands under sticky nav | Rely on global `scroll-padding-top`; deep-link script re-scrolls on `load` for layout shift |
| Demo missing on an entry | `SlopEntry` only mounts `BeforeAfter` when `entry.demo` is truthy |
| Clipboard / ✓ flash fails | Permalink still updates hash and scrolls; clipboard is best-effort (`.catch(() => {})`) |

## Related pages

<CardGroup>
  <Card title="Installation" href="/installation">
    Install website dependencies and the kill-ai-slop skill for local work.
  </Card>
  <Card title="Build and deploy" href="/build-and-deploy">
    Static `dist/` output, deploy-anywhere assumptions, zero-JS-by-default ops notes.
  </Card>
  <Card title="Catalogue model" href="/catalogue-model">
    How `catalogue.ts` is the single source of truth and how demos/i18n attach.
  </Card>
  <Card title="Catalogue and demos data" href="/catalogue-data-reference">
    Fields and shapes for entries, locale copy, and demo HTML payloads.
  </Card>
  <Card title="Design tokens" href="/design-tokens">
    Paper/ink palette, single editorial accent, hierarchy rules, banned defaults.
  </Card>
  <Card title="Extend the catalogue" href="/extend-catalogue">
    Add or update a tell end-to-end on the site and skill taxonomy.
  </Card>
  <Card title="Quickstart" href="/quickstart">
    Shortest path to a first scanner report and a local field-guide run.
  </Card>
</CardGroup>
