# Cache-First Anti-Pattern Audit Instructions

## Goal

Scan the codebase for places where `ndkFetchEvents` is called in a way that blocks rendering or user-visible UI when cached data could be used instead. Report each finding so a developer can apply the cache-first fix.

---

## Background

Read `docs/cache-first-page-patterns.md` first. It explains the three data APIs:

- `queryCache(filters)` — fast, local IndexedDB, 5s timeout
- `ndkFetchEvents(filters)` — slow, relay network, 15s timeout
- `subscribe(filters, opts)` — live streaming, no timeout

The rule: **never `await ndkFetchEvents(...)` in the critical render path if the data could exist in cache.** Instead, use `queryCache` first, render immediately, then fire-and-forget `ndkFetchEvents` for background hydration.

---

## What to Search For

### Pattern 1: `await ndkFetchEvents(...)` in page HTML files

Search all `www/*.html` files for:

```
await ndkFetchEvents(
```

For each match, determine:
- Is this in the main initialization flow (inside `main()` or the top-level IIFE)?
- Is there a `queryCache` call before it for the same or similar filter?
- Could the data plausibly exist in IndexedDB cache (i.e., it was fetched before on a previous page load)?

**Report as a finding if**: `await ndkFetchEvents` is called without a preceding `queryCache` for the same data, and the result is used to render UI that the user sees.

**Exclude**: Cases where `ndkFetchEvents` is used with `void` (fire-and-forget) or inside a `.then()` chain — those are already non-blocking.

### Pattern 2: `await ndkFetchEvents(...)` in shared modules

Search all `www/js/*.mjs` files for:

```
await ndkFetchEvents
```

or

```
await ndkFetchEventsFn
```

For each match, determine:
- Is this function called during page initialization or rendering?
- Does the module have access to a `queryCache` / `queryCacheFn` function?
- If not, is `queryCache` being passed through the dependency chain from the page?

**Report as a finding if**: A module-level function awaits `ndkFetchEvents` without first trying cache, AND the module does not have `queryCacheFn` available.

### Pattern 3: Missing `queryCache` in dependency threading

Search all `www/js/*.mjs` files for functions that accept a deps/options object containing `ndkFetchEvents`:

```
ndkFetchEvents
```

in destructuring patterns like `const { ndkFetchEvents, ... } = deps;`

For each match, check:
- Does the same destructuring also include `queryCache`?
- If the function forwards deps to another module, does it forward `queryCache` too?

**Report as a finding if**: A function destructures `ndkFetchEvents` from a deps object but does NOT also destructure `queryCache`.

### Pattern 4: Pages that import `ndkFetchEvents` but not `queryCache`

Search all `www/*.html` files for import statements from `init-ndk.mjs`:

```
import {
```

Check whether the import includes both `ndkFetchEvents` and `queryCache`.

**Report as a finding if**: A page imports `ndkFetchEvents` but does NOT import `queryCache`.

---

## Files to Scan

### HTML pages (check all):
- `www/*.html`

### JavaScript modules (check all):
- `www/js/*.mjs`

### Specifically check these known integration points:
- `www/js/post-interactions.mjs` — embed hydration, interaction fetching
- `www/js/post-interactions2.mjs` — dependency forwarding
- `www/js/mute-list.mjs` — mute list loading
- `www/js/profile-cache.mjs` — profile resolution
- `www/js/blossom-ui.mjs` — blossom server loading
- `www/js/relay-ui.mjs` — relay status loading
- `www/js/zaps.mjs` — zap-related fetches
- `www/js/utilities.mjs` — utility functions that may fetch

---

## Output Format

For each finding, report:

```
FILE: www/example.html (or www/js/example.mjs)
LINE: 123
PATTERN: [1|2|3|4] — [brief description]
CODE: `await ndkFetchEvents({ kinds: [1], ... })`
CONTEXT: [What this code does — e.g., "fetches user's kind 1 posts for feed render"]
SEVERITY: [HIGH if it blocks visible UI, MEDIUM if it blocks secondary content, LOW if it's a dep threading gap]
FIX HINT: [e.g., "Add queryCache call before this, render from cache, make this fire-and-forget"]
```

---

## What NOT to Flag

- `void ndkFetchEvents(...)` — already fire-and-forget, correct pattern
- `ndkFetchEvents(...)` inside `.then()` chains — already non-blocking
- `await ndkFetchEvents(...)` for `publishEvent` confirmation — must await
- `ndkFetchEvents` used only in background refresh intervals (e.g., `setInterval`)
- `subscribe(...)` calls — these are already event-driven
