Getting started
Single-page view · as markdown
What is Wispist
Wispist / Getting started
Wispist is a lightweight data engine for simple websites. It gives ordinary HTML and JavaScript a persistent document store, safe concurrent mutations, and live updates while keeping the site itself static.
On a Wispdeck-hosted site, Wispist is already there:
const = ;
const = await ;
await ;
There is no connection call, project identifier, endpoint, API key, or secret in that code. Wispdeck identifies the site and its active release from the request, then supplies an opaque namespace and policy to the embedded Wispist Engine. The same-origin browser client cannot choose another site's store.
Static code, persistent data #
A Wispist site is still a static bundle:
site.zip
├── index.html
├── app.js
├── styles.css
└── wispist.json
wispist.json declares which collections the release may use and who may perform each operation. Wispdeck validates that declaration when the bundle is uploaded, and inserts a small parser-blocking client before site-authored elements in every served HTML head, so globalThis.wispist exists before later site scripts run.
The site's documents live in SQLite, outside the immutable release. Republishing code therefore keeps production data. An idle site has no dedicated process, timer, poller, goroutine, or database connection; work happens only while a viewer or mutation is active.
The data model #
Wispist v1 has three main concepts:
- A namespace is the host-selected isolation boundary. Wispdeck uses separate
liveanddraftnamespaces for each site. - A collection is a declared, ordered set of documents, such as
before-you-go. - A document contains an opaque ID, an opaque revision, server timestamps, and a caller-owned JSON object in
data.
Every replacement and deletion is conditional on an observed revision. If two browsers edit the same document concurrently, one succeeds and the other receives a revision conflict rather than silently overwriting work it did not see.
Subscriptions use Server-Sent Events. The client first lists a consistent collection view, then consumes retained changes after that list cursor. It reconnects after ordinary network interruptions and relists if the retained history is no longer sufficient.
Policy is public, enforcement is not #
The release declaration contains policy, not credentials. The concise shared profile deliberately allows every visitor to list, read, create, update, delete, and subscribe:
That is suitable for a genuinely public collaborative checklist. It is not user authorisation. Exact-origin checks, quotas, and request limits reduce cross-site and automated abuse, but any visitor can still change a shared collection.
Expanded declarations can set every operation to anyone, authenticated, or nobody. Wispdeck's first integration supplies anonymous principals to hosted site code, so authenticated is reserved for future identity integration rather than a way to reuse the dashboard cookie.
Draft and live state #
Wispdeck previews use a fresh private origin. Draft code reads and writes the site's draft namespace. The Current selector on that preview origin reads the live namespace with an unconditional server-side read-only override.
Publishing changes which release supplies public code and policy. It does not promote draft documents, clear live documents, or create a new production store. This prevents test data from silently replacing real data.
What v1 deliberately leaves out #
Wispist v1 is document CRUD plus live collection updates. It does not expose SQL, run user functions, execute scheduled jobs, perform joins, provide offline conflict resolution, accept file uploads, or offer multi-document transactions. A data directory supports one active process.
The small surface is intentional: Wispist is for the state that turns a static page into a useful little shared application, not a general application server.
Where to go next #
To build the checklist from the snippet above end to end, follow Build a shared checklist.
For the data model in full — namespaces, envelopes, revisions, conditional mutation — read Documents and collections.
For every field the declaration file accepts, read the wispist.json reference.
Build a shared checklist
Wispist / Getting started
This page builds the smallest useful Wispist site: a checklist that persists and updates in every open browser. The site has no build step and no connection configuration.
Declare the collection #
Create wispist.json at the root of the site bundle:
The shared profile lets every viewer read and change the collection. Use it only when that is the intended product behaviour. The two limits lower Wispist's installation defaults for this collection.
Write the page #
Create index.html:
<!doctype html>
Before you go
Before you go
New item
Add
Loading…
Do not add the Wispist client script yourself on Wispdeck. Wispdeck inserts it before the page's own script element, so wispist exists when app.js runs.
Add and render documents #
Create app.js:
const = ;
const = ;
const = ;
const = ;
let = new;
;
add creates a document with a generated ID and returns the complete document envelope. The client supplies the required idempotency key automatically.
Apply safe updates #
Add a delegated change listener:
;
update accepts the observed document, not only its ID. It shallow-merges the new fields locally and sends a replacement conditional on item.revision. A stale revision becomes a typed revision conflict.
Subscribe #
Start the live collection at the end of app.js:
const = ;
subscribe returns immediately. It lists every page, opens a change stream from that list cursor, maintains a document map, and calls render with the initial state and every later state.
Call unsubscribe() when a long-lived page no longer needs the collection. Closing a page closes its EventSource automatically.
Upload and test #
Put the three files at the ZIP root:
checklist.zip
├── index.html
├── app.js
└── wispist.json
Upload the archive as a Wispdeck site draft. In preview, the checklist uses draft data. Publish the release, open the public site in two independent browser windows, and add or check an item in one. The other should update without a refresh.
When a later draft exists, changes made in Draft remain separate. Select Current to see live data in read-only mode. Publishing that draft changes the code and declaration while leaving the public checklist intact.
Where to go next #
- Documents and collections — the envelope, revision, and conditional-mutation model behind
update. - Live updates — what
subscribedoes underneath: snapshot, cursor, Server-Sent Events, reconnect, reset. - wispist.json reference — every declaration field, profile, and limit.