Intermediate Prompts
Use these prompts when a page needs forms, tables, custom renderers, registry handlers, and local CRUD actions.
Form and table prompt
TXT
Create a VibeFlui form-and-table example for inventory products.
Return separate files with path labels:
- schemas/products/product.resource.schema.ts
- components/vibeflui/renderers/products/ProductStatusBadge.tsx
- lib/vibeflui/registry.tsx
- lib/vibeflui/examples/product-crud-actions.ts
- app/products/page.tsx
Requirements:
- resource: products
- title: Product inventory
- identity key: id and param: id
- table columns: sku, name, category, stock, status
- status column uses renderer ProductStatusBadge
- table search enabled
- form mode modal
- form fields: sku, name, category, stock, reorderPoint, status
- category select options hardware, software, service
- status select options draft, active, discontinued
- create, edit, delete enabled
- delete uses confirm true and danger variant
- local data lives in page state
- CRUD functions live in product-crud-actions.ts
- page calls createProductCrudActions(setRows)
- no inline async handlers in <FluiKit>
- registry only imports ProductStatusBadge and registers it
- no JSX inside createRegistryExpected action helper shape
lib/vibeflui/examples/product-crud-actions.ts
TS
import type { Dispatch, SetStateAction } from "react";
import type { FluiKitSubmitContext } from "@vibeflui/core";
export type ProductRow = {
id: string;
sku: string;
name: string;
category: string;
stock: number;
reorderPoint: number;
status: string;
};
export function createProductCrudActions(setRows: Dispatch<SetStateAction<ProductRow[]>>) {
return {
createProduct: async (values: Record<string, unknown>) => {
const product = mapValuesToProduct(values);
setRows((current) => [...current, product]);
return { status: true, code: 200, message: "Product created" };
},
updateProduct: async (values: Record<string, unknown>, context: FluiKitSubmitContext) => {
const id = String(context.row?.id ?? "");
const product = mapValuesToProduct(values, id);
setRows((current) => current.map((row) => (row.id === id ? product : row)));
return { status: true, code: 200, message: "Product updated" };
},
deleteProduct: async (row: Record<string, unknown>) => {
const id = String(row.id ?? "");
setRows((current) => current.filter((item) => item.id !== id));
return { status: true, code: 200, message: "Product deleted" };
}
};
}
function mapValuesToProduct(values: Record<string, unknown>, id = crypto.randomUUID()): ProductRow {
return {
id,
sku: String(values.sku ?? ""),
name: String(values.name ?? ""),
category: String(values.category ?? "hardware"),
stock: Number(values.stock ?? 0),
reorderPoint: Number(values.reorderPoint ?? 0),
status: String(values.status ?? "draft")
};
}List response mapping prompt
Use this when a real backend already returns a specific JSON shape and the AI needs to map it into a VibeFlui table — which key holds the row array, which key holds the total count, and which response fields become which columns.
TXT
Configure a VibeFlui users table against this exact backend response for GET /api/users.
Do not change the response shape; map the schema to it.
Backend response:
{
"success": true,
"result": {
"rows": [
{ "id": "usr_1", "full_name": "Ada Lovelace", "email_address": "ada@example.test", "is_active": true },
{ "id": "usr_2", "full_name": "Alan Turing", "email_address": "alan@example.test", "is_active": false }
],
"count": 2
}
}
Requirements:
- table.dataPath must point at the array (result.rows)
- table.totalPath must point at the count (result.count)
- table column "full_name" displays as label "Name"
- table column "email_address" displays as label "Email", type email
- table column "is_active" displays as label "Active", rendered as Yes/No (boolean), not the raw true/false value
- identity key and param are both "id"
- explain which response key you used for each of dataPath/totalPath and whyExpected mapping the AI should produce and explain back:
| Response key | Schema key | Purpose |
|---|---|---|
result.rows | table.dataPath: "result.rows" | Array of rows rendered in the table. |
result.count | table.totalPath: "result.count" | Total row count used for pagination. |
full_name | table.columns[].key: "full_name", label: "Name" | Displayed column. |
email_address | table.columns[].key: "email_address", label: "Email", type: "email" | Displayed column. |
is_active | table.columns[].key: "is_active", label: "Active", boolean-formatted | Displayed column — this is the field that is "true/false" per row, not the backend's overall success flag. |
Note the difference between success at the top of this response (whether the request succeeded) and is_active inside each row (a business field about that user). Only map fields that should actually be visible to table.columns — do not surface the top-level success flag as a column.
Custom field prompt
TXT
Add a custom Notes field to the products form.
Return separate files:
- components/vibeflui/fields/ProductNotesField.tsx
- lib/vibeflui/registry.tsx
- schemas/products/product.resource.schema.ts
Rules:
- include a file path label before each code block
- field uses type custom and component ProductNotesField
- ProductNotesField is a React component file
- registry imports ProductNotesField and registers it under components
- schema references component by string
- no JSX inside registry