# 12 — Building Consumer Apps: The Curriculum and the Workflow

*Ch. 10 established that MKStack is buildable outside Shakespeare, on any model provider. This chapter answers the next question: once you can build there, what counts as "done" — the 19-skill directory as the definition-of-done checklist, the three-rung workflow Soapbox's own team uses to decide what to build and how, and the five concepts that separate a working prototype from a Nostr-native one.*

**Verified: 2026-07-10**

Confidence:
- **High** — all 19 skill files (fetched live, raw, this pass), the dev-ladder quotes and the 48h Agora/HRF data point (fetched live from the source post), the domain/NIP mapping (independently re-verified against the live marketing page — matches the earlier gap-analysis draft exactly).
- **Medium** — builder-criticality ratings (Core/Common/Situational) in the skill table below: this manual's own judgment call, applied consistently, not a ranking Soapbox publishes anywhere.
- **Medium** — the AI-team roster: three personas confirmed live (Dirk Rost, Quilly, Sheila), each announced independently with no roster page tying them together. Treat as a plurality snapshot, not a closed list, and re-verify currency before citing any one as "the" example.
- **Low** — whether the §9.0 lane mapping to the dev ladder (below) is a parallel Soapbox intends or one this manual draws by analogy; no source states the two frameworks correspond.

---

## What This Chapter Is

Three chapters now stack on top of each other. Ch. 10 covers MKStack's scaffold anatomy, dependency versions, and the `AGENTS.md`/`.mcp.json` agent contract. Ch. 11 covers Nostrify, the interface layer every scaffolded app compiles against — `NStore`/`NRelay`, signers, policies, uploaders. Neither is repeated here. This chapter covers the layer above both: what a coding agent (or the human directing it) must still get right after the scaffold compiles clean and the interfaces are wired, and how Soapbox's own team decides what to build in the first place. Two threads, in order: the 19-skill curriculum as the spec for "done," and the workflow culture that produces Soapbox's own apps 48 hours at a time.

## The Soapbox Dev Ladder

Soapbox doesn't build consumer Nostr apps with one tool — it picks a rung based on how well the shape of the thing is already known [1]:

| Rung | Tool | When | What it optimizes for |
|---|---|---|---|
| 1 | **Shakespeare** | "where ideas start" | fastest path from a thought to a working Nostr app — ideation and quick prototyping [1] |
| 2 | **OpenCode** | "once an idea is worth building for real" | agentic AI coding, fine control over every file — going deep [1] |
| 3 | **Clone MKStack** | "when we already know exactly what we're making" | known shape; the template is the starting point, not a re-derivation [1] |

```mermaid
flowchart LR
    IDEA["An idea"] -->|"ideation, quick prototyping"| SHAKE["Rung 1: Shakespeare\nfastest thought-to-app path"]
    SHAKE -->|"worth building for real"| OC["Rung 2: OpenCode\nagentic coding, file-level control"]
    OC -->|"shape is already known"| CLONE["Rung 3: Clone MKStack\ntemplate as starting point"]
    CLONE --> SHIP["Ship\nproducer reviews, owns the standard"]
```

The ladder isn't strictly one-way — a team that already knows the shape can start straight at rung 3. Ch. 07 §9.0 codifies TresPies's own parallel structure: four lanes (Enterprise / TresPies-hosted / IDE agents / Local-routed) picked by *who's driving and which model provider*, not by *how well-known the shape is* — a different axis on the same instinct: match the tool to how much is already decided before you start. Read loosely rather than as a Soapbox-stated equivalence, the two frameworks line up:

| Dev-ladder rung | Nearest §9.0 lane | Shared logic |
|---|---|---|
| Shakespeare (ideation) | Local / routed — cost-floor mockup volume | Cheapest, fastest, most disposable output; nothing here is meant to survive |
| OpenCode (deep work) | IDE agents — operator-in-the-loop editing | Fine-grained control, a human steering every file, not a one-shot generation |
| Clone MKStack (known shape) | TresPies-hosted / Enterprise — house builds, contract work | The shape is already decided; the remaining choice is execution, not exploration |

The culture behind the ladder is stated twice in the same post. First, the producer framing:

> "In music, the producer doesn't play every instrument; they bring taste, direction, and the judgment to know when it's done. That's the role." [1]
> "The AI writes the code; the human owns the vision and the standard." [1]

Second, prompting itself is named as a craft with a learning curve, not a shortcut around one:

> "Prompting is a skill. Learning how to speak to an AI, how to frame a problem, how much context to give, when to steer and when to get out of the way, how to recognize why a model went sideways and correct it, is a real, earned craft." [1]
> "The best people on our team aren't the ones with the fanciest setup; they're the ones who've put in the reps." [1]

The data point behind the claim: Agora — ch. 03's non-custodial BTC fundraising product — was built in **48 hours at the HRF hackathon**, using both Shakespeare and OpenCode, and "Venezuelan activists were on it within hours" of shipping [1]. That is the ladder under real time pressure, not a marketing abstraction.

## The 19-Skill Curriculum: The Definition of Done

Ch. 10 established that `.agents/skills/*/SKILL.md` is a Claude-Skill-shaped directory an agent loads by name from `AGENTS.md`. What ch. 10 didn't do is open all 19 files — this chapter does, live, and treats the resulting list as the operational definition of "done": a shipped app that never touched a skill's territory hasn't finished that dimension, whether or not an agent wrote code near it.

Legend: **Core** = load-bearing for nearly any consumer app on this stack. **Common** = frequent, but scoped to a feature category. **Situational** = specific product shape only. Ratings are this manual's judgment — no Soapbox-published ranking exists.

| Skill | Teaches | Criticality |
|---|---|---|
| `nostr-security` | XSS threat model for a client holding `nsec` in `localStorage`: CSP, URL/CSS sanitization, author-filtering on trust-sensitive queries [6] | Core |
| `testing` | Vitest + RTL unit tests via the `TestApp` wrapper and pre-mocked browser APIs; run the full suite, not just one file [7] | Core |
| `nip19-routing` | One root `/:nip19` route decodes npub/nprofile/note/nevent/naddr; decode before filtering, scope addressable queries by author, never render a decoded `nsec` [9] | Core |
| `nostr-relay-pools` | Target specific relays or curated groups via `nostr.relay()`/`nostr.group()`; read write-relays from NIP-65 metadata, never hardcode a relay list [5] | Core |
| `nostr-infinite-scroll` | `useInfiniteQuery` + intersection observer, paginated by `until` timestamp, deduplicated by event id [19] | Core |
| `note-content` | The `NoteContent` renderer: linkifies URLs/hashtags/mentions, embeds media/invoices/quoted notes, sanitizes all of it; guard recursive embeds against unbounded nesting [20] | Core |
| `theming` | Fonts via `@fontsource`, light/dark CSS variables, shadcn/ui-consistent styling; the `isolate` + negative-`z-index` stacking-context gotcha [8] | Common |
| `file-uploads` | `useUploadFile` posts to a Blossom server, returns NIP-94 `imeta` tags; requires a signed-in signer, prefer `mutateAsync` before publishing the referencing event [10] | Common |
| `nostr-encryption` | NIP-44 (legacy NIP-04 fallback) encrypt/decrypt through the logged-in user's signer only; never derive a shared secret yourself [12] | Common |
| `edit-profile` | Drop-in kind-0 profile form (name/about/picture/banner/nip05), reusing `useUploadFile` for images [15] | Common |
| `nostr-comments` | Threaded comments (NIP-22 kind 1111) attachable to events, URLs, hashtags, or NIP-73 identifiers; NIP-09 deletion isn't guaranteed network-wide [18] | Common |
| `relay-management` | User-facing NIP-65 relay-list editor, publishes kind 10002 — the write-side companion to the outbox model's login-time auto-sync [23] | Common |
| `nwc` | Nostr Wallet Connect (NIP-47) + WebLN + NIP-57 zap requests; NWC connection strings are secrets, store like passwords [11] | Situational |
| `onchain-bitcoin` | Derives a Taproot BTC address straight from the Nostr pubkey (same secp256k1 key), PSBT signing across all three signer types, kind-8333 onchain zaps; verify amounts on-chain, the `amount` tag is self-reported [21] | Situational |
| `capacitor` | Wraps the web app as native iOS/Android — haptics, Keychain/KeyStore, deep links, no Swift/Kotlin; `bootstrapNative()` must run before React mounts [14] | Situational |
| `lockdown-mode` | Maps what Apple Lockdown Mode blocks (IndexedDB, Service Workers, WASM, WebGL, WebRTC) and the fallback per API; no official detection API exists [16] | Situational |
| `nip85-stats` | Pulls pre-computed engagement stats from a trusted NIP-85 assertion provider instead of scanning raw events; always author-filtered, not a source of truth for per-user interactivity [17] | Situational |
| `ai-chat` | `useShakespeare` hook wires Nostr-authenticated chat completions to the Shakespeare API, streaming plus dynamic model discovery [13] | Situational |
| `plausible-analytics` | Privacy-friendly analytics via `@plausible-analytics/tracker`, wired through `AppConfig` and `VITE_PLAUSIBLE_*` env vars; guard `init()` with a ref, it only runs once [22] | Situational |

**Scope warning:** `nostr-security` covers XSS/CSP/content-sanitization only. It documents the *consequence* of `nsec` living in `localStorage` — "Nostr private keys (`nsec`) are stored in plaintext in `localStorage`" [6] — not how to secure that storage, and it says nothing about `.env`/`VITE_*` discipline. Other skills in this table hand an agent raw secrets to wire up with no shared skill governing where those values may live or how they stay out of a client bundle — `plausible-analytics`'s `VITE_PLAUSIBLE_*` vars [22], `nwc`'s connection strings [11]. This is not hypothetical: a same-day production audit of this stack found `VITE_` vars get "baked into the public bundle as literal strings" and that "default gitleaks has zero Nostr rules — a committed `nsec1…` passes CI today" [29]. Key-custody architecture and env-var discipline are specced for ch. 15 (forthcoming, already scoped) [29]. A clean `nostr-security` pass is not a security audit of either.

## Hook and Component Inventory, by Consumer Domain

The marketing page organizes its "50+ NIPs" claim [2] around four consumer domains; independently re-verified against the live page this pass, the mapping matches the earlier gap-analysis draft exactly:

| Domain | NIPs | Skills / components that implement it |
|---|---|---|
| **Social** | 01, 02, 18, 25 (profiles, follows, reposts, reactions) | `edit-profile` [15], `useAuthor`, `LoginArea` [2] |
| **Messaging** | 17, 28, 29, 44 (DMs, public chat, groups, encryption) | `nostr-encryption` [12]; gift-wrap DMs and groups — see Scaffold vs. Product, below |
| **Payments** | 47, 57, 60, 61 (NWC, zaps, Cashu, nutzaps) | `nwc` [11]; `onchain-bitcoin` [21] as the kind-8333 alternative rail |
| **Content** | 23, 52, 53, 94 (long-form, calendar, live events, file metadata) | `file-uploads` [10], `note-content` [20], `nostr-comments` [18], `nostr-infinite-scroll` [19] |

Eight named hooks and components recur across the marketing page, the skill files, and ch. 10's scaffold anatomy — the primitives worth knowing by name before reading any app's source:

| Name | Role |
|---|---|
| `useNostr` | Base hook: the active relay pool, underneath every query and publish [2] |
| `useNostrPublish` | Signs and broadcasts an event through the current user's signer [2] |
| `useAuthor` | Resolves a pubkey to kind-0 profile metadata, cached [2] |
| `useCurrentUser` | The logged-in identity plus signer; gates any action requiring auth (uploads, publishes) [2][10] |
| `useUploadFile` | Blossom upload, returns NIP-94-ready metadata [2][10] |
| `LoginArea` | Account-switching UI, the NIP-07/NIP-46 login entry point [2][10] |
| `RelaySelector` | User-facing relay picker [2] |
| `NoteContent` | Sanitized, embed-aware note renderer — see the `note-content` skill row, above [2][20] |

## Scaffold vs. Product: An Opportunity, Not a Contradiction

Ch. 10's NIP-support table, read against ch. 02's Ditto findings, produces a fact worth stating plainly rather than leaving as a footnote: **the MKStack scaffold documents support for NIP-17 (gift-wrap DMs) and NIP-29 (relay-based groups) that Ditto — Soapbox's own flagship community server — does not have.** Ch. 02 confirms the Ditto side directly: NIP-17/NIP-04 is "absent from Ditto's own official NIP reference list," and NIP-29 groups are "Flotilla's model, not Ditto's" [24]. Ch. 10 confirms the scaffold side: the template's README lists NIP-17 and NIP-29 among the roughly twenty NIPs it ships wired [26].

Read as a contradiction, this looks like the manual disagreeing with itself. It isn't. Ditto is a *product* — one opinionated deployment of the stack, scoped to what its own team chose to ship. MKStack is the *scaffold* every product forks from, and it carries broader protocol coverage than any single downstream app needs or exposes. A builder who wants private DMs or relay-based groups doesn't wait for Ditto to add them — the scaffold already has the pieces (`nostr-encryption` [12] for the crypto, the README's NIP-17/29 wiring for the event shapes). Ditto's gap is a product-scoping decision, not a stack ceiling. Carry that distinction into every future "does the stack support X" question: check the scaffold, not just the flagship app built on it.

## Five Load-Bearing Concepts

Five ideas recur across all 19 skills and both chapters this one draws from. Miss one and an agent-built app still compiles, still passes `tsc`/`eslint`/`vitest` (ch. 10's validate-then-commit gate) — and still breaks in ways that gate never catches.

| Concept | Statement | What breaks if ignored |
|---|---|---|
| One interface, many backends | Storage is a swap, not a rewrite: ch. 11 documents `NStore` (event/query/count/remove) and `NRelay` as one shape shared by an in-memory store, `NPostgres`, `NIndexedDB`, a single relay, or a full `NPool` [28]. Every skill in this table is written against that shape, not a specific relay | Locking a component to one relay implementation forecloses the in-memory/IndexedDB/Postgres swaps the framework exists to allow |
| Signer discipline across three standards | NIP-07 (extension) and NIP-46 (remote/bunker) are detailed in ch. 06 [25]; NIP-55 (Android signer intents, e.g. Amber) is the third standard MKStack's own contract names, not yet covered there. Ch. 11 confirms the shape underneath all three: six `NostrSigner` implementations, each a `window.nostr` drop-in with `nip04`/`nip44` built in [28]. Every skill above that touches a key routes through that interface, never a raw `nsec` | `nostr-encryption` [12], `nostr-security` [6], and `onchain-bitcoin` [21] each independently name the same failure mode: a raw `nsec` reachable by client-side JS turns any XSS into full account — and, with `onchain-bitcoin` installed, wallet — compromise |
| Outbox is routing, not config | NIP-65 read/write relay sets, auto-synced on login (ch. 10's `NostrSync`) and user-editable via `relay-management` [23]. `nostr-relay-pools` states the rule directly: "Don't hard-code user-facing relay lists" [5]; ch. 11 names the failure mode in the same words this chapter's skills point at: "a hardcoded relay list is the single most common reason 'my app can't find this user's events'" [28] | Hardcoded relay URLs are this stack's most common "can't find events" report — an event published to a user's write relays never reaches a reader whose client only queries a fixed default |
| Local-first, not CRUD-with-a-backend | Frontends are disposable; data lives on relays plus a local cache. `lockdown-mode` [16] makes the dependency legible in reverse: strip IndexedDB, which Apple Lockdown Mode does outright, and the caching layer most apps quietly lean on is simply gone. Ch. 11 confirms the same weak point from the framework side — `NIndexedDB` "degrades to a silent no-op under iOS Lockdown Mode" [28] | Builders arriving from a typical web-app background reach for a backend database by reflex; there isn't one here, and code assuming persistent server-side state has no home in this architecture |
| Skills-as-spec | The 19-skill directory (table, above) is the audit checklist for "done," not a menu an agent copies boilerplate from | Shipping a skill's happy path without its warnings — e.g. `file-uploads` without the `useCurrentUser` guard [10] — ships the documented failure mode still live |

The three chapters compose rather than compete: ch. 11 supplies the interface guarantee (a relay and a Postgres table look the same to your code), this chapter supplies the feature-by-feature checklist for using that guarantee correctly, and ch. 10 supplies the agent contract that loads both by name. An app that only reads one of the three will compile — `tsc`/`eslint`/`vitest` don't check for a hardcoded relay list or a signer bypass — but won't hold up past the first relay outage or the first security review.

## The AI-Team Pattern

Soapbox's own build culture is not purely human. At least three named AI personas do production work, each announced independently, with no roster page connecting them — a plurality snapshot, not a closed team list; re-verify currency before citing any one as "the" example [1][3][4].

| Persona | Role | Runs on | Announced |
|---|---|---|---|
| **Dirk Rost** | Code review, merge-request approval, "a bird's-eye view across every project" [1] | Open-source infra; personality "defined in plain markdown anyone can read" [1] | Referenced in the ships-fast post; no dedicated announcement found this pass |
| **Quilly** | Docs, Nostr community engagement, GitLab contributions (blog posts, team-page updates), real-world Shakespeare testing, team coordination via Signal [3] | OpenClaw (open-source agent framework) in an LXC container; personality split across `SOUL.md`/`AGENTS.md`/`USER.md`/`TOOLS.md` [3] | 2026-01-26 [3] |
| **Sheila** | Full contractor-payment lifecycle — invoices, ACH/wire/Bitcoin payouts, bookkeeping, expense tracking, OpenCollective submissions [4] | OpenCode, human-supervised ("I see what she's doing before it goes out" [4]); 50+ single-purpose TypeScript scripts under a 600-line `AGENTS.md` [4] | 2026-03-06 [4] |

The pattern holds across all three: markdown-defined personality on infrastructure Soapbox controls, not a closed-source assistant product. Quilly's own `SOUL.md` states the operating principle plainly: "Be genuinely helpful, not performatively helpful. Have opinions. Be resourceful before asking." [3] The same open-infra, plain-markdown-personality shape that governs `AGENTS.md`'s relationship to a coding agent (ch. 10) governs Soapbox's relationship to its own AI teammates — one contract format, applied to both code-writing and operational work.

## Open Questions

- Whether the Core/Common/Situational criticality ratings in the skill table would look different if Soapbox published its own ranking — no such ranking exists in any source found this pass; treat these as this manual's judgment, re-derivable, not authoritative.
- Whether `nostr-security`'s XSS-only scope is a deliberate boundary or a gap Soapbox hasn't yet closed — the same-day production audit [29] reads it as the latter; Soapbox has not stated a position either way.
- Whether Cursor or Windsurf read `.agents/skills/*/SKILL.md` the same way Claude Code and OpenCode do — ch. 10 flagged this as unconfirmed, and it remains unconfirmed here; no dedicated rules file for either was found this pass.
- Whether a fourth AI persona exists beyond Dirk Rost, Quilly, and Sheila — no roster page surfaced in this pass either; given the cadence of the three found (Jan, then Mar 2026), the count may already be stale by the time this is read.

---

## Sources

1. [How Soapbox Ships Fast — Soapbox Blog](https://soapbox.pub/blog/how-soapbox-ships-fast) — the Shakespeare/OpenCode/clone-MKStack ladder, producer-role quotes, prompting-as-craft quotes, the 48h Agora/HRF hackathon data point, Dirk Rost's role. Accessed 2026-07-10.
2. [MKStack — AI-Powered Nostr App Framework](https://soapbox.pub/mkstack) — marketing page: named hooks/components, NIP-to-domain mapping, "50+ NIPs" / "8 minutes" claims. Accessed 2026-07-10.
3. [Meet Quilly — Soapbox Blog](https://soapbox.pub/blog/meet-quilly) — Quilly's role, OpenClaw infrastructure, SOUL.md quote. Published 2026-01-26. Accessed 2026-07-10.
4. [Announcing Sheila — Soapbox Blog](https://soapbox.pub/blog/announcing-sheila) — Sheila's role, OpenCode operation, human-oversight model. Published 2026-03-06. Accessed 2026-07-10.
5. [mkstack — .agents/skills/nostr-relay-pools/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/nostr-relay-pools/SKILL.md) — accessed 2026-07-10.
6. [mkstack — .agents/skills/nostr-security/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/nostr-security/SKILL.md) — accessed 2026-07-10.
7. [mkstack — .agents/skills/testing/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/testing/SKILL.md) — accessed 2026-07-10.
8. [mkstack — .agents/skills/theming/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/theming/SKILL.md) — accessed 2026-07-10.
9. [mkstack — .agents/skills/nip19-routing/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/nip19-routing/SKILL.md) — accessed 2026-07-10.
10. [mkstack — .agents/skills/file-uploads/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/file-uploads/SKILL.md) — accessed 2026-07-10.
11. [mkstack — .agents/skills/nwc/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/nwc/SKILL.md) — accessed 2026-07-10.
12. [mkstack — .agents/skills/nostr-encryption/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/nostr-encryption/SKILL.md) — accessed 2026-07-10.
13. [mkstack — .agents/skills/ai-chat/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/ai-chat/SKILL.md) — accessed 2026-07-10.
14. [mkstack — .agents/skills/capacitor/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/capacitor/SKILL.md) — accessed 2026-07-10.
15. [mkstack — .agents/skills/edit-profile/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/edit-profile/SKILL.md) — accessed 2026-07-10.
16. [mkstack — .agents/skills/lockdown-mode/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/lockdown-mode/SKILL.md) — accessed 2026-07-10.
17. [mkstack — .agents/skills/nip85-stats/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/nip85-stats/SKILL.md) — accessed 2026-07-10.
18. [mkstack — .agents/skills/nostr-comments/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/nostr-comments/SKILL.md) — accessed 2026-07-10.
19. [mkstack — .agents/skills/nostr-infinite-scroll/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/nostr-infinite-scroll/SKILL.md) — accessed 2026-07-10.
20. [mkstack — .agents/skills/note-content/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/note-content/SKILL.md) — accessed 2026-07-10.
21. [mkstack — .agents/skills/onchain-bitcoin/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/onchain-bitcoin/SKILL.md) — accessed 2026-07-10.
22. [mkstack — .agents/skills/plausible-analytics/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/plausible-analytics/SKILL.md) — accessed 2026-07-10.
23. [mkstack — .agents/skills/relay-management/SKILL.md (raw)](https://gitlab.com/soapbox-pub/mkstack/-/raw/main/.agents/skills/relay-management/SKILL.md) — accessed 2026-07-10.
24. This manual, [ch. 02 — Community Ops](02-community-ops.md) — cross-referenced for Ditto's documented absence of NIP-17/NIP-04 DMs and NIP-29 groups.
25. This manual, [ch. 06 — Nostr Foundations](06-nostr-foundations.md) — cross-referenced for NIP-07/NIP-46 signer mechanics; does not yet document NIP-55.
26. This manual, [ch. 10 — MKStack](10-mkstack.md) — cross-referenced for scaffold anatomy, the AGENTS.md agent contract, and the README-derived NIP-support table; not duplicated here.
27. This manual, ch. 15 (forthcoming) — planned home for `.env`/`VITE_*` discipline and key-custody architecture, outside `nostr-security`'s XSS/CSP scope.
28. This manual, [ch. 11 — Nostrify](11-nostrify.md) — cross-referenced for `NStore`/`NRelay`'s shared interface shape, `NPool` outbox routing and its hardcoded-relay-list finding, the six `NostrSigner` implementations, and `NIndexedDB`'s Lockdown Mode degradation; not duplicated here.
29. Maintainers' internal production-secrets-longevity audit note (companion document, not part of this public chapter set) — same-day audit grounding the ch. 15 spec; source of the `VITE_` public-bundle finding and the zero-Nostr-rules gitleaks finding cited in this chapter's scope warning.
