Building apps (hds-lib)
If you ask the agent to build a web page or a Node script that talks to
HDS — rather than “agent processes my folder and writes events” — the
agent should always reach for hds-lib.
It wraps Pryv and adds everything HDS-aware: the data-model singleton,
item lookup, HDSService, app-template scaffolding, localisation,
converters. hds-lib already bundles Pryv and re-exports it as
HDSLib.pryv, so there is never a reason to load the raw pryv SDK as
a separate dependency.
Install via npm + bundler — not via CDN
Section titled “Install via npm + bundler — not via CDN”hds-lib ships as a git-URL npm package. Use any bundler you like — Vite
is the fastest from-scratch path:
npm create vite@latest my-hds-app -- --template vanillacd my-hds-appnpm installnpm install git+https://github.com/healthdatasafe/hds-lib-js.gitThen import * as HDSLib from 'hds-lib' in your code.
Full reference: healthdatasafe.github.io/hds-lib-js.
The API surface behind HDSLib.pryv (api batching, streamed events,
attachments, HF events, auth customization) is covered by
Pryv’s agent reference and the
pryv/lib-js README — documentation
only: Pryv’s docs describe standalone use, so ignore their
npm install pryv — never install pryv as a second dependency.
Development permissions
Section titled “Development permissions”While building, request a wide scope — manage on * streams — against a
demo account, so your app and your agent can create and reshape the
streams they need. Before the app meets a real account, shrink the
requested permissions to the minimal set the finished flow uses. See
Connect & permissions.
itemDef-first: derive streams + event shapes from the model — never hardcode
Section titled “itemDef-first: derive streams + event shapes from the model — never hardcode”No item for your data? Don’t hardcode strings or dump to note/txt.
Register your own itemDef — initHDSModel({ overload: { items: { … } } })
merges a brand-new item (plus its streams/eventTypes) into the model, and
from then on it behaves like any core item (itemsDefs.forKey,
eventTemplate, getNecessaryListForItems). A working custom itemDef is
the same shape as a core data-model definition, so propose it upstream
to grow the catalogue rather than keeping it private. (Overrides of an
existing item are limited to display fields; structural fields are
immutable. An app token cannot create a top-level root — request a new
root in the initial OAuth scope with a defaultName, or parent your custom
item under an existing root.)
Keeping the user signed in across reloads
Section titled “Keeping the user signed in across reloads”pryv.Browser.setupAuth already writes a cookie (pryv-libjs-<appId>)
and tries to auto-restore from it — so the “tokens in memory only” advice
you’ll see elsewhere describes the MCP server, not a browser app, and the
cookie auto-restore is inconsistent in practice. Pick a persistence model
deliberately: cookie (the lib default), localStorage (survives reload,
app-managed), or in-memory (re-OAuth each reload). The apiEndpoint is a
bearer credential reachable by XSS wherever you store it — never log it or
send it to a third party. Validate a restored token before trusting it:
call getAccessInfo (a revoked/expired token returns 403
invalid-access-token), and on failure clear it and fall back to sign-in.
A patient app should also re-provision its streams on restore
(StreamsAutoCreate.ensureExistsForItems), since the model may have grown
since last visit.
Helpful exports inside hds-lib
Section titled “Helpful exports inside hds-lib”A few exports an agent building on hds-lib will reach for often:
toolkit.StreamsAutoCreate.attachToConnection(conn).ensureExistsForItems(itemKeys)— provisions every stream a set of items needs (parents first, idempotent) in one call. Use this instead of any hand-written stream tree.getHDSModel().streams.getNecessaryListForItems(itemKeys, { knowExistingStreamsIds })— the lower-level primitive: the rawstreams.createpayloads, if you need them (e.g. to derive a read filter).getHDSModel().itemsDefs.forKey(key).eventTemplate()—{ streamIds, type }for an item’s write; picks the first variation automatically.eventToShortText(event)— shared formatter for displaying events as"60 Kg"/"Aspirin · 100mg"/ etc.MonitorScope— progressive event loading + WebSocket subscribe; use for live timelines and dashboards.computeReminders(item, source)— “what’s due now” computation.HDSSettings,getPreferredInput,getPreferredDisplay— per-user unit / locale / date-format awareness.appTemplates.*— the legal/consent shape every HDS app uses (AppManagingAccount,AppClientAccount,Collector,CollectorClient).
The full flat enumeration with one-line descriptions lives in hds-lib-js/AGENTS.md.
Companion libraries
Section titled “Companion libraries”For richer apps, hds-lib is the foundation — these build on top of it
(all expect a bundler, no CDN script tags; all install via git+https://…,
none are on the npm registry):
| Library | What it gives you | Agent docs |
|----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------|
| hds-forms-js | <HDSFormField> — React form input that auto-renders from an HDS item definition. | AGENTS.md |
| hds-feminine-cycle-ui | FEMM / Billings / Creighton / Mira chart cells + cervix-position glyphs for cycle-tracking events. | AGENTS.md |
| lib-bridge-js | Express skeleton for HDS bridges — backend services that sync a third-party platform’s data into HDS. | AGENTS.md |