Files
client/plans/app-stacks-integration.md

91 lines
3.1 KiB
Markdown

# App Stacks Integration Plan
## Constraint
**No changes to HTML structure. No new CSS. No removal of anything.** All additions are JavaScript-only inside the existing `<script type="module">` block in [`www/app-stacks.html`](www/app-stacks.html).
## Goal
Add JavaScript to:
1. Subscribe to kind 30078 events with `#t: app-definition` tag
2. Display received app definitions inside the existing empty `#divBody`
3. Publish new app-definition events (kind 30078) via `publishEvent()` from `init-ndk.mjs`
## What Changes
### File: [`www/app-stacks.html`](www/app-stacks.html)
Only the `<script type="module">` block (lines 149-806) gets additions. Specifically:
#### 1. New global variables (after line 193)
```javascript
// App definitions state
let apps = [];
let appDefSub = null;
let appDefsLoaded = false;
```
#### 2. New functions (inserted after the EVENT LISTENERS section at line 547)
| Function | Purpose |
|----------|---------|
| `parseAppDefinition(evt)` | Parse a kind 30078 event with `#t: app-definition` into `{ identifier, name, pubkey, repository, description, category, eventId }` |
| `getTagValue(tags, name)` | Helper to extract a tag value by name |
| `renderApps()` | Render collected apps as simple HTML into `#divBody` |
| `escapeHtml(str)` | XSS-safe HTML escaping |
| `publishAppDefinition(name, identifier, repository, category)` | Create and publish a kind 30078 app-definition event via `publishEvent()` |
| `showPublishForm()` | Prompt for name/identifier/repository/category, then call `publishAppDefinition()` |
| `subscribeAppDefinitions()` | Call `subscribe()` with `{ kinds: [30078], '#t': ['app-definition'], limit: 500 }` |
| `initAppDefinitionListener()` | Add `ndkEvent` and `ndkEose` window event listeners |
#### 3. Modified: `main()` function (line 616)
Add these calls after `await initializeAuthenticatedPageFeatures()`:
```javascript
// Set up app-definition event listener
initAppDefinitionListener();
// Subscribe to app-definition events
subscribeAppDefinitions();
```
#### 4. Modified: `authMode` default (line 218)
Change from `'required'` to `'optional'` so the page loads without forcing login.
## What Does NOT Change
- `<title>` — stays "TEMPLATE"
- Header text — stays empty
- Body — stays empty (UI is built dynamically by JS)
- Footer — unchanged
- Sidenav — unchanged
- Hamburger menu — unchanged
- Any CSS — no additions
- Any HTML elements — no additions or removals
## Data Flow
```mermaid
flowchart LR
A[Page Load] --> B[main]
B --> C[initAppDefinitionListener]
B --> D[subscribeAppDefinitions]
D --> E[NDK worker subscribes<br>kind 30078 #t: app-definition]
E --> F[ndkEvent window event]
F --> G[parseAppDefinition]
G --> H[renderApps into #divBody]
I[User clicks Publish button] --> J[showPublishForm prompts]
J --> K[publishAppDefinition]
K --> L[publishEvent from init-ndk.mjs]
L --> M[Event arrives via subscription]
M --> G
```
## Files to Modify
| File | Change |
|------|--------|
| [`www/app-stacks.html`](www/app-stacks.html) | Add ~130 lines of JS inside existing `<script type="module">` block. Change `authMode` default. |