Hosted oncibercultura-25-26.hyper.mediavia theHypermedia Protocol

AppViews for Seed Hypermedia: Research and ProposalWe want similar extensibility for Seed, adapted to our P2P architecture

    Seed Hypermedia is a P2P document protocol. ATProto (Bluesky) enables third-party "AppViews" — full applications built on protocol data (WhiteWind for blogging, Frontpage for link aggregation, Smoke Signal for events). We want similar extensibility for Seed, adapted to our P2P architecture.

    Key difference: ATProto is server-centric (PDS → Relay/Firehose → AppView). Seed is P2P (daemon ↔ daemon via libp2p). There is no global firehose. This fundamentally changes the AppView architecture.

    User → PDS (data storage) → Relay (aggregates all PDSes into firehose)
                                        ↓
                                  AppView (consumes firehose, indexes, serves UI)
                                        ↓
                                  Client (queries PDS, which proxies to AppView)

      Lexicon schemas define all record types (like JSON-Schema). Custom schemas = custom apps.

      Feed Generators return ranked lists of post URIs (lightweight, algorithm-only services).

      Labelers attach moderation/classification labels to content.

      AppViews are heavy: process entire network firehose, maintain full databases.

      Equal API access: official Bluesky app uses same APIs as third parties.

    ATProto vs Seed: Key Architectural Differences

      Seed's P2P advantage: No firehose bottleneck. Apps subscribe to relevant data only. Running an "AppView" is cheap — you don't need to process the entire network.

    Four Approaches (Light → Heavy)

      1. Embedded AppViews (Block-Level Extensions)

        What: Custom interactive widgets inside documents. Examples: Poll block, code playground, data table, map, chart, invoice block.

        What exists:

          Block.type is open string (documents.proto:789)

          HMBlockSchema = union(HMBlockKnownSchema, HMBlockUnknownSchema) in hm-types.ts:1168

          BlockContentUnknown fallback in blocks-content.tsx:1102

          Editor preserves unknown types via originalType/originalData

        What to build:

          Block Extension Registry injected into BlocksContentContext

          @shm/block-sdk package with types, helpers, createBlockExtension() factory

          Block dispatch modification: consult registry before BlockContentUnknown fallback

        type BlockExtension = {
          type: string              // "Poll", "DataTable", "Map"
          renderer: React.ComponentType<BlockContentProps>
          editor?: React.ComponentType<BlockEditorProps>
          schema?: z.ZodSchema      // optional attribute validation
          icon?: React.ComponentType
          label?: string
        }
        

        Effort: Small (2-4 weeks). No protocol/backend changes needed.

      2. View AppViews (Document-Level Views)

        What: Alternative ways to visualize document collections. Examples: Kanban board, calendar, gallery, graph, table/spreadsheet, timeline.

        What exists:

          VIEW_TERMS = [':activity', ':comments', ':collaborators', ':directory', ':feed'] in entity-id-url.ts:45

          navRouteSchema discriminated union in routes.ts:204

          Query blocks already aggregate documents with includes/sort/limit

          ListDirectory RPC with sorting options

        What to build:

          View Extension Registry (similar pattern to block extensions)

          Make VIEW_TERMS, viewTermToRouteKey(), navRouteSchema dynamically extensible

          Update URL parsing + Remix catch-all route (routes/$.tsx)

          @shm/view-sdk package

        type ViewExtension = {
          key: string                              // 'kanban', 'calendar'
          viewTerm: string                         // ':kanban'
          renderer: React.ComponentType<ViewProps>
          panelRenderer?: React.ComponentType      // optional panel variant
        }
        

        Effort: Medium (4-8 weeks). Frontend route system changes across web + desktop.

      3. Standalone AppViews (Full Applications)

        What: Entirely new apps on Seed data (like ATProto AppViews). Examples: Recipe app, project management, wiki, academic papers, event management, social reader.

        What exists:

          Full gRPC API surface (50+ RPCs) via Connect-RPC (JSON over HTTP)

          UniversalClient wraps all requests with type safety

          Web API routes already proxy gRPC

          Capability delegation for third-party auth

        What to build:

          @shm/sdk — standalone npm package extracted from @shm/shared

          Documented REST API (formalize existing api.$.tsx routes)

          CORS support in seed-site

          READER role in capability system (currently only WRITER/AGENT)

          App capability authorization flow (like OAuth but using crypto capabilities)

          Extension registry/manifest format

        import { SeedClient } from '@shm/sdk'
        const client = SeedClient.connect('http://localhost:56001')
        const doc = await client.documents.get({ account: 'z6Mk...', path: 'recipes/pasta' })
        

        Effort: Large (2-4 months).

      4. Feed/Index AppViews (Data Processing)

        What: Custom indexers, feed algorithms, labelers processing Seed events. Examples: Trending content, tag indexer, citation graph, content moderation, notifications, cross-space search.

        What exists:

          ListEvents RPC with multi-dimensional filtering (already a selective firehose)

          Subscriptions service for selective P2P sync

          Entity search (FTS5) and mention tracking

        What to build:

          SSE/WebSocket streaming endpoint (real-time ListEvents)

          Feed Generator protocol (service returns ordered HM document IDs)

          Labeler protocol (attach signed labels to documents)

          Webhook registration for headless processors

        Effort: Medium-Large (6-10 weeks).

    Schema Strategy

      Recommendation: Don't adopt Lexicon yet. The existing open primitives are sufficient:

        Publish a Block Type Registry (public list of known types + expected attribute shapes)

        Provide optional Zod schemas per block type (validate when available, passthrough when not)

        Define metadata conventions (namespace custom fields: x-kanban-status, x-recipe-ingredients)

      Lexicon solves federation interop (every PDS must understand every type). Seed's CRDT model handles this differently — unknown types round-trip without data loss. Adopt a formal schema system only if the ecosystem grows to need it.

    Novel Ideas Beyond ATProto

        Document-as-App: A document declares metadata.appType: 'kanban' and renders itself as a Kanban board. No installation — the "app" IS a document.

        1

        Composable Views via Query Blocks: Enhance Query block with attributes.style: 'Kanban'. Combines block extension with view extension without a separate view system.

        P2P Extension Sync: Extensions are Seed documents containing code. When you open a document with a custom block type, the daemon discovers and syncs the extension from the block type's namespace.

        WASM Block Renderers: Language-agnostic, sandboxed block rendering via WebAssembly instead of requiring React.

    Summary

      Seed already has the raw materials for an AppView ecosystem. The block type system, arbitrary metadata, capability delegation, and activity feed are all extension-ready. The P2P architecture is actually an advantage — it makes running AppViews cheaper than ATProto's firehose model.

      The recommended path: start with block extensions (cheapest, backward-compatible, immediate value), then view extensions, then SDK/API formalization, then feed generators. Each phase validates developer interest before investing in the next.