Skip to the page

Invented app · built on Kindling · Why Kindling · The apps · The library · The spec

face up

Under the hood

How Face Up is built on Kindling

An app that plays its cards face up, and opens any Pool it may read. Here are the three layers for one Pool, the decks and what each gathers, how any other Pool opens under its own name, our two rules and the spec behind the rest, our settings mapped to the spec, the one Pool we host, the block lists we honor, and where v0.1 can’t yet say what we mean.

Three layers, one Pool

Belay Partners, three ways

The same Pool is a page on its host’s own site, a JSON file anyone can read, and a card in any app that reads it. Every Face Up card links back to the other two, and any Pool opens here: this one in the Climbing deck, a seed swap under its own name.

1. The site

Belay Partners is a page on Drip Line’s own site, in its own design, run by its own staff.

Climbers who passed a staff belay check at Drip Line and would like to be asked to climb, most often on Saturday mornings.

Belay Partners on Drip Line

2. The data

The manifest is a file at the Pool’s own address §3.1. Any app may read it, and every entry carries the person’s yes.

drip-line-belay.json

An excerpt, as the file says it
{
  "schema_version": "0.1",
  "id": "drip-line-belay",
  "name": "Belay Partners",
  "intent_tags": [
    "climbing",
    "belay",
    "partners"
  ],
  "visibility": "public",
  "consent_model": "vouching-required",
  "charter": "Climbers who passed a staff belay check at Drip Line and would like to be asked to climb, most often on Saturday mornings. …",
  "curator": [
    {
      "display_name": "Pilar Echeverría",
      "verification_level": "oauth"
    },
    {
      "display_name": "Emil Kowalczyk",
      "verification_level": "oauth"
    }
  ],
  "entries": "6 entries; one of them:"
}
{
  "profile_url": "https://beto-aguilar.carrd.example",
  "verification_level": "curator-vouched",
  "parsed_profile": {
    "display_name": "Roberto “Beto” Aguilar",
    "pronouns": "he/him",
    "location": {
      "city": "Seattle",
      "region": "Washington",
      "country": "United States"
    },
    "intent_tags": [
      "bouldering",
      "climbing",
      "belay",
      "friendship"
    ],
    "about": "Electrician. At the bouldering wall most Tuesday nights, and glad to catch anyone on a rope on Saturdays. Leads 5.10 and falls off 5.11 cheerfully.",
    "messaging_preferences": {
      "accept_from": "shared-pool",
      "no_cold_messages": false,
      "minimum_curator_verification": "email"
    }
  },
  "consent_proof": {
    "handshake_id": "hs-drip-line-drip-line-belay-beto",
    "accepted_at": "2025-10-15T02:10:00Z",
    "method": "curator-vouching"
  }
}

3. The app

The card Face Up deals from it, in the Climbing deck, as Fatima sees it.

Illustration: Beto laughing, with a mustache, in a navy flannel shirt

Beto

he/him · Seattle · your city

Vouched for by the curator

from Belay Partners, kept by Pilar Echeverría

Climbers who passed a staff belay check at Drip Line and would like to be asked to climb, most often on Saturday mornings.

public · climbing, belay, partners · Drip Line · JSON · also in Tuesday Regulars

Decks

Shortcuts, and what each gathers

DeckIts yesPools it gathersTags it gathersOrders
DatingYes, a dateFace Up: Cascadia
Heartwood: Nearby
Sundial: Cascadia
Card Catalog: Cascadia
Many Moons: Harbor Counties
Date-Me Docs: Cascadia
The Singles Shelf
With the address: Queer Harbor: Dating, The Tuesday Table, Second Chapters
datingNewest here, Nearest, Most in common, Shuffle
Climbing partnersYes, climb togetherBelay Partners
Tuesday Regulars
New to Climbing
With the address: Thursday Night: Women and Nonbinary Climbers
climbing, belay, boulderingChecked first, Newest here, Shuffle
The Saturday RunYes, run togetherThe Saturday RunrunningNewest here, Longest running, Shuffle
Bandmates and playersYes, play togetherStart a Band: Port Ellery
Friday Subs
Session Players
Horns and Strings for Records
band, sub, sessionNewest here, Friday subs first, Shuffle
Game nightYes, share a tablePort Ellery Thursdays
Olympia Thursdays
Tacoma Thursdays
Portland Thursdays
Rain Check: Everyone
game-nightNearest table, Newest here, Shuffle
Walking partnersYes, walk togetherTuesday Morning WalkerswalkingNewest here, Longest walking, Shuffle
First-generation mentorsYes, ask to meetMidspan Mentors (through its curator)
Cape Tarrow First-Gen Alumni
mentorshipNewest here, Nearest, Shuffle
Under its own nameThe Pool’s own verb, or “Yes, say hello”; “Write a letter” in Correo Lento; none where a Pool is listed for context onlyAny Pool no deck gathers: 40 today, listed on the About page. Also the people a deck can’t deal from a Pool it gathers: Many Moons: Harbor Counties, for its members whose own tags don’t say dating.None neededNewest here, Longest here, Shuffle

Every Pool in the library, and where it opens in Face Up, is in the table on our About page.

How a Pool opens under its own name

  1. Open a Pool from “Open a Pool”, beside the decks, or load a product, or paste an unlisted Pool’s address. The address bar says what is open: #pool-seed-swap, or #load-board.
  2. Face Up puts each of its Pools in the deck that gathers it. The rest go together into one deck named for what you opened: the Pool, or the product.
  3. Each card still names its own Pool, a line of its charter and its tags. The yes names the Pool, in its own verb where its charter gives one, and never in a dating word unless the Pool is tagged dating.
  4. A resting Pool opens and says it is resting. Nobody in it is hidden for it.

Rules

Two rules

These are the only rules Face Up claims. What else a reader owes a Pool is in the spec, cited below, and in each Pool’s own words.

  1. Every card shows the Pool’s name, charter and tags. Every card, in every deck and under every own name, carries the Pool it came from: its name, one line of its charter and its tags, with its visibility, its curator and links to the Pool on its own site and to its JSON. So does every card on “Yes to you”, and the two cards that turn when you both say yes.
  2. No one is shown as open to dating unless their own tags say so. The Dating deck deals only people whose own intent_tags include dating: the tag itself, not a Pool they are in. So Tamsin and Anouk in Harbor Counties, who are friends first, and Nadia, a matchmaker, are never in it. It holds for you too: if your own tags don’t say dating, the Dating deck deals you nobody and deals you to nobody. The build checks this against the deck the app actually deals, and stops if it fails.

What the spec asks of every reader

  • Visibility. An invite-only Pool is never read. An unlisted Pool is read for someone who is in it, or who pastes its address; Drip Line’s Thursday Pool asks members to add it themselves, so we wait for the paste. §3.2
  • Messaging and introductions. KindlingDemo.canMessage runs Pool by Pool, with each Pool’s address, its members and its own sender floor, against each person’s own rules, and the card shows every answer in words. consent_model says how people join; where a Pool’s charter or governance says introductions go through a curator or steward (Midspan Mentors, Late Supper’s tables, Hearthhold’s stewards, Seen Work’s Harbor Trades, Meals When It’s Hard), a yes is a request to them. §7
  • A Pool’s own words. Correo Lento’s Pools are slow letters, by email, one a week at most, and the co-op holds every first letter until both people say they would like to write: there a yes is “Write a letter”. The Orchard Street Household is listed “so the people we date can see how we are connected”, so Face Up shows it for context only, with no yes. Foul Weather Friends asks apps not to read the Check-In Circle, so we don’t. §3.2
  • Pictures. Drawn from each person’s own page by the shared portrait renderer, seeded by their id, and never copied. A page with no picture is dealt as a letter, the way its Pool’s own site shows it. §2.5

Settings

What we chose, and why

SettingValueSpecWhy Face Up chose it
Decks7 shortcuts: Dating, Climbing partners, The Saturday Run, Bandmates and players, Game night, Walking partners, First-generation mentors; any other Pool under its own name§1.2UIs are ours to design. A deck is a ready-made shortcut, and never a wall: any Pool we may read opens.
Pools read60 public today, and 7 unlisted ones only with the address; 3 never§8.3Well-known files are readable without asking. Unlisted Pools we never guess; invite-only Pools we never read; a site that asks us not to read a Pool is left alone.
The Dating deckOnly people whose own intent_tags include dating§2.4Rule 2 of the draft proposal: “No one is shown as open to dating unless their own tags say so.”
Pool hostedFace Up: Cascadia, public, tagged dating§3.2One Pool of our own, readable by any app, so the face check has a home.
Consent modelvouching-required: the face check, then the handshake§5.4A stricter model may add a step before the handshake and never remove the owner’s no or their leaving.
The face checkA curator’s vouch, local to our Pool§4.4It means this face is the person who said yes, in this Pool only. We say so wherever it shows.
Handshake window14 days, carried in each request’s expires_at§5.2The manifest has no field for it; our governance rules say so too.
VerificationOn every card, in words and with an icon, as the level in the Pool the card came through§4.5A conforming UI must show it. We add the Pool and its curator.
The orderChosen per deck, each with one honest line§1.2Nobody pays to be higher, and every order is written on the screen.
YesesApp-local; each names its purpose and its Pool; free to see; no limit§6.3v0.1 has no message for a yes, so a yes can’t travel between apps. We say so on the “Yes to you” tab.
Two yesesBoth said yes in one deck; counts as mutual interest§7.2For people who take no cold messages, two yeses are the confirmed mutual interest their rule asks for. In Correo Lento they let the first letter go.
A request to a curatorAn intro message to the curator, through that Pool§6.3Where a Pool’s curator introduces people, the yes goes to them. Nothing goes to the person.
Messaging rulesEach person’s accept_from and no_cold_messages; each Pool’s own sender floor§7.2Checked with the shared kit, Pool by Pool, before anything is sent, and the reason shown in words.
Identity gatingUnverified senders are held back§7.1Our Pool’s own floor is email. Friday Subs sets its own floor at OAuth, and we honor it.
Block listsKindling’s public list and The Circular’s§7.3The same two our Pool subscribes to. A personal block is kept on the other person’s identity, in every deck.
Leaving a PoolOne tap; a withdrawal message to the curator§5.3The Pool must act within 60 seconds. Ours acts at once.
PicturesShown from each person’s page, never stored§2.5Portraits here are illustrations of invented people.
NoindexRespected§2.7A page that says kindling-noindex is in no Pool, so it is never in a deck.
MessagesEmail underneath, a thread in the app§6.1Nobody needs Face Up to answer.
ContinuityTwo curators; Brody Kaleikini first in line§9.3If the Pool goes quiet for 90 days, members can keep it going.
MoneyNothing charged at the connection layer§1.3Face Up nights and an optional page-hosting membership pay for it.

Our Pool

Face Up: Cascadia

Face Up is for people dating in Cascadia, from Eugene to Vancouver, who like to see a face first. Right if you would like to hear from someone, left if you would not, and when you both go right, you can write. Every face here has been checked by our trust desk against a live selfie, so the person in the photos is the person who said yes. Photos stay on your own page and we show them from there. Nobody pays to be seen, and nobody pays to see who liked them.

The manifest, in plain words

Address
https://faceup.example/pools/face-up-cascadia.json
Visibility
public
Consent model
vouching-required
Intent
dating
Where
Cascadia
Sender minimum
email
Block lists
2, below
Created
6 April 2026
Updated
27 September 2026
Entries
22, each with its consent proof

Curators

  • Adaeze Nwosu Signed in with OAuth adaeze@mail.example · primary
  • Brody Kaleikini Signed in with OAuth brody@mail.example

The manifest as JSON · The request Simone receives

Governance

Vouching-required. Before anyone is listed, a member of Face Up’s trust desk compares a live selfie, taken in the app, with the photos on that person’s own page, and vouches for them only if they are the same face. The vouch means that and nothing more: this face belongs to the person who said yes. It says nothing about age, character or intentions, and it is local to this Pool; it carries into no other Pool and no other app. The selfie is deleted as soon as the check is done; we keep only the date and who checked. If the photos on your page change, the desk asks for a new selfie before the new ones show. Anyone may ask the desk to look again, or report a card, at trust@faceup.example. Leaving is one tap, and your card is gone within a minute.

Our discovery file

.well-known/kindling-pool §10.1 §10.2

{
  "schema_version": "0.1",
  "pools": [
    {
      "manifest_url": "https://faceup.example/pools/face-up-cascadia.json",
      "name": "Face Up: Cascadia",
      "intent_tags": [
        "dating"
      ],
      "visibility": "public",
      "status": "active",
      "geographic_scope": {
        "region": "Cascadia"
      },
      "last_updated": "2026-09-27T21:40:00Z"
    }
  ],
  "operator": {
    "name": "Face Up, an app that plays its cards face up",
    "contact": "hello@faceup.example",
    "url": "https://faceup.example"
  }
}
Everyone listed, and who checked them
NameCityIn this PoolListedFace checked by
Keisha HollowayTacomaVouched for by the curator13 April 2026Adaeze Nwosu
Kwame AsanteSeattleVouched for by the curator19 April 2026Brody Kaleikini
Olena KravetsPortlandVouched for by the curator28 April 2026Adaeze Nwosu
Fergal ByrneVancouverVouched for by the curator3 May 2026Brody Kaleikini
Thuy NguyenSeattleVouched for by the curator10 May 2026Adaeze Nwosu
Maya LindgrenSeattleVouched for by the curator20 May 2026Brody Kaleikini
Tomás HerreraPortlandVouched for by the curator29 May 2026Brody Kaleikini
Kalani AkanaTacomaVouched for by the curator4 June 2026Adaeze Nwosu
Hamid KarimiVancouverVouched for by the curator12 June 2026Brody Kaleikini
Sione TaufaTacomaVouched for by the curator19 June 2026Adaeze Nwosu
Paloma QuinteroEugeneVouched for by the curator27 June 2026Brody Kaleikini
Gabe MorrowPort ElleryVouched for by the curator4 July 2026Brody Kaleikini
Rodrigo SalinasSalemVouched for by the curator16 July 2026Adaeze Nwosu
Jasleen GillVancouverVouched for by the curator22 July 2026Brody Kaleikini
Luis ArriagaOlympiaVouched for by the curator31 July 2026Adaeze Nwosu
Amara TesfayeSeattleVouched for by the curator8 August 2026Brody Kaleikini
Liam O’ConnellPort ElleryVouched for by the curator15 August 2026Adaeze Nwosu
Itzel CárdenasSalemVouched for by the curator21 August 2026Brody Kaleikini
Owen TremblayVancouverVouched for by the curator1 September 2026Adaeze Nwosu
Astrid NilsenBellinghamVouched for by the curator8 September 2026Brody Kaleikini
Julian MercerPort ElleryVouched for by the curator17 September 2026Adaeze Nwosu
Sasha PetrovOlympiaVouched for by the curator22 September 2026Brody Kaleikini

Discovery

How a deck is dealt

  1. Read every .well-known/kindling-pool file we know of §8.3, and keep every public Pool, resting ones too. Add an unlisted Pool only for someone who is in it or pastes its address §3.2. Never an invite-only one, and never one its site asks apps not to read.
  2. Fetch each manifest, check it against the schema, and check its major version §12.2.
  3. Drop anyone whose page says noindex §2.7, anyone on a block list we honor §7.3, and anyone you blocked.
  4. Put each Pool in the deck that gathers it by its tags, and the rest under their own names. For the Dating deck, keep only people whose own tags say dating, and read each one’s own page for age, gender, pictures, prompts and answers. Everywhere else, use the parsed profile in the Pool file, and a page’s job, languages and interests only where the Pool lists that page. Keep none of it.
  5. For dating, filter by who you’re looking for (and who’s looking for you), age and distance between rough city centers, and never on a field a page leaves blank. Elsewhere, choose which of the deck’s Pools to read. Every filter is free.
  6. Put them in the order you chose for that deck, with the count of cards left on the screen.

Safety that travels

The block lists we honor

Kindling public block list

Version 3, published 20 September 2026. The list as JSON.

  • scrapekit/0.3 · implementation · scraping
  • promo-blast@mail.example · identity · spam

The Circular consortium block list

Version 8, published 27 September 2026. The list as JSON.

  • listed-them-anyway@mail.example · curator_identity · consent_violation
  • https://free-friends-now.example/pools/everyone.json · pool_url · consent_violation
  • bulk-intros@relay.example · identity · spam
  • scrapekit/0.3 · implementation · scraping

Sample messages this app sends, validated against the schema: hello-simone-to-tomas.json · withdrawal-keisha.json · hello-fatima-to-beto.json · request-ruben-to-fina.json.

Conformance

A Pool host, a Pool UI and a messaging client

  • Compliant Pool host §11.1.A manifest, the handshake, continuity with a co-curator, and a discovery file.
  • Compliant Pool UI §11.2.Verification beside every person, the Pool on every card, the §7 layers, withdrawal in one tap, and no silent inclusion.
  • Compliant messaging client §11.4.Envelopes that validate, the sender’s level shown, §7.1 gating, and each Pool’s own floor.

Honest limits

What the v0.1 schema can’t say yet

Where the spec text and a schema disagree, our JSON follows the schema.

  1. A yes has no message (§6.3, §7.2). The spec’s message types are handshake-request, handshake-response, intro and reply; the schema adds withdrawal and system. None says “yes, let’s climb” or “I like you”. So a Face Up yes lives only in Face Up, in one deck: other apps can’t see it, and we can’t see theirs. Two yeses are ours to record, and we treat them as the confirmed mutual interest that no_cold_messages asks for.
  2. A request to a curator has no message of its own (§6.3). Where a Pool’s curator introduces people, Face Up sends the curator an intro message through that Pool, with the person’s name in the words. Nothing in the envelope says “please introduce me to this entry”, so the curator reads it as a person would.
  3. Intent tags are free text (§3.2). Our decks gather Pools by their intent_tags, which have no shared vocabulary. We publish the tags each deck gathers, above. A Pool none of them names still opens, under its own name, so a free-text tag never keeps a Pool out of Face Up.
  4. A site’s word about its own Pool has no field (§3.2, §10). Foul Weather Friends asks apps not to read the Check-In Circle. A manifest can say unlisted, not “please don’t read this”; the request lives in its governance rules, and we honor it the way a browser leaves a site alone that asks not to be read.
  5. “For context only” has no field (§3.2). The Orchard Street Household is listed “so the people we date can see how we are connected”. Nothing in the manifest says a Pool takes no introductions; its charter says it, and we read the charter.
  6. “Members add it themselves” has no field (§3.2). Drip Line’s Thursday Pool is unlisted and asks members to add its address to an app themselves. The manifest can say unlisted, not that; it lives in the governance rules, and we read them.
  7. A curator route has no field (§5.4). Whether a yes should go to the curator is in each Pool’s charter and governance rules, in words. vouching-required sometimes means a check at the door and sometimes an introducer for every meeting. We read the words, Pool by Pool, and say what we decided in the About page’s table.
  8. A personal block can’t travel yet (§7.3). Block lists are for known abuse, published by the project or a third party, and every client subscribes. A person’s own block has no message and no list of its own. We keep yours on the other person’s Kindling identity, and point out that your email can hold it too.
  9. Pages say more than the parsed profile (§2.4). Age, gender, pictures, prompts and answers aren’t fields in parsed_profile.schema.json. We read them from each person’s own page at display time and never copy them, which is also what §2.5 asks for pictures. Outside dating we show only a page’s job, languages and interests, and only when the Pool lists that very page.
  10. Verification level names (§4.5). The spec text says email-verified, oauth-verified, curator-vouched and unverified. The schemas use email, oauth, curator-vouched, unverified and cryptographic. Our JSON follows the schema; the screen shows words.
  11. A vouch is per Pool, and the entry says so (§4.4). Entries carry curator-vouched for our face check and for Drip Line’s belay check, but a parsed profile’s own verification repeats it without naming the Pool. An app that copied that field into another deck would overstate it. We show the level only beside the Pool it belongs to.
  12. The handshake window (§5.2). The spec says 14 days, “configurable per Pool”. The manifest has no field for it, so our requests carry it in expires_at and our governance rules say so.
  13. Where a field came from (§2.3). The spec asks parsers to record h-card versus inferred fields in extraction_source. The parsed-profile schema has no such field and forbids extra ones.
  14. The Pool reference and the version field (§6.2, §12.1). The spec says pool_ref and kindling_version; the schemas say via_pool and schema_version. We use the schema’s names.
  15. Messaging rule names (§7.2). The spec names open-to-all, pool-mates-only, vouched-only, no-cold-messages and minimum-sender-verification. The profile schema has accept_from and a no_cold_messages flag, and only a Pool can set a sender minimum.