Welcome to Vanilla Breeze
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
JSON request/response schemas for every /go/ endpoint — what backend implementations must fulfill and what VBService consumers can rely on.
JSON request/response schemas for every /go/ endpoint. VB ships the contracts and a VBService client; you ship a backend that fulfils them. Pick the worker, framework, or service of your choice.
application/json. VBService sets the request content-type automatically and parses JSON responses.VBService.configure({ headers: { Authorization: '…' } }) and validate server-side however you like.200 on read success, 201 on create, 202 on async accept, 204 when there is no body, 4xx/5xx on errors.limit, since where listed. Beyond v1, add cursor-based pagination as needed.Every /go/ endpoint uses a single error envelope on non-2xx responses. VBService wraps this in a VBServiceError with { status, body, role, path } for consistent client-side handling.
{ "error": "not_found", "message": "Subscription sub_abc123 not found", "status": 404}
error — short snake_case code (not_found, invalid_input, rate_limited, unauthorized, internal)message — human-readable detail; safe to show in dev consoles, not necessarily user-facingstatus — mirrors the HTTP status code for clients that don’t plumb the response status through their wrapperPowers <notification-wc> in panel mode, plus the page-watch subscription flow.
Fetch notifications for the current user/session.
| Param | Type | Default | Purpose |
|---|---|---|---|
since | ISO datetime | — | Only return notifications after this timestamp |
type | string | — | Filter by type (update, alert, watch, stewardship, …) |
unread | boolean | — | Only return unread notifications |
limit | number | 50 | Maximum items to return |
{ "items": [ { "id": "release-3.0", "type": "update", "title": "v3.0 Released", "body": "New notification system.", "url": "/changelog#v3", "date": "2026-04-10T00:00:00Z", "read": false, "priority": "normal", "expires": null } ], "total": 12, "unread": 3}
Mark a notification as read or dismissed.
{ "read": true }// or{ "dismissed": true }
{ "id": "release-3.0", "read": true }
Subscribe to page-watch or topic notifications. The notify array selects delivery channels — panel (in-app via notification-wc) and/or email (via /go/email).
{ "url": "/docs/getting-started", "type": "page-watch", "notify": ["panel"], "email": "user@example.com"}
{ "id": "sub_abc123", "status": "active" }
{ "status": "removed" }
List active subscriptions.
{ "subscriptions": [ { "id": "sub_abc123", "url": "/docs/getting-started", "type": "page-watch", "notify": ["panel"], "createdAt": "2026-04-13T16:00:00Z" } ]}
Changelog / what’s-new entries in JSON. Same data source as /rss, different format. <notification-wc> can read this for “new release” notifications; build pipelines can render both feeds from one source.
| Param | Type | Default | Purpose |
|---|---|---|---|
since | ISO datetime | — | Only return entries after this date |
limit | number | 20 | Maximum items |
{ "items": [ { "id": "v3.0", "type": "update", "title": "v3.0 — Notification System", "body": "New notification panel and service layer.", "url": "/changelog#v3.0", "date": "2026-04-10" } ]}
Relationship to /rss. /rss serves the same content as RSS/Atom for feed readers; /go/feed serves it as JSON for the notification panel and any in-app changelog component. Generate both from the same source — a CHANGELOG.md, a CMS, or a database.
{ "email": "user@example.com", "lists": ["weekly-digest", "release-notes"]}
{ "status": "subscribed", "lists": ["weekly-digest", "release-notes"] }
{ "email": "user@example.com", "lists": ["weekly-digest"]}
{ "status": "unsubscribed", "lists": ["weekly-digest"] }
Required query param: email.
{ "subscriptions": ["release-notes"], "available": ["weekly-digest", "release-notes", "security-alerts"]}
Used by page-watch alerts, GoodURL digests, contact-form submissions, and newsletter welcomes. The contract is template-driven: VB names the template, the backend renders it.
{ "to": "user@example.com", "template": "page-watch-update", "data": { "pageTitle": "Getting Started", "pageUrl": "/docs/getting-started", "changeDescription": "Section 3 rewritten" }}
{ "status": "queued", "id": "msg_xyz" }
VB defines named templates and the data fields each one expects. The backend implements the rendering — pick whichever templating engine you like.
| Template | Data fields | Used by |
|---|---|---|
page-watch-update | pageTitle, pageUrl, changeDescription | Page-watch (see page-watch.md) |
goodurl-digest | items, score, trend | GoodURL daily digest |
contact-form | name, email, message, subject | Contact-form submissions |
newsletter-welcome | email, lists | Newsletter sign-ups |
None are required — the JSON shapes above are enough to write your own backend in any language. VB ships starter kits at admin/reference-implementations/:
node admin/reference-implementations/dev-stub/server.mjs and point VBService.configure({ baseUrl: 'http://localhost:3010/go' }) at it. Wide-open CORS so it works from https://vb.test. Available now.wrangler deploy after replacing the KV id. Available now.npm start. Available now.The URL namespace these contracts live under, plus the VBService client that calls them.
Consumes /go/notify for dynamic notifications and the panel-mode unread badge.