Author SHA1 Message Date
Bendik Aagaard LynghaugandClaude Fable 5 31e17aad70 Flaunt 'voices echoed so far' on the index, live from the relay's /pulse
Lint and reload / lint (pull_request) Successful in 3s
Lint and reload / reload (pull_request) Skipped
A 'The count so far' feature in the index's 'Meet a network' alternative
fetches https://relay.redoal.com/pulse (redoal ADR-0023) with a kind:url
resource and shapes { voices_echoed: N } into one card — the number as
the heading, 'voices echoed so far' beneath. Lint-clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-10 07:34:06 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 87a4877596 An /advantages page (grouped by need) + a memory deep-dive; index stays lean
Lint and reload / lint (pull_request) Successful in 2s
Lint and reload / reload (pull_request) Skipped
Keep index.yaml short: a 'See what it's good for' alternative routes to
a new /advantages page instead of piling on features. /advantages sorts
the advantages by what a visitor is after (a community keeping its own
memory; an artist placing work; anyone done with accounts) — each with
several features — and its 'go deeper' alternative routes to
/advantages/memory, the rarity-aware preservation model on its own.
Lint-clean (question_lint: 10 questions valid).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 23:57:17 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 2cee770041 Pin portal v0.3.33: head preloads for fonts and wordmark
Lint and reload / lint (push) Successful in 2s
Lint and reload / reload (push) Successful in 1s
Deploy instance / deploy (push) Successful in 1s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y42TyF8Zu7NGRR2893vNcZ
2026-09-02 11:52:43 +02:00
bl d96a020d0b Update questions/reported.yaml
Lint and reload / lint (push) Successful in 3s
Lint and reload / reload (push) Successful in 0s
2026-09-01 21:13:59 +00:00
Bendik Aagaard Lynghaug f1855d3f8b Pin portal v0.3.32
Deploy instance / deploy (push) Successful in 1s
Lint and reload / lint (push) Successful in 3s
Lint and reload / reload (push) Successful in 0s
2026-09-01 22:15:10 +02:00
Bendik Aagaard Lynghaug 86ca5228de Pin portal v0.3.31
Deploy instance / deploy (push) Successful in 1s
Lint and reload / lint (push) Successful in 3s
Lint and reload / reload (push) Successful in 0s
2026-09-01 21:51:02 +02:00
Bendik Aagaard Lynghaug e68e5c0c37 Pin portal v0.3.30
Deploy instance / deploy (push) Successful in 1s
Lint and reload / lint (push) Successful in 3s
Lint and reload / reload (push) Successful in 0s
2026-09-01 21:45:06 +02:00
Bendik Aagaard Lynghaug a732d1eb1b Pin portal v0.3.29
Deploy instance / deploy (push) Successful in 1s
Lint and reload / lint (push) Successful in 3s
Lint and reload / reload (push) Successful in 1s
2026-09-01 21:39:39 +02:00
Bendik Aagaard Lynghaug ec78a76ae9 Pin portal v0.3.28
Deploy instance / deploy (push) Successful in 1s
Lint and reload / lint (push) Successful in 3s
Lint and reload / reload (push) Successful in 0s
2026-09-01 20:33:30 +02:00
Bendik Aagaard Lynghaug 5db9e42a6b Pin portal v0.3.27
Deploy instance / deploy (push) Successful in 0s
Lint and reload / lint (push) Successful in 2s
Lint and reload / reload (push) Successful in 0s
2026-09-01 20:29:11 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 10f220b928 wordmark_invert: true (white-stroke mark)
Lint and reload / lint (push) Successful in 2s
Lint and reload / reload (push) Successful in 1s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y42TyF8Zu7NGRR2893vNcZ
2026-09-01 20:26:44 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 16bd2e41eb Pin portal v0.3.24
Deploy instance / deploy (push) Successful in 1s
Lint and reload / lint (push) Successful in 3s
Lint and reload / reload (push) Successful in 0s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y42TyF8Zu7NGRR2893vNcZ
2026-09-01 20:03:57 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 e58aa9d43c Pin portal v0.3.23
Deploy instance / deploy (push) Successful in 1s
Lint and reload / lint (push) Successful in 2s
Lint and reload / reload (push) Successful in 0s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y42TyF8Zu7NGRR2893vNcZ
2026-09-01 17:26:12 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 7f4058901b Pin portal v0.3.21: markdown images, optional sign-in, hero centering
Deploy instance / deploy (push) Successful in 1s
Lint and reload / lint (push) Successful in 3s
Lint and reload / reload (push) Successful in 1s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y42TyF8Zu7NGRR2893vNcZ
2026-09-01 17:13:51 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 19eccfd212 Pin portal v0.3.18: convergence animation, overlay results
Deploy instance / deploy (push) Successful in 1s
Lint and reload / lint (push) Successful in 2s
Lint and reload / reload (push) Successful in 0s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y42TyF8Zu7NGRR2893vNcZ
2026-09-01 16:01:03 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 c2f2fdb546 Report a recording: per-voice review link, desk, and lifecycle
Deploy instance / deploy (push) Successful in 1s
Lint and reload / lint (push) Successful in 3s
Lint and reload / reload (push) Successful in 1s
Every recording card links to /report/<digest>. Filing opens a
redoal_reports record; the Reports desk decides — Remove it acts for
real (the relay deletes the recording everywhere), Keep it closes
with the voice in place. Pins portal v0.3.17 for markdown in cards.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y42TyF8Zu7NGRR2893vNcZ
2026-08-31 17:22:48 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 02d3901610 One card: Built in the open at UHHM
Lint and reload / lint (push) Successful in 3s
Lint and reload / reload (push) Successful in 0s
Merges the facilitator credit and the young-and-honest card.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y42TyF8Zu7NGRR2893vNcZ
2026-08-31 13:51:29 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 bc96601001 Credit UHHM as facilitator; varde link follows its repo home
Lint and reload / lint (push) Successful in 4s
Lint and reload / reload (push) Successful in 0s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y42TyF8Zu7NGRR2893vNcZ
2026-08-31 13:33:40 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 2007e80851 Pin portal v0.3.16
Deploy instance / deploy (push) Successful in 1s
Lint and reload / lint (push) Successful in 3s
Lint and reload / reload (push) Successful in 0s
Hidden fields lose their stray label row (the Address listing under
Email in the watcher card) and the announce sweeper refreshes open
event records from content.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y42TyF8Zu7NGRR2893vNcZ
2026-08-30 23:16:01 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 dcbeda34b7 Watchers: double opt-in
Lint and reload / lint (push) Successful in 3s
Lint and reload / reload (push) Successful in 0s
redoal_watchers starts pending; /watching (the confirmation mail's
landing page) confirms to open or drops. Only open watchers are told.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 19:37:10 +02:00
Bendik Aagaard Lynghaug 865c426266 Pin portal v0.3.14 - icon column
Deploy instance / deploy (push) Successful in 1s
Lint and reload / lint (push) Successful in 2s
Lint and reload / reload (push) Successful in 0s
2026-08-30 16:58:21 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 bee1ba406b Hero: clip the bleed at the header, never overflow the document
Lint and reload / lint (push) Successful in 2s
Lint and reload / reload (push) Successful in 0s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 16:48:33 +02:00
Bendik Aagaard Lynghaug 137415ee92 Pin portal v0.3.13 - voice keeps on submit
Deploy instance / deploy (push) Successful in 1s
Lint and reload / lint (push) Successful in 3s
Lint and reload / reload (push) Successful in 1s
2026-08-30 16:38:17 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 57c7bc7528 Place page: preview-of-the-app copy, review before keeping
Lint and reload / lint (push) Successful in 2s
Lint and reload / reload (push) Successful in 0s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 16:37:44 +02:00
Bendik Aagaard Lynghaug 98c1213d02 Pin portal v0.3.12
Deploy instance / deploy (push) Successful in 1s
Lint and reload / lint (push) Successful in 2s
Lint and reload / reload (push) Successful in 0s
2026-08-30 16:08:59 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 66c31786ce Places: /shape/<key>, voices, address newsletter
Lint and reload / lint (push) Successful in 2s
Lint and reload / reload (push) Successful in 0s
The landing gesture leads to /shape/{curve.key} - the place page:
what was left there (the relay's /place, playable), leave your voice
(type: voice at value "{key}"), hear from exactly this address
(redoal_watchers, exact key), and the cards. Email leaves the landing
page. A card for iroh through varde. Desks for voices and watchers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 16:05:26 +02:00
Bendik Aagaard Lynghaug 605eb549f8 Pin portal v0.3.11 - templated action lint fix
Deploy instance / deploy (push) Successful in 0s
Lint and reload / lint (push) Successful in 2s
Lint and reload / reload (push) Successful in 0s
2026-08-30 16:04:59 +02:00
Bendik Aagaard Lynghaug 8303626e78 Pin portal v0.3.10 - voice, places
Deploy instance / deploy (push) Successful in 1s
Lint and reload / lint (push) Successful in 2s
Lint and reload / reload (push) Successful in 0s
2026-08-30 16:00:07 +02:00
Bendik Aagaard Lynghaug aae9ea5592 Pin portal v0.3.9 - templated actions, pickable places
Lint and reload / lint (push) Successful in 2s
Deploy instance / deploy (push) Successful in 1s
Lint and reload / reload (push) Successful in 0s
2026-08-30 15:42:12 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 6bac75891f Hero: the field bleeds past its box
Lint and reload / lint (push) Successful in 2s
Lint and reload / reload (push) Successful in 1s
25% overscan on every side, drawing scaled to the piece so nothing
grows; html overflow-x: clip keeps the bleed from scrolling sideways.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 15:17:26 +02:00
Bendik Aagaard LynghaugandClaude Fable 5 671b20b3c2 Exhibition: 23 October 19:00, «Big Tech må vekk», linked
Lint and reload / lint (push) Successful in 2s
Lint and reload / reload (push) Successful in 0s
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 14:47:40 +02:00
Bendik Aagaard Lynghaug 0dff54e2cd Pin portal v0.3.8 - markdown descriptions
Lint and reload / lint (push) Successful in 2s
Deploy instance / deploy (push) Successful in 1s
Lint and reload / reload (push) Successful in 0s
2026-08-30 14:46:59 +02:00
Bendik Aagaard Lynghaug bef058af8f Pin portal v0.3.7 - feature links
Deploy instance / deploy (push) Successful in 1s
Lint and reload / lint (push) Successful in 2s
Lint and reload / reload (push) Successful in 0s
2026-08-30 14:42:01 +02:00
bl b02a3c2a42 Merge pull request 'Landing page: talking points drawn from the zine' (#1) from zine-talking-points into main
Lint and reload / reload (push) Successful in 0s
Lint and reload / lint (push) Successful in 3s
Reviewed-on: #1
2026-08-30 12:35:23 +00:00
16 changed files with 522 additions and 67 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ on:
- .gitea/workflows/deploy.yml
env:
PORTAL_RELEASE: v0.3.6
PORTAL_RELEASE: v0.3.33
INSTANCE: redoal-portal
jobs:
+24
View File
@@ -14,3 +14,27 @@ aggregates:
unsubscribed: { event: unsubscribed }
transitions:
open: [unsubscribed]
# Double opt-in: a watcher is pending until the address confirms from
# the mail n8n sends (redoal: confirm watching); only open watchers
# are told when something lands at their shape.
- bucket: redoal_watchers
initial: pending
states:
pending: { event: requested }
open: { event: confirmed }
unsubscribed: { event: unsubscribed }
transitions:
pending: [open, unsubscribed]
open: [unsubscribed]
# Reports on recordings. The relay watches this bucket: a record
# moved to "removed" deletes the recording from its store, the varde
# pin, and discovery. "kept" closes the report with the recording in
# place. Decisions are human, never automatic.
- bucket: redoal_reports
initial: open
states:
open: { event: reported }
removed: { event: removed }
kept: { event: kept }
transitions:
open: [removed, kept]
+12 -3
View File
@@ -18,18 +18,27 @@
//
// prefers-reduced-motion freezes the field fully drawn either way.
import { makePaths, drawPaths } from './paths.js';
import { makePaths, drawPaths, OVERSCAN } from './paths.js';
const STYLE_ID = 'redoal-hero-style';
const CYCLE_MS = 28000;
const SEED = 7;
const COUNT = 47;
const BLEED = `${((OVERSCAN - 1) / 2) * -100}%`;
const STYLE_TEXT = `
/* The field bleeds 25% past the hero piece on every side. Sideways
it is clipped at the header box (clip, not hidden: no scroll
container, and overflow-y stays visible) - an element wider than
the viewport, even unscrollable, makes phones re-size the layout
viewport when it appears, which read as the page jumping as the
input loaded. Vertically it may run into the copy below. */
.hero-module { overflow-x: clip; overflow-y: visible; }
.redoal-paths {
position: absolute;
inset: 0;
overflow: hidden;
inset: ${BLEED};
overflow: visible;
pointer-events: none;
--redoal-t: 0;
--redoal-seed: ${SEED};
+6 -1
View File
@@ -8,6 +8,11 @@
// engine likes, and unseeded randomness would reshuffle the picture on
// every repaint.
// The field bleeds past its box: the painted element is this much
// larger than the hero piece on each axis (25% each side), and the
// drawing scales to the piece, not the element, so nothing grows.
export const OVERSCAN = 1.5;
export function mulberry32(seed) {
let a = seed >>> 0;
return () => {
@@ -118,7 +123,7 @@ const smooth = (u) => u * u * (3 - 2 * u);
export function drawPaths(ctx, width, height, paths, t, colors) {
ctx.clearRect(0, 0, width, height);
const s = Math.min(width, height) * 0.9;
const s = (Math.min(width, height) / OVERSCAN) * 0.9;
ctx.save();
ctx.translate(width / 2, height / 2);
ctx.lineWidth = 1;
+99
View File
@@ -0,0 +1,99 @@
id: /advantages
name: What is it good for?
description: >
The same one trick — a drawing is an address — answers different
needs. Here's what redoal gives you, grouped by what you're trying to
do. None of it needs an account, a server that owns your words, or a
platform's permission.
alternatives:
- name: A community keeping its own memory
description: >
No company holds the recordings. The people who show up are the
infrastructure, and the network is built so their memory survives
them.
features:
- name: No server owns the words
description: >
Recordings live on the phones of the people who visit a
place, handed peer to peer. There is no central store to
seize, subpoena, or switch off — the memory is only ever
where its people are.
icon: lucide:server-off
- name: Attention is what preserves
description: >
Every time someone listens, their phone keeps a copy and
quietly becomes another place you can get it from. A voice
heard by many is, by that fact alone, held by many. The more
a thing is cared about, the harder it is to lose.
icon: lucide:ear
- name: The infrastructure points the right way
description: >
When a relay helps, it points visitors toward each other — it
never becomes the place the words live. The fewer servers it
takes to keep a voice reachable, the more the network is
doing what it was built to do.
icon: lucide:git-fork
- name: An artist placing work where it's found
description: >
Leave something at a shape, and it belongs to that shape — found
by feel, answered in kind, and not quietly unsaid later.
features:
- name: The drawing is the address
description: >
Your line becomes a twenty-byte fingerprint that reconstructs
back into the shape you drew. Similar drawings land at the
same place, so work is found by gesture, not by a name in a
directory.
icon: lucide:pen-tool
- name: A place holds voices, and answers
description: >
Leave a short recording at a shape; anyone who arrives hears
it, and can answer — not only with their own voice, but with
a drawn gesture that points somewhere, a reply in the same
wordless language.
icon: lucide:radio
- name: What's left is kept
description: >
A voice left at a place isn't retracted out from under the
people who heard it. The record is forward-only — you build
on it, you don't erase it.
icon: lucide:history
- name: Anyone tired of accounts and platforms
description: >
A network you carry in your hand, that asks nothing of you before
you use it.
features:
- name: Nothing to sign up for
description: >
No account, no profile, no directory of you. You draw, you
arrive, you're part of it — the gesture is the only
credential, and it's yours the moment your hand lifts.
icon: lucide:user-x
- name: Sovereign by construction
description: >
The parts that keep it running are ones you can run yourself —
no dependence on a big platform's servers to find each other
or move a recording. The whole design leans toward fewer
rented middlemen, not more.
icon: lucide:shield-check
- name: Leaving costs nothing
description: >
Your phone reclaims space on its own, and letting go of a
recording never deletes it from the world — the network
fetches it back the next time someone arrives wanting it. You
can travel light and still be a full member.
icon: lucide:feather
- name: Go deeper on how it remembers
description: >
The preservation model has a twist worth seeing on its own: your
phone protects what's *rare*.
action: /advantages/memory
consequence: [Show me how the memory works]
features:
- name: Memory that protects what's rare
description: >
Your phone can't hold everything, so it keeps the voices few
others do — releasing the ones already safe on many devices,
holding the ones in danger of vanishing. The network
preserves itself without anyone deciding what survives.
icon: lucide:gem
+46
View File
@@ -0,0 +1,46 @@
id: /advantages/memory
name: How redoal remembers
description: >
A place's voices should stay reachable as long as people care about
them, and no longer — and no phone should fill up preserving voices
nobody returns to. redoal gets there with three forces that need no
coordinator: attention spreads a voice, scarcity keeps it, and the
person who spoke it is the anchor of last resort.
alternatives:
- name: The three forces
description: >
No server decides what survives. The incentives do — and they
pull in exactly the right directions.
features:
- name: Attention replicates
description: >
Every time someone listens to a recording, their phone keeps
a copy and quietly announces itself as another place you can
get it from. A voice heard by a hundred people is, by that
fact alone, held by a hundred phones. Listening is hosting.
icon: lucide:ear
- name: Scarcity is kept
description: >
When a phone runs low on room, it doesn't drop the oldest
voice — it drops the safest one. The network already knows
how many phones hold each recording, so each device keeps the
ones held by almost no one and lets go of the ones held by
many. Everyone reaching for the rare voice is exactly what
protects it.
icon: lucide:gem
- name: The speaker anchors
description: >
Whoever left a recording never forgets their own — a place's
origin is always reachable through the person who made it.
Below everything else, the author is the backstop, so no
voice falls all the way out of the world while its speaker
still carries a phone.
icon: lucide:anchor
- name: Letting go is safe
description: >
A phone releasing a voice isn't deleting it — the drawing
still leads there, and the network fetches it back on demand
the next time someone arrives wanting it. Reclaiming space
and preserving memory are separate, which is what lets a
small phone be a full member without fear.
icon: lucide:recycle
+21 -13
View File
@@ -1,16 +1,17 @@
# The group exhibition at Podium, connected to the conference: opens
# 21 October 2026 and runs for a month. Announced in every header
# while it runs (portal's event: window); afterwards a followup, and
# a "post what happened" task lands on /review.
# The group exhibition at Podium, part of Attac's «Big Tech må vekk»
# 2026: opens 23 October 2026 at 19:00 and runs for a month. Announced
# in every header while it runs (portal's event: window); afterwards a
# followup, and a "post what happened" task lands on /review.
name: Where can you see it in person?
description: >
redoal is part of the group exhibition at Podium, opening 21 October
and running for a month alongside the conference. Draw on the
screens, leave a voice at a shape, hear who came before you.
redoal is part of the group exhibition at Podium, opening 23 October
and running for a month — the art strand of the conference
«Big Tech må vekk». Draw on the screens, leave a voice at a shape,
hear who came before you.
event:
starts: 2026-10-21T18:00:00+02:00
starts: 2026-10-23T19:00:00+02:00
duration: 31d
place: Podium, Oslo
place: Podium, Hausmanns gate 34, Oslo
alternatives:
- name: Come draw on the wall
description: >
@@ -18,12 +19,19 @@ alternatives:
you can stand in front of together — the network at the scale
of a room.
features:
- name: Opening 21 October
- name: Opening 23 October, 19:00
description: >
The exhibition opens on the 21st and stays up for a month,
within the conference programme. Come to the opening, or
any day after.
At [Podium](https://podium.enterprises/), Hausmanns gate 34,
and up for a month. Come to the opening, or any Saturday
or Sunday after.
icon: lucide:calendar-days
- name: Part of «Big Tech må vekk»
description: >
Attac's conference on digital counterculture returns to
Hausmania — the same building — on 31 October; the
exhibition is its art strand. Programme and details on
[attac.no](https://attac.no/arrangement/big-tech-ma-vekk-2026/).
icon: lucide:megaphone
- name: Draw, then listen
description: >
Draw a shape on the touch screen and arrive at a place.
+53 -17
View File
@@ -13,12 +13,10 @@ alternatives:
description: >
By associating similar movements while facilitating discourse we
discover signal within chaos. Draw a path — the network answers
with the shapes it heard nearby.
action: /shape
# Announced, not yet open: the network answers with echoes today,
# what follows a shape is still being built.
disabled: true
consequence: [Find what follows]
with the shape it heard, and with the places kept nearby. Pick
one of those and it becomes your address.
action: /shape/{curve.key}
consequence: [Go to the place]
record_as: redoal_gestures
encouragements:
- What you don't know — your collaborators will.
@@ -36,16 +34,29 @@ alternatives:
type: gesture
relay: wss://relay.redoal.com
optional: true
- name: email
label: Email, if the echoes should reach you later
type: email
optional: true
- name: Meet a network you carry in your hand
description: >
The one trick, and what it enables — the parts that run today,
said plainly.
features:
- name: The count so far
description: >
Live from the front-door relay — the running tally of what's
been left at places.
icon: lucide:activity
resource:
source:
kind: url
url: https://relay.redoal.com/pulse
public: true
# /pulse (redoal ADR-0023) returns { voices_echoed: N }; shape
# it into one card — the number as the heading, the phrase
# beneath. The card renders unlinked when the relay is quiet.
jq: >
[{ "name": (.voices_echoed | tostring),
"description": "voices echoed so far" }]
empty: The first voice hasn't echoed yet.
- name: A drawing is an address
description: >
The computer measures how your line curves, turns, and keeps
@@ -83,15 +94,25 @@ alternatives:
script arrives on the same terms as everyone else — that is
the whole entry requirement.
icon: lucide:hand
- name: Young, and honest about it
- name: Carried by iroh, through varde
description: >
A prototype and an artwork before it is a product. The
gesture math, the fingerprints, the voice recordings, and the
machine-to-machine fetching are real and running; the
What is left at a place is kept and mirrored by
[varde](https://project.uhhm.no/uhhm/varde), a small
daemon that moves bytes between consenting machines over
[iroh](https://iroh.computer) — verified, rate-limited, and
legible to the network it runs on. Recordings travel that way,
with no company carrying them.
icon: lucide:waypoints
- name: Built in the open at UHHM
description: >
[UHHM](https://uhhm.no) builds and carries the gesture math,
the relay, and the portal this page runs on — and hosts the
network's first node. It is a prototype and an artwork before
it is a product: what you can touch is real and running, the
transport that reaches across the internet is being built
now. The edges are rough, and the edges are where the
interesting questions live.
icon: lucide:sprout
now, and the rough edges are where the interesting questions
live.
icon: lucide:anvil
- name: Follow the build as it lands
description: >
@@ -122,6 +143,21 @@ alternatives:
.[] | {name: .name, description: .body, tag: .tag_name,
published: .published_at, url: null}
- name: See what it's good for
description: >
The same one trick answers different needs — a community keeping
its own memory, an artist placing work where it's found, anyone
done with accounts and platforms.
action: /advantages
consequence: [Show me the advantages]
features:
- name: Grouped by what you're after
description: >
Not a feature list — the advantages sorted by the thing
you're trying to do, including the one worth seeing on its
own: how your phone protects what's rare.
icon: lucide:sparkles
- name: Hear from us when it matters
description: >
Notes from the build — sent only when there is something worth
+47
View File
@@ -0,0 +1,47 @@
# One recording, held up for human review: /report/<digest>. Reached
# from the place page's per-recording link. Filing creates an open
# record in redoal_reports; the desk decides, and a removal decision
# deletes the recording from the relay, varde, and discovery.
name: Should this stay?
description: >
Every voice here was left by a person, and a person looks at every
report. Tell us what you heard and why it needs eyes on it — the
recording stays reachable until someone has listened and decided.
alternatives:
- name: Ask for a review
description: >
Goes straight to the review desk. If the recording breaks
something — a person's privacy, the law, basic decency — it is
removed everywhere this network keeps it.
action: /reported
consequence: [Send it to review]
record_as: redoal_reports
encouragements:
- A person will listen.
features:
- name: What you heard
description: >
A sentence or two is plenty. Leave an email if you want to
hear what was decided.
icon: lucide:flag
requirements:
- name: digest
label: Recording
type: hidden
value: "{digest}"
- name: reason
label: Why
type: textarea
placeholder: What is wrong with this recording?
- name: email
label: Email
type: email
optional: true
- name: Go back to listening
description: >
The place you came from holds the rest of its voices.
features:
- name: Nothing sent
description: >
Leaving this page files nothing — only the button does.
icon: lucide:undo-2
+11
View File
@@ -0,0 +1,11 @@
# Landing after filing a report.
followup: true
name: What happens now?
description: >
Your report is on the review desk. A person listens, decides, and
the decision acts everywhere this network keeps the recording.
alternatives:
- name: Draw another
description: >
The paper keeps listening.
action: /
+64
View File
@@ -38,6 +38,70 @@ alternatives:
- to: unsubscribed
label: Unsubscribe
- name: Voices
description: >
Recordings left through the web, one answer per upload: the
address, the digest, the length. The audio itself lives in the
relay's node and in varde.
features:
- name: ""
description: ""
resource:
source:
kind: kv
bucket: redoal_voices
requires_group: owners
- name: Reports
description: >
Recordings a visitor asked a person to listen to. "Remove it"
acts for real: the relay watches this bucket and deletes the
recording from its store, the varde pin, and discovery. "Keep
it" closes the report with the voice in place.
action: /review
consequence: [Decide]
features:
- name: ""
description: ""
resource:
source:
kind: kv
bucket: redoal_reports
requires_group: owners
transitions:
- from: open
to: removed
label: Remove it
- from: open
to: kept
label: Keep it
- name: Watchers
description: >
Who asked to hear from one exact address. Unsubscribing is
theirs (the link in their receipt); the desk can retire an
address that bounces.
action: /review
consequence: [Confirm]
features:
- name: ""
description: ""
resource:
source:
kind: kv
bucket: redoal_watchers
requires_group: owners
transitions:
- from: pending
to: open
label: Confirm by hand
- from: pending
to: unsubscribed
label: Drop
- from: open
to: unsubscribed
label: Unsubscribe
- name: Announced pages
description: >
Pages with an `event:` window, kept here by portal itself. When a
-32
View File
@@ -1,32 +0,0 @@
id: /shape
route: ^/shape
followup: true
name: Where does the path lead?
description: >
Your shape is in the room now. Echoes of it reach whoever draws
nearby — and theirs reach you, whenever you come back to draw again.
alternatives:
- name: What just happened
description: ""
features:
- name: An address, not an upload
description: >
The stroke became a 20-byte gesture key — a compressed
encoding of its shape. Similar shapes land on nearby keys;
that proximity is the whole network.
- name: Nothing to undo
description: >
A drawn path is a fact, not an account. There is no profile
behind it unless you left an email.
- name: What arrives here next
description: >
In the full network a drawing is a place that holds voices —
recordings left by whoever came before, and live talk with
whoever is standing here now. On this site it holds echoes
today; the voices follow.
- name: Draw another
description: >
The network gets more interesting with every shape it hears.
action: /
consequence: [Back to the canvas]
+101
View File
@@ -0,0 +1,101 @@
# The place a drawn (or picked) path leads to: /shape/<gesture key>.
# Reached through the landing alternative's templated action
# (/shape/{curve.key}); the key is the URL. What is kept here comes
# from the relay - the first redoal node - over its /place endpoint,
# and a voice left here goes back the same way (ADR-0015 in redoal).
name: Where does the path lead?
description: >
This is a place: the 20-byte address your path became — or the one
you picked from what the network keeps nearby. Voices left here play
here, for whoever draws their way to this shape. What you see on
this site is a preview of the app: the same network, reached
through a relay instead of your own machine.
alternatives:
- name: Listen to what was left here
description: ""
features:
- name: ""
description: ""
icon: lucide:ear
resource:
source:
kind: url
url: "https://relay.redoal.com/place/{key}"
public: true
empty: Nothing has been left at this address yet — yours could be the first voice here.
jq: >
.recordings[] | {name: ((.duration_ms / 1000 | round | tostring) + " seconds of voice"),
description: ("sealed by " + .author[0:8] + "… · [have it reviewed](/report/" + .digest + ")"),
audio: ("https://relay.redoal.com" + .audio)}
- name: Leave your voice here
description: >
A preview of what the app will give you in full. Record in your
browser, listen back, and press *Keep it here* — nothing leaves
your phone before that. The relay, the network's first node,
keeps it at exactly this address and mirrors it on, sealed with
its own key on your behalf; a key of your own comes with the app.
action: /shape/{voice.key}
consequence: [Keep it here]
record_as: redoal_voices
encouragements:
- It stays where you left it.
features:
- name: ""
description: >
Up to a minute. Record, listen back, record again if you like
— it is sealed as it is once you keep it.
icon: lucide:mic
requirements:
- name: voice
label: Voice
type: voice
relay: wss://relay.redoal.com
value: "{key}"
optional: true
- name: Hear from this address
description: >
The fallback for a phone without the app: one note when
something is left at exactly this shape — and nothing about
anywhere else.
action: /subscribed
consequence: [Watch this address]
record_as: redoal_watchers
encouragements:
- Your shape now has a listener.
features:
- name: Where the note goes
description: >
The note is about one exact address, so it needs one exact
place to land. One mail comes first, asking you to confirm —
nothing is sent before you do, and at most one note a day
after.
icon: lucide:mail
requirements:
- name: email
label: Email
type: email
- name: key
label: Address
type: hidden
value: "{key}"
- name: What just happened
description: ""
features:
- name: An address, not an upload
description: >
The stroke became a 20-byte gesture key — an ordered chain of
headings, drawn back for you under the stroke. Similar shapes
land on nearby keys; picking a kept place makes its key yours.
- name: Nothing to undo
description: >
A drawn path is a fact, not an account. There is no profile
behind it unless you asked to hear from an address.
- name: Draw another
description: >
The network gets more interesting with every shape it hears.
action: /
consequence: [Back to the canvas]
+9
View File
@@ -21,3 +21,12 @@ alternatives:
bucket: redoal_subscribers
to: unsubscribed
label: Unsubscribe me
- name: Stop watching an address
description: >
Using the link from a note about a shape? Confirm below and that
address goes quiet for you.
self_transition:
bucket: redoal_watchers
to: unsubscribed
label: Stop watching
+27
View File
@@ -0,0 +1,27 @@
# Landing page of the confirmation mail: /watching?chain=<record>&email=<address>.
# A followup - never in the nav; the record id in the link is the only
# way here, and it plus the matching email is what authorizes the
# transition (portal's self_transition).
followup: true
name: Are you watching this address?
description: >
Someone asked to hear from a shape on redoal with your address. Say
yes and you get one note when something is left there — nothing
else, ever. Say it wasn't you and the request is dropped.
alternatives:
- name: Yes, watch it
description: >
One note per day at most, only when a recording or a program
lands at exactly this shape.
self_transition:
bucket: redoal_watchers
to: open
label: Yes, watch it
- name: That wasn't me
description: >
The request is dropped and the address stays unused.
self_transition:
bucket: redoal_watchers
to: unsubscribed
label: Drop it
+1
View File
@@ -4,3 +4,4 @@ wordmark: https://project.uhhm.no/redoal/questions/raw/branch/main/wordmark.svg
hero:
kind: module
module: hero.js # this repo's sine-swings piece, served at /site/hero.js
wordmark_invert: true