Pairing with a Stone: QR Activation and the Self-Pair
Pairing with a Stone: QR Activation and the Self-Pair
Every account in Stone Maps starts with a stone. Not a user profile. Not an onboarding flow. A stone โ or rather, the act of pairing with one.
This is not metaphor. It's schema design.
The Physical Object
Each physical Stone Maps stone has a QR code printed on it. When you scan it, you land on an activation URL โ something like stnmps.com/pair/stone-Silver-Birch-07. The code embedded in that URL is unique to that stone. It has never been paired. It belongs to no one.
Scanning it claims it.
After activation, you complete the genesis questions โ five prompts designed to situate you in place and time. Your answers become genesisTraits on the stone record:
export type GenesisTraits = {
placeLikeHome?: string;
qualityToHold?: string;
deepTime?: string;
wonderPlace?: string;
intention?: string;
};
These aren't profile fields. They're not preferences. They're your first act of journaling: a place that feels like home, a quality you want to carry, something that makes you think about deep time, a place of wonder, and what you're here for.
The Emissary reads them. They inform the texture of every conversation.
Stone vs. Pebble
The schema distinguishes two kinds: stone and pebble.
export const stoneKinds = ['stone', 'pebble'] as const;
A stone is what you get from a physical object โ a real stone with a QR code, shipped or distributed or found. A pebble is its digital counterpart: a virtual stone that can be created without a physical artifact. The word "pebble" is smaller, lighter. It's for people who want to try the experience without waiting for a stone to arrive.
Both work. Both can pair. The Emissary doesn't treat them differently in conversation โ but over time, we expect the physical stone to carry more weight. Something about holding an object while you decide to claim it.
The Self-Pair Relationship
Once you activate a stone, the key database record that gets created is the self_pair:
export const selfPairs = pgTable('self_pairs', {
userId: uuid('user_id').references(() => users.id).notNull(),
stoneId: uuid('stone_id').references(() => stones.id).notNull(),
stoneName: text('stone_name').notNull(),
initialArtifact: text('initial_artifact'),
agentState: jsonb('agent_state').$type<{
lastPromptAt?: string;
conversationCount?: number;
themes?: string[];
}>(),
...
});
This is the core relationship. Not "user has account," not "user has settings." User has self-pair with stone.
Without a self-pair, you can't start a conversation with the Emissary. You can't write journal entries. The app essentially doesn't work. The self-pair is the prerequisite for everything.
stoneName is what you call it. You give your stone a name during activation โ not a username for yourself, but a name for the stone. This inverts the usual registration flow in a small but deliberate way: you're not setting up your account, you're introducing yourself to the stone.
agentState tracks what the Emissary knows about your relationship: when it last prompted you, how many conversations you've had, what themes have emerged. It's a lightweight journal of the journal.
QR Code Format
The QR code value follows a pattern: stone-Word-Word-NN or pebble-Word-Word-NN. Human-readable, two random words, a two-digit number. Long enough to be unique in early access, short enough to be scannable and memorable.
The activationUrl on the stone record is the canonical URL that the QR code resolves to. It's stored separately from the qrCode field so the URL can change (domain migration, path restructuring) without invalidating the physical QR codes already printed and in the world.
Premapped Locations
Some stones ship premapped โ they know where they are before anyone scans them. This is for stones placed at specific landmarks or sites of interest: a museum, a coastal path, a particular street corner. The premappedLocationId links to a locations record with coordinates already attached.
When you scan one of these stones, your journal starts at a place. The Emissary knows it. The map knows it. Your first entry is already situated.
This is the feature we're most curious about. It makes the physical placement of stones meaningful in a way that a purely digital system can't replicate.
What Happens After
Once the self-pair exists, the rest of the app unlocks. The journal is a channel scoped to your self-pair. Conversations draw on your genesis traits and stone traits. The map shows where you and others have been.
The stone doesn't do anything. It just started the relationship.