@vibes.diy/prompts 14.3.79 → 14.3.81

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.
Files changed (42) hide show
  1. package/llms/access.md +120 -85
  2. package/llms/backend.js +2 -2
  3. package/llms/backend.js.map +1 -1
  4. package/llms/backend.md +51 -43
  5. package/llms/bluesky.md +16 -14
  6. package/llms/board-games.d.ts +2 -0
  7. package/llms/board-games.js +29 -0
  8. package/llms/board-games.js.map +1 -0
  9. package/llms/board-games.md +477 -0
  10. package/llms/calendar.js +19 -2
  11. package/llms/calendar.js.map +1 -1
  12. package/llms/calendar.md +119 -1
  13. package/llms/callai.md +91 -20
  14. package/llms/connections.md +5 -4
  15. package/llms/create-vibe.md +5 -4
  16. package/llms/fireproof.md +261 -109
  17. package/llms/image-gen.md +44 -27
  18. package/llms/index.d.ts +2 -1
  19. package/llms/index.js +3 -0
  20. package/llms/index.js.map +1 -1
  21. package/llms/p5.md +9 -11
  22. package/llms/spotify.md +5 -2
  23. package/llms/three-js.md +163 -166
  24. package/llms/use-vibe.md +30 -8
  25. package/llms/use-viewer.md +61 -45
  26. package/llms/voxel.md +32 -37
  27. package/llms/youtube.md +5 -2
  28. package/package.json +4 -4
  29. package/prompts.d.ts +4 -2
  30. package/prompts.js +47 -24
  31. package/prompts.js.map +1 -1
  32. package/system-prompt-initial-oneshot.md +15 -12
  33. package/system-prompt-initial.md +14 -11
  34. package/system-prompt.md +36 -54
  35. package/themes/colorsets.js +18 -2
  36. package/themes/colorsets.js.map +1 -1
  37. package/themes/looks/pouf/brief.md +65 -47
  38. package/themes/looks/pouf/catalog.generated.d.ts +1 -1
  39. package/themes/looks/pouf/catalog.generated.js +103 -10
  40. package/themes/looks/pouf/catalog.generated.js.map +1 -1
  41. package/themes/looks/pouf/variety.js +2 -2
  42. package/themes/looks/pouf/variety.js.map +1 -1
package/llms/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export { backendConfig } from "./backend.js";
2
2
  export { calendarConfig } from "./calendar.js";
3
+ export { boardGamesConfig } from "./board-games.js";
3
4
  export { callaiConfig } from "./callai.js";
4
5
  export { fireproofConfig } from "./fireproof.js";
5
6
  export { imageGenConfig } from "./image-gen.js";
@@ -46,5 +47,5 @@ export { poufLandingConfig } from "./pouf-landing.js";
46
47
  export { poufCalendarConfig } from "./pouf-calendar.js";
47
48
  export { poufTestimonialsConfig } from "./pouf-testimonials.js";
48
49
  export type { LlmConfig } from "./types.js";
49
- export declare const allConfigs: readonly [import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig];
50
+ export declare const allConfigs: readonly [import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig, import("./types.js").LlmConfig];
50
51
  export declare const FAST_SKILLS: readonly ["callai", "image-gen", "fireproof", "three-js", "d3", "webxr", "calendar", "spotify"];
package/llms/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { backendConfig } from "./backend.js";
2
2
  import { calendarConfig } from "./calendar.js";
3
+ import { boardGamesConfig } from "./board-games.js";
3
4
  import { callaiConfig } from "./callai.js";
4
5
  import { fireproofConfig } from "./fireproof.js";
5
6
  import { imageGenConfig } from "./image-gen.js";
@@ -47,6 +48,7 @@ import { poufCalendarConfig } from "./pouf-calendar.js";
47
48
  import { poufTestimonialsConfig } from "./pouf-testimonials.js";
48
49
  export { backendConfig } from "./backend.js";
49
50
  export { calendarConfig } from "./calendar.js";
51
+ export { boardGamesConfig } from "./board-games.js";
50
52
  export { callaiConfig } from "./callai.js";
51
53
  export { fireproofConfig } from "./fireproof.js";
52
54
  export { imageGenConfig } from "./image-gen.js";
@@ -107,6 +109,7 @@ export const allConfigs = [
107
109
  createVibeConfig,
108
110
  backendConfig,
109
111
  calendarConfig,
112
+ boardGamesConfig,
110
113
  accessConfig,
111
114
  connectionsConfig,
112
115
  youtubeConfig,
package/llms/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../jsr/llms/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../jsr/llms/index.ts"],"names":[],"mappings":"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"}
package/llms/p5.md CHANGED
@@ -24,7 +24,7 @@ the instance so remounts do not leak a second draw loop.
24
24
  ```jsx
25
25
  import React from "react";
26
26
  import p5 from "https://esm.sh/p5@1.11.13";
27
- import { Button } from "@vibes.diy/look";
27
+ import { Button, Row, Stack } from "@vibes.diy/pouf";
28
28
 
29
29
  const TAU = Math.PI * 2;
30
30
 
@@ -191,16 +191,14 @@ export default function App() {
191
191
 
192
192
  return (
193
193
  <div className="min-h-screen bg-background text-foreground font-sans p-6">
194
- <div
195
- ref={hostRef}
196
- className="w-full h-[70vh] overflow-hidden rounded-lg border border-border shadow-md touch-none"
197
- />
198
- <Button
199
- className="mt-3"
200
- onClick={() => setParams((prev) => ({ ...prev, seed: Math.floor(Math.random() * 100000) }))}
201
- >
202
- Reseed
203
- </Button>
194
+ <Stack gap={3}>
195
+ <div ref={hostRef} className="w-full aspect-video overflow-hidden rounded-lg border border-border shadow-md touch-none" />
196
+ <Row>
197
+ <Button type="button" onClick={() => setParams((prev) => ({ ...prev, seed: Math.floor(Math.random() * 100000) }))}>
198
+ Reseed
199
+ </Button>
200
+ </Row>
201
+ </Stack>
204
202
  </div>
205
203
  );
206
204
  }
package/llms/spotify.md CHANGED
@@ -306,6 +306,7 @@ function artistRow(a) {
306
306
  ### `App.jsx`
307
307
  ```jsx app=spotify-browser
308
308
  import React, { useState } from "react";
309
+ import { Button, Field, Input, Row } from "@vibes.diy/pouf";
309
310
 
310
311
  const SETUP_STEPS = [
311
312
  "Open the Spotify developer dashboard and log in.",
@@ -333,8 +334,10 @@ export default function App() {
333
334
 
334
335
  return (
335
336
  <div>
336
- <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Search Spotify" />
337
- <button onClick={search}>Search</button>
337
+ <Row gap={2} align="top">
338
+ <Field label="Search">{(id, describedBy) => <Input id={id} describedBy={describedBy} value={query} onChange={setQuery} placeholder="Search Spotify" />}</Field>
339
+ <Button type="button" onClick={search}>Search</Button>
340
+ </Row>
338
341
 
339
342
  {problem?.reason === "missing-key" && (
340
343
  <section>
package/llms/three-js.md CHANGED
@@ -1213,7 +1213,7 @@ Structure your component in this order:
1213
1213
  import React, { useState, useEffect, useRef, useCallback } from "react";
1214
1214
  import { useFireproof } from "use-fireproof";
1215
1215
  import * as THREE from "three";
1216
- import { Card, CardContent, CardHeader, CardTitle } from "@vibes.diy/look";
1216
+ import { Card, Heading, Stack, Text } from "@vibes.diy/pouf";
1217
1217
 
1218
1218
  export default function SkyGlider() {
1219
1219
  const { database, useLiveQuery } = useFireproof("skyGliderScores");
@@ -1613,31 +1613,34 @@ export default function SkyGlider() {
1613
1613
  return (
1614
1614
  <div className="relative h-screen w-full bg-background text-foreground font-sans">
1615
1615
  <canvas ref={canvasRef} className="absolute inset-0" />
1616
- <Card className="absolute top-4 left-4">
1617
- <CardHeader>
1618
- <CardTitle>Sky Glider</CardTitle>
1619
- </CardHeader>
1620
- <CardContent>
1621
- <p>Score: {currentScore}</p>
1622
- <p className="mt-2 text-muted-foreground">WASD/Arrows: Fly, Space: Thrust</p>
1623
- </CardContent>
1624
- </Card>
1625
- {scoreData.length > 0 && (
1626
- <Card className="absolute top-4 right-4">
1627
- <CardHeader>
1628
- <CardTitle>High Scores</CardTitle>
1629
- </CardHeader>
1630
- <CardContent>
1631
- {scoreData
1632
- .sort((a, b) => b.value - a.value)
1633
- .slice(0, 3)
1634
- .map((score, i) => (
1635
- <div key={score._id}>
1636
- #{i + 1}: {score.value}
1637
- </div>
1638
- ))}
1639
- </CardContent>
1616
+ {/* A pouf Card takes no className: a plain wrapper carries its placement. */}
1617
+ <div className="absolute top-4 left-4">
1618
+ <Card>
1619
+ <Stack gap={2}>
1620
+ <Heading level={2}>Sky Glider</Heading>
1621
+ <Text num>Score: {currentScore}</Text>
1622
+ <Text size="sm" muted>
1623
+ WASD/Arrows: Fly, Space: Thrust
1624
+ </Text>
1625
+ </Stack>
1640
1626
  </Card>
1627
+ </div>
1628
+ {scoreData.length > 0 && (
1629
+ <div className="absolute top-4 right-4">
1630
+ <Card>
1631
+ <Stack gap={2}>
1632
+ <Heading level={2}>High Scores</Heading>
1633
+ {scoreData
1634
+ .sort((a, b) => b.value - a.value)
1635
+ .slice(0, 3)
1636
+ .map((score, i) => (
1637
+ <Text key={score._id} num>
1638
+ #{i + 1}: {score.value}
1639
+ </Text>
1640
+ ))}
1641
+ </Stack>
1642
+ </Card>
1643
+ </div>
1641
1644
  )}
1642
1645
  </div>
1643
1646
  );
@@ -1654,8 +1657,8 @@ import { OrbitControls } from "three/addons/controls/OrbitControls.js";
1654
1657
  import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";
1655
1658
  import { RenderPass } from "three/addons/postprocessing/RenderPass.js";
1656
1659
  import { HalftonePass } from "three/addons/postprocessing/HalftonePass.js";
1657
- import { Button, Card, CardContent, CardHeader, CardTitle, Input, Label, Separator } from "@vibes.diy/look";
1658
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@vibes.diy/look/overlay";
1660
+ import { Button, Card, Field, Heading, Input, RowCard, Stack, Text } from "@vibes.diy/pouf";
1661
+ import { Checkbox, Select, Separator, Slider } from "@vibes.diy/pouf/interactive";
1659
1662
 
1660
1663
  export default function HalftoneArtStudio() {
1661
1664
  const { database, useLiveQuery } = useFireproof("halftoneStudio");
@@ -2001,154 +2004,148 @@ export default function HalftoneArtStudio() {
2001
2004
  const shapeName = ["", "Dot", "Ellipse", "Line", "Square"][parameters.shape] || "Dot";
2002
2005
  const blendModeName = ["", "Linear", "Multiply", "Add", "Lighter", "Darker"][parameters.blendingMode] || "Linear";
2003
2006
  const actionNames = {
2004
- "before-randomize": "🎲 Before Random",
2005
- randomized: "✨ Randomized",
2006
- manual: "✏️ Manual Edit",
2007
+ "before-randomize": "Before Random",
2008
+ randomized: "Randomized",
2009
+ manual: "Manual Edit",
2007
2010
  };
2008
2011
 
2009
2012
  return (
2010
2013
  <div className="relative h-screen w-full overflow-hidden bg-background text-foreground font-sans">
2011
2014
  <canvas ref={canvasRef} className="absolute inset-0" />
2012
2015
 
2013
- {/* One control panel. The look's `Card` IS the panel — its `className`
2014
- carries placement only; the cushion, corner and ink are its own. */}
2015
- <Card className="absolute inset-y-4 left-4 w-80 overflow-y-auto">
2016
- <CardHeader>
2017
- <CardTitle>RGB Halftone Studio</CardTitle>
2018
- </CardHeader>
2019
- <CardContent>
2020
- <Button className="w-full" onClick={generateRandomScene} disabled={isGenerating}>
2021
- {isGenerating ? "Generating…" : "🎲 Random Art"}
2022
- </Button>
2023
- <Button variant="secondary" className="w-full" onClick={() => setShowParameters(!showParameters)}>
2024
- {showParameters ? "🔼 Hide Controls" : "🔽 Show Controls"}
2025
- </Button>
2026
-
2027
- {showParameters && (
2028
- <div className="space-y-4">
2029
- <Separator />
2030
-
2031
- {/* A chooser is `Select`, and its props do the styling. */}
2032
- <div className="space-y-2">
2033
- <Label htmlFor="shape">Shape: {shapeName}</Label>
2034
- <Select value={String(parameters.shape)} onValueChange={(value) => setParameters((prev) => ({ ...prev, shape: parseInt(value) }))}>
2035
- <SelectTrigger id="shape" className="w-full">
2036
- <SelectValue />
2037
- </SelectTrigger>
2038
- <SelectContent>
2039
- <SelectItem value="1">Dot</SelectItem>
2040
- <SelectItem value="2">Ellipse</SelectItem>
2041
- <SelectItem value="3">Line</SelectItem>
2042
- <SelectItem value="4">Square</SelectItem>
2043
- </SelectContent>
2044
- </Select>
2045
- </div>
2046
-
2047
- {/* A range slider and a checkbox are NOT in the package, so they
2048
- stay plain elements you style by hand. Blend amount and the
2049
- per-channel R/G/B rotations are this same Label + range pair,
2050
- one per uniform. */}
2051
- <div className="space-y-2">
2052
- <Label htmlFor="size">Size: {parameters.radius.toFixed(1)}</Label>
2053
- <input
2054
- id="size"
2055
- type="range"
2056
- min="1"
2057
- max="25"
2058
- step="0.5"
2059
- value={parameters.radius}
2060
- onChange={(e) => setParameters((prev) => ({ ...prev, radius: parseFloat(e.target.value) }))}
2061
- className="w-full"
2016
+ {/* One control panel. The pouf `Card` IS the panel — it takes no className,
2017
+ so a plain wrapper carries its placement; the cushion, corner and ink are its own. */}
2018
+ <div className="absolute inset-y-4 left-4 w-80 overflow-y-auto">
2019
+ <Card>
2020
+ <Stack gap={3}>
2021
+ <Heading level={2}>RGB Halftone Studio</Heading>
2022
+ <Button block loading={isGenerating} onClick={generateRandomScene}>
2023
+ {isGenerating ? "Generating…" : "Random Art"}
2024
+ </Button>
2025
+ <Button block variant="quiet" aria-expanded={showParameters} onClick={() => setShowParameters(!showParameters)}>
2026
+ {showParameters ? "Hide Controls" : "Show Controls"}
2027
+ </Button>
2028
+
2029
+ {showParameters && (
2030
+ <Stack gap={4}>
2031
+ <Separator />
2032
+
2033
+ {/* A chooser is `Select`; its options are data. */}
2034
+ <Field label={`Shape: ${shapeName}`}>
2035
+ {(id, describedBy) => (
2036
+ <Select
2037
+ id={id}
2038
+ describedBy={describedBy}
2039
+ value={String(parameters.shape)}
2040
+ onChange={(value) => setParameters((prev) => ({ ...prev, shape: parseInt(value) }))}
2041
+ options={[
2042
+ { value: "1", label: "Dot" },
2043
+ { value: "2", label: "Ellipse" },
2044
+ { value: "3", label: "Line" },
2045
+ { value: "4", label: "Square" },
2046
+ ]}
2047
+ />
2048
+ )}
2049
+ </Field>
2050
+
2051
+ {/* A range is `Slider`, which hands over an array of values. Blend amount
2052
+ and the per-channel R/G/B rotations are this same labelled Slider,
2053
+ one per uniform. */}
2054
+ <Stack gap={2}>
2055
+ <Text size="sm">Size: {parameters.radius.toFixed(1)}</Text>
2056
+ <Slider
2057
+ label="Size"
2058
+ min={1}
2059
+ max={25}
2060
+ step={0.5}
2061
+ value={[parameters.radius]}
2062
+ onChange={([radius]) => setParameters((prev) => ({ ...prev, radius }))}
2063
+ />
2064
+ </Stack>
2065
+
2066
+ <Stack gap={2}>
2067
+ <Text size="sm">Scatter: {(parameters.scatter * 100).toFixed(0)}%</Text>
2068
+ <Slider
2069
+ label="Scatter"
2070
+ min={0}
2071
+ max={1}
2072
+ step={0.01}
2073
+ value={[parameters.scatter]}
2074
+ onChange={([scatter]) => setParameters((prev) => ({ ...prev, scatter }))}
2075
+ />
2076
+ </Stack>
2077
+
2078
+ <Field label={`Blend Mode: ${blendModeName}`}>
2079
+ {(id, describedBy) => (
2080
+ <Select
2081
+ id={id}
2082
+ describedBy={describedBy}
2083
+ value={String(parameters.blendingMode)}
2084
+ onChange={(value) => setParameters((prev) => ({ ...prev, blendingMode: parseInt(value) }))}
2085
+ options={[
2086
+ { value: "1", label: "Linear" },
2087
+ { value: "2", label: "Multiply" },
2088
+ { value: "3", label: "Add" },
2089
+ { value: "4", label: "Lighter" },
2090
+ { value: "5", label: "Darker" },
2091
+ ]}
2092
+ />
2093
+ )}
2094
+ </Field>
2095
+
2096
+ <Checkbox
2097
+ label="Greyscale"
2098
+ checked={parameters.greyscale}
2099
+ onChange={(checked) => setParameters((prev) => ({ ...prev, greyscale: checked === true }))}
2062
2100
  />
2063
- </div>
2064
-
2065
- <div className="space-y-2">
2066
- <Label htmlFor="scatter">Scatter: {(parameters.scatter * 100).toFixed(0)}%</Label>
2067
- <input
2068
- id="scatter"
2069
- type="range"
2070
- min="0"
2071
- max="1"
2072
- step="0.01"
2073
- value={parameters.scatter}
2074
- onChange={(e) => setParameters((prev) => ({ ...prev, scatter: parseFloat(e.target.value) }))}
2075
- className="w-full"
2101
+ <Checkbox
2102
+ label="Disable Effect"
2103
+ checked={parameters.disable}
2104
+ onChange={(checked) => setParameters((prev) => ({ ...prev, disable: checked === true }))}
2076
2105
  />
2077
- </div>
2078
-
2079
- <div className="space-y-2">
2080
- <Label htmlFor="blend-mode">Blend Mode: {blendModeName}</Label>
2081
- <Select
2082
- value={String(parameters.blendingMode)}
2083
- onValueChange={(value) => setParameters((prev) => ({ ...prev, blendingMode: parseInt(value) }))}
2084
- >
2085
- <SelectTrigger id="blend-mode" className="w-full">
2086
- <SelectValue />
2087
- </SelectTrigger>
2088
- <SelectContent>
2089
- <SelectItem value="1">Linear</SelectItem>
2090
- <SelectItem value="2">Multiply</SelectItem>
2091
- <SelectItem value="3">Add</SelectItem>
2092
- <SelectItem value="4">Lighter</SelectItem>
2093
- <SelectItem value="5">Darker</SelectItem>
2094
- </SelectContent>
2095
- </Select>
2096
- </div>
2097
-
2098
- <div className="flex items-center gap-2">
2099
- <input id="greyscale" type="checkbox" checked={parameters.greyscale} onChange={(e) => setParameters((prev) => ({ ...prev, greyscale: e.target.checked }))} />
2100
- <Label htmlFor="greyscale">Greyscale</Label>
2101
- </div>
2102
- <div className="flex items-center gap-2">
2103
- <input id="disable" type="checkbox" checked={parameters.disable} onChange={(e) => setParameters((prev) => ({ ...prev, disable: e.target.checked }))} />
2104
- <Label htmlFor="disable">Disable Effect</Label>
2105
- </div>
2106
-
2107
- <div className="space-y-2">
2108
- <Label htmlFor="preset-name">Preset name</Label>
2109
- <Input id="preset-name" placeholder="Preset name…" value={presetName} onChange={(e) => setPresetName(e.target.value)} className="w-full" />
2110
- <Button variant="secondary" className="w-full" onClick={savePreset} disabled={!presetName.trim()}>
2111
- 💾 Save Preset
2106
+
2107
+ <Field label="Preset name">
2108
+ {(id, describedBy) => (
2109
+ <Input id={id} describedBy={describedBy} placeholder="Preset name…" value={presetName} onChange={setPresetName} />
2110
+ )}
2111
+ </Field>
2112
+ <Button block variant="quiet" onClick={savePreset} disabled={!presetName.trim()}>
2113
+ Save Preset
2112
2114
  </Button>
2113
- </div>
2114
-
2115
- {/* A row that selects something is a `Button`, and which one is
2116
- chosen is a `variant` — never a colour `className`. */}
2117
- {presets.length > 0 && (
2118
- <div className="space-y-2">
2119
- <h4 className="font-bold">💾 Saved Presets</h4>
2120
- {presets
2121
- .sort((a, b) => b.timestamp - a.timestamp)
2122
- .map((preset) => (
2123
- <Button
2124
- key={preset._id}
2125
- variant={currentPreset?._id === preset._id ? "default" : "secondary"}
2126
- className="w-full justify-start"
2127
- onClick={() => loadPreset(preset)}
2128
- >
2129
- {preset.name} · {["", "Dot", "Ellipse", "Line", "Square"][preset.parameters.shape]}
2130
- </Button>
2131
- ))}
2132
- </div>
2133
- )}
2134
-
2135
- {parameterHistory.length > 0 && (
2136
- <div className="space-y-2">
2137
- <h4 className="font-bold">📜 Parameter History</h4>
2138
- {parameterHistory
2139
- .sort((a, b) => b.timestamp - a.timestamp)
2140
- .slice(0, 10)
2141
- .map((state) => (
2142
- <Button key={state._id} variant="outline" className="w-full justify-start" onClick={() => loadParameterState(state)}>
2143
- {actionNames[state.action] || "⚙️ Unknown"} · {new Date(state.timestamp).toLocaleTimeString()}
2144
- </Button>
2145
- ))}
2146
- </div>
2147
- )}
2148
- </div>
2149
- )}
2150
- </CardContent>
2151
- </Card>
2115
+
2116
+ {/* A row that selects something is a `RowCard`, and which one is
2117
+ chosen is its `selected` prop. */}
2118
+ {presets.length > 0 && (
2119
+ <Stack gap={2}>
2120
+ <Heading level={3}>Saved Presets</Heading>
2121
+ {presets
2122
+ .sort((a, b) => b.timestamp - a.timestamp)
2123
+ .map((preset) => (
2124
+ <RowCard key={preset._id} selected={currentPreset?._id === preset._id} onClick={() => loadPreset(preset)}>
2125
+ {preset.name} · {["", "Dot", "Ellipse", "Line", "Square"][preset.parameters.shape]}
2126
+ </RowCard>
2127
+ ))}
2128
+ </Stack>
2129
+ )}
2130
+
2131
+ {parameterHistory.length > 0 && (
2132
+ <Stack gap={2}>
2133
+ <Heading level={3}>Parameter History</Heading>
2134
+ {parameterHistory
2135
+ .sort((a, b) => b.timestamp - a.timestamp)
2136
+ .slice(0, 10)
2137
+ .map((state) => (
2138
+ <RowCard key={state._id} onClick={() => loadParameterState(state)}>
2139
+ {actionNames[state.action] || "Unknown"} · {new Date(state.timestamp).toLocaleTimeString()}
2140
+ </RowCard>
2141
+ ))}
2142
+ </Stack>
2143
+ )}
2144
+ </Stack>
2145
+ )}
2146
+ </Stack>
2147
+ </Card>
2148
+ </div>
2152
2149
  </div>
2153
2150
  );
2154
2151
  }
package/llms/use-vibe.md CHANGED
@@ -16,9 +16,26 @@ Pass the Fireproof database name you are writing to. You get:
16
16
 
17
17
  While `pending` is set, show a quiet checking state — never a sign-in prompt, never the raw `reason` token, and never a blank space where the write surface was. A pending verdict means "we don't know yet", not "you may not"; it resolves on its own within a moment, so anything that reads as a refusal is wrong for that moment, and hiding the surface with nothing in its place makes the app look broken.
18
18
 
19
+ Holding on `ready` works the same way: put `if (!ready) return <Skeleton />` above the first `can.*(…).ok` read, so the surface's place shows a checking state until the verdict lands.
20
+
21
+ The same order carries a creator-only line. Check `ready` first and the founder sees a quiet placeholder for that moment, then the invite button; the "Only the founder…" sentence is for a member the verdict actually turns away:
22
+
23
+ ```jsx
24
+ import { useVibe } from "use-vibes";
25
+ import { Button, Skeleton, Text } from "@vibes.diy/pouf";
26
+
27
+ function InviteRow({ guild, onInvite }) {
28
+ const { can, me, ready } = useVibe("quiltGuilds");
29
+ const invite = can.create({ type: "invite", guildId: guild._id, authorHandle: me?.userHandle });
30
+ if (!ready) return <Skeleton variant="row" />;
31
+ if (!invite.ok) return <Text muted>Only the guild's founder sends invites, so ask them to bring in your quilting friends.</Text>;
32
+ return <Button onClick={onInvite}>Invite a quilter</Button>;
33
+ }
34
+ ```
35
+
19
36
  On a real denial (`!ok` and no `pending`), explain it in your app's own words — `reason` is a machine token, not display copy. Let it *inform* the sentence you write ("Join the team channel to post here"), and never render it directly: a token like `pending` or `not in channel: team` printed into the page is internal vocabulary leaking at a user.
20
37
 
21
- Never stamp author fields from `me` while the verdict is pending — `me` is null until identity resolves, and a write that skips the gate lands authorless.
38
+ Stamp `authorHandle: me.userHandle` inside the write an allowed verdict renders — the submit handler of the form `can.create` let through — so every document lands with its author. Never stamp author fields from `me` while the verdict is pending — `me` is null until identity resolves, and a write that skips the gate lands authorless.
22
39
 
23
40
  **Build the candidate from the doc you'll actually write.** `can.create(draft)` runs the access function against `draft`, so `draft` must carry the fields the function checks — `authorHandle`, `channelId`, etc. A bare `can.create({ type: "post" })` gets denied (e.g. `"not author"`) and hides the form even from users who could post. Stamp the same fields you'll `put`: `can.create({ type: "post", channelId, authorHandle: me?.userHandle })`. And gate the **same database** you write to — `useVibe(dbName)` selects the access function and grants by `dbName`, so a gate on a different db won't reflect server enforcement.
24
41
 
@@ -28,27 +45,32 @@ Gate every write affordance on `can.*`. Hold it while `pending`, and write your
28
45
 
29
46
  ### `App.jsx`
30
47
  ```jsx
48
+ import { useState } from "react";
31
49
  import { useVibe } from "use-vibes";
32
- import { Button, Input, Skeleton } from "@vibes.diy/look";
50
+ import { Button, Field, Input, Row, Skeleton, Text } from "@vibes.diy/pouf";
33
51
 
34
52
  function PromptBar({ database }) {
35
53
  const { can, me } = useVibe("aestheticBoard");
54
+ const [text, setText] = useState("");
36
55
  const v = can.create({ type: "tile", authorHandle: me?.userHandle });
37
56
  // 1. still resolving — a quiet placeholder, no refusal wording, no empty hole
38
- if (v.pending) return <Skeleton className="h-10 w-full" aria-busy="true" />;
57
+ if (v.pending) return <div aria-busy="true"><Skeleton variant="row" /></div>;
39
58
  // 2. resolved denial — your words, informed by v.reason, never v.reason itself
40
- if (!v.ok) return <p className="text-muted-foreground">Join the board to add a tile.</p>;
59
+ if (!v.ok) return <Text muted>Join the board to add a tile.</Text>;
41
60
  // 3. allowed
42
61
  return (
43
62
  <form
44
- onSubmit={(e) => {
63
+ onSubmit={async (e) => {
45
64
  e.preventDefault();
46
- database.put({ type: "tile", authorHandle: me?.userHandle, text: e.target.tile.value });
65
+ await database.put({ type: "tile", authorHandle: me?.userHandle, text });
66
+ setText("");
47
67
  }}
48
68
  >
49
69
  {/* no current-user pill — identity + sign-in live in the Vibes Switch (the logo) */}
50
- <Input name="tile" placeholder="Add a tile…" />
51
- <Button type="submit">Post</Button>
70
+ <Row gap={2} align="top">
71
+ <Field label="New tile">{(id, describedBy) => <Input id={id} describedBy={describedBy} value={text} onChange={setText} placeholder="Add a tile…" />}</Field>
72
+ <Button type="submit">Post</Button>
73
+ </Row>
52
74
  </form>
53
75
  );
54
76
  }