@vibes.diy/prompts 0.20.3-dev-push → 0.20.5-dev-cli-stable-entry

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.
@@ -0,0 +1 @@
1
+ export declare function buildSchemaSystemMessage(schema: object): Promise<string>;
@@ -0,0 +1,18 @@
1
+ import { generate } from "json-schema-faker";
2
+ async function buildExample(schema) {
3
+ const result = await generate(schema, { optionalsProbability: 1 });
4
+ if (!result) {
5
+ return {};
6
+ }
7
+ return result;
8
+ }
9
+ export async function buildSchemaSystemMessage(schema) {
10
+ const example = await buildExample(schema);
11
+ return `Return ONLY a JSON object inside a \`\`\`json code fence. Conform to this schema: ${JSON.stringify(schema)}
12
+
13
+ Example of expected output:
14
+ \`\`\`json
15
+ ${JSON.stringify(example, null, 2)}
16
+ \`\`\``;
17
+ }
18
+ //# sourceMappingURL=build-schema-prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-schema-prompt.js","sourceRoot":"","sources":["../jsr/build-schema-prompt.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,QAAQ,EAAmB,MAAM,mBAAmB,CAAC;AAE9D,KAAK,UAAU,YAAY,CAAC,MAAkB;IAC5C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,EAAE,oBAAoB,EAAE,CAAC,EAAE,CAAC,CAAC;IACnE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,MAAc;IAC3D,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,MAAoB,CAAC,CAAC;IACzD,OAAO,qFAAqF,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;;;;EAIlH,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;OAC3B,CAAC;AACR,CAAC"}
package/index.d.ts CHANGED
@@ -7,3 +7,4 @@ export * from "./style-prompts.js";
7
7
  export { parseContent } from "./segment-parser.js";
8
8
  export { resolveEffectiveModel } from "./prompts.js";
9
9
  export { normalizeComponentExports, transformImports, coreImportMap } from "./component-transforms.js";
10
+ export { buildSchemaSystemMessage } from "./build-schema-prompt.js";
package/index.js CHANGED
@@ -7,4 +7,5 @@ export * from "./style-prompts.js";
7
7
  export { parseContent } from "./segment-parser.js";
8
8
  export { resolveEffectiveModel } from "./prompts.js";
9
9
  export { normalizeComponentExports, transformImports, coreImportMap } from "./component-transforms.js";
10
+ export { buildSchemaSystemMessage } from "./build-schema-prompt.js";
10
11
  //# sourceMappingURL=index.js.map
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../jsr/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAE/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAGrD,OAAO,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../jsr/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAC9B,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAE/B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAGrD,OAAO,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAEvG,OAAO,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC"}
package/llms/callai.js CHANGED
@@ -1,7 +1,6 @@
1
1
  export const callaiConfig = {
2
2
  name: "callai",
3
3
  label: "callAI",
4
- llmsTxtUrl: "https://use-fireproof.com/callai-llms.txt",
5
4
  module: "openrouter",
6
5
  description: "easy API for LLM requests with streaming support",
7
6
  importModule: "call-ai",
@@ -1 +1 @@
1
- {"version":3,"file":"callai.js","sourceRoot":"","sources":["../../jsr/llms/callai.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAc;IACrC,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,QAAQ;IACf,UAAU,EAAE,2CAA2C;IACvD,MAAM,EAAE,YAAY;IACpB,WAAW,EAAE,kDAAkD;IAC/D,YAAY,EAAE,SAAS;IACvB,UAAU,EAAE,QAAQ;CACrB,CAAC"}
1
+ {"version":3,"file":"callai.js","sourceRoot":"","sources":["../../jsr/llms/callai.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,YAAY,GAAc;IACrC,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,YAAY;IACpB,WAAW,EAAE,kDAAkD;IAC/D,YAAY,EAAE,SAAS;IACvB,UAAU,EAAE,QAAQ;CACrB,CAAC"}
package/llms/callai.md ADDED
@@ -0,0 +1,76 @@
1
+ # CallAI Helper Function
2
+
3
+ The `callAI` function returns structured JSON from an AI model. It always requires a schema and returns a string that you `JSON.parse()`.
4
+
5
+ ## Basic Usage
6
+
7
+ ```javascript
8
+ import { callAI } from "call-ai";
9
+
10
+ const response = await callAI("Give me a todo list for learning React", {
11
+ schema: {
12
+ properties: {
13
+ todos: {
14
+ type: "array",
15
+ description: "List of actionable todo items",
16
+ items: { type: "string" },
17
+ },
18
+ },
19
+ },
20
+ });
21
+ const todoData = JSON.parse(response);
22
+ console.log(todoData.todos);
23
+ ```
24
+
25
+ ## Items with properties
26
+
27
+ ```javascript
28
+ const response = await callAI(
29
+ "Generate 4 items with label, status, priority (low, medium, high, critical), and notes. Return as structured JSON with these fields.",
30
+ {
31
+ schema: {
32
+ properties: {
33
+ items: {
34
+ type: "array",
35
+ items: {
36
+ type: "object",
37
+ properties: {
38
+ label: { type: "string", description: "Short name for the item" },
39
+ status: { type: "string", description: "Current status (active, done, blocked)" },
40
+ priority: { type: "string", description: "Priority level (low, medium, high, critical)" },
41
+ notes: { type: "string", description: "Additional context or details" },
42
+ },
43
+ },
44
+ },
45
+ },
46
+ },
47
+ }
48
+ );
49
+ const demoData = JSON.parse(response);
50
+ console.log(demoData.items); // Array of item objects
51
+ ```
52
+
53
+ ### Schema Tips
54
+
55
+ - Flat schemas perform better across all models. Avoid nesting deeper than 2 levels.
56
+ - Use simple property names like `name`, `type`, `items`, `price`.
57
+ - Keep array items simple (strings or flat objects).
58
+
59
+ ## Error Handling
60
+
61
+ ```javascript
62
+ import { callAI } from "call-ai";
63
+
64
+ try {
65
+ const response = await callAI("Generate some content", {
66
+ schema: {
67
+ properties: {
68
+ result: { type: "string" },
69
+ },
70
+ },
71
+ });
72
+ console.log(JSON.parse(response));
73
+ } catch (error) {
74
+ console.error("API error:", error.message);
75
+ }
76
+ ```
package/llms/d3.md CHANGED
@@ -126,11 +126,22 @@ bars
126
126
 
127
127
  ## Complete Examples for Coding Agents
128
128
 
129
+ ### Code Structure for D3 + React Apps
130
+
131
+ Structure your component in this order:
132
+
133
+ 1. **D3 helper functions** — visualization logic separate from React
134
+ 2. **Hooks and state** — useFireproof, useRef, useState
135
+ 3. **Effects** — useEffect to call D3 helpers when data changes
136
+ 4. **ClassNames object** — colors, dimensions right before JSX so they stay consistent
137
+ 5. **JSX return** — layout with refs for D3 to target
138
+
129
139
  ### 1. Simple Bar Chart
130
140
 
131
141
  ```js
132
142
  import * as d3 from "d3";
133
143
 
144
+ // 1. Design tokens and dimensions
134
145
  const data = [4, 8, 15, 16, 23, 42];
135
146
  const width = 500;
136
147
  const height = 300;
package/llms/fireproof.js CHANGED
@@ -1,7 +1,6 @@
1
1
  export const fireproofConfig = {
2
2
  name: "fireproof",
3
3
  label: "useFireproof",
4
- llmsTxtUrl: "https://use-fireproof.com/llms-full.txt",
5
4
  module: "use-fireproof",
6
5
  description: "local-first database with encrypted live sync",
7
6
  importModule: "use-fireproof",
@@ -1 +1 @@
1
- {"version":3,"file":"fireproof.js","sourceRoot":"","sources":["../../jsr/llms/fireproof.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAc;IACxC,IAAI,EAAE,WAAW;IACjB,KAAK,EAAE,cAAc;IACrB,UAAU,EAAE,yCAAyC;IACrD,MAAM,EAAE,eAAe;IACvB,WAAW,EAAE,+CAA+C;IAC5D,YAAY,EAAE,eAAe;IAC7B,UAAU,EAAE,cAAc;CAC3B,CAAC"}
1
+ {"version":3,"file":"fireproof.js","sourceRoot":"","sources":["../../jsr/llms/fireproof.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,eAAe,GAAc;IACxC,IAAI,EAAE,WAAW;IACjB,KAAK,EAAE,cAAc;IACrB,MAAM,EAAE,eAAe;IACvB,WAAW,EAAE,+CAA+C;IAC5D,YAAY,EAAE,eAAe;IAC7B,UAAU,EAAE,cAAc;CAC3B,CAAC"}
@@ -7,7 +7,7 @@ Fireproof is a lightweight embedded document database with encrypted live sync,
7
7
  - **Apps run anywhere:** Bundle UI, data, and logic in one file.
8
8
  - **Real-Time & Offline-First:** Automatic persistence and live queries, runs in the browser - no loading or error states.
9
9
  - **Unified API:** TypeScript works with Deno, Bun, Node.js, and the browser.
10
- - **React Hooks:** Leverage `useLiveQuery` and `useDocument` for live collaboration.
10
+ - **React Hooks:** Leverage `useLiveQuery` and `useDocument` for live collaboration. Note: these are NOT top-level exports — they are returned by the `useFireproof()` hook. Always destructure from `const { useLiveQuery, useDocument, database } = useFireproof("db-name")`.
11
11
 
12
12
  Fireproof enforces cryptographic causal consistency and ledger integrity using hash history, providing git-like versioning with lightweight blockchain-style verification. Data is stored and replicated as content-addressed encrypted blobs, making it safe and easy to sync via commodity object storage providers.
13
13
 
@@ -55,25 +55,19 @@ const App = () => {
55
55
  return (
56
56
  <div>
57
57
  <form onSubmit={submit}>
58
- <input
59
- value={doc.text}
60
- onChange={(e) => merge({ text: e.target.value })}
61
- placeholder="New document"
62
- />
58
+ <input value={doc.text} onChange={(e) => merge({ text: e.target.value })} placeholder="New document" />
63
59
  <button type="submit">Submit</button>
64
60
  </form>
65
61
 
66
62
  <h3>Recent Documents</h3>
67
63
  <ul>
68
64
  {docs.map((doc) => (
69
- <li key={doc._id}>
70
- {doc.text}
71
- </li>
72
- ))}
65
+ <li key={doc._id}>{doc.text}</li>
66
+ ))}
73
67
  </ul>
74
68
  </div>
75
69
  );
76
- }
70
+ };
77
71
  ```
78
72
 
79
73
  ### Editing Documents
@@ -87,18 +81,34 @@ const { doc, merge, submit, save, reset } = useDocument({ _id: "user-profile:abc
87
81
  ```
88
82
 
89
83
  The `useDocument` hook provides several methods:
84
+
90
85
  - `merge(updates)`: Update the document with new fields, without saving. Use this instead of keeping a `useState` for document data.
91
86
  - `submit(e)`: Handles form submission by preventing default, saving, and resetting
92
87
  - `save()`: Save the current document state
93
88
  - `reset()`: Reset to initial state
94
89
 
95
90
  For form-based creation flows, use `submit`:
91
+
96
92
  ```js
97
93
  <form onSubmit={submit}>
98
94
  ```
99
95
 
100
96
  When you call submit, the document is reset, so if you didn't provide an `_id` then you can use the form to create a stream of new documents as in the basic example above.
101
97
 
98
+ ### Updating Documents in Event Handlers
99
+
100
+ To update an existing document from a click handler or callback, use `database.put()` directly. Never call `useDocument` inside an event handler — that violates React's Rules of Hooks.
101
+
102
+ ```js
103
+ // ✅ Correct — use database.put() in handlers
104
+ onClick={() => database.put({ ...doc, favorite: !doc.favorite })}
105
+
106
+ // ❌ Wrong — never call hooks inside handlers
107
+ function toggleFavorite(id) {
108
+ const { doc, save } = useDocument({ _id: id }) // BREAKS Rules of Hooks
109
+ }
110
+ ```
111
+
102
112
  ### Query Data
103
113
 
104
114
  Data is queried by sorted indexes defined by the application. Sort by strings, numbers, or booleans, as well as arrays for grouping. Use numbers when possible for sorting continuous data.
@@ -110,16 +120,18 @@ Here are other common patterns:
110
120
  #### Query by Key Range
111
121
 
112
122
  Passing a string to `useLiveQuery` will index by that field. You can use the key argument to filter by a specific value:
123
+
113
124
  ```js
114
- const { docs } = useLiveQuery("agentName", {
115
- key: "agent-1" // all docs where doc.agentName === "agent-1", sorted by _id
125
+ const { docs } = useLiveQuery("agentName", {
126
+ key: "agent-1", // all docs where doc.agentName === "agent-1", sorted by _id
116
127
  });
117
128
  ```
118
129
 
119
130
  You can also query a range within a key:
131
+
120
132
  ```js
121
- const { docs } = useLiveQuery("agentRating", {
122
- range: [3, 5]
133
+ const { docs } = useLiveQuery("agentRating", {
134
+ range: [3, 5],
123
135
  });
124
136
  ```
125
137
 
@@ -127,23 +139,21 @@ const { docs } = useLiveQuery("agentRating", {
127
139
 
128
140
  Documents can be updated by multiple clients, and synced later. To create an event counter, don't increment a number on a single doc, instead write a small document per counted event, and query them with an index. Example:
129
141
 
130
-
131
142
  ```js
132
143
  const App = () => {
133
144
  const { useLiveQuery, database } = useFireproof("my-ledger");
134
145
 
135
- const { docs } = useLiveQuery('counter', { key : 'my-event-name'});
136
- const counterValue = docs.length
146
+ const { docs } = useLiveQuery("counter", { key: "my-event-name" });
147
+ const counterValue = docs.length;
137
148
 
138
149
  function countEvent() {
139
150
  database.put({
140
- counter : 'my-event-name'
141
- })
151
+ counter: "my-event-name",
152
+ });
142
153
  }
143
154
 
144
155
  // Call countEvent() to count each event, and render counterValue in the UI.
145
-
146
- }
156
+ };
147
157
  ```
148
158
 
149
159
  This pattern ensures the count is accurate even during sync.
@@ -155,13 +165,14 @@ Use a custom index function to normalize and transform document data, for instan
155
165
  ```js
156
166
  const { docs } = useLiveQuery(
157
167
  (doc) => {
158
- if (doc.type == 'listing_v1') {
168
+ if (doc.type == "listing_v1") {
159
169
  return doc.sellerId;
160
- } else if (doc.type == 'listing') {
170
+ } else if (doc.type == "listing") {
161
171
  return doc.userId;
162
172
  }
163
- },
164
- { key : routeParams.sellerId });
173
+ },
174
+ { key: routeParams.sellerId }
175
+ );
165
176
  ```
166
177
 
167
178
  #### Array Indexes and Prefix Queries
@@ -186,26 +197,23 @@ Sortable lists are a common pattern. Here's how to implement them using Fireproo
186
197
  ```js
187
198
  function App() {
188
199
  const { database, useLiveQuery } = useFireproof("my-ledger");
189
-
200
+
190
201
  // Initialize list with evenly spaced positions
191
202
  async function initializeList() {
192
203
  await database.put({ list: "xyz", position: 1000 });
193
204
  await database.put({ list: "xyz", position: 2000 });
194
205
  await database.put({ list: "xyz", position: 3000 });
195
206
  }
196
-
207
+
197
208
  // Query items on list xyz, sorted by position. Note that useLiveQuery('list', { key:'xyz' }) would be the same docs, sorted chronologically by _id
198
- const queryResult = useLiveQuery(
199
- (doc) => [doc.list, doc.position],
200
- { prefix: ["xyz"] }
201
- );
209
+ const queryResult = useLiveQuery((doc) => [doc.list, doc.position], { prefix: ["xyz"] });
202
210
 
203
211
  // Insert between existing items using midpoint calculation
204
212
  async function insertBetween(beforeDoc, afterDoc) {
205
213
  const newPosition = (beforeDoc.position + afterDoc.position) / 2;
206
- await database.put({
207
- list: "xyz",
208
- position: newPosition
214
+ await database.put({
215
+ list: "xyz",
216
+ position: newPosition,
209
217
  });
210
218
  }
211
219
 
@@ -213,7 +221,7 @@ function App() {
213
221
  <div>
214
222
  <h3>List xyz (Sorted)</h3>
215
223
  <ul>
216
- {queryResult.docs.map(doc => (
224
+ {queryResult.docs.map((doc) => (
217
225
  <li key={doc._id}>
218
226
  {doc._id}: position {doc.position}
219
227
  </li>
@@ -268,10 +276,10 @@ database.subscribe((changes) => {
268
276
 
269
277
  ### Working with Files
270
278
 
271
- Attach files to a document by adding them to the _files property. For example:
279
+ Attach files to a document by adding them to the \_files property. For example:
272
280
 
273
281
  ```html
274
- <input accept="image/*" title="save to Fireproof" type="file" id="files" multiple>
282
+ <input accept="image/*" title="save to Fireproof" type="file" id="files" multiple />
275
283
  ```
276
284
 
277
285
  ```js
@@ -279,11 +287,11 @@ function handleFiles() {
279
287
  const fileList = this.files;
280
288
  const doc = {
281
289
  type: "files",
282
- _files: {}
290
+ _files: {},
283
291
  };
284
292
  for (const file of fileList) {
285
293
  // Assign each File object to the document
286
- doc._files[file.name] = file;
294
+ doc._files[file.name] = file;
287
295
  }
288
296
  database.put(doc);
289
297
  }
@@ -330,30 +338,33 @@ function handleSubmit(e) {
330
338
 
331
339
  ## Example React Application
332
340
 
333
- Code listing for todo tracker App.jsx:
341
+ Code listing for todo tracker App.jsx. Note the code ordering: hooks, then handlers, then classNames right before JSX.
342
+
334
343
  ```js
335
344
  import React from "react";
336
345
  import { useFireproof } from "use-fireproof";
337
346
 
338
347
  export default function App() {
348
+ // 1. Hooks and document shapes
339
349
  const { useLiveQuery, useDocument, database } = useFireproof("todo-list-db");
340
350
 
341
351
  const {
342
352
  doc: newTodo,
343
353
  merge: mergeNewTodo,
344
- submit: submitNewTodo
354
+ submit: submitNewTodo,
345
355
  } = useDocument({
346
356
  todo: "",
347
357
  type: "todo",
348
358
  completed: false,
349
- createdAt: Date.now()
359
+ createdAt: Date.now(),
350
360
  });
351
361
 
352
- const { docs: todos } = useLiveQuery("type", {
362
+ const { docs: todos } = useLiveQuery("type", {
353
363
  key: "todo",
354
- descending: true
364
+ descending: true,
355
365
  });
356
366
 
367
+ // 2. Event handlers
357
368
  const handleInputChange = (e) => {
358
369
  mergeNewTodo({ todo: e.target.value });
359
370
  };
@@ -363,13 +374,25 @@ export default function App() {
363
374
  submitNewTodo();
364
375
  };
365
376
 
377
+ // 3. ClassNames — right before JSX so colors stay consistent
378
+ const c = {
379
+ bg: "bg-white",
380
+ card: "bg-gray-50",
381
+ border: "border-gray-200",
382
+ accent: "bg-[#e63946]",
383
+ text: "text-gray-500",
384
+ };
385
+
386
+ // 4. JSX return
366
387
  return (
367
- <div className="max-w-md mx-auto p-4 bg-white shadow rounded">
388
+ <div className={`max-w-md mx-auto p-4 ${c.bg} shadow rounded`}>
368
389
  <h2 className="text-2xl font-bold mb-4">Todo List</h2>
369
390
  <form onSubmit={handleSubmit} className="mb-4">
370
- <label htmlFor="todo" className="block mb-2 font-semibold">Todo</label>
391
+ <label htmlFor="todo" className="block mb-2 font-semibold">
392
+ Todo
393
+ </label>
371
394
  <input
372
- className="w-full border border-gray-300 rounded px-2 py-1"
395
+ className={`w-full ${c.border} border rounded px-2 py-1`}
373
396
  id="todo"
374
397
  type="text"
375
398
  onChange={handleInputChange}
@@ -378,7 +401,7 @@ export default function App() {
378
401
  </form>
379
402
  <ul className="space-y-3">
380
403
  {todos.map((doc) => (
381
- <li className="flex flex-col items-start p-2 border border-gray-200 rounded bg-gray-50" key={doc._id}>
404
+ <li className={`flex flex-col items-start p-2 ${c.border} border rounded ${c.card}`} key={doc._id}>
382
405
  <div className="flex items-center justify-between w-full">
383
406
  <div className="flex items-center">
384
407
  <input
@@ -389,16 +412,11 @@ export default function App() {
389
412
  />
390
413
  <span className="font-medium">{doc.todo}</span>
391
414
  </div>
392
- <button
393
- className="text-sm bg-red-500 text-white px-2 py-1 rounded"
394
- onClick={() => database.del(doc._id)}
395
- >
415
+ <button className={`text-sm ${c.accent} text-white px-2 py-1 rounded`} onClick={() => database.del(doc._id)}>
396
416
  Delete
397
417
  </button>
398
418
  </div>
399
- <div className="text-xs text-gray-500 mt-1">
400
- {new Date(doc.createdAt).toISOString()}
401
- </div>
419
+ <div className={`text-xs ${c.text} mt-1`}>{new Date(doc.createdAt).toISOString()}</div>
402
420
  </li>
403
421
  ))}
404
422
  </ul>
@@ -409,37 +427,66 @@ export default function App() {
409
427
 
410
428
  ### Example Image Uploader
411
429
 
412
- This React example shows a simple image uploader application that uses Fireproof to store and sort images by creation date. These APIs easily work with plain JavaScript also.
430
+ This React example shows a simple image uploader application that uses Fireproof to store and sort images by creation date. These APIs easily work with plain JavaScript also.
413
431
 
414
432
  Code listing for App.jsx:
433
+
415
434
  ```js
416
435
  import { useFireproof, ImgFile } from "use-fireproof";
417
- import { useState, useEffect } from "react";
436
+ import { useState } from "react";
418
437
 
419
438
  export default function App() {
439
+ // 1. Hooks and document shapes
420
440
  const { useDocument, useLiveQuery } = useFireproof("image-uploads");
421
441
  const { doc, merge, submit } = useDocument({ _files: {}, description: "" });
422
442
  const { docs } = useLiveQuery("_id", { descending: true, limit: 5 });
423
443
  const [error, setError] = useState(false);
424
444
 
445
+ // 2. Event handlers
446
+ const handleFileChange = (e) => {
447
+ if (e.target.files[0]) merge({ _files: { uploaded: e.target.files[0] } });
448
+ };
449
+
450
+ const handleUpload = () => {
451
+ if (doc.description.trim()) {
452
+ submit();
453
+ } else {
454
+ setError(true);
455
+ }
456
+ };
457
+
458
+ // 3. ClassNames
459
+ const c = {
460
+ bg: "bg-white",
461
+ card: "bg-gray-50",
462
+ accent: "bg-blue-500 hover:bg-blue-600",
463
+ text: "text-gray-700",
464
+ };
465
+
466
+ // 4. JSX return
425
467
  return (
426
- <div className="p-6 max-w-lg mx-auto bg-white shadow-lg rounded-lg">
468
+ <div className={`p-6 max-w-lg mx-auto ${c.bg} shadow-lg rounded-lg`}>
427
469
  <h2 className="text-2xl font-bold mb-4">Image Uploader</h2>
428
- <input type="file" accept="image/*" onChange={e => e.target.files[0] && merge({ _files: { uploaded: e.target.files[0] } })} className="mb-2 border p-2 w-full rounded" />
429
- <input
430
- type="text"
431
- placeholder="Enter description"
432
- value={doc.description}
433
- onChange={e => {setError(false); merge({ description: e.target.value });}}
470
+ <input type="file" accept="image/*" onChange={handleFileChange} className="mb-2 border p-2 w-full rounded" />
471
+ <input
472
+ type="text"
473
+ placeholder="Enter description"
474
+ value={doc.description}
475
+ onChange={(e) => {
476
+ setError(false);
477
+ merge({ description: e.target.value });
478
+ }}
434
479
  className={`w-full p-2 border rounded mb-4 ${error ? "border-red-500" : "border-gray-300"}`}
435
480
  />
436
- <button onClick={() => doc.description.trim() ? submit() : setError(true)} className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">Upload</button>
481
+ <button onClick={handleUpload} className={`px-4 py-2 ${c.accent} text-white rounded`}>
482
+ Upload
483
+ </button>
437
484
  <h3 className="text-lg font-semibold mt-6">Recent Uploads</h3>
438
485
  <div className="grid grid-cols-2 gap-4 mt-2">
439
- {docs.map(doc => (
440
- <div key={doc._id} className="border p-2 rounded shadow-sm bg-gray-50">
486
+ {docs.map((doc) => (
487
+ <div key={doc._id} className={`border p-2 rounded shadow-sm ${c.card}`}>
441
488
  {doc._files?.uploaded && <ImgFile file={doc._files.uploaded} alt="Uploaded Image" className="w-full h-auto rounded" />}
442
- <p className="text-sm text-gray-700 mt-2">{doc.description || "No description"}</p>
489
+ <p className={`text-sm ${c.text} mt-2`}>{doc.description || "No description"}</p>
443
490
  </div>
444
491
  ))}
445
492
  </div>
package/llms/image-gen.js CHANGED
@@ -1,7 +1,6 @@
1
1
  export const imageGenConfig = {
2
2
  name: "image-gen",
3
3
  label: "Image Generation",
4
- llmsTxtUrl: "https://use-fireproof.com/imggen-llms.txt",
5
4
  module: "OpenAi",
6
5
  description: "Generate and edit images",
7
6
  importModule: "use-vibes",
@@ -1 +1 @@
1
- {"version":3,"file":"image-gen.js","sourceRoot":"","sources":["../../jsr/llms/image-gen.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAAc;IACvC,IAAI,EAAE,WAAW;IACjB,KAAK,EAAE,kBAAkB;IACzB,UAAU,EAAE,2CAA2C;IACvD,MAAM,EAAE,QAAQ;IAChB,WAAW,EAAE,0BAA0B;IACvC,YAAY,EAAE,WAAW;IACzB,UAAU,EAAE,QAAQ;CACrB,CAAC"}
1
+ {"version":3,"file":"image-gen.js","sourceRoot":"","sources":["../../jsr/llms/image-gen.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,cAAc,GAAc;IACvC,IAAI,EAAE,WAAW;IACjB,KAAK,EAAE,kBAAkB;IACzB,MAAM,EAAE,QAAQ;IAChB,WAAW,EAAE,0BAA0B;IACvC,YAAY,EAAE,WAAW;IACzB,UAAU,EAAE,QAAQ;CACrB,CAAC"}
@@ -7,7 +7,7 @@ The ImgGen component can be used in three ways:
7
7
  1. **With no props** - Shows a form UI for users to enter a prompt and/or upload images:
8
8
 
9
9
  ```jsx
10
- import { ImgGen } from 'use-vibes';
10
+ import { ImgGen } from "use-vibes";
11
11
 
12
12
  function MyComponent() {
13
13
  return <ImgGen />; // Shows built-in form for prompt entry and image upload
@@ -17,7 +17,7 @@ function MyComponent() {
17
17
  2. **With a prompt prop** - Immediately generates an image (no form shown):
18
18
 
19
19
  ```jsx
20
- import { ImgGen } from 'use-vibes';
20
+ import { ImgGen } from "use-vibes";
21
21
 
22
22
  function MyComponent() {
23
23
  return <ImgGen prompt="A sunset over mountains" />; // Direct generation, no form
@@ -27,32 +27,31 @@ function MyComponent() {
27
27
  3. **With images prop** - Edits or combines images with AI (no form shown):
28
28
 
29
29
  ```jsx
30
- import { ImgGen } from 'use-vibes';
30
+ import { ImgGen } from "use-vibes";
31
31
 
32
32
  function MyComponent() {
33
33
  const [files, setFiles] = useState([]);
34
34
  return (
35
- <ImgGen
36
- prompt="Create a gift basket with these items"
35
+ <ImgGen
36
+ prompt="Create a gift basket with these items"
37
37
  images={files} // Array of File objects
38
38
  />
39
39
  );
40
40
  }
41
41
  ```
42
42
 
43
- 4. **With an _id prop** - Loads a specific image from the database (no form shown):
43
+ 4. **With an \_id prop** - Loads a specific image from the database (no form shown):
44
44
 
45
- If there is no image generated for the document yet, but it has a `prompt` field, it will generate a new image with the prompt. If there an images is stored, at doc._files.original, it will use that as the base image.
45
+ If there is no image generated for the document yet, but it has a `prompt` field, it will generate a new image with the prompt. If there an images is stored, at doc.\_files.original, it will use that as the base image.
46
46
 
47
47
  ```jsx
48
- import { ImgGen } from 'use-vibes';
48
+ import { ImgGen } from "use-vibes";
49
49
 
50
50
  function MyComponent() {
51
51
  return <ImgGen _id="my-image-id" />; // Loads specific image by ID
52
52
  }
53
53
  ```
54
54
 
55
-
56
55
  ## List by ID
57
56
 
58
57
  Images and prompts are tracked in a Fireproof database with a `type` of `image`. If a database is not provided, it uses `"ImgGen"` as the database name.
@@ -60,13 +59,13 @@ Images and prompts are tracked in a Fireproof database with a `type` of `image`.
60
59
  Display stored images by their ID. Ensure you do this, so users can find the images they created.
61
60
 
62
61
  ```jsx
63
- import { useFireproof } from 'use-fireproof';
64
- import { ImgGen } from 'use-vibes';
62
+ import { useFireproof } from "use-fireproof";
63
+ import { ImgGen } from "use-vibes";
65
64
 
66
65
  function MyComponent() {
67
66
  const { database, useLiveQuery } = useFireproof("my-db-name");
68
- const { docs: imageDocuments } = useLiveQuery('type', {
69
- key: 'image',
67
+ const { docs: imageDocuments } = useLiveQuery("type", {
68
+ key: "image",
70
69
  descending: true,
71
70
  });
72
71
 
@@ -103,8 +102,8 @@ ImgGen supports custom styling through CSS variables or custom class names:
103
102
  }
104
103
 
105
104
  // With custom class names
106
- <ImgGen
107
- prompt="A landscape"
105
+ <ImgGen
106
+ prompt="A landscape"
108
107
  className="my-custom-image"
109
108
  classes={{
110
109
  root: 'custom-container',