Files
Oleks bfc6a65638 fix(app): architecture + UI/UX review fixes
Multi-agent arch/UX review pass. Architecture: real HTTP 404 on not-found,
breadcrumb links by slug not lowercased title, CMS pages surface their
plugins, shared status taxonomy (src/lib/statuses.ts) consumed by all three
frontend consumers, data-driven status filter, typed emdash collections
(src/emdash-collections.d.ts), removed unused @astrojs/react + react deps and
dead pnpm block, tsconfig extends Astro strict preset, dev deps pruned from
the runtime image. UI/UX: fixed StatusBadge WCAG-AA contrast, labelled the
search/filter controls, canonical URL + BreadcrumbList JSON-LD + og:type,
human status labels, filtered result count + recoverable empty state,
auto-submit filters, mobile overflow fixes, skip-to-content, :focus-visible.

Commit the npm lockfile so the Dockerfile's `npm ci` path engages.
astro check: 0 errors / 0 warnings / 0 hints.
2026-06-02 03:24:52 +03:00

96 lines
4.1 KiB
Markdown

# CLAUDE.md
Guidance for Claude Code agents working in this repository.
## What this repo is
A browseable catalog of CMS plugins built on [Emdash](https://github.com/emdash-cms/emdash).
Phase 0 — scaffold + chart + pipeline are in place, no live deploy yet.
Seeded with the WordPress → Emdash plugin parity matrix from
`~/projects/kotkanagrilli.fi/` and `~/projects/emdash.kotkanagrilli.fi/docs/parity.md`.
## Linked repos
- `~/projects/kotkanagrilli.fi/` — legacy WordPress site. **Do not edit
from here.** Source of the seeded plugin entries.
- `~/projects/emdash.kotkanagrilli.fi/` — Emdash replacement for that site.
The Dockerfile, Helm chart, Woodpecker pipeline, and DDEV setup in this
repo are deliberate copies of that one. Treat it as the reference
implementation; deviations should be justified.
- `~/projects/servers/anton/anton-helm-workloads/` — where the FluxCD
`HelmRelease`s for `cms-plugins-{staging,production}.kotkanagrilli.fi`
live. `deploy/fleet-overlay/` in this repo is the template set to copy
into that repo. **Do not commit to anton-helm-workloads without
explicit confirmation** — secrets need sops-encryption with the right
age recipients.
- `~/projects/servers/fleet/` — personal fleet repo. Owns
`emdash-kotkanagrilli-{staging,production}` but NOT cms-plugins.
## Layout
- `app/` — Emdash scaffold (node target, no i18n, no Cloudflare boundary).
Three collections in `seed/seed.json`: `cmses`, `plugins`, `pages`.
- `Dockerfile` + `docker/entrypoint.sh` — production image.
- `deploy/helm/` — the chart Flux pulls from `./deploy/helm` on the
matching branch.
- `deploy/fleet-overlay/cms-plugins-{staging,production}/` — HelmRelease
+ GitRepository + image-automation + secrets templates ready to drop
into `anton-helm-workloads`.
- `.woodpecker/container.yaml` — build pipeline (arm64; deploy target is
`kotkan`).
- `.ddev/` — local dev.
- `DEPLOYMENT.md` — full pipeline walkthrough.
- `ARCHITECTURE.md` — chart / image / Flux contracts.
## Common commands
```bash
# Local dev
ddev start # https://cms-plugins.ddev.site/
# or, without DDEV:
cd app && npm install && npm run bootstrap && npx emdash dev
# Build production image
docker build -t cms-plugins:dev .
# Typecheck
cd app && npm run typecheck
```
## Architectural constraints to respect
- **One repo, one app, node target.** No Cloudflare boundary files yet;
adding them is a deliberate Phase-N call, not casual work.
- **SQLite single-writer.** One replica, pinned to `kotkan`, `local-path`
PVC. No StatefulSet, no horizontal scale.
- **Chart pulled directly from git by Flux** — no `helm push` step. Chart
changes ship in the same commit as the code that needs them.
- **Image is pinned by digest in the HelmRelease.** `ImageUpdateAutomation`
rewrites the digest setter; `helm upgrade` only sees a change because
of that. The floating `<branch>` tag alone wouldn't roll the pod.
- **The legacy WP site keeps running.** This repo doesn't migrate
kotkanagrilli.fi — it's a catalog ABOUT plugins, not the site itself.
## Emdash gotchas (from the kotkanagrilli reference)
- All content pages must be server-rendered (`output: "server"`); no
`getStaticPaths()` for CMS content.
- `entry.id` is the slug (URLs); `entry.data.id` is the database ULID
(used for API calls / cross-collection refs).
- Image fields are `{ src, alt }` objects, not strings.
- Always `Astro.cache.set(cacheHint)` on pages that query content.
- Taxonomy names in queries match `seed.json`'s `name` field exactly.
## What NOT to do
- Don't `npm install` random kotkanagrilli plugins (the e-commerce ones).
This is a catalog, not a store.
- Don't push to `anton-helm-workloads` without explicit confirmation —
unencrypted secrets would leak.
- Don't change branch promotion semantics (fast-forward only across
`develop``staging``production`). Mirroring emdash-kotkanagrilli's
flow is intentional.
- Don't commit the dev SQLite DB. `data.db` / `data.db-shm` / `data.db-wal`
are dev artifacts (gitignored + dockerignored); they must never live in
the source tree. Regenerate via `npm run bootstrap` (`emdash init`).