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
24 changes: 20 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ What this repo owns:

- docs content and navigation under `src/content/docs/`
- docs-specific components and styling under `src/components/`
- feed-directory presentation and client behavior (`FeedDirectory.astro`, `feed-directory.js`)
- feed-directory presentation and client behavior (`src/components/feed-directory/`)

What this repo does not own:

Expand All @@ -30,7 +30,7 @@ Before substantial edits, state cross-repo context in your notes:
Common contracts:

- Feed Directory browse data comes from `{instance}/api/v1/configs` on a running `html2rss-web` instance (see OpenAPI in `html2rss-web`).
- Instance URL persistence: default public instance, `#!url=` hash deep link from the web app, and browser localStorage (see `feed-directory.js`).
- Instance URL persistence: default public instance, `#!url=` hash deep link from the web app, browser localStorage, and filter state in URL query params (`q`, `topic`, `lang`, `sort`, `page`).
- Deep link from `html2rss-web`: `https://html2rss.github.io/feed-directory/#!url={encodedInstanceUrl}` must keep working.
- Catalog metadata in YAML (`directory.title`, `directory.summary`, `directory.topics`) is authored in `html2rss-configs` only.
- Ruby gem docs should match `html2rss` behavior and CLI output.
Expand All @@ -44,6 +44,20 @@ If a cross-repo behavior changed but upstream is not updated yet, document the g
- Do not reintroduce `bin/data-update`, `src/data/configs.json`, or a `html2rss-configs` gem dependency in this repo.
- Wire shape v1 is defined in `html2rss-web` request specs and OpenAPI (`catalog_version`, `parameters.schema`, `parameters.defaults`).
- When the instance is unreachable or returns `404` with `catalog_disabled`, show an error state — no static fallback list.
- **Wire parsing only in** `src/components/feed-directory/adapters/catalog-api.ts`. Domain modules must not parse API envelopes or wire rows.
- See `CONTEXT.md` for glossary (`FeedDirectoryEntry`, catalog seam, instance persistence contract).

### Module layout (`src/components/feed-directory/`)

| Layer | Path | Role |
| -------- | ----------- | ------------------------------------------------------------------------------------------ |
| adapters | `adapters/` | Catalog API fetch/parse, browser storage, URL filters, OPML download |
| domain | `domain/` | Pure behavior — filters, language, feed URLs, OPML build; no `window` / `document` |
| app | `app/` | State transitions (`directory-state.ts`), view model, event wiring (`FeedDirectoryApp.ts`) |
| ui | `ui/` | HTML rendering from `FeedDirectoryViewModel` |
| lib | `lib/` | Shared utilities (escape, debounce) |

Entry point: `feed-directory/FeedDirectory.astro` mounts `FeedDirectoryApp` directly.

## Generated Artifacts

Expand All @@ -58,11 +72,13 @@ Run commands from `html2rss.github.io/`:
- `make build` builds production output
- `make lint` checks formatting
- `make lintfix` applies formatting fixes
- `make test` runs Vitest on feed-directory pure modules
- `make check` runs `lint` and `test`

Preferred verification flow for docs/content changes:

1. Run targeted check(s) first (`make lint` or `make build`).
2. Run the broader check set before PR (`make lint` and `make build`).
1. Run targeted check(s) first (`make lint`, `make test`, or `make build`).
2. Run the broader check set before PR (`make lint`, `make test`, and `make build`).
3. For feed-directory UI changes, spot-check against a running instance with catalog enabled (`GET /api/v1/configs` returns entries).

## Docs Authoring Rules
Expand Down
51 changes: 51 additions & 0 deletions CONTEXT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Feed Directory glossary

Terms used across the `src/components/feed-directory/` module tree.

## Feed Directory

The browse UI embedded on `/feed-directory/`. It is a thin client: it loads catalog JSON from an active `html2rss-web` instance, renders rows client-side, and builds RSS links from each entry's `path`.

## FeedDirectoryEntry

Normalized domain type for one catalog row after wire parsing. Required fields only — no OpenAPI nullability leaks into filters or render code. Produced exclusively by `adapters/catalog-api.ts`.

| Field | Meaning |
| -------------------------------------- | ---------------------------------------------------- |
| `id` | Config identifier (e.g. `bbc.com/mundo`) |
| `path` | RSS path on the instance (e.g. `/bbc.com/mundo.rss`) |
| `siteKey` | Host key derived from `id` for display and site sort |
| `title`, `summary`, `topics` | Directory metadata from YAML |
| `channelUrl`, `language` | Channel metadata |
| `parameterSchema`, `parameterDefaults` | Dynamic feed parameters |

## Catalog seam

The boundary between the instance API and domain logic:

- **Wire:** `GET /api/v1/configs` envelope (`success`, `data.configs`, `meta.catalog_version`)
- **Adapter:** `adapters/catalog-api.ts` — fetch, envelope validation, row validation, version gate (supported: `[1]`)
- **Domain:** `FeedDirectoryEntry[]` consumed by filters, OPML build, and render

Wire parsing must stay in `adapters/catalog-api.ts` only.

## Instance persistence contract

| Mechanism | Key / format | Behavior |
| ---------------- | ------------------------------------------------------- | ---------------------------------------------------------------- |
| Default instance | `DEFAULT_INSTANCE_URL` in `adapters/browser-storage.ts` | `https://1.h2r.workers.dev/` |
| Deep link | `#!url={encodedInstanceUrl}` | Read on load, normalized to https/http, persisted, hash stripped |
| localStorage | `html2rss.feedDirectory.instanceUrl` | Stores custom instance when different from default |
| Filter state | URL query params `q`, `topic`, `lang`, `sort`, `page` | Managed by `adapters/browser-location.ts` |

Deep link from `html2rss-web`: `https://html2rss.github.io/feed-directory/#!url={encodedInstanceUrl}` must keep working.

## Module layout

| Layer | Path | Role |
| -------- | ----------- | -------------------------------------------------- |
| adapters | `adapters/` | Browser I/O and catalog API wire translation |
| domain | `domain/` | Pure behavior — no `window` / `document` |
| app | `app/` | Orchestration — state transitions and event wiring |
| ui | `ui/` | HTML string rendering from view model |
| lib | `lib/` | Shared utilities (escape, debounce) |
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ build-full:
lint:
npm run lint

test:
npm run test

check: lint test

lintfix:
npm run lintfix

Expand Down
Loading
Loading