The Seed mobile app
The Expo and React Native app for iOS, Android and the web that reads documents and discussions from a Seed site, keeps identities in an on-device vault, and chats with Seed Agents.

The Seed mobile app puts Hypermedia on a phone. It opens documents from a Seed site, shows their discussions, lets you comment as one of your identities, shows your notifications, and lets you talk to your agents. It runs no daemon and keeps no copy of the network. Every read and write goes through a site's Seed API. It is under active development and builds for iOS, Android and the web from one codebase.

Where the code is

frontend/apps/mobile, package @shm/mobile: Expo 54, React Native 0.81 with the new architecture, React 19, React Navigation, React Query 4, MMKV for storage on native and localStorage on the web.

Path

What it holds

index.ts, App.tsx

The entry point and providers.

src/navigation/RootNavigator.tsx

The screen stack.

src/screens/

Server select, account, identities, vault, vault connect, document, comment, notifications.

src/components/

React Native renderers for blocks, embeds, query blocks, discussions and the comment composer.

src/client/

The Seed API client for the chosen server and its /hm/api/config.

src/vault/

The on-device vault: encrypted envelope, secure key storage, vault connect, remote sync.

src/agents/

The agents screens.

src/notifications/notify.ts

The signed client for the notify service.

dev/mock-agents-server.ts

A scripted agents server for UI work.

Why it sits outside the pnpm workspace

The root pnpm workspace pins React 18 for the desktop and web apps, and React Native 0.81 needs React 19. So pnpm-workspace.yaml excludes this app, and it installs its own dependencies with npm. It still uses repository code without publishing it:

    @seed-hypermedia/client, the SDK, is aliased to frontend/packages/client in metro.config.js, tsconfig.json and jest.config.js. The client's own dependencies resolve from the root node_modules, so run pnpm install at the root first.

    @shm/ui/agents/* is mapped to the shared agents code, limited to .ts files so an accidental import of a web component fails at bundle time.

    Metro's resolveRequest forces one copy of react and @tanstack/react-query. Without it, a shared module resolves React 18 from the root and its hooks break.

    Metro watches only a short list of package folders. Watching the repository root crawls over a million files and crash-loops watchman, so a new cross-package import means adding its folder to that list.

How it talks to the network

The app talks to one server at a time, chosen on the server screen and saved on the device. The default is https://dev.hyper.media today. It will switch to https://hyper.media. Add https://hyper.media or any Seed site to use production data now.

    Reads use createSeedClient(serverUrl) from the SDK: Resource, InteractionSummary and the other typed /api/<Key> requests. The documents and discussions it renders are the same data the web app shows. See The web API.

    Writes are signed on the phone. The comment composer builds a comment blob with the SDK's createComment and sends it with publish, the PublishBlobs action of the Seed API.

    Site config comes from the server's /hm/api/config, which is also how the app learns the site's notify service.

Identities and the vault

The app keeps identities in its own device vault, a TypeScript port of the daemon's vault in backend/storage/vault. Private keys are stored in the platform keychain through expo-secure-store with the WHEN_UNLOCKED_THIS_DEVICE_ONLY access setting, so the keychain does not copy them to other devices. On the web build, which is for development and tests, the secret store falls back to browser storage.

You get an identity into the app in one of three ways:

    Create a new key on the device.

    Import a 12-word recovery phrase. The derivation matches the daemon: BIP-39 seed, SLIP-10 path m/44'/104109'/0', Ed25519. See Keys.

    Connect a remote vault, https://hyper.media/vault by default. The app runs the same vault connect handshake as the desktop app and then syncs identities with the remote vault, merging changes from both sides. The handshake is described on the vault page. You can also import an unencrypted .seedkey file exported from the desktop app. Password-protected exports need Argon2id, which the app's JavaScript engine cannot run.

Running it

pnpm mobile:install # npm install inside the app; run pnpm install at the root first pnpm mobile # Expo dev server: scan the QR code, or press w for the web build pnpm mobile:web # web build only pnpm mobile:test # jest unit tests pnpm mobile:typecheck

The ios/ and android/ folders are generated and are not in git. Create them with npx expo prebuild, then run npx expo run:ios or npx expo run:android. Release builds go through Expo Application Services (eas.json). npm run submit builds and submits the iOS app. The bundle id is media.hyper.seed.mobile and the URL scheme is hm.

The end-to-end tests live in the repository's tests/ package. mobile-web.integration.test.ts drives the web build with Playwright against a real daemon and web app, and mobile-vault.integration.test.ts covers the vault.

Working with it

In the Seed app

The mobile app shares identities with the desktop app only through a connected remote vault. It does not read the desktop app's local data.

SDK

The app is a working example of the SDK in React Native: the client, createComment, CBOR and signing all run under React Native with a few shims.

Web API

Everything the app shows comes from a site's /api/<Key> routes and /hm/api/config. Images come from the site service /hm/api/image/<cid>, which resizes them. See The web API.

Agents

The Agents screens list your Seed Agents, open sessions and chat. They reuse the platform-neutral half of the shared agents code: the signed client, React Query models, chat row model and tool summaries. Only the views are rewritten. The agents server defaults to https://agentic.seed.hyper.media, overridable with EXPO_PUBLIC_SEED_AGENT_SERVER_URL or in the app.

For UI work without spending tokens, npm run mock-agents serves a scripted agents server on http://localhost:3052 that streams replies, shows pending tool calls, advances a plan and parks a run for an answer. It does not verify signatures, binds to loopback only, and must never be deployed.

Do you like what you are reading? Subscribe to receive updates.

Unsubscribe anytime