Files
client/app-stacks/plan.md
T

5.0 KiB

App Stacks — Forward Plan

Current State

www/app-stacks.html has:

  • A publish form that takes a Gitea URL + category and publishes a kind 30078 app-definition event
  • A subscription that displays received app-definition events grouped by category

New Understanding

  • Categories are actually app stacks — kind 30267 events (App curation set)
  • An app stack is a curated collection of apps, e.g. "Nostr Clients", "Bitcoin & Lightning Wallets"
  • An app definition (kind 30078) belongs to an app stack, not a free-text category
  • We need two separate publish flows:
    1. Create an App Stack — publishes a kind 30267 event
    2. Publish App Definition — selects an existing app stack to belong to

Nostr Event Types

App Stack (kind 30267)

{
  "kind": 30267,
  "content": "{\"name\":\"Nostr Clients\",\"description\":\"Nostr-native social and communication clients.\"}",
  "tags": [
    ["d", "nostr-clients"],
    ["t", "app-stack"],
    ["name", "Nostr Clients"],
    ["description", "Nostr-native social and communication clients."],
    // References to apps in this stack:
    ["a", "30078:<pubkey>:app-com.vitorpamplona.amethyst", "wss://relay.zapstore.dev"],
    ["a", "30078:<pubkey>:app-com.example.other", "wss://relay.zapstore.dev"]
  ]
}

App Definition (kind 30078) — updated

{
  "kind": 30078,
  "content": "{\"name\":\"Amethyst\",\"identifier\":\"com.vitorpamplona.amethyst\",\"repository\":\"...\",\"description\":\"\"}",
  "tags": [
    ["d", "app-com.vitorpamplona.amethyst"],
    ["t", "app-definition"],
    ["t", "nostr-clients"],           // ← references the app stack's d tag
    ["name", "Amethyst"],
    ["repository", "https://github.com/vitorpamplona/amethyst"],
    ["gitea", "com.vitorpamplona.amethyst"]
  ]
}

Implementation Phases

Phase 1: App Stack CRUD

Goal: Create, list, and display app stacks (kind 30267 events).

Changes to www/app-stacks.html (JS only):

  1. New subscription — subscribe to kind 30267 with #t: app-stack:

    subscribe({ kinds: [30267], '#t': ['app-stack'], limit: 200 }, ...);
    
  2. New function: parseAppStack(evt) — parse kind 30267 events into { dTag, name, description, appRefs: [], eventId }

  3. New function: renderStacks() — display app stacks in a section above or alongside app definitions

  4. New function: publishAppStack(name, description) — create and publish a kind 30267 event:

    {
      kind: 30267,
      content: JSON.stringify({ name, description }),
      tags: [
        ['d', name.toLowerCase().replace(/\s+/g, '-')],
        ['t', 'app-stack'],
        ['name', name],
        ['description', description],
      ],
      created_at: Math.floor(Date.now() / 1000),
    }
    
  5. New function: showCreateStackForm() — form with name and description fields

  6. Update renderApps() — add a "Create App Stack" button/area

Goal: App definitions select an app stack instead of typing a free-text category.

Changes to www/app-stacks.html (JS only):

  1. Update publish form — replace the free-text category input with a <select> dropdown populated from loaded app stacks

  2. Update doPublish() — use the selected stack's d tag value as the #t category tag

  3. Update renderApps() — group apps by the app stack they reference, not by free-text category

Phase 3: Stack Membership Management

Goal: Add/remove apps from stacks, and display stack membership.

Changes to www/app-stacks.html (JS only):

  1. Update publishAppDefinition() — also add an a tag referencing the app stack:

    ['a', '30267:<pubkey>:' + stackDTag, 'wss://relay.zapstore.dev']
    
  2. Display stack membership — show which stack(s) each app belongs to

  3. Stack detail view — show all apps in a stack

Data Flow

flowchart TD
    subgraph "Publishing"
        A[Create App Stack form] --> B[publishEvent kind 30267]
        C[Publish App Definition form] --> D[Select stack from dropdown]
        D --> E[publishEvent kind 30078<br>with #t: stack-d-tag]
    end
    
    subgraph "Subscriptions"
        F[Subscribe kind 30267 #t: app-stack] --> G[Collect stacks]
        H[Subscribe kind 30078 #t: app-definition] --> I[Collect apps]
    end
    
    subgraph "Rendering"
        G --> J[Render stack list]
        I --> K[Group apps by stack reference]
        K --> L[Render apps under each stack]
    end

Files to Modify

File Change
www/app-stacks.html Add JS for kind 30267 subscription, parsing, rendering, publishing. Update app-definition form to use stack dropdown.
app-stacks/README.md Update with new event structures and flow

What NOT to Change

  • No HTML changes to the template shell
  • No CSS additions
  • No removal of existing functionality