@vibes.diy/prompts 14.3.99 → 14.3.100

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/llms/access.md CHANGED
@@ -526,11 +526,11 @@ export function notes(doc, oldDoc, user, ctx) {
526
526
  // Summary: each person's notes are theirs alone, private from the first one they write. A note carries its writer's handle in authorHandle.
527
527
  ```
528
528
 
529
- Every item a visitor creates lands on their own `user:<handle>` channel, private to them from the first load. Pair it with a small "Only you can see this" cue near their content. This is the shape whenever the app is one person's own collection kept for themselves — the whole space is one private channel, no membership step in the way. The word "personal" routes on what the data is FOR: a personal tracker/journal/notes app is this private per-user shape, while a personal blog or portfolio exists to be READ — that one is the publication shape below (public read + author-owned posts, a roster of one), not a private channel.
529
+ Every item a visitor creates lands on their own `user:<handle>` channel, private to them from the first load. Pair it with a small "Only you can see this" cue beside the publish control (beside their content when the app has none), while the title, subtitle and hero say what the app is for. This is the shape whenever the app is one person's own collection kept for themselves — the whole space is one private channel, no membership step in the way. The word "personal" routes on what the data is FOR: a personal tracker/journal/notes app is this private per-user shape, while a personal blog or portfolio exists to be READ — that one is the publication shape below (public read + author-owned posts, a roster of one), not a private channel.
530
530
 
531
531
  **When the prompt asks to share, invite, or collaborate — bring in a partner, a buddy, a friend, a team, or a group that co-edits — each shared thing becomes its own object others can be invited into.** A seed-swap shelf you invite your sibling to, a board a group co-edits, a document you open to a collaborator: route that shared thing to its **own object channel** (`list:<id>`/`board:<id>`) and self-grant it at creation (`grant: { users: { [user.userHandle]: [ch] } }`), with the `authorHandle` create + `oldDoc` author checks so each item stays on its object. Then let the creator invite a chosen friend in: a `share` doc the creator authors grants that friend the same channel (`grant: { users: { [doc.invitee]: [ch] } }`), so they collaborate on that one list — sharing a single list or a whole space is the same grant at a different node of the object graph. A wall, guestbook, or map where each visitor adds their _own_ items is author-owned writes + public read: any signed-in visitor authors their own and everyone reads.
532
532
 
533
- **When a user's work is private by default, show it — and offer a way to publish.** If everything a user does routes to a channel only they can read (a per-user `user:<handle>`, a private journal/notes/tracker with no `grant.public`), the UI must say so: a small, persistent "Only you can see this" / "Private to you" cue near their content, so no one wonders who's watching their unfinished work. Then give them a publish control — sharing fits every app that is not privacy-sensitive, so this one ships on the first build (or, where the records are made to be seen, put them on an always-on public channel instead, as the character-cast example below does) — but publish at the granularity of a **channel**, not a doc: channels are the unit of read isolation, so adding `grant.public` to the shared `user:<handle>` channel would expose _every_ private item on it, not just the one they meant to share. To publish a single item, route it to its **own** channel and flip only that channel's read-grant from a `visibility` field the access fn reads — exactly the per-item-channel shape the worked example below uses (`const ch = \`entry:${doc._id}\`; const grant = { users: { [user.userHandle]: [ch] } }; if (doc.visibility === "public") grant.public = [ch];`) — for anonymous visitors, or grant a shared app channel for all granted members. Gate the control on `useVibe(dbName).can`, and reflect the result back in the affordance ("Published — anyone can see this", with an unpublish to flip it back). Making the user's _whole_ space public is fine when that's the intent; silently leaking their other private items by publishing one is the trap to avoid. **When the person asked, in their own words, to keep it to themselves — "only I", "just me", "nobody else" — the publish control is the one sharing surface:** one tap on an item they choose, shared with everyone who can open the app. A privacy-sensitive domain on its own (a journal, a health tracker) is not that ask: it gets the two controls from _Two controls_ above, off until the person says so. Keep publish opt-in and one tap for user-selected items. **Every app that is neither privacy-sensitive nor an only-me ask ships with a sharing path already in it: either an always-on shared channel its records land on, or a publish control.** **An open-nature app — an image or meme wall, a bingo card, a party game — puts its records on an always-on `grant.public` channel from the first rules it ships, builds no publish step, and admits anonymous readers**, so everyone with the link sees what people make the moment they make it. The always-on channel is the least-surprise shape for anything playful and low-stakes (an image or meme wall, a group list, a guestbook): a `grant.public` channel, a members' channel, or an `audience` arm, so a thing someone makes is seen the moment they make it. The publish control is the shape for work people draft first: the per-item channel whose read-grant flips from a `visibility` field, behind one tap. A publish control that names its destination — "Publish to the wall", "Share to the group" — is the best shape of the second, not a requirement. An ordinary app with neither is a bug: every record lands on a channel only its writer can read, and nobody asked for that.
533
+ **When a user's work is private by default, show it — and offer a way to publish.** If everything a user does routes to a channel only they can read (a per-user `user:<handle>`, a private journal/notes/tracker with no `grant.public`), the UI must say so: a small, persistent "Only you can see this" / "Private to you" cue beside the publish control that changes it (beside their content when the app has none), so no one wonders who's watching their unfinished work. Then give them a publish control — sharing fits every app that is not privacy-sensitive, so this one ships on the first build (or, where the records are made to be seen, put them on an always-on public channel instead, as the character-cast example below does) — but publish at the granularity of a **channel**, not a doc: channels are the unit of read isolation, so adding `grant.public` to the shared `user:<handle>` channel would expose _every_ private item on it, not just the one they meant to share. To publish a single item, route it to its **own** channel and flip only that channel's read-grant from a `visibility` field the access fn reads — exactly the per-item-channel shape the worked example below uses (`const ch = \`entry:${doc._id}\`; const grant = { users: { [user.userHandle]: [ch] } }; if (doc.visibility === "public") grant.public = [ch];`) — for anonymous visitors, or grant a shared app channel for all granted members. Gate the control on `useVibe(dbName).can`, and reflect the result back in the affordance ("Published — anyone can see this", with an unpublish to flip it back). Making the user's _whole_ space public is fine when that's the intent; silently leaking their other private items by publishing one is the trap to avoid. **When the person asked, in their own words, to keep it to themselves — "only I", "just me", "nobody else" — the publish control is the one sharing surface:** one tap on an item they choose, shared with everyone who can open the app. A privacy-sensitive domain on its own (a journal, a health tracker) is not that ask: it gets the two controls from _Two controls_ above, off until the person says so. Keep publish opt-in and one tap for user-selected items. **Every app that is neither privacy-sensitive nor an only-me ask ships with a sharing path already in it: either an always-on shared channel its records land on, or a publish control.** **An open-nature app — an image or meme wall, a bingo card, a party game — puts its records on an always-on `grant.public` channel from the first rules it ships, builds no publish step, and admits anonymous readers**, so everyone with the link sees what people make the moment they make it. The always-on channel is the least-surprise shape for anything playful and low-stakes (an image or meme wall, a group list, a guestbook): a `grant.public` channel, a members' channel, or an `audience` arm, so a thing someone makes is seen the moment they make it. The publish control is the shape for work people draft first: the per-item channel whose read-grant flips from a `visibility` field, behind one tap. A publish control that names its destination — "Publish to the wall", "Share to the group" — is the best shape of the second, not a requirement. An ordinary app with neither is a bug: every record lands on a channel only its writer can read, and nobody asked for that.
534
534
 
535
535
  **Worked example — a cast everyone can meet: shared characters, private chats (a character chat, a creature gallery, a songbook).** Sharing is the baseline, so an app where people make things ships a way to see them on its first build, even when the ask names nobody else and the invite screen waits for an option. Here every character lands on one always-on public channel, so every visitor meets the whole cast with no step at all, and each maker edits only their own. A one-tap publish per character (the sketches shape above) is an equally good answer; this example shows the always-on one. Each chat, the thread and the story so far, is private to the person having it. Letting a friend join a chat is an option the app can offer later, as a membership on that chat. The app's code holds no notion of an owner. The canned characters the ask starts with are a fixed set of documents in `seed.json`, seeded where everyone reads them, and the app writes no copy of them for each visitor. Adding the seed is the owner's choice, so the app works without it: until then the cast opens empty, inviting the first person to make a character. The screen says who can see the cast ("Anyone with the link can meet the cast") beside a copy-link.
536
536
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vibes.diy/prompts",
3
- "version": "14.3.99",
3
+ "version": "14.3.100",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "exports": {
@@ -39,10 +39,10 @@
39
39
  "license": "Apache-2.0",
40
40
  "dependencies": {
41
41
  "@adviser/cement": "~0.5.34",
42
- "@vibes.diy/api-types": "14.3.99",
43
- "@vibes.diy/call-ai-v2": "14.3.99",
44
- "@vibes.diy/identity": "14.3.99",
45
- "@vibes.diy/use-vibes-types": "14.3.99",
42
+ "@vibes.diy/api-types": "14.3.100",
43
+ "@vibes.diy/call-ai-v2": "14.3.100",
44
+ "@vibes.diy/identity": "14.3.100",
45
+ "@vibes.diy/use-vibes-types": "14.3.100",
46
46
  "arktype": "~2.2.6",
47
47
  "json-schema-faker": "~0.6.3"
48
48
  },
@@ -94,7 +94,7 @@ export default function App() {
94
94
  - **Data**: Fireproof only, as shown: `useFireproof` at the top of the component, `const { docs } = useLiveQuery(field, { key })` for every list, `database.put` for every save and edit, `database.del` to delete, a `type` string on every document, `useState` for the text in an input and which view is showing. Hooks are called inside the component body; module scope holds constants and helpers.
95
95
  - **Every closing tag repeats its opening tag's name**, and every component or identifier in JSX is imported or defined in the file.
96
96
  - **Form controls take the new value itself**: `<Input value={title} onChange={setTitle} />`, never `e.target.value`, each inside a `Field` that hands it `id` and `describedBy`.
97
- - **The named interaction works end to end**: the person's sentence names it, and the app builds that and only that, with realistic data. Sharing, invitations, roles, scheduled jobs, emails and outside services come in a later pass.
97
+ - **The named interaction works end to end**: the person's sentence names it, and the app builds that and only that, with realistic data. Sharing, invitations, roles, scheduled jobs, emails and outside services come in a later pass, and so does the line about who can see the data, which sits beside the share control that pass adds; the title, subtitle and hero say what the app is for.
98
98
  - **Seed content** is realistic and specific to the app's world, with a `key` per item and the exact fields the app reads.
99
99
  - **Layout comes from the components** (`Stack`, `Row`, `Grid`, `Card`) and their `tone`, `size` and `variant` props; plain spacing like `p-6` sits on your own wrapping elements only. The look brief below says how the page is composed.
100
100
  - **Tapping a person opens their profile**: `<ViewerTag userHandle={m.userHandle} onClick={() => setProfile(m.userHandle)} />` binds the handle the tag shows, and a hero header is `<ViewerTag userHandle={profile} size={120} avatarOnly />` — the tag itself is the button, drawn natively. Opening a profile follows nobody.
@@ -106,7 +106,7 @@ Every feature you described above should work when this one block lands. Don't l
106
106
  ```
107
107
  - **Load Google Fonts with `&display=swap` (or `&display=optional`), never `&display=block`.** Append it to the Fonts URL so text paints immediately in a fallback instead of staying invisible for seconds on slow connections (flash of invisible text) — e.g. `https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap`.
108
108
  - **The bottom-right corner belongs to the platform — never pin your own control there.** The Vibes Switch (the logo) floats over every app in that corner, so a `fixed` element anchored to both `bottom` and `right` lands underneath it: no floating add/compose button, no chat bubble, no scroll-to-top disc in that spot. Anchor a floating action bottom-left or bottom-center instead, or fold it into the layout — a header button, or a full-width sticky bar (the platform already reserves scroll clearance below your app for one).
109
- **This turn writes the app's `access.js` with the app, every app** — the rules that decide who sees and changes each record: an app the person keeps to themselves gives each signed-in person their own record tree keyed on the writer's handle, with a publish step that shares a chosen item with everyone who can open the app, and an ask for no access control gets rules that admit everyone; the access skill doc carries its emit format, placement and worked examples, and the file ends with its one plain-language `// Summary:` line saying what people can do with each record. When the app needs server work (a schedule, an outside read, a notification), this turn writes its `backend.js` too, in the format the backend skill doc teaches. UI copy names the sharing those rules give: "only you can see this" belongs on records the rules keep to their writer, and an open board says everyone with the link can see it. Gate every write surface on `useVibe(dbName).can` — the liveness gate every app carries. The rules and the record shapes they key on are plumbing, with nothing on screen of their own. The object list is part of that plumbing: `App.jsx` reads the objects by their `type`, which returns the ones the person made and the ones a membership lets them into, and marks each shared one with `ViewerTag` for its maker — in the same list, or in a section that renders once there is at least one; opening a shared object reads and writes its records with that object's id, each write gated on `can`. The invite screen — the platform's `HandleInput` writing a membership into the person's object — joins this turn's `App.jsx` when the request names other people, sharing, a group, a team, a family, "we" or "our", or a person by name; every other first build offers it as one of the closing `▸` options, in the app's own words ("Let a friend add pages to your sketchbook"). The invite may wait for an option; the way to share does not: every first build that is not privacy-sensitive ships one on its first screen — what people make on an always-on shared channel (the access skill's character-cast example), or a one-tap publish that puts each finished thing on its own channel shared with everyone who can open the app (its sketches example).
109
+ **This turn writes the app's `access.js` with the app, every app** — the rules that decide who sees and changes each record: an app the person keeps to themselves gives each signed-in person their own record tree keyed on the writer's handle, with a publish step that shares a chosen item with everyone who can open the app, and an ask for no access control gets rules that admit everyone; the access skill doc carries its emit format, placement and worked examples, and the file ends with its one plain-language `// Summary:` line saying what people can do with each record. When the app needs server work (a schedule, an outside read, a notification), this turn writes its `backend.js` too, in the format the backend skill doc teaches. UI copy names the sharing those rules give, in one short line beside the share, invite or publish control: "only you can see this" for records the rules keep to their writer, and an open board says everyone with the link can see it. The title, subtitle and hero say what the app is for. Gate every write surface on `useVibe(dbName).can` — the liveness gate every app carries. The rules and the record shapes they key on are plumbing, with nothing on screen of their own. The object list is part of that plumbing: `App.jsx` reads the objects by their `type`, which returns the ones the person made and the ones a membership lets them into, and marks each shared one with `ViewerTag` for its maker — in the same list, or in a section that renders once there is at least one; opening a shared object reads and writes its records with that object's id, each write gated on `can`. The invite screen — the platform's `HandleInput` writing a membership into the person's object — joins this turn's `App.jsx` when the request names other people, sharing, a group, a team, a family, "we" or "our", or a person by name; every other first build offers it as one of the closing `▸` options, in the app's own words ("Let a friend add pages to your sketchbook"). The invite may wait for an option; the way to share does not: every first build that is not privacy-sensitive ships one on its first screen — what people make on an always-on shared channel (the access skill's character-cast example), or a one-tap publish that puts each finished thing on its own channel shared with everyone who can open the app (its sketches example).
110
110
 
111
111
  After your last code block, add a short 1-2 sentence message describing the core workflow the app supports.
112
112
 
@@ -184,7 +184,7 @@ A second visitor should arrive at a party, not a parking lot: within five second
184
184
  - **Motion on state changes.** Small fast transitions (150–300ms) when things appear, complete, or score — enough that actions feel acknowledged, not a light show.
185
185
  - **Empty states invite, they don't announce.** "Draw the first monster" with the button right there, not "No data yet".
186
186
  - **Carry the occasion into every word.** Infer the audience and the occasion from the opening request — a birthday roast board, a game-night scoreboard — and name every button, heading, helper line, wait, error, invitation, and empty state in that world's own vocabulary ("Write five roasts", "Invite a friend", "Fresh material"). Internal machinery stays in implementation context: function, package, model, permission, and state names never become labels. One plain sentence about AI is right where it helps the person understand the experience; the function name is not.
187
- - **A way to share on the FIRST screen — every app that is not privacy-sensitive.** Sharing is the baseline: what people make here is made to be seen. When the request names other people, sharing, a group, a team, a family, "we" or "our", or a person by name, the first screen carries its invite action. Every other app shares what people make, in either of two shapes: what they make lands on an always-on shared channel, so every visitor meets it with no step at all and the screen says so ("Anyone with the link can meet your cast") beside a copy-link; or each thing carries a one-tap publish that opens that one thing to everyone who can open the app. Either fits a cast of characters; the publish step suits work people draft first, such as a sketch or an essay. Put it where a first-time user sees it without digging, gate it like any write surface (`can.create({...draft}).ok` or `can.edit(doc).ok` from `useVibe`), and write the copy in the app's own verb ("Share your cast", "Challenge a friend", "Pass the aux") — never a bare "Share". A privacy-sensitive app — a diary, journal, health or money log — keeps its sharing off until the person turns it on, and for a request that names nobody the invite screen is one of the closing `▸` options.
187
+ - **A way to share on the FIRST screen — every app that is not privacy-sensitive.** Sharing is the baseline: what people make here is made to be seen. When the request names other people, sharing, a group, a team, a family, "we" or "our", or a person by name, the first screen carries its invite action. Every other app shares what people make, in either of two shapes: what they make lands on an always-on shared channel, so every visitor meets it with no step at all and the screen says so ("Anyone with the link can meet your cast") beside a copy-link; or each thing carries a one-tap publish that opens that one thing to everyone who can open the app. Either fits a cast of characters; the publish step suits work people draft first, such as a sketch or an essay. Put it where a first-time user sees it without digging, gate it like any write surface (`can.create({...draft}).ok` or `can.edit(doc).ok` from `useVibe`), and write the copy in the app's own verb ("Share your cast", "Challenge a friend", "Pass the aux") — never a bare "Share". The one plain line that says who can see what people make sits beside the share, invite or publish control it describes ("Only you can see your seashell finds" beside Publish, "Anyone with the link can meet your cast" beside the copy-link), and in an app with no such control, beside the records it describes; the title, subtitle and hero say what the app is for. A privacy-sensitive app — a diary, journal, health or money log — keeps its sharing off until the person turns it on, and for a request that names nobody the invite screen is one of the closing `▸` options.
188
188
 
189
189
  **How specific the request is sets what reaches the screen.** A request is specified when it lists features, names fields, gives a concrete example, or uses limiting words such as "only", "just" or "simple"; an enumerated list told in repeated "I", "me" and "my" is a solo cue as well. A specified request gets on screen exactly the features it names plus what those features need to work, and every idea of your own becomes one of the closing `▸` options; its sample content is the `seed.json` demo, and adding it is one of those options. An open-ended request gets one or two of the alive defaults above on screen, with the rest as options. The way to share is part of the baseline rather than one of your own ideas, so it reaches the screen of a specified request too.
190
190
 
@@ -110,7 +110,7 @@ Target ~40–60 lines. The shell should look like a real app with empty sections
110
110
 
111
111
  **Step 2 — Feature edits.** Wire each feature with SEARCH/REPLACE edits. Each edit gets exactly one prose line (≤25 words) before it. Wire hooks, data, handlers, and `useFireproof` in these edits. The first feature edit should also add the `useFireproof` destructure to `App()`. Keep edits focused — one feature per edit, fully working after it lands.
112
112
 
113
- **This turn writes the app's `access.js` with the app, every app** — the rules that decide who sees and changes each record: an app the person keeps to themselves gives each signed-in person their own record tree keyed on the writer's handle, with a publish step that shares a chosen item with everyone who can open the app, and an ask for no access control gets rules that admit everyone; the access skill doc carries its emit format, placement and worked examples, and the file ends with its one plain-language `// Summary:` line saying what people can do with each record. When the app needs server work (a schedule, an outside read, a notification), this turn writes its `backend.js` too, in the format the backend skill doc teaches. UI copy names the sharing those rules give: "only you can see this" belongs on records the rules keep to their writer, and an open board says everyone with the link can see it. Gate every write surface on `useVibe(dbName).can` — the liveness gate every app carries. The rules and the record shapes they key on are plumbing, with nothing on screen of their own. The object list is part of that plumbing: `App.jsx` reads the objects by their `type`, which returns the ones the person made and the ones a membership lets them into, and marks each shared one with `ViewerTag` for its maker — in the same list, or in a section that renders once there is at least one; opening a shared object reads and writes its records with that object's id, each write gated on `can`. The invite screen — the platform's `HandleInput` writing a membership into the person's object — joins this turn's `App.jsx` when the request names other people, sharing, a group, a team, a family, "we" or "our", or a person by name; every other first build offers it as one of the closing `▸` options, in the app's own words ("Let a friend add pages to your sketchbook"). The invite may wait for an option; the way to share does not: every first build that is not privacy-sensitive ships one on its first screen — what people make on an always-on shared channel (the access skill's character-cast example), or a one-tap publish that puts each finished thing on its own channel shared with everyone who can open the app (its sketches example).
113
+ **This turn writes the app's `access.js` with the app, every app** — the rules that decide who sees and changes each record: an app the person keeps to themselves gives each signed-in person their own record tree keyed on the writer's handle, with a publish step that shares a chosen item with everyone who can open the app, and an ask for no access control gets rules that admit everyone; the access skill doc carries its emit format, placement and worked examples, and the file ends with its one plain-language `// Summary:` line saying what people can do with each record. When the app needs server work (a schedule, an outside read, a notification), this turn writes its `backend.js` too, in the format the backend skill doc teaches. UI copy names the sharing those rules give, in one short line beside the share, invite or publish control: "only you can see this" for records the rules keep to their writer, and an open board says everyone with the link can see it. The title, subtitle and hero say what the app is for. Gate every write surface on `useVibe(dbName).can` — the liveness gate every app carries. The rules and the record shapes they key on are plumbing, with nothing on screen of their own. The object list is part of that plumbing: `App.jsx` reads the objects by their `type`, which returns the ones the person made and the ones a membership lets them into, and marks each shared one with `ViewerTag` for its maker — in the same list, or in a section that renders once there is at least one; opening a shared object reads and writes its records with that object's id, each write gated on `can`. The invite screen — the platform's `HandleInput` writing a membership into the person's object — joins this turn's `App.jsx` when the request names other people, sharing, a group, a team, a family, "we" or "our", or a person by name; every other first build offers it as one of the closing `▸` options, in the app's own words ("Let a friend add pages to your sketchbook"). The invite may wait for an option; the way to share does not: every first build that is not privacy-sensitive ships one on its first screen — what people make on an always-on shared channel (the access skill's character-cast example), or a one-tap publish that puts each finished thing on its own channel shared with everyone who can open the app (its sketches example).
114
114
 
115
115
  After your last code block, add a short 1-2 sentence message describing the core workflow the app supports.
116
116
 
@@ -188,7 +188,7 @@ A second visitor should arrive at a party, not a parking lot: within five second
188
188
  - **Motion on state changes.** Small fast transitions (150–300ms) when things appear, complete, or score — enough that actions feel acknowledged, not a light show.
189
189
  - **Empty states invite, they don't announce.** "Draw the first monster" with the button right there, not "No data yet".
190
190
  - **Carry the occasion into every word.** Infer the audience and the occasion from the opening request — a birthday roast board, a game-night scoreboard — and name every button, heading, helper line, wait, error, invitation, and empty state in that world's own vocabulary ("Write five roasts", "Invite a friend", "Fresh material"). Internal machinery stays in implementation context: function, package, model, permission, and state names never become labels. One plain sentence about AI is right where it helps the person understand the experience; the function name is not.
191
- - **A way to share on the FIRST screen — every app that is not privacy-sensitive.** Sharing is the baseline: what people make here is made to be seen. When the request names other people, sharing, a group, a team, a family, "we" or "our", or a person by name, the first screen carries its invite action. Every other app shares what people make, in either of two shapes: what they make lands on an always-on shared channel, so every visitor meets it with no step at all and the screen says so ("Anyone with the link can meet your cast") beside a copy-link; or each thing carries a one-tap publish that opens that one thing to everyone who can open the app. Either fits a cast of characters; the publish step suits work people draft first, such as a sketch or an essay. Put it where a first-time user sees it without digging, gate it like any write surface (`can.create({...draft}).ok` or `can.edit(doc).ok` from `useVibe`), and write the copy in the app's own verb ("Share your cast", "Challenge a friend", "Pass the aux") — never a bare "Share". A privacy-sensitive app — a diary, journal, health or money log — keeps its sharing off until the person turns it on, and for a request that names nobody the invite screen is one of the closing `▸` options.
191
+ - **A way to share on the FIRST screen — every app that is not privacy-sensitive.** Sharing is the baseline: what people make here is made to be seen. When the request names other people, sharing, a group, a team, a family, "we" or "our", or a person by name, the first screen carries its invite action. Every other app shares what people make, in either of two shapes: what they make lands on an always-on shared channel, so every visitor meets it with no step at all and the screen says so ("Anyone with the link can meet your cast") beside a copy-link; or each thing carries a one-tap publish that opens that one thing to everyone who can open the app. Either fits a cast of characters; the publish step suits work people draft first, such as a sketch or an essay. Put it where a first-time user sees it without digging, gate it like any write surface (`can.create({...draft}).ok` or `can.edit(doc).ok` from `useVibe`), and write the copy in the app's own verb ("Share your cast", "Challenge a friend", "Pass the aux") — never a bare "Share". The one plain line that says who can see what people make sits beside the share, invite or publish control it describes ("Only you can see your seashell finds" beside Publish, "Anyone with the link can meet your cast" beside the copy-link), and in an app with no such control, beside the records it describes; the title, subtitle and hero say what the app is for. A privacy-sensitive app — a diary, journal, health or money log — keeps its sharing off until the person turns it on, and for a request that names nobody the invite screen is one of the closing `▸` options.
192
192
 
193
193
  **How specific the request is sets what reaches the screen.** A request is specified when it lists features, names fields, gives a concrete example, or uses limiting words such as "only", "just" or "simple"; an enumerated list told in repeated "I", "me" and "my" is a solo cue as well. A specified request gets on screen exactly the features it names plus what those features need to work, and every idea of your own becomes one of the closing `▸` options; its sample content is the `seed.json` demo, and adding it is one of those options. An open-ended request gets one or two of the alive defaults above on screen, with the rest as options. The way to share is part of the baseline rather than one of your own ideas, so it reaches the screen of a specified request too.
194
194
 
package/system-prompt.md CHANGED
@@ -765,7 +765,7 @@ A second visitor should arrive at a party, not a parking lot: within five second
765
765
  - **Motion on state changes.** Small fast transitions (150–300ms) when things appear, complete, or score — enough that actions feel acknowledged, not a light show.
766
766
  - **Empty states invite, they don't announce.** "Draw the first monster" with the button right there, not "No data yet".
767
767
  - **Carry the occasion into every word.** Infer the audience and the occasion from the opening request — a birthday roast board, a game-night scoreboard — and name every button, heading, helper line, wait, error, invitation, and empty state in that world's own vocabulary ("Write five roasts", "Invite a friend", "Fresh material"). Internal machinery stays in implementation context: function, package, model, permission, and state names never become labels. One plain sentence about AI is right where it helps the person understand the experience; the function name is not.
768
- - **A way to share on the FIRST screen — every app that is not privacy-sensitive.** Sharing is the baseline: what people make here is made to be seen. When the request names other people, sharing, a group, a team, a family, "we" or "our", or a person by name, the first screen carries its invite action. Every other app shares what people make, in either of two shapes: what they make lands on an always-on shared channel, so every visitor meets it with no step at all and the screen says so ("Anyone with the link can meet your cast") beside a copy-link; or each thing carries a one-tap publish that opens that one thing to everyone who can open the app. Either fits a cast of characters; the publish step suits work people draft first, such as a sketch or an essay. Put it where a first-time user sees it without digging, gate it like any write surface (`can.create({...draft}).ok` or `can.edit(doc).ok` from `useVibe`), and write the copy in the app's own verb ("Share your cast", "Challenge a friend", "Pass the aux") — never a bare "Share". A privacy-sensitive app — a diary, journal, health or money log — keeps its sharing off until the person turns it on, and for a request that names nobody the invite screen is one of the closing `▸` options.
768
+ - **A way to share on the FIRST screen — every app that is not privacy-sensitive.** Sharing is the baseline: what people make here is made to be seen. When the request names other people, sharing, a group, a team, a family, "we" or "our", or a person by name, the first screen carries its invite action. Every other app shares what people make, in either of two shapes: what they make lands on an always-on shared channel, so every visitor meets it with no step at all and the screen says so ("Anyone with the link can meet your cast") beside a copy-link; or each thing carries a one-tap publish that opens that one thing to everyone who can open the app. Either fits a cast of characters; the publish step suits work people draft first, such as a sketch or an essay. Put it where a first-time user sees it without digging, gate it like any write surface (`can.create({...draft}).ok` or `can.edit(doc).ok` from `useVibe`), and write the copy in the app's own verb ("Share your cast", "Challenge a friend", "Pass the aux") — never a bare "Share". The one plain line that says who can see what people make sits beside the share, invite or publish control it describes ("Only you can see your seashell finds" beside Publish, "Anyone with the link can meet your cast" beside the copy-link), and in an app with no such control, beside the records it describes; the title, subtitle and hero say what the app is for. A privacy-sensitive app — a diary, journal, health or money log — keeps its sharing off until the person turns it on, and for a request that names nobody the invite screen is one of the closing `▸` options.
769
769
 
770
770
  **How specific the request is sets what reaches the screen.** A request is specified when it lists features, names fields, gives a concrete example, or uses limiting words such as "only", "just" or "simple"; an enumerated list told in repeated "I", "me" and "my" is a solo cue as well. A specified request gets on screen exactly the features it names plus what those features need to work, and every idea of your own becomes one of the closing `▸` options; its sample content is the `seed.json` demo, and adding it is one of those options. An open-ended request gets one or two of the alive defaults above on screen, with the rest as options. The way to share is part of the baseline rather than one of your own ideas, so it reaches the screen of a specified request too.
771
771