Docs

The deck format

A deck is one JSON file plus its media. If your tool can write JSON, it can publish decks — humans use the submit page, agents and scripts write the format directly.

Quick start (solo mode)

Need Node? Install the LTS release from nodejs.org first. In the folder where your project lives (Node 20+):

TERMINAL
npx riah-swipe
npx riah-swipe add my-batch.swipe.json   # validates + registers it
npx riah-swipe validate                  # checks everything in decks/

Windows: the first run may show a firewall prompt. Allow it or the phone URL will not work.

First run creates decks/ (batches in), swipe-results/ (verdicts out), a config file, and a Welcome deck that teaches the swipe in six cards — no account needed for that one. Open the printed URL on desktop, or the wifi URL on your phone. When you subscribe, your dashboard gives you a license key; the app asks for it once.

A minimal deck

Schema riah-swipe.deck/1. A deck is one homogeneous batch — one project, one kind of decision, reviewed in one sitting. A batch file holds decks and cards. Card kinds: image, video, audio, script, chapter, line, logline, text — unknown kinds degrade to text, so a deck never fails to load.

BATCH.SWIPE.JSON
{
  "schema": "riah-swipe.deck/1",
  "decks": [{
    "id": "poster-round-2",
    "name": "Poster — round 2 (6 variants)",
    "source": "my-poster-pipeline",
    "kind": "image",
    "note": "Round 1 notes applied: warmer palette, bigger title.",
    "selectingFor": "the one-sheet we print",
    "returnTo": "poster-pipeline",
    "rev": 0
  }],
  "cards": [{
    "id": "poster-r2-a",
    "deckId": "poster-round-2",
    "title": "Variant A — dawn palette",
    "kind": "image",
    "media": "decks/poster-round-2/a.png",
    "caption": "Warmer, per your round-1 note",
    "preview": "Longer context if the reviewer needs it.",
    "tag": "round 2",
    "meta": { "outFile": "renders/a.png", "seed": 41 }
  }]
}

What comes back

When the last card is decided, swipe-results/<deckId>.results.json appears — schema riah-swipe.results/2. One entry per card: decision, note, and your meta echoed back for routing.

POSTER-ROUND-2.RESULTS.JSON
{
  "schema": "riah-swipe.results/2",
  "batchId": "poster-round-2",
  "returnTo": "poster-pipeline",
  "decidedCount": 6,
  "cardCount": 6,
  "results": [{
    "cardId": "poster-r2-a",
    "decision": "keep",            // keep | revise | discard
    "approved": true,
    "revised": false,
    "note": "this one — but try the title 10% bigger",
    "meta": { "outFile": "renders/a.png", "seed": 41 },
    "decidedAt": "2026-07-14T09:12:03.000Z"
  }]
}

Your pipeline watches that folder: file the keeps, regenerate the discards, and apply the note on every revise. A deck can never finish with a missing decision — the app re-queues undecided cards instead.

Teaching your agents

A drop-in skill file teaches AI agents to publish valid decks in one shot — Claude, GPT, scripts, cron jobs, anything that writes JSON. It ships with every workspace and with the launcher — docs/skill/SKILL.md in the repo and in your install. It teaches the deck format, the one-kind-per-deck rule, and the publish/validate commands in one page.

The loop it enables: agent generates a batch → publishes a deck → you swipe on the couch → agent reads the results → next round is better. You become the taste, not the bottleneck.

Cloud agents / two computers

Hosted workspaces are the product: teams submit via submit links and review from anywhere at the hosted app. The local launcher remains the offline/solo mode — same deck and results formats either way.

For solo/offline sync across machines, run the launcher from a folder shared by Dropbox, Google Drive, or OneDrive and keep decks/ and swipe-results/ inside it. Data-URI media works without separate media files.

Answers you'll want eventually