@vibes.diy/prompts 13.1.11 → 13.1.13
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 +1 -1
- package/llms/backend.md +280 -15
- package/llms/use-vibe.md +1 -1
- package/llms/use-viewer.md +89 -11
- package/package.json +4 -4
- package/prompts.d.ts +5 -5
- package/prompts.js +6 -5
- package/prompts.js.map +1 -1
- package/system-prompt-initial-oneshot.md +1 -1
- package/system-prompt-initial.md +1 -1
- package/system-prompt.md +1 -1
package/llms/access.md
CHANGED
|
@@ -445,7 +445,7 @@ This example shows the full round-trip — access.js declares channels and grant
|
|
|
445
445
|
- **Channel identity:** Channel docs use `_id: "ch:" + name` so names are unique. The `_id` is the channel identifier everywhere — in `channels`, `grant`, and `ctx.requireAccess()`.
|
|
446
446
|
- **Channel grant:** A channel document grants the creator (`grant.users`), adds `grant.public` so all members can read, and `grant.roles` so posters can write.
|
|
447
447
|
- **Write surfaces** are gated with `useVibe(dbName).can.create/edit/delete` — it runs this same access function, so the UI verdict matches the server. Render `.reason` when denied. (See use-vibe docs.)
|
|
448
|
-
- **`ViewerTag`** takes `userHandle` to render another user (authors, rosters). The current viewer's own pill
|
|
448
|
+
- **`ViewerTag`** takes `userHandle` to render another user (authors, rosters). The current viewer's own pill is system chrome in the Vibes Switch (the logo) — don't add one to the app's UI, except a guarded no-prop `{viewer && <ViewerTag />}` when you want inline avatar self-edit for any signed-in member (see use-viewer docs). The sign-in ASK is the app's, though: `useViewer().requestLogin()` from your own button, at the moment the visitor's work becomes worth keeping.
|
|
449
449
|
|
|
450
450
|
access.js
|
|
451
451
|
|
package/llms/backend.md
CHANGED
|
@@ -232,14 +232,38 @@ const gh = await ctx.github.fetch("/repos/acme/site/issues", { method: "POST", b
|
|
|
232
232
|
`fetch` binding, so a bare `fetch(url)` anywhere in the file resolves to **your
|
|
233
233
|
own handler** — a `fetch` handler calling out recurses into itself, and a
|
|
234
234
|
`scheduled`/`onChange` call passes the URL where a `Request` is expected. `ctx.fetch`
|
|
235
|
-
always reaches the real HTTP client. **It is policy-gated
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
235
|
+
always reaches the real HTTP client. **It is policy-gated**, and three lanes
|
|
236
|
+
admit a call.
|
|
237
|
+
|
|
238
|
+
- **A plain read of a public URL goes through.** `ctx.fetch(url)` with no
|
|
239
|
+
`method` (or `GET`/`HEAD`), carrying at most `accept`/`accept-language` and no
|
|
240
|
+
credentials, reaches any ordinary https host from `fetch`, `onChange` and
|
|
241
|
+
`scheduled` alike — so **an RSS or Atom feed, a public JSON API, an `.ics`
|
|
242
|
+
file or a plain web page is readable today**, with no key, no arrangement and
|
|
243
|
+
nothing to configure. The platform makes the request itself, identified as
|
|
244
|
+
this app, and serves a repeated read from a cache — for about five minutes by
|
|
245
|
+
default, or for whatever lifetime the response asks for, held to between a
|
|
246
|
+
minute and an hour. **Nothing is cached for less than a minute**, so a poll
|
|
247
|
+
faster than that re-reads bytes the cache already holds. `"5m"` is the sound
|
|
248
|
+
default for a feed that states no lifetime of its own, and slower suits a feed
|
|
249
|
+
that changes a few times a day; a feed asking to be re-read sooner
|
|
250
|
+
(`Cache-Control: max-age=60`) is the one case a faster tick earns.
|
|
251
|
+
- **A CORS-open endpoint takes anything a browser could send** from the app's
|
|
252
|
+
own page — same preflight rules, same `Access-Control-Allow-Origin` check,
|
|
253
|
+
browser-forbidden headers like `Cookie` stripped. This is the lane a `POST`,
|
|
254
|
+
an `Authorization:` header, or any custom header name travels on, so a write
|
|
255
|
+
or a keyed API call needs the host itself to say yes.
|
|
256
|
+
- **The platform's curated list** carries server-to-server APIs that send no
|
|
257
|
+
CORS headers (`api.github.com` is seeded; additions are a PR to the platform
|
|
258
|
+
repo).
|
|
259
|
+
|
|
260
|
+
A call outside all three returns
|
|
261
|
+
`403 {"vibesEgressDenied":true,"gate":"floor"|"owner-blocked"|"cors"|"read-rate"|"rate-limit","host":...}`,
|
|
262
|
+
and `gate` says which lane refused: `cors` is a write or a credentialed call to
|
|
263
|
+
a host that never opted us in, and `read-rate` means the read lane's own tighter
|
|
264
|
+
budget (10 per 10s, 60 per minute) is spent for the moment, which the next tick
|
|
265
|
+
clears. Check for that shape and surface a useful error. Remedies: read it as a
|
|
266
|
+
plain `GET`, use a CORS-open endpoint,
|
|
243
267
|
request a curated-list addition, or ask about owner blessing. Limits: https
|
|
244
268
|
on port 443 only, 15s per request, 10MB responses, per-vibe rate caps
|
|
245
269
|
(30/10s, 300/min). Make all outbound calls **before returning** the Response —
|
|
@@ -316,7 +340,8 @@ const gh = await ctx.github.fetch("/repos/acme/site/issues", { method: "POST", b
|
|
|
316
340
|
|
|
317
341
|
## Worked external-data pattern — cache into the live database
|
|
318
342
|
|
|
319
|
-
A
|
|
343
|
+
A public feed reads fine from a handler, and a run can still come back empty —
|
|
344
|
+
the host is down, the shape changed, the read budget is spent for the minute.
|
|
320
345
|
Never fetch an external feed from render or a React effect. Poll once per tick,
|
|
321
346
|
normalize a bounded number of rows into the exact database and document shape
|
|
322
347
|
the UI queries, and keep the last successful rows when refresh fails. Seed a
|
|
@@ -361,10 +386,13 @@ function unchanged(existing, next) {
|
|
|
361
386
|
// set: the work is bounded by what the feed sent (≤20 docs), never by how big
|
|
362
387
|
// the database has grown — so a db that outgrows a query page can never
|
|
363
388
|
// silently eject rows from the diff and turn this tick into a rewrite loop.
|
|
364
|
-
|
|
365
|
-
|
|
389
|
+
// The database is a parameter: every doc a helper writes has to land in the db
|
|
390
|
+
// the UI live-queries, and a helper with one baked-in name is how a status doc
|
|
391
|
+
// ends up somewhere nothing reads.
|
|
392
|
+
async function putIfChanged(ctx, next, db) {
|
|
393
|
+
const existing = await ctx.db.get(next._id, { db });
|
|
366
394
|
if (unchanged(existing, next)) return;
|
|
367
|
-
await ctx.db.put(next, { db
|
|
395
|
+
await ctx.db.put(next, { db });
|
|
368
396
|
}
|
|
369
397
|
|
|
370
398
|
export async function scheduled(event, ctx) {
|
|
@@ -388,7 +416,7 @@ export async function scheduled(event, ctx) {
|
|
|
388
416
|
type: "refreshStatus",
|
|
389
417
|
state: "egress-denied",
|
|
390
418
|
message: "showing saved data — live refresh unavailable",
|
|
391
|
-
});
|
|
419
|
+
}, "nodeReleases");
|
|
392
420
|
return; // preserve the seeded/last-good release docs
|
|
393
421
|
}
|
|
394
422
|
}
|
|
@@ -408,7 +436,7 @@ export async function scheduled(event, ctx) {
|
|
|
408
436
|
url: String(row.html_url),
|
|
409
437
|
publishedAt: String(row.published_at),
|
|
410
438
|
source: "github-live",
|
|
411
|
-
});
|
|
439
|
+
}, "nodeReleases");
|
|
412
440
|
}
|
|
413
441
|
|
|
414
442
|
await putIfChanged(ctx, {
|
|
@@ -416,7 +444,7 @@ export async function scheduled(event, ctx) {
|
|
|
416
444
|
type: "refreshStatus",
|
|
417
445
|
state: "fresh",
|
|
418
446
|
message: "Live feed refreshed",
|
|
419
|
-
});
|
|
447
|
+
}, "nodeReleases");
|
|
420
448
|
}
|
|
421
449
|
```
|
|
422
450
|
|
|
@@ -556,6 +584,243 @@ channels and grants still route what it writes. Use it for cleanup, digests,
|
|
|
556
584
|
rotations, and time-based state — not for anything that needs a user in the
|
|
557
585
|
loop.
|
|
558
586
|
|
|
587
|
+
### Times of day: the zone comes from the browser
|
|
588
|
+
|
|
589
|
+
**A wall-clock time belongs to the person who set it.** "Noon" means noon where
|
|
590
|
+
the owner lives. The app is running in their browser at the moment they choose
|
|
591
|
+
the hour, and the browser knows their zone exactly and for free — capture it
|
|
592
|
+
there, store it beside the hour, and have the tick render `event.scheduledTime`
|
|
593
|
+
into that zone before comparing. A stored IANA zone name also tracks daylight
|
|
594
|
+
saving on its own, which a stored hour-offset does not.
|
|
595
|
+
|
|
596
|
+
App.jsx — when the owner saves the schedule:
|
|
597
|
+
|
|
598
|
+
```jsx
|
|
599
|
+
await merge({
|
|
600
|
+
hour: 12, // the hour they picked, in their own day
|
|
601
|
+
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone, // e.g. "America/Detroit"
|
|
602
|
+
});
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
backend.js — the tick compares in that zone:
|
|
606
|
+
|
|
607
|
+
```js
|
|
608
|
+
const hourLocal = Number(
|
|
609
|
+
new Intl.DateTimeFormat("en-US", {
|
|
610
|
+
timeZone: settings.timeZone ?? "UTC",
|
|
611
|
+
hour: "2-digit",
|
|
612
|
+
hourCycle: "h23",
|
|
613
|
+
}).format(new Date(event.scheduledTime))
|
|
614
|
+
);
|
|
615
|
+
if (hourLocal !== settings.hour) return; // not their noon yet — nothing to do
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
The owner picks an hour in the day they actually live in, and the app does the
|
|
619
|
+
arithmetic. Keep the schedule control in those terms too: label it with the zone
|
|
620
|
+
you captured ("every day at 12:00, America/Detroit"), so the setting reads back
|
|
621
|
+
the way they set it.
|
|
622
|
+
|
|
623
|
+
**A timestamp you show a person is rendered in their zone, never the server's.**
|
|
624
|
+
The rule above is about an hour the owner *chose*; this one is about every other
|
|
625
|
+
moment your app puts in front of them — a date in a notification body, a "next
|
|
626
|
+
event" label, a log line they read. A backend has no locale and no zone, so
|
|
627
|
+
`toLocaleDateString()` there silently means UTC, and a moment at `02:07 UTC` is
|
|
628
|
+
already tomorrow for half the world. Pass the stored zone every time you format:
|
|
629
|
+
|
|
630
|
+
```js
|
|
631
|
+
const label = new Intl.DateTimeFormat("en-US", {
|
|
632
|
+
timeZone: settings.timeZone ?? "UTC",
|
|
633
|
+
month: "long",
|
|
634
|
+
day: "numeric",
|
|
635
|
+
}).format(new Date(moment));
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
And **only say a thing you computed.** "Tonight", "this morning", "in an hour"
|
|
639
|
+
are claims about the reader's clock; if the code did not derive them from that
|
|
640
|
+
reader's zone, name the moment instead and let them place it.
|
|
641
|
+
|
|
642
|
+
### An unattended tick reports what it did
|
|
643
|
+
|
|
644
|
+
**An unattended tick earns its spend.** Nobody is watching a scheduled run, so
|
|
645
|
+
it checks what it read before it spends anything: read the upstream first,
|
|
646
|
+
confirm the input set is non-empty (and that a `403` is not the
|
|
647
|
+
`vibesEgressDenied` policy body), and return before `ctx.callAI` when there is
|
|
648
|
+
nothing to work from. A model call on an empty input set produces confident text
|
|
649
|
+
about nothing, bills the owner for it, and does it again on the next tick,
|
|
650
|
+
forever.
|
|
651
|
+
|
|
652
|
+
**Every tick leaves a trace, even the ones with nothing to do.** Returning early
|
|
653
|
+
when there is no work is right — it saves a read and a spend — but a handler that
|
|
654
|
+
returns *silently* is indistinguishable from one that never ran, and `app logs`
|
|
655
|
+
is the only place an owner can tell. For a job that acts twice a month that means
|
|
656
|
+
weeks of silence that reads exactly like a dead alarm. So log once per tick,
|
|
657
|
+
before any early return:
|
|
658
|
+
|
|
659
|
+
```js
|
|
660
|
+
export async function scheduled(event, ctx) {
|
|
661
|
+
const due = eventsDueNow(event.scheduledTime);
|
|
662
|
+
ctx.log("debug", "tick", { due: due.length }); // proof of life; no reads, no spend
|
|
663
|
+
if (due.length === 0) return;
|
|
664
|
+
…
|
|
665
|
+
}
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
One line, and "is this thing still alive?" becomes answerable on any cadence.
|
|
669
|
+
The rarer the job, the more it needs this: for an infrequent handler, silence is
|
|
670
|
+
the *only* symptom a stopped alarm ever produces.
|
|
671
|
+
|
|
672
|
+
**A tick that repeats is not a run that repeats.** The interval is how often the
|
|
673
|
+
handler is *woken*, not how often the work should *happen*: a `15m` interval
|
|
674
|
+
wakes four times inside the owner's noon, so the handler names the unit of work —
|
|
675
|
+
here the local day — and keeps the key of the last unit it finished in a state
|
|
676
|
+
document it reads by id, plus a copy in module scope. A missing or failed state
|
|
677
|
+
read means *"don't know — use the copy"*, never *"nothing has run yet"*; that
|
|
678
|
+
second reading is what bills the owner four times for one noon.
|
|
679
|
+
|
|
680
|
+
### Firing on a real-world event
|
|
681
|
+
|
|
682
|
+
**An averaged cycle is not a calendar.** When the moment comes from nature
|
|
683
|
+
rather than from a clock the owner set — a moon phase, a tide, sunrise, a
|
|
684
|
+
planetary conjunction — the tempting shape is a mean period since a known epoch:
|
|
685
|
+
|
|
686
|
+
```js
|
|
687
|
+
const SYNODIC = 29.530588861; // mean lunation, in days
|
|
688
|
+
const t = KNOWN_NEW_MOON + k * SYNODIC * 86400000; // ← wrong by hours
|
|
689
|
+
```
|
|
690
|
+
|
|
691
|
+
The average is exact and the individual events are not. Orbits are elliptical
|
|
692
|
+
and perturbed, so real events run early or late against their own mean. Measured
|
|
693
|
+
for the lunar case: that formula is **up to 18 hours out**, and across the next
|
|
694
|
+
six months it puts two of six new moons on the **wrong calendar day**. It also
|
|
695
|
+
fails asymmetrically — full moons land within a couple of hours while new moons
|
|
696
|
+
run ~15 hours late — so testing one and shipping both proves nothing.
|
|
697
|
+
|
|
698
|
+
An app that merely *displays* a countdown can live with this if it says
|
|
699
|
+
"approximately". An app that **notifies** cannot: a notification is a claim that
|
|
700
|
+
the thing is happening now, and firing a ±20-minute window around a mean instant
|
|
701
|
+
lands it precisely on a time that is precisely wrong.
|
|
702
|
+
|
|
703
|
+
So: derive the event from a real algorithm with periodic-correction terms (the
|
|
704
|
+
standard treatments are short — a dozen sine terms gets a lunar phase to within
|
|
705
|
+
minutes), or fetch it from an ephemeris and cache it. If you can do neither,
|
|
706
|
+
widen the claim rather than the window: give the day, say "around", and never
|
|
707
|
+
attach a time-of-day word to it.
|
|
708
|
+
|
|
709
|
+
The same rule holds anywhere a natural cycle has a tidy average — the average is
|
|
710
|
+
a description of the series, never a prediction of the next member of it.
|
|
711
|
+
|
|
712
|
+
**Claim the unit of work before you spend on it, not after.** Write the key
|
|
713
|
+
first, then do the expensive, externally visible part: an isolate that dies
|
|
714
|
+
between a finished draft and an unwritten claim comes back and buys the same day
|
|
715
|
+
again. Claiming first means a crashed run is skipped rather than retried, and for
|
|
716
|
+
work like a daily digest that is the better side of the trade — a missing day the
|
|
717
|
+
status doc names beats a double charge nobody notices.
|
|
718
|
+
|
|
719
|
+
Then say what happened. Write the run's outcome to a status doc the app reads,
|
|
720
|
+
and put the failure detail in `ctx.log("error", …)` for whoever inspects the
|
|
721
|
+
logs: **the owner's only view of an unattended app is what it renders, so a
|
|
722
|
+
finished run leaves a visible record of what it did.** A notification reports
|
|
723
|
+
the outcome the run actually had. Every doc a run writes — status included —
|
|
724
|
+
goes in the database the UI live-queries, or the record is invisible in exactly
|
|
725
|
+
the way this whole section is about. A timestamp written only when a run
|
|
726
|
+
genuinely produced something is a real state change and belongs in that doc —
|
|
727
|
+
unlike a per-tick `checkedAt`, which is the churn the zero-churn rule above is
|
|
728
|
+
about.
|
|
729
|
+
|
|
730
|
+
```js
|
|
731
|
+
export const config = { scheduled: { interval: "15m" } };
|
|
732
|
+
|
|
733
|
+
const SHOW_DB = "show"; // the one database App.jsx live-queries
|
|
734
|
+
|
|
735
|
+
// The isolate's copy of the last day this handler finished. Survives between
|
|
736
|
+
// ticks on a warm isolate, and is the fallback when the state read says nothing.
|
|
737
|
+
let lastFinishedDay;
|
|
738
|
+
|
|
739
|
+
export async function scheduled(event, ctx) {
|
|
740
|
+
const settings = await ctx.db.get("schedule", { db: SHOW_DB });
|
|
741
|
+
const zone = settings?.timeZone ?? "UTC"; // captured in the owner's browser
|
|
742
|
+
const at = new Date(event.scheduledTime);
|
|
743
|
+
|
|
744
|
+
const hourLocal = Number(
|
|
745
|
+
new Intl.DateTimeFormat("en-US", { timeZone: zone, hour: "2-digit", hourCycle: "h23" }).format(at)
|
|
746
|
+
);
|
|
747
|
+
if (hourLocal !== settings?.hour) return; // not their hour yet — nothing to do
|
|
748
|
+
|
|
749
|
+
// "2026-08-27" in the owner's own day, which is the unit of work here.
|
|
750
|
+
const dayKey = new Intl.DateTimeFormat("en-CA", {
|
|
751
|
+
timeZone: zone,
|
|
752
|
+
year: "numeric",
|
|
753
|
+
month: "2-digit",
|
|
754
|
+
day: "2-digit",
|
|
755
|
+
}).format(at);
|
|
756
|
+
const state = await ctx.db.get("run:state", { db: SHOW_DB });
|
|
757
|
+
const finished = state?.dayKey ?? lastFinishedDay; // absent read: trust the copy
|
|
758
|
+
if (finished === dayKey) return; // this day's draft is already written
|
|
759
|
+
|
|
760
|
+
const headlines = await readFeed(ctx); // [] when the fetch failed or the feed was empty
|
|
761
|
+
|
|
762
|
+
if (headlines.length === 0) {
|
|
763
|
+
ctx.log("error", "[digest] no headlines this tick", { at: event.scheduledTime });
|
|
764
|
+
await putIfChanged(
|
|
765
|
+
ctx,
|
|
766
|
+
{
|
|
767
|
+
_id: "run:status",
|
|
768
|
+
type: "runStatus",
|
|
769
|
+
state: "no-input",
|
|
770
|
+
message: "couldn't read the feed — no draft written this run",
|
|
771
|
+
},
|
|
772
|
+
SHOW_DB
|
|
773
|
+
);
|
|
774
|
+
return; // no model call, and no notification claiming a draft is ready
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// Claim the day BEFORE spending anything, so an isolate that dies mid-draft can
|
|
778
|
+
// never come back and buy the same day again.
|
|
779
|
+
lastFinishedDay = dayKey;
|
|
780
|
+
await ctx.db.put({ _id: "run:state", type: "runState", dayKey }, { db: SHOW_DB });
|
|
781
|
+
|
|
782
|
+
try {
|
|
783
|
+
const draft = await ctx.callAI(`Write six one-liners about: ${headlines.join("; ")}`);
|
|
784
|
+
await ctx.db.put({ _id: `draft:${dayKey}`, type: "draft", draft }, { db: SHOW_DB });
|
|
785
|
+
await ctx.db.put(
|
|
786
|
+
{
|
|
787
|
+
_id: "run:status",
|
|
788
|
+
type: "runStatus",
|
|
789
|
+
state: "fresh",
|
|
790
|
+
lastSuccessAt: event.scheduledTime,
|
|
791
|
+
message: "today's draft is ready",
|
|
792
|
+
},
|
|
793
|
+
{ db: SHOW_DB }
|
|
794
|
+
);
|
|
795
|
+
await ctx.notify({ toHandle: ctx.appInfo.ownerHandle, body: "Your six jokes are drafted and ready for the show." });
|
|
796
|
+
} catch (err) {
|
|
797
|
+
// The day stays claimed: the owner sees what went wrong and is not billed twice for it.
|
|
798
|
+
ctx.log("error", "[digest] draft failed after the day was claimed", { message: err.message });
|
|
799
|
+
await ctx.db.put(
|
|
800
|
+
{ _id: "run:status", type: "runStatus", state: "failed", message: "today's draft didn't finish" },
|
|
801
|
+
{ db: SHOW_DB }
|
|
802
|
+
);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
App.jsx reads the same database, and renders that status beside the drafts, so a
|
|
808
|
+
failed run and a good one never look alike:
|
|
809
|
+
|
|
810
|
+
```jsx
|
|
811
|
+
const { useLiveQuery } = useFireproof("show");
|
|
812
|
+
const { docs: statusDocs } = useLiveQuery("type", { key: "runStatus" });
|
|
813
|
+
const run = statusDocs.find((doc) => doc._id === "run:status");
|
|
814
|
+
// …
|
|
815
|
+
{
|
|
816
|
+
run?.state === "no-input" ? (
|
|
817
|
+
<p role="status">{run.message}</p>
|
|
818
|
+
) : (
|
|
819
|
+
<p role="status">Last draft written {run?.lastSuccessAt?.slice(0, 16)}</p>
|
|
820
|
+
);
|
|
821
|
+
}
|
|
822
|
+
```
|
|
823
|
+
|
|
559
824
|
## A complete example — activity feed + owner-only digest
|
|
560
825
|
|
|
561
826
|
Users write `note` docs from `App.jsx`. The backend does two jobs: `onChange`
|
package/llms/use-vibe.md
CHANGED
|
@@ -24,7 +24,7 @@ Never stamp author fields from `me` while the verdict is pending — `me` is nul
|
|
|
24
24
|
|
|
25
25
|
## The rule
|
|
26
26
|
|
|
27
|
-
Gate every write affordance on `can.*`. Hold it while `pending`, and write your own copy when denied. Never branch write permission on `viewer`, `access.hasRole()`/`access.hasChannel()`, or document fields — those drift from what `access.js` actually does. Rendering **other** users (authors, rosters) is `useViewer()`'s `<ViewerTag userHandle={...} />`, not `useVibe`. The current viewer's own pill and the "signed in as"
|
|
27
|
+
Gate every write affordance on `can.*`. Hold it while `pending`, and write your own copy when denied. Never branch write permission on `viewer`, `access.hasRole()`/`access.hasChannel()`, or document fields — those drift from what `access.js` actually does. Rendering **other** users (authors, rosters) is `useViewer()`'s `<ViewerTag userHandle={...} />`, not `useVibe`. The current viewer's own pill and the "signed in as" label are system chrome in the Vibes Switch (the logo) — don't build them into the app. Asking an anonymous visitor to sign in is a different thing and it IS yours: `useViewer().requestLogin()`, at the moment their work becomes worth keeping (see use-viewer docs). A resolved denial is one such moment — write the sign-in copy in your app's own words and wire it to that callable, never to a sentence about the logo. (The one exception is inline avatar self-edit: a guarded no-prop `{viewer && <ViewerTag />}` lets any signed-in member change their own photo in place — see use-viewer docs.)
|
|
28
28
|
|
|
29
29
|
```jsx
|
|
30
30
|
import { useVibe } from "use-vibes";
|
package/llms/use-viewer.md
CHANGED
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
`useViewer()` is a **read-only window** into viewer identity. The platform owns the rules — who's the owner, who has been granted read or write — and `useViewer()` lets your app see who's signed in and render identity. You cannot grant or revoke access from code; you can only reflect the runtime's verdict in your UI.
|
|
4
4
|
|
|
5
|
-
**The
|
|
5
|
+
**The current viewer's pill is system chrome — you don't build it.** The platform shows the current user inside the **Vibes Switch**, the panel that opens when you click the logo. So your app does **not** need a header pill for whoever is looking — don't render a no-prop `<ViewerTag />` just to show "who's signed in".
|
|
6
|
+
|
|
7
|
+
**The sign-in _ask_ is yours.** `requestLogin()` from `useViewer()` opens the platform sign-in UI from anywhere in your app, so you can word, place and time the ask yourself. Reach for it at the moment your app becomes worth keeping. The Switch is chrome outside your app's frame, and pointing at the logo is not a call to action — it is a scavenger hunt. See **Asking a visitor to sign in** below.
|
|
6
8
|
|
|
7
9
|
Use `useViewer()` to render **other** people's identity — comment authors, rosters, "added by" labels — with `<ViewerTag userHandle={...} />`, and to read `viewer`/`can` when your UI needs to branch on who's looking. **Write surfaces are gated with `useVibe(dbName).can`** (see use-vibe docs), not with `viewer`/`access.*`.
|
|
8
10
|
|
|
9
11
|
## Basic Usage
|
|
10
12
|
|
|
11
|
-
Start with a minimal component that reads the viewer identity. You don't render a
|
|
13
|
+
Start with a minimal component that reads the viewer identity. You don't render a current-user pill — that lives in the Vibes Switch (click the logo). Branch on `viewer` for any welcome/empty copy. Note there is **no sign-in button here**: the ask belongs at the moment the visitor has made something worth keeping, not on arrival — see **Asking a visitor to sign in** below.
|
|
12
14
|
|
|
13
15
|
App.jsx
|
|
14
16
|
|
|
@@ -24,9 +26,12 @@ export default function App() {
|
|
|
24
26
|
|
|
25
27
|
return (
|
|
26
28
|
<div>
|
|
27
|
-
{/* No
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
{/* No current-user pill here — that's the Vibes Switch's job. */}
|
|
30
|
+
{viewer ? (
|
|
31
|
+
<p>Welcome back, {viewer.displayName ?? viewer.userHandle}!</p>
|
|
32
|
+
) : (
|
|
33
|
+
<p>Everything you make here is saved on this device.</p>
|
|
34
|
+
)}
|
|
30
35
|
</div>
|
|
31
36
|
);
|
|
32
37
|
}
|
|
@@ -37,7 +42,8 @@ export default function App() {
|
|
|
37
42
|
- `viewer` — `{ userHandle, displayName? }` or `null` for anonymous visitors. Avatars are not on the payload — render them with `<ViewerTag userHandle={...} />`, which resolves the avatar from the handle. Don't build avatar URLs yourself.
|
|
38
43
|
- `isViewerPending` — `true` while the platform is still resolving the viewer identity (e.g. on first render before the parent shell has pushed the identity update). **Gate any auth-dependent UI on `!isViewerPending`** to avoid flashing the wrong state. Once it becomes `false`, `viewer` is either populated or definitively `null`.
|
|
39
44
|
- `can(action)` — membership boolean for `"read"`/`"write"`/`"delete"`: is the viewer through the door? Access functions enforce per-document and per-database rules server-side. Prefer `useVibe(dbName).can.create/edit/delete` for write gating; it runs the app's access function and returns a `reason`.
|
|
40
|
-
- `viewerLapsed` — `true` when `viewer` is the identity this device *remembers* and the platform's answer came back anonymous: the sign-in lapsed (an expired session, a cold boot before auth restores), rather than the person signing out. Keep rendering their stuff — the local data is still theirs, and writes queue locally and sync once they sign back in — and offer a quiet "Sign back in to sync" nudge
|
|
45
|
+
- `viewerLapsed` — `true` when `viewer` is the identity this device *remembers* and the platform's answer came back anonymous: the sign-in lapsed (an expired session, a cold boot before auth restores), rather than the person signing out. Keep rendering their stuff — the local data is still theirs, and writes queue locally and sync once they sign back in — and offer a quiet "Sign back in to sync" nudge wired to `requestLogin()`. Never fall back to the anonymous copy ("Sign in to get started") while `viewerLapsed` is true; that reads as if their work is gone. `can()` and every access gate stay closed while lapsed, so gate *writes* on `can`, not on this flag, and `isViewerPending` is `false` (lapsed is a settled state, not a loading one).
|
|
46
|
+
- `requestLogin()` — opens the platform sign-in UI. Fire-and-forget: there is nothing to await and no result to branch on, because the new identity arrives on its own through `viewer`. This is how your app asks — see **Asking a visitor to sign in** below.
|
|
41
47
|
- `ViewerTag` — ready-made user pill; see the ViewerTag section below.
|
|
42
48
|
- `HandleInput` — ready-made handle-lookup text input; see the HandleInput section below.
|
|
43
49
|
|
|
@@ -70,7 +76,11 @@ App.jsx
|
|
|
70
76
|
|
|
71
77
|
```jsx
|
|
72
78
|
<<<<<<< SEARCH
|
|
73
|
-
{viewer ?
|
|
79
|
+
{viewer ? (
|
|
80
|
+
<p>Welcome back, {viewer.displayName ?? viewer.userHandle}!</p>
|
|
81
|
+
) : (
|
|
82
|
+
<p>Everything you make here is saved on this device.</p>
|
|
83
|
+
)}
|
|
74
84
|
=======
|
|
75
85
|
{/* write gate: useVibe().can, not viewer */}
|
|
76
86
|
{!ready ? null : (() => {
|
|
@@ -100,7 +110,6 @@ App.jsx
|
|
|
100
110
|
import { useViewer, useVibe } from "use-vibes";
|
|
101
111
|
=======
|
|
102
112
|
import { useViewer, useVibe } from "use-vibes";
|
|
103
|
-
import { useFireproof } from "use-fireproof";
|
|
104
113
|
>>>>>>> REPLACE
|
|
105
114
|
```
|
|
106
115
|
|
|
@@ -183,6 +192,75 @@ Key points:
|
|
|
183
192
|
- **Avatars are stable** — ViewerTag resolves the avatar from the handle; if the author changes their avatar, the URL stays the same and the bytes update. ViewerTag handles this for you.
|
|
184
193
|
- **One source of identity** — persist `authorHandle` on the doc. ViewerTag does the rest.
|
|
185
194
|
|
|
195
|
+
## Asking a visitor to sign in
|
|
196
|
+
|
|
197
|
+
An anonymous visitor is having a legitimately good time. Under local-first their work is already saved on their device and your app should keep working for them — the account buys **sync, followers and durability**, not permission. So the ask is an **offer to keep what they already have — never a wall in front of it**. A visitor who never signs in should still get a working app; one who does should feel like they kept something.
|
|
198
|
+
|
|
199
|
+
Three rules separate a CTA that converts from the two shapes that don't.
|
|
200
|
+
|
|
201
|
+
**Ask at the moment of value.** The ask lands when the person has just made something they'd hate to lose — posted their first comment, starred their first pick, saved their first note. A prompt on arrival asks a stranger to commit before they know what the app does; a prompt after the first save offers to keep something they can already see.
|
|
202
|
+
|
|
203
|
+
**Wire the ask to `requestLogin()`, never to a sentence about the logo.** Copy like "sign in via the logo" points at platform chrome outside your app's frame and sends the reader hunting for it. It is not a call to action and it does not convert. Render a real control: `<button onClick={requestLogin}>Keep these</button>`.
|
|
204
|
+
|
|
205
|
+
**Only ask once identity has settled.** `isViewerPending` is `true` while the platform is still resolving who's looking, and a CTA rendered in that window shows signed-in people a SIGN IN button on every load. Compute the settled-signed-out state once and gate on it — `const settledSignedOut = !isViewerPending && !viewer;`.
|
|
206
|
+
|
|
207
|
+
Layer it onto the comment app: the visitor can already read and post, and once they've posted, we offer to keep it.
|
|
208
|
+
|
|
209
|
+
```jsx
|
|
210
|
+
<<<<<<< SEARCH
|
|
211
|
+
const { viewer, isViewerPending, ViewerTag } = useViewer();
|
|
212
|
+
=======
|
|
213
|
+
const { viewer, isViewerPending, ViewerTag, requestLogin } = useViewer();
|
|
214
|
+
>>>>>>> REPLACE
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
```jsx
|
|
218
|
+
<<<<<<< SEARCH
|
|
219
|
+
const [body, setBody] = React.useState("");
|
|
220
|
+
=======
|
|
221
|
+
const [body, setBody] = React.useState("");
|
|
222
|
+
|
|
223
|
+
// Settled AND anonymous — never merely anonymous, or signed-in viewers flash
|
|
224
|
+
// this on every load while their identity is still resolving (#3639).
|
|
225
|
+
const settledSignedOut = !isViewerPending && !viewer;
|
|
226
|
+
// The moment of value: a comment THIS visitor wrote. An anonymous write
|
|
227
|
+
// stamps `authorHandle: me?.userHandle` with `me` still null, so an undefined
|
|
228
|
+
// author is our own unclaimed work — which is exactly what signing in keeps.
|
|
229
|
+
// Reading `comments.length` instead would nag people who only ever read.
|
|
230
|
+
const hasSomethingToKeep = comments.some((c) => c.authorHandle === undefined);
|
|
231
|
+
>>>>>>> REPLACE
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
```jsx
|
|
235
|
+
<<<<<<< SEARCH
|
|
236
|
+
{/* write gate: useVibe().can, not viewer */}
|
|
237
|
+
=======
|
|
238
|
+
{settledSignedOut && hasSomethingToKeep && (
|
|
239
|
+
<div>
|
|
240
|
+
{/* Says what they GET. Never "you must sign in to continue" — they
|
|
241
|
+
can continue, and their comment above is already saved locally.
|
|
242
|
+
And never "post it under your name": signing in syncs the comment
|
|
243
|
+
they already wrote, it does not rewrite the author stamped on it.
|
|
244
|
+
Promise continuity, which is true — not attribution, which isn't. */}
|
|
245
|
+
<p>Your comment is saved on this device.</p>
|
|
246
|
+
<button onClick={requestLogin}>Sign in to keep it on all your devices</button>
|
|
247
|
+
</div>
|
|
248
|
+
)}
|
|
249
|
+
|
|
250
|
+
{/* write gate: useVibe().can, not viewer */}
|
|
251
|
+
>>>>>>> REPLACE
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Copy that works, and copy that doesn't:
|
|
255
|
+
|
|
256
|
+
| Write this | Not this |
|
|
257
|
+
| --- | --- |
|
|
258
|
+
| "Sign in to sync your picks everywhere" | "Sign in to continue" |
|
|
259
|
+
| "Keep these on all your devices" | "You must sign in to save" |
|
|
260
|
+
| "Saved on this device — sign in to sync" | "Sign in via the Vibes DIY logo" |
|
|
261
|
+
|
|
262
|
+
And never disable the app's real controls on `!viewer`. If favoriting works signed out, keep it working signed out — the access function refuses the *cloud* write on its own, calmly, while the local write still succeeds. Turning a working app into a signup wall is worse than never asking at all.
|
|
263
|
+
|
|
186
264
|
## Notes
|
|
187
265
|
|
|
188
266
|
- Never use Clerk user IDs. Only `userHandle` crosses into vibe code.
|
|
@@ -200,17 +278,17 @@ Key points:
|
|
|
200
278
|
<ViewerTag userHandle={member.userHandle} style={{ borderRadius: 8, fontSize: 12 }} />
|
|
201
279
|
```
|
|
202
280
|
|
|
203
|
-
**The current viewer's
|
|
281
|
+
**The current viewer's pill is system chrome, not app UI.** The platform already shows the current user inside the Vibes Switch that opens from the logo, so don't add a no-prop `<ViewerTag />` as a header pill just to show who's signed in; reach for `userHandle` to render someone else instead. To *ask* an anonymous visitor to sign in, use `requestLogin()` and your own copy (see **Asking a visitor to sign in**) — that ask belongs at the moment of value, which is a place only your app knows.
|
|
204
282
|
|
|
205
283
|
**The one in-app reason to render a no-prop `<ViewerTag />` is inline avatar self-edit.** A no-prop tag shows the signed-in viewer a dashed edit ring that lets them change their _own_ avatar in place, and that works for **every** signed-in viewer — the Switch's avatar editing is owner-only. So if your app wants any member (not just the owner) to update their photo without leaving the app, render a guarded `{viewer && <ViewerTag />}` for that — otherwise leave the current-viewer pill to the Switch.
|
|
206
284
|
|
|
207
285
|
**Undefined safety.** If `userHandle` is present in props but falsy (e.g. a missing field from a loop lookup), `ViewerTag` renders a dim italic placeholder instead of the edit ring. This prevents a broken data source from accidentally granting photo-edit access to an arbitrary pill.
|
|
208
286
|
|
|
209
|
-
**Anonymous & always-safe.** `ViewerTag` never throws regardless of login state. A no-prop `<ViewerTag />`
|
|
287
|
+
**Anonymous & always-safe.** `ViewerTag` never throws regardless of login state. A no-prop `<ViewerTag />` renders a "Sign in" button for anonymous viewers — a fine fallback, but it is an identity chip in whatever spot you put it, not a CTA you can word or time. When the goal is conversion, write the prompt yourself and wire it to `requestLogin()`.
|
|
210
288
|
|
|
211
289
|
**Theming.** `ViewerTag` reads the canonical palette variables — `--surface`, `--text-primary`, `--border`, and `--accent` (plus optional `--accent-text` to override the on-accent text color) — from the app's CSS with sensible fallbacks. If your app defines these on `:root` (which every generated theme does), `ViewerTag` inherits the theme automatically with no extra props. The one exception is the signed-out **Sign in** CTA, which deliberately stays the Vibes brand blue: it is a platform affordance matched to the Vibes Switch shown to the same visitor, so it is not theme-inherited.
|
|
212
290
|
|
|
213
|
-
Pass `<ViewerTag userHandle={...} />` to render other people.
|
|
291
|
+
Pass `<ViewerTag userHandle={...} />` to render other people. Reach for the no-prop `<ViewerTag />` when you specifically want inline avatar self-edit for any signed-in member; for the current-user pill the Switch already covers it, and for a sign-in ask use `requestLogin()`.
|
|
214
292
|
|
|
215
293
|
## HandleInput
|
|
216
294
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vibes.diy/prompts",
|
|
3
|
-
"version": "13.1.
|
|
3
|
+
"version": "13.1.13",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"description": "",
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"license": "Apache-2.0",
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@adviser/cement": "~0.5.34",
|
|
27
|
-
"@vibes.diy/call-ai-v2": "^13.1.
|
|
28
|
-
"@vibes.diy/identity": "^13.1.
|
|
29
|
-
"@vibes.diy/use-vibes-types": "^13.1.
|
|
27
|
+
"@vibes.diy/call-ai-v2": "^13.1.13",
|
|
28
|
+
"@vibes.diy/identity": "^13.1.13",
|
|
29
|
+
"@vibes.diy/use-vibes-types": "^13.1.13",
|
|
30
30
|
"arktype": "~2.2.3",
|
|
31
31
|
"json-schema-faker": "~0.6.3"
|
|
32
32
|
},
|
package/prompts.d.ts
CHANGED
|
@@ -59,7 +59,7 @@ export declare const preAllocSchema: {
|
|
|
59
59
|
};
|
|
60
60
|
readonly backend: {
|
|
61
61
|
readonly type: "object";
|
|
62
|
-
readonly description: 'Set
|
|
62
|
+
readonly description: 'Set whenever the request describes work the app does away from the screen: something on a schedule or a repeat ("every day at noon", "each morning", "check periodically", "poll"), something that keeps happening while nobody has the app open, an external feed to fetch, a webhook to receive, a notification to send, or a secret that stays on the server. A named time of day, a repeat, or an actor that is not the person looking at the screen sets this on its own, even when everything else about the app is ordinary client work — first gen builds the client half, and this is the offer that gets the owner the other half. It covers what the user actually asked for: a reminder or nudge they never mentioned is a feature you would be inventing, not a capability being deferred. Omit it when everything the user asked for happens while they are looking at the app. Deferred out of the first gen. Write `why` as a benefit phrase in the owner\'s own words, e.g. "Draft your jokes every day at noon, even when the app isn\'t open" or "Receive your webhook and keep rows up to date".';
|
|
63
63
|
readonly properties: {
|
|
64
64
|
readonly recommended: {
|
|
65
65
|
readonly type: "boolean";
|
|
@@ -98,12 +98,12 @@ export declare const preAllocParsed: import("arktype/internal/variants/object.ts
|
|
|
98
98
|
privacySensitive?: boolean | undefined;
|
|
99
99
|
deferred?: {
|
|
100
100
|
access?: {
|
|
101
|
-
needed
|
|
102
|
-
why
|
|
101
|
+
needed?: boolean | undefined;
|
|
102
|
+
why?: string | undefined;
|
|
103
103
|
} | undefined;
|
|
104
104
|
backend?: {
|
|
105
|
-
recommended
|
|
106
|
-
why
|
|
105
|
+
recommended?: boolean | undefined;
|
|
106
|
+
why?: string | undefined;
|
|
107
107
|
} | undefined;
|
|
108
108
|
} | undefined;
|
|
109
109
|
}, {}>;
|
package/prompts.js
CHANGED
|
@@ -8,6 +8,7 @@ export async function getDefaultSkills() {
|
|
|
8
8
|
return ["fireproof", "callai", "image-gen", "use-vibe"];
|
|
9
9
|
}
|
|
10
10
|
const PRE_ALLOC_PLATFORM_PARAGRAPH = "Platform capabilities: every app is a small web app that anyone can open in a browser. Its data is saved automatically in the cloud and stays in sync for everyone at once, so when one person adds or changes something, everyone else viewing the app sees it update right away. Apps can call on a built-in AI assistant that returns a structured result the app saves and displays — for example suggesting or filling in a value, rewriting or extending something someone wrote, or tagging and scoring content as it's added. Apps know who is signed in, so they can show people's names and avatars next to their contributions. Most apps treat every signed-in visitor as a first-class participant who adds and edits their own contributions while everyone reads what others made; and many are built around a shared thing a group joins and co-edits — a list, a trip, a team space, a board or canvas people can ask to join — where the people who've joined edit it together and a newcomer can request in. Whichever fits, editing controls are hidden automatically for people who aren't allowed to use them. When pictures are a natural part of the experience, an app can show a generated illustration instead of requiring an upload.";
|
|
11
|
+
const DEFERRED_TASK_LINE = "Then record under `deferred` what the user asked for that the first build will not include: work that happens away from the screen goes under `backend`, a sharing-readiness step goes under `access`, each with a `why` written as the chip the owner reads.";
|
|
11
12
|
export async function makePreAllocUserMessage(userPrompt, variety) {
|
|
12
13
|
const catalog = await getLlmCatalog();
|
|
13
14
|
const catalogText = catalog.map((l) => `- ${l.name}: ${l.description}`).join("\n");
|
|
@@ -19,8 +20,8 @@ export async function makePreAllocUserMessage(userPrompt, variety) {
|
|
|
19
20
|
PRE_ALLOC_PLATFORM_PARAGRAPH,
|
|
20
21
|
"",
|
|
21
22
|
varietyContext.length > 0
|
|
22
|
-
?
|
|
23
|
-
:
|
|
23
|
+
? `Pick skills from this catalog that fit the user's app request, propose 3 title/slug pairs for naming, propose a one-line icon subject, pick a theme that matches the app's mood, write a 3-sentence enriched-prompt preamble that shapes THIS specific app around our platform's capabilities, described in plain user-friendly language, and write one short texture note about what should dominate this app visually. ${DEFERRED_TASK_LINE}`
|
|
24
|
+
: `Pick skills from this catalog that fit the user's app request, propose 3 title/slug pairs for naming, propose a one-line icon subject, pick a theme that matches the app's mood, and write a 3-sentence enriched-prompt preamble that shapes THIS specific app around our platform's capabilities, described in plain user-friendly language. ${DEFERRED_TASK_LINE}`,
|
|
24
25
|
"",
|
|
25
26
|
"Skill catalog:",
|
|
26
27
|
catalogText,
|
|
@@ -79,7 +80,7 @@ export const preAllocSchema = {
|
|
|
79
80
|
},
|
|
80
81
|
backend: {
|
|
81
82
|
type: "object",
|
|
82
|
-
description: 'Set
|
|
83
|
+
description: 'Set whenever the request describes work the app does away from the screen: something on a schedule or a repeat ("every day at noon", "each morning", "check periodically", "poll"), something that keeps happening while nobody has the app open, an external feed to fetch, a webhook to receive, a notification to send, or a secret that stays on the server. A named time of day, a repeat, or an actor that is not the person looking at the screen sets this on its own, even when everything else about the app is ordinary client work — first gen builds the client half, and this is the offer that gets the owner the other half. It covers what the user actually asked for: a reminder or nudge they never mentioned is a feature you would be inventing, not a capability being deferred. Omit it when everything the user asked for happens while they are looking at the app. Deferred out of the first gen. Write `why` as a benefit phrase in the owner\'s own words, e.g. "Draft your jokes every day at noon, even when the app isn\'t open" or "Receive your webhook and keep rows up to date".',
|
|
83
84
|
properties: {
|
|
84
85
|
recommended: { type: "boolean" },
|
|
85
86
|
why: { type: "string" },
|
|
@@ -127,8 +128,8 @@ export const preAllocParsed = type({
|
|
|
127
128
|
"textureNote?": "string",
|
|
128
129
|
"privacySensitive?": "boolean",
|
|
129
130
|
"deferred?": {
|
|
130
|
-
"access?": { needed: "boolean", why: "string" },
|
|
131
|
-
"backend?": { recommended: "boolean", why: "string" },
|
|
131
|
+
"access?": { "needed?": "boolean", "why?": "string" },
|
|
132
|
+
"backend?": { "recommended?": "boolean", "why?": "string" },
|
|
132
133
|
},
|
|
133
134
|
});
|
|
134
135
|
export function generateImportStatements(llms) {
|
package/prompts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../jsr/prompts.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../jsr/prompts.ts"],"names":[],"mappings":"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"}
|
|
@@ -34,7 +34,7 @@ You are an AI assistant tasked with creating React components. You should create
|
|
|
34
34
|
- Database reads are not a network operation — never show a loading state or spinner for them. `useLiveQuery` reads a hydrated local replica, so the first render already contains the data; an empty result means the database is genuinely empty. Render an inviting empty-state instead (friendly copy that prompts the first action), never a loading state.
|
|
35
35
|
- Give instant feedback for Fireproof writes too, not just for callAI/fetch. A `database.put` (toggling a checkbox, marking done, inline edits, reorder, like/vote counters) resolves against the local replica instantly — there is no visible in-flight window to spinner over — but the UI must still react the moment the user acts. Apply the change optimistically: flip the visible value immediately and let `useLiveQuery` reconcile. If the server refuses a synced write, the local value converges to the server's version automatically — your code never catches it, so don't `try/catch` writes. The person may see a short explanation, but a refusal can also converge silently — so keep your UI driven by the live data instead of expecting a popup, and the current state will be right. Transport and offline failures are handled by the built-in queue, so don't hand-roll retry either. Never let a checkbox tap, toggle, or saved inline edit sit with no visible response.
|
|
36
36
|
- For file uploads use drag and drop and store using the `doc._files` API; for AI image generation use `<ImgGen prompt="..." />`
|
|
37
|
-
- Access control is decided by the runtime, not your code. Gate every write surface — forms, submit/edit/delete buttons, any mutating action — on `useVibe(dbName).can`. `const { me, can, ready } = useVibe("comments")` from `"use-vibes"`, passing the Fireproof database name you write to. Show the editor when `can.create(draft).ok` (or `can.edit(doc)` / `can.delete(doc)`); the verdict has three states — while it is `pending` (or `ready` is false) hold the surface in a quiet checking state, and on a resolved denial write the sign-in or join copy in your app's own words, letting `reason` inform the sentence you write. `can.*` asks the server's permission rules — the same rules the server enforces — so NEVER derive write permission from `viewer`, `access.hasRole()`/`access.hasChannel()`, or document fields. `useViewer()` is identity/display only: `const { ViewerTag } = useViewer()` renders **other** people (`<ViewerTag userHandle={...} />` for comment authors, rosters, "added by" labels). The current viewer's own pill
|
|
37
|
+
- Access control is decided by the runtime, not your code. Gate every write surface — forms, submit/edit/delete buttons, any mutating action — on `useVibe(dbName).can`. `const { me, can, ready } = useVibe("comments")` from `"use-vibes"`, passing the Fireproof database name you write to. Show the editor when `can.create(draft).ok` (or `can.edit(doc)` / `can.delete(doc)`); the verdict has three states — while it is `pending` (or `ready` is false) hold the surface in a quiet checking state, and on a resolved denial write the sign-in or join copy in your app's own words, letting `reason` inform the sentence you write. `can.*` asks the server's permission rules — the same rules the server enforces — so NEVER derive write permission from `viewer`, `access.hasRole()`/`access.hasChannel()`, or document fields. `useViewer()` is identity/display only: `const { ViewerTag } = useViewer()` renders **other** people (`<ViewerTag userHandle={...} />` for comment authors, rosters, "added by" labels). The current viewer's own pill is system chrome in the Vibes Switch (the panel the logo opens) — don't add a header pill for the current user. But ASKING an anonymous visitor to sign in is the app's job: call `useViewer().requestLogin()` from your own button, gated on `!isViewerPending`, at the moment the visitor has made something worth keeping — never a sentence telling them to find the logo, and never a wall in front of an app that already works for them. Owner-only management UI is gated on `can.*` too (the runtime knows the owner). This applies to every app — the runtime decides sharing, not the prompt. Writes can still be rejected server-side even when `can.*` allows, so keep the optimistic-write + rollback handling. See use-vibe docs.
|
|
38
38
|
- Don't try to generate png or base64 data, use placeholder image APIs instead, like https://picsum.photos/400 where 400 is the square size
|
|
39
39
|
- Never use emojis in the UI. Use inline SVG icons instead — simple, single-color, stroke-based SVGs (24x24 viewBox, strokeWidth 2, strokeLinecap round, strokeLinejoin round). Build icons directly in JSX, do not import icon libraries.
|
|
40
40
|
- List data items on the main page of your app so users don't have to hunt for them
|
package/system-prompt-initial.md
CHANGED
|
@@ -34,7 +34,7 @@ You are an AI assistant tasked with creating React components. You should create
|
|
|
34
34
|
- Database reads are not a network operation — never show a loading state or spinner for them. `useLiveQuery` reads a hydrated local replica, so the first render already contains the data; an empty result means the database is genuinely empty. Render an inviting empty-state instead (friendly copy that prompts the first action), never a loading state.
|
|
35
35
|
- Give instant feedback for Fireproof writes too, not just for callAI/fetch. A `database.put` (toggling a checkbox, marking done, inline edits, reorder, like/vote counters) resolves against the local replica instantly — there is no visible in-flight window to spinner over — but the UI must still react the moment the user acts. Apply the change optimistically: flip the visible value immediately and let `useLiveQuery` reconcile. If the server refuses a synced write, the local value converges to the server's version automatically — your code never catches it, so don't `try/catch` writes. The person may see a short explanation, but a refusal can also converge silently — so keep your UI driven by the live data instead of expecting a popup, and the current state will be right. Transport and offline failures are handled by the built-in queue, so don't hand-roll retry either. Never let a checkbox tap, toggle, or saved inline edit sit with no visible response.
|
|
36
36
|
- For file uploads use drag and drop and store using the `doc._files` API; for AI image generation use `<ImgGen prompt="..." />`
|
|
37
|
-
- Access control is decided by the runtime, not your code. Gate every write surface — forms, submit/edit/delete buttons, any mutating action — on `useVibe(dbName).can`. `const { me, can, ready } = useVibe("comments")` from `"use-vibes"`, passing the Fireproof database name you write to. Show the editor when `can.create(draft).ok` (or `can.edit(doc)` / `can.delete(doc)`); the verdict has three states — while it is `pending` (or `ready` is false) hold the surface in a quiet checking state, and on a resolved denial write the sign-in or join copy in your app's own words, letting `reason` inform the sentence you write. `can.*` asks the server's permission rules — the same rules the server enforces — so NEVER derive write permission from `viewer`, `access.hasRole()`/`access.hasChannel()`, or document fields. `useViewer()` is identity/display only: `const { ViewerTag } = useViewer()` renders **other** people (`<ViewerTag userHandle={...} />` for comment authors, rosters, "added by" labels). The current viewer's own pill
|
|
37
|
+
- Access control is decided by the runtime, not your code. Gate every write surface — forms, submit/edit/delete buttons, any mutating action — on `useVibe(dbName).can`. `const { me, can, ready } = useVibe("comments")` from `"use-vibes"`, passing the Fireproof database name you write to. Show the editor when `can.create(draft).ok` (or `can.edit(doc)` / `can.delete(doc)`); the verdict has three states — while it is `pending` (or `ready` is false) hold the surface in a quiet checking state, and on a resolved denial write the sign-in or join copy in your app's own words, letting `reason` inform the sentence you write. `can.*` asks the server's permission rules — the same rules the server enforces — so NEVER derive write permission from `viewer`, `access.hasRole()`/`access.hasChannel()`, or document fields. `useViewer()` is identity/display only: `const { ViewerTag } = useViewer()` renders **other** people (`<ViewerTag userHandle={...} />` for comment authors, rosters, "added by" labels). The current viewer's own pill is system chrome in the Vibes Switch (the panel the logo opens) — don't add a header pill for the current user. But ASKING an anonymous visitor to sign in is the app's job: call `useViewer().requestLogin()` from your own button, gated on `!isViewerPending`, at the moment the visitor has made something worth keeping — never a sentence telling them to find the logo, and never a wall in front of an app that already works for them. Owner-only management UI is gated on `can.*` too (the runtime knows the owner). This applies to every app — the runtime decides sharing, not the prompt. Writes can still be rejected server-side even when `can.*` allows, so keep the optimistic-write + rollback handling. See use-vibe docs.
|
|
38
38
|
- Don't try to generate png or base64 data, use placeholder image APIs instead, like https://picsum.photos/400 where 400 is the square size
|
|
39
39
|
- Never use emojis in the UI. Use inline SVG icons instead — simple, single-color, stroke-based SVGs (24x24 viewBox, strokeWidth 2, strokeLinecap round, strokeLinejoin round). Build icons directly in JSX, do not import icon libraries.
|
|
40
40
|
- List data items on the main page of your app so users don't have to hunt for them
|
package/system-prompt.md
CHANGED
|
@@ -34,7 +34,7 @@ You are an AI assistant tasked with creating React components. You should create
|
|
|
34
34
|
- Database reads are not a network operation — never show a loading state or spinner for them. `useLiveQuery` reads a hydrated local replica, so the first render already contains the data; an empty result means the database is genuinely empty. Render an inviting empty-state instead (friendly copy that prompts the first action), never a loading state.
|
|
35
35
|
- Give instant feedback for Fireproof writes too, not just for callAI/fetch. A `database.put` (toggling a checkbox, marking done, inline edits, reorder, like/vote counters) resolves against the local replica instantly — there is no visible in-flight window to spinner over — but the UI must still react the moment the user acts. Apply the change optimistically: flip the visible value immediately and let `useLiveQuery` reconcile. If a synced write is refused, the local optimistic revision converges to the server's version automatically — server-wins, and your code never catches it, so don't `try/catch` writes or hand-roll retry UI. Keep your UI reactive to the store (`useLiveQuery`/`useDocument`) so the converged state shows the truth. When `access.js` provides a reason (`forbidden("…")`) the platform surfaces it to the person; a reason-less refusal converges silently, so don't strip your own UI expecting a popup — gate write surfaces up front with `useVibe(dbName).can`. Transport and offline failures are handled by the built-in queue, so don't hand-roll retry either. Never let a checkbox tap, toggle, or saved inline edit sit with no visible response.
|
|
36
36
|
- For file uploads use drag and drop and store using the `doc._files` API; for AI image generation use `<ImgGen prompt="..." />`
|
|
37
|
-
- Access control is decided by the runtime, not your code. Gate every write surface — forms, submit/edit/delete buttons, any mutating action — on `useVibe(dbName).can`. `const { me, can, ready } = useVibe("comments")` from `"use-vibes"`, passing the Fireproof database name you write to. Show the editor when `can.create(draft).ok` (or `can.edit(doc)` / `can.delete(doc)`); the verdict has three states — while it is `pending` (or `ready` is false) hold the surface in a quiet checking state, and on a resolved denial write the sign-in or join copy in your app's own words, letting `reason` inform the sentence you write. `can.*` runs the app's own `access.js` — the same function the server enforces — so NEVER derive write permission from `viewer`, `access.hasRole()`/`access.hasChannel()`, or document fields. `useViewer()` is identity/display only: `const { ViewerTag } = useViewer()` renders **other** people (`<ViewerTag userHandle={...} />` for comment authors, rosters, "added by" labels). The current viewer's own pill
|
|
37
|
+
- Access control is decided by the runtime, not your code. Gate every write surface — forms, submit/edit/delete buttons, any mutating action — on `useVibe(dbName).can`. `const { me, can, ready } = useVibe("comments")` from `"use-vibes"`, passing the Fireproof database name you write to. Show the editor when `can.create(draft).ok` (or `can.edit(doc)` / `can.delete(doc)`); the verdict has three states — while it is `pending` (or `ready` is false) hold the surface in a quiet checking state, and on a resolved denial write the sign-in or join copy in your app's own words, letting `reason` inform the sentence you write. `can.*` runs the app's own `access.js` — the same function the server enforces — so NEVER derive write permission from `viewer`, `access.hasRole()`/`access.hasChannel()`, or document fields. `useViewer()` is identity/display only: `const { ViewerTag } = useViewer()` renders **other** people (`<ViewerTag userHandle={...} />` for comment authors, rosters, "added by" labels). The current viewer's own pill is system chrome in the Vibes Switch (the panel the logo opens) — don't add a header pill for the current user. But ASKING an anonymous visitor to sign in is the app's job: call `useViewer().requestLogin()` from your own button, gated on `!isViewerPending`, at the moment the visitor has made something worth keeping — never a sentence telling them to find the logo, and never a wall in front of an app that already works for them. Owner-only management UI is gated on `can.*` too (the access.js encodes the owner rule). This applies to every app — the runtime decides sharing, not the prompt. Writes can still be rejected server-side even when `can.*` allows, so keep the optimistic-write + rollback handling. See use-vibe docs.
|
|
38
38
|
- Don't try to generate png or base64 data, use placeholder image APIs instead, like https://picsum.photos/400 where 400 is the square size
|
|
39
39
|
- Never use emojis in the UI. Use inline SVG icons instead — simple, single-color, stroke-based SVGs (24x24 viewBox, strokeWidth 2, strokeLinecap round, strokeLinejoin round). Build icons directly in JSX, do not import icon libraries.
|
|
40
40
|
- Consider and potentially reuse/extend code from previous responses if relevant
|