Seed is the open-source implementation of the Hypermedia protocol. It is a small family of programs: a daemon that holds the data and talks to the network, apps that put a person in front of that daemon, services that add email, identity and agents, and tools for scripting. This section has one page per program. Each page is a map for contributors and operators. It is not a user manual.
Everything lives in one repository, github.com/seed-hypermedia/seed. The Go daemon and the protobuf definitions are built with Please and the ./dev script. The TypeScript apps are a pnpm workspace under frontend/. The vault and the agents service are separate Bun workspaces. The mobile app manages its own dependencies with npm. Contributing explains the setup.
The programs
Program | What it is | Where | Talks to the daemon over |
|---|---|---|---|
The Go node: storage, indexing, signing, libp2p sync, gRPC and HTTP. |
| It is the daemon. | |
The Electron app: browser, editor, archive and a full peer. Spawns its own daemon and a local agents server. |
| gRPC-web on the daemon's HTTP port. | |
The site server and gateway: server-rendered pages, the Seed API, site services, browser signing. |
| gRPC-web on the daemon's HTTP port, with a per-request bearer token. | |
The command-line client for documents, comments, contacts, capabilities and keys, and the tool that publishes this folder. |
| The Seed API of a site over HTTPS; optionally a local daemon. | |
The notifications and email service. |
| The daemon's activity feed over gRPC-web. | |
The zero-knowledge identity vault that keeps account keys and delegates session keys to browsers. |
| gRPC-web to the site's daemon for account lookups and signing, and | |
The Expo app for iOS, Android and web. |
| The Seed API of a site. | |
A raw-data browser for the network: documents, blobs, feeds, an API lab. |
| The Seed API of a site. | |
The agent runtime: a signed action API, sessions, tools and triggers. |
| The Seed API, as a client with delegated keys. |
The shared packages
Four TypeScript packages sit under the apps, in frontend/packages/.
@seed-hypermedia/client, the SDK. It has no framework dependency and is published to npm. It holds Hypermedia ids and types, blob creation and signing, CBOR, the HTTP client for the Seed API, markdown conversion, the query grammar, key files and vault helpers, and the Hypermedia Schemas engine. Every app uses it, and so do the CLI, the vault and the agents service.
@shm/shared, the app layer: generated gRPC clients, the typed API router and its HTTP server adapter, the universal client abstraction, React Query models, routes and translations. It is not published.
@shm/ui, the React component library, page components, and the shared agents client and models used by desktop, web and mobile. Its reusable buttons, form controls, dialogs, logo and theme can be built as a standalone npm package for services such as SeedHost. Application-specific components and private workspace dependencies stay inside the monorepo; see the package build and release instructions. The Publish UI package workflow validates changes on pull requests and main; an explicit version-confirmed run on main publishes the tested tarball to npm. Publish the package before updating and deploying SeedHost's locked dependency.
@shm/editor, the block editor, a BlockNote fork on TipTap and ProseMirror, with a server-side renderer.
The dependency direction is client, then shared, then ui, then editor. The vault and the agents service consume client and shared through Bun file: dependencies, which copy the packages at install time. A watcher script reinstalls them during development.
Shared embed presentation
Web and desktop use the same content embed components in documents, comments, and discussion quotes. The host owns editing controls and navigation services. It must not supply a different body renderer or override embed typography.
@shm/ui/embed-views loads resources and resolves versions and routes. Card, Link, and Comments display modes retain their existing shared components.
@shm/ui/content-embed owns block selection, fragment selection, expansion state, and author placement. A document fragment expands to its block. A comment fragment expands to the whole comment. A source or range change resets expansion.
@shm/ui/embed-wrapper owns the source action, green rule, and caret control. Links within the content remain separate from the source link. QuotedDocBlock uses the same presentation with source navigation disabled.
@shm/editor/readonly-viewer owns block conversion, highlights, content typography, gallery behavior, and the browser/server rendering contract. EmbedEditorView is a compatibility adapter. The shared context avoids a UI-to-editor dependency. Browser and server implementations both limit nested embed depth.
@shm/ui/account-avatar owns compact and regular author identity. Inline profile mentions share the name primitive and retain their inline link behavior. An account home document remains a document card; it is not a separate profile-card type.
Full document and comment typography are intentional content variants. Collapsed text block quotes and fragments use plain text with the same small text style in every host. Expansion restores the source formatting without changing the stored content. Image and video block embeds open their source; previews preserve aspect ratio, have a 240 px media height limit, and use half the available width (up to 400 px) when their container is at least 480 px wide. Narrower containers use the available width, still capped at 400 px. External video embeds show a static play preview rather than loading a player. Renderer roots isolate typography from surrounding comment styles. This isolation uses CSS @scope, supported by Chrome 118+, Safari 17.4+, and Firefox 146+.
For a repeatable visual review, run direnv exec . node frontend/packages/editor/e2e/capture-embed-gallery.mjs. It builds production components with fixed resource data and writes an interactive HTML file, screenshots, and browser check results to an OS temporary directory. It does not start a server or replace tests in the running web and desktop apps.
Ports at a glance
Port | Prod | Dev | Belongs to |
|---|---|---|---|
Daemon P2P | 56000 | 58000 | daemon, spawned by the desktop app |
Daemon HTTP, gRPC-web, | 56001 | 58001 | daemon |
Daemon native gRPC | 56002 | 58002 | daemon, unused by the TypeScript apps |
Daemon metrics | 56003 | 58003 | daemon |
Desktop API bridge, | 56004 | 58004 | desktop app |
Agents server | 3050 | 3051 | agents |
Vault | 3030 | vault | |
Web app | 3000 | web | |
Notify | 3060 | notify | |
Explorer | 5173 | explore |
A daemon started on its own, without the desktop app, defaults to 55000, 55001 and 55002. Hosted sites run their daemon on 56000 behind a reverse proxy.
See also
Building on Hypermedia, for using these programs from your own code.
Self-hosting, for running a site.
Contributing, for developing them.
The web API, the Seed API most of these programs speak.
Seed Agents, what the agents service runs.
The protocol, what the daemon implements.
A custom HTML page is not a component but a kind of document: one whose html metadata names a UnixFS folder that the desktop opens as a sandboxed HTML page.
Do you like what you are reading? Subscribe to receive updates.
Unsubscribe anytime