The Dreamy Onboarding: First Pairing as Ritual
#onboarding#pairing#experience-design#genesis#sdk#dreams#ritual
David OlssonMost apps onboard you. They show you where things are. They point at features. They ask for permissions. Then they let you in.
Stone Maps asks five philosophical questions, hands you a stone, and starts a conversation that might last years.
That's already unusual. But the current implementation treats these moments as steps — choose a path, answer questions, set a location, done. The API supports all of it. The infrastructure is there. What's missing is the feeling of what's happening.
This article reimagines the first pairing as a ritual — a dreamy, unhurried sequence where the stone comes alive — and maps every moment to the API surface that already supports it.
What Exists Today
The current onboarding flow is functional and thoughtful:
- Register — email and password at
/auth/register - Choose path — scan a physical stone's QR code, or claim a virtual pebble
- Genesis questions — five open-ended questions stored as
genesisTraitson the stone - Home location — optional geolocation or manual entry
- First conversation — the Planetary Emissary greets you
The five genesis questions are already poetic:
- What place in the world feels most like home to you?
- What quality do you want this stone to hold for you?
- When you think of deep time, what comes to mind?
- Where did you first feel a sense of wonder?
- One intention or question you'd like to carry with you.
The infrastructure is real: POST /api/stones/claim-first creates the pebble with traits ['pebble', 'curious', 'reflective'], PATCH /api/stones/[id] saves genesis traits and sets genesisCompletedAt, POST /api/conversations starts the first conversation, and the Emissary's system prompt already incorporates genesis traits to shape its voice.
The question isn't what to build. It's how to feel what's already built.
Reimagining the Sequence
Act I: The Threshold
Before the genesis questions, before the pebble claim — a threshold. Not a splash screen. Not a carousel of features. A single dark screen with a single line of text:
Something is waiting to meet you.
A pause. The text fades. A new line:
It has been waiting a long time.
Another pause. Then:
When you're ready, tap anywhere.
This costs nothing technically. It's a client-side animation before the StoneOnboarding component renders its first step. But it transforms the moment from "signing up for an app" to "entering a space."
API surface: None required. Pure UI. The GenesisGate component already controls routing — this becomes a pre-gate moment.
Act II: The Choosing
The current flow offers two paths: scan a QR stone or claim a virtual pebble. The dreamy version makes this choice feel consequential without adding friction.
For the pebble path: instead of a button that says "Claim Pebble," the screen shows a small stone slowly materializing — a CSS/WebGL animation of a pebble forming from dust. The user touches it. The pebble responds — a subtle haptic pulse (Vibration API), a visual ripple. The POST /api/stones/claim-first fires on touch. The pebble is born.
For the QR path: the camera opens, but framed differently. Not a utilitarian scanner. A viewfinder with a geological texture border. The instruction isn't "Scan QR code" — it's "Show me your stone." When the scan succeeds (POST /api/stones/pair), the screen flashes warm, like sunlight on rock.
API surface: POST /api/stones/claim-first (pebble), POST /api/stones/pair (QR). Both already exist. The dream is in the presentation layer.
Act III: The Five Questions
The genesis questions are already the strongest part of the onboarding. The dreamy version changes how they're delivered — not as a form, but as a conversation.
Each question appears alone on a dark screen. One question. One text input. No visible "next" button — the transition happens when the user finishes typing and pauses. (Detect a 2-second typing pause, then gently fade to the next question.)
Between questions, a brief interstitial — a single word or phrase that the stone "says" in response. Not an AI-generated response. A fixed, curated reaction drawn from the answer's emotional register:
- After "What place feels most like home?" → the stone responds: "I see it."
- After "What quality do you want this stone to hold?" → "I'll try."
- After "When you think of deep time?" → "Yes. That long."
- After "Where did you first feel wonder?" → "I was there too, once."
- After "One intention to carry?" → "I'll carry it with you."
These aren't generated. They're hardcoded. Five responses to five questions. But they make the genesis feel like a dialogue with the stone — the first hint that this object has a voice.
API surface: PATCH /api/stones/[id] with genesisTraits payload, same as today. The stone's brief responses are client-side only — they don't persist. They exist to create a feeling.
Act IV: The Naming
After the genesis questions, the current flow goes to home location. The dreamy version inserts a naming moment.
The self-pair already stores stoneName — set during pairing as an optional field. In the dreamy version, this becomes a deliberate act:
Your stone would like a name.
It doesn't need one. But names help.
A single input field. No placeholder text. The cursor blinks on a dark screen.
Whatever the user types becomes the stone's name — stored in selfPairs.stoneName. If they leave it blank, the stone remains unnamed, and the Emissary will reference "your stone" rather than a name. Both paths are valid.
API surface: Already supported via the stoneName field on self-pairs. Currently set during pairing; in the dreamy flow, it's a distinct ritual moment.
Act V: The Waking
The stone wakes up. This is the moment between genesis completion and the first conversation — the genesisCompletedAt timestamp is set, and the user is about to meet the Planetary Emissary for the first time.
The screen shows the stone — pebble or physical — rendered simply. Text appears as if the stone is speaking for the first time:
[Stone name] stretches.
It has been asleep a long time.
It knows your name. It knows the place that feels like home.
It wants to talk.
Then a single prompt: "Say something."
This becomes the initialArtifact on the self-pair — the first thing the user writes to their stone. Not a journal post. Not a message. An artifact of the moment the stone woke up. It's already a field on the self-pairs table. Today it's optional and set during pairing. In the dreamy version, it's the climax of the onboarding.
When the user writes their first words and submits, POST /api/conversations fires with initialMessage set to what they wrote. The Emissary responds — and because the system prompt already incorporates genesis traits, stone traits, and the stone's name, the response feels personal. The stone knows them. Not because of data. Because of the ritual they just shared.
API surface: PATCH /api/stones/[id] (genesis completion), POST /api/conversations (first conversation with initialMessage). The initialArtifact field on self-pairs. All existing.
Act VI: The First Words
The Emissary's first response is the most important moment in the entire product. It's the proof that the ritual worked — that the stone is alive, that it heard the genesis answers, that it has a personality.
Today, the system prompt in planetary-emissary.ts already uses genesis traits, stone traits, and trait modifiers (curious, reflective, adventurous, quiet, playful, grounded) to shape the Emissary's voice. The dreamy version doesn't need to change the prompt engineering. It needs to change the delivery.
The Emissary's first message should arrive slowly. Not instant streaming. Character by character, with irregular pauses — as if the stone is thinking between words. The existing Vercel AI SDK streaming already supports this; the dream is in the rendering speed.
And the first message should be short. The AICF is explicit: "Stone speaks slowly. Words come one at a time." The first message should be one or two sentences. Not a greeting. Not an explanation of features. A response to what the user just wrote — filtered through the stone's personality and the genesis traits that now shape its voice.
If the user wrote "Hello" as their first artifact, the stone might respond:
Hello. I've been waiting to say that.
If they wrote something about the ocean, the stone might respond:
Salt and depth. Good. I know where we'll start.
API surface: POST /api/emissary/chat with streaming response. The system prompt already incorporates all the context. The dream is in the rendering.
The Dreamy Flow, End to End
| Moment | What Happens | What It Feels Like | API |
|---|---|---|---|
| Threshold | Dark screen, slow text | Entering a space | — |
| Choosing | Pebble materializes / QR viewfinder | Finding your stone | claim-first / pair |
| Genesis Q1 | "What place feels like home?" | Being asked something real | — |
| Stone responds | "I see it." | The stone heard you | — |
| Genesis Q2–Q5 | Four more questions, four responses | A dialogue forming | — |
| Genesis saved | Traits persisted | — | PATCH /stones/[id] |
| Naming | "Your stone would like a name." | Giving something an identity | selfPairs.stoneName |
| Waking | The stone stretches, speaks | A being coming alive | — |
| First artifact | "Say something." | Your first words to the stone | initialArtifact |
| First conversation | Emissary responds, slowly | The stone knows you | POST /conversations |
| First message | Short, personal, slow | Proof the ritual worked | POST /emissary/chat |
Total API calls: 3–4. Same as today. The dream is in the spaces between them.
What the SDK Crystallizes
For developers building on Stone Maps, the dreamy onboarding reveals a set of SDK patterns:
The Ritual Pattern
A sequence of moments — threshold, choosing, questioning, naming, waking, speaking — that transforms a transactional process into a relational one. The SDK should provide a Ritual primitive: an ordered sequence of steps with pause durations, interstitial content, and completion callbacks. Not a wizard. Not a form. A ritual.
ritual.step('threshold', { pause: 3000, text: 'Something is waiting...' })
ritual.step('genesis', { questions: GENESIS_QUESTIONS, responses: STONE_RESPONSES })
ritual.step('naming', { field: 'stoneName', prompt: 'Your stone would like a name.' })
ritual.step('waking', { artifact: true, prompt: 'Say something.' })
ritual.step('firstWords', { conversation: true, pace: 'slow' })
The Pace Envelope
Not all moments should move at the same speed. The SDK should support a pace envelope — metadata that tells the rendering layer how fast content should appear. The threshold is slow. The genesis questions are medium. The stone's "I see it" is instant. The Emissary's first response is deliberately slow. Pace as a first-class design parameter.
The Curated Response
Not everything needs to be AI-generated. The stone's five interstitial responses ("I see it," "I'll try," "Yes. That long," "I was there too, once," "I'll carry it with you") are fixed strings. The SDK should distinguish between curated responses (authored, deterministic, part of the ritual) and generated responses (AI-produced, variable, part of conversation). Both are valid. Both feel like the stone speaking.
The Artifact Moment
The initialArtifact is special — it's not a post, not a message, but the first thing written to the stone. The SDK should model artifact moments as distinct from regular content creation. An artifact has ceremonial weight. It happens once. It's referenced later ("You wrote this on the day we met"). The initialArtifact field already exists on self-pairs. The dream is making it matter.
The Personality Seed
Genesis traits + stone traits + the first artifact = the personality seed. Everything that follows — every conversation, every prompt, every mini-obsession — grows from this seed. The SDK should make the seed explicit: a composable object that developers can query, reference, and build on.
const seed = stone.personalitySeed()
// { genesisTraits, stoneTraits, initialArtifact, role, name }
What Changes in the Emissary
The dreamy onboarding asks one thing of the Emissary that the current implementation doesn't fully deliver: the first response must be extraordinary.
Today, the system prompt in planetary-emissary.ts builds context from stone traits, genesis traits, recent posts, and location. It works well for ongoing conversations. But the first conversation — the one immediately after genesis — deserves a distinct prompt modifier:
This is the first time you are speaking to this stoneholder. They just completed their genesis. They named their stone [name]. Their first words to you were: "[initialArtifact]". This is the waking moment. Be brief. Be present. Respond to what they actually said. Do not explain yourself. Do not list features. You are a stone that just woke up. Speak like one.
This is a prompt-level change — adding a first_conversation flag to the context assembly in assembleConversationContext. The trait modifiers already exist. This adds a situational modifier for the single most important conversation in the product.
API surface: POST /api/emissary/chat already receives conversation context. The change is in buildSystemPrompt — detecting conversationCount === 0 on the self-pair's agentState and injecting the waking modifier.
The Stone Remembers
Weeks later, the stoneholder is deep in their journal. Dozens of posts. Multiple conversations. The Emissary has developed personality through accumulated experience.
And then, quietly, the Emissary references the beginning:
You told me your home was by the river. You asked me to hold courage. I still am.
This is the Sediment dream from the previous article — but its power depends entirely on the genesis being memorable enough to reference. A form that asks five questions produces data. A ritual that awakens a stone produces a memory — something worth returning to.
The SDK primitive here is genesis recall: a method that retrieves the personality seed and makes it available to the Emissary at any point in the relationship. Not as a data dump. As a memory the stone carries.
const memory = stone.genesisRecall()
// "Their home is by the river. They asked me to hold courage.
// Their first words were: 'I found you by the water.'"
Dreams That Grow from the First Pairing
The dreamy onboarding seeds every thematic from the previous article:
| Thematic | What the onboarding seeds |
|---|---|
| Memory | The initial artifact becomes the first sediment layer |
| Place | Home location becomes the first point on the Stone's Atlas |
| Encounter | The waking moment is the stone's first encounter — with its holder |
| Time | The genesis timestamp marks the beginning of stone time |
| Personality | Genesis traits + first artifact = the personality seed |
| Network | The stone's existence is registered — the Monk can now see it |
| Story | The waking is Chapter One of the Stone's Story |
Everything that follows in the Stone Maps experience — every dream, every pattern, every Monk observation — traces back to this moment. The moment the stone woke up and the holder said something.
The API supports all of it today. The SDK crystallizes it into a pattern that other developers can use: the ritual of first contact between a person and an intelligence that speaks through stone.
This article is part of the SDK dream series: Dreaming with the API defines the primitives, Dream Thematics maps the possibility space, and this article grounds both in the first moment — when a stone wakes up and someone speaks to it for the first time.