Status · 24 h
Riverside Bakery225 rec ◆ 0The Orchard56 rec ▲ +10The Orchard Group28 rec ◆ 0poezine.orguptschoonover.comupTEMP43.5°C ▲ +1.1°DISK60.1% ▲ +1.7 ptMEM53% ▲ +1 ptLOAD0.46 ▼ -0.22UP6d 11hTUNNELrunningRADICLEdown
poezine.org

Windows

Showing a republic on your own website: verified variables, live votes, and signing that never touches your site.

A window shows a Git Republic on another website: a co-op's own site, a blog, a dashboard. The website stays an ordinary website; what the window shows is not the website's to change. Each visitor's browser fetches the republic's record, checks every signature and link with the republic's own code, and only then shows anything. Signing happens in a small window served by the republic's own node, never on the host website, which only learns the result.

§02Adding one

Load window.js from the republic's node, then place elements:

<script type="module" src="https://riverside.poezine.org/window.js"></script>

<gr-seal src="https://riverside.poezine.org/"></gr-seal>
<p>Money in circulation: <gr-var src="https://riverside.poezine.org/" name="supply"></gr-var></p>
<gr-list src="https://riverside.poezine.org/" name="offices"></gr-list>
<gr-votes src="https://riverside.poezine.org/" limit="5"></gr-votes>
<gr-join src="https://riverside.poezine.org/">Become a member</gr-join>

Elements render plain markup with gr-* classes (gr-seal, gr-office, gr-grant, gr-proposal, gr-tally, gr-error, …), so the host site's own stylesheet styles them.

ElementShows
<gr-seal>the republic's name, its record length, verified in this browser; an alarm if copies disagree
<gr-var name="…" arg="…">one variable, as text
<gr-list name="…">a list: offices, grants, committees, members, decisions
<gr-votes limit="…" [readonly]>open votes with live tallies, and buttons to vote
<gr-act kind="…" fields='{…}' label="…">a button that signs any act
<gr-join>a button to apply to join

Add also="https://mirror.example/ https://another.example/" to any element to compare other copies: if one disagrees, the seal says so plainly.

§03Variables
NameValue
name, id, founded, records, head, verified, modulesthe republic itself
members, member-countactive members, with display names
officeseach office, its title, seats and current holders
holders (arg: an office id)who holds that office now
committeeseach committee and its members
grantseach grant in force: title, what it may do, and who holds it now
supply, currency, balance (arg: a member id)the value module's money
settings, setting (arg: a key)every setting, or one
proposalsopen proposals with tallies and deadlines
decisions (arg: how many)the latest closed proposals
statute (arg: a wiki page)the text of an enacted statute: title, body, version
§04From JavaScript
import { connect } from 'https://riverside.poezine.org/window.js';

const r = await connect('https://riverside.poezine.org/', { also: ['https://mirror.example/'] });
r.ok;                          // the record verified
r.get('holders', 'treasurer'); // ['ana']
r.get('grants');               // [{ title, may, holders, … }]
r.on('record', (recs) => …);   // the record grew: every new record, verified
r.on('ballot.cast', (rec) => …); // any kind of record, as it arrives
r.on('disagreement', (urls) => …);
await r.act('ballot.cast', { proposal: 'd-…', choice: 'for' }, 'Vote for the budget');

act opens the republic's signing window, which shows exactly what will be signed and signs it with the visitor's own key, password or passkey. It resolves once the act is sent and the record has been verified again.

§05Streams

Windows stay current by themselves: the node announces new records on /window/events, and each window fetches and verifies them before showing them. Every element repaints; on(kind, …) hears each new record by kind.

§06Headless republics

A republic without the page module has no page of its own, but its windows work all the same: a co-op can live entirely inside its own website, with the record, the signatures and the verification still the republic's.