kibbleforms
编码代理构建的站点的入站表单。表单存在于你的代码中; 粗磨 处理提交后的所有事情:验证、垃圾邮件保护、随表单变化保持一致的存储、部分提交以及发送到电子邮件和webhook。
一个包裹,三样东西:
- 反应组件 那一副从盒子里拿出来的样子
kibbleforms)在…之上 无头原语 (kibbleforms/headless) - 一个 客户端SDK (
kibbleforms/client)与幂等,重试提交 - 这个
kibbleCLI (npx kibble …),用于配置、推送模式、测试和检查构建
npm install kibbleforms
反应18或19。工作在Next.js(应用路由器),Vite, Astro + React, Remix。文档: kibbleforms.com/docs ·每个版本都有哪些变化: 更新日志。
60秒快速入门(也适用于代理商)
npx kibble init # sandbox project; writes kibble.json, .kibble/secret, kibble/client.ts, an AGENTS.md section,
# adds withKibble()/kibble() to your next/vite/astro config and the CSS imports, prints a claim link
// kibble/forms/waitlist.ts
import { defineForm } from 'kibbleforms/schema';
export const waitlist = defineForm({
slug: 'waitlist',
name: 'Waitlist',
pages: [
{
fields: [
{ key: 'email', type: 'email', label: 'Work email', required: true },
{ key: 'name', type: 'short_text', label: 'Name' },
{ key: 'role', type: 'dropdown', label: 'Role', options: ['Founder', 'Engineer', 'Other'] },
{ key: 'consent', type: 'consent', label: 'Email me when we launch', required: true },
],
},
],
settings: {
submitLabel: 'Join the waitlist',
success: { type: 'message', title: 'You are on the list', message: 'We will be in touch.' },
},
});
// anywhere in your site
import { Form } from 'kibbleforms';
import { kibble } from '@/kibble/client';
import { waitlist } from '@/kibble/forms/waitlist';
export function Waitlist() {
return <Form schema={waitlist} client={kibble} />;
}
npm run dev # the plugin registers a form whenever its file is saved
npx kibble test waitlist # send a test submission from localhost and confirm it landed
没有需要记住的推进步骤: withKibble(nextConfig) (kibbleforms/next)或 kibble() (kibbleforms/vite(也包括Astro和React Router)从开发服务器注册表单并运行 kibble sync 在构建。项目认领后, npx kibble env vercel (或 netlify, print)为部署构建提供键,以便它们也注册它们的表单;没有它,只有当访问者被拒绝时,构建才会失败。
这是一个本地主机上的工作表单,没有人工步骤。要上线,一个人打开索赔链接(npx kibble claim --open),登录并命名生产域。在此之前,该项目是一个 沙盒:它只接受来自本地主机的提交,其数据在72小时后过期。
字段类型: short_text, long_text, email, phone, url, number, single_choice, multiple_choice, dropdown, yes_no, rating, date, consent, hidden. 多于一页的表单是多步骤表单;每一步之后都会保存进度。
条件逻辑,预填充,自动完成,调度
- 条件字段和页面:
showWhen: { field: 'role', op: 'eq', value: 'other' }(或{ all: [...] }/{ any: [...] })在一个领域或一页。隐藏字段不被验证,不是必需的,永远不会发送;没有可见字段的页面将被跳过并Progress只计算可见页面。钩子暴露了visibleKeys,visiblePages,isFieldVisible(key),isPageVisible(i)。 - 预先填充:
prefill: { query: 'email' }在挂载时填充URL查询中的字段(隐藏字段默认为自己的键);initialValues在Form/useKibbleForm是程序化的预填充和获胜。 - 自动完成:
autocomplete: 'name' | 'given-name' | 'organization' | …成为HTML属性(email/tel/url字段得到合理的默认值)。 - 调度:
success: { type: 'schedule', url: 'https://calendly.com/acme/demo' }重定向,name和email肾上腺素和utm_*通过;redirect接受prefill了。钩子暴露了successUrl和resolveSuccessUrl()用于自定义ui,以及navigate让你替换window.location.assign。
代理
表格可以由代理填写。 settings.agents 是 'accept' (默认;已声明的代理被标记)或 'block', settings.agentNotes 描述好的答案;代理读 GET /v1/projects/<projectId>/forms/<slug>/schema.json 然后提交 meta.actor: { type: 'agent', name }. 在SDK中: createClient({ actor }) 或 useKibbleForm(schema, { actor }). 一个 block 政策的回报 agents_blocked;的风格 Form 显示服务器的消息和提示。
CSS设置
组件是用Tailwind v4实用程序编写的,该实用程序读取 --kb-* CSS变量。选择一个:
顺风v4主机 你的CSS文件; kibble init 添加):
@import "tailwindcss";
@import "kibbleforms/theme.css"; /* --kb-* tokens + @theme mapping (bg-kb-primary, rounded-kb, …) */
@import "kibbleforms/themes/shadcn.css"; /* shadcn/ui sites: use your --primary, --radius, … (v3: shadcn-v3.css) */
@source "../node_modules/kibbleforms/dist"; /* let Tailwind see the component classes; adjust the relative path */
该表单继承您的字体并跟随 .dark / [data-theme="dark"] 祖先。使用道具进行调整: theme (颜色, radius, font, colorScheme), size (sm | md | lg), layout ({ columns: 2 }), classNames (按部分上课),上 Form 或者曾经 KibbleProvider。
没有顺风 (任何捆绑者,或一个 <link>):
import 'kibbleforms/styles.css'; // compiled and scoped to [data-kibble]; nothing leaks into your page
定制
-
CSS变量 -两种分布都一样。全局或每个表单设置它们:
:root { --kb-primary: #2563eb; --kb-radius: 999px; --kb-font: var(--font-sans); } [data-kibble] { --kb-space: 1rem; }令牌:
--kb-primary,--kb-primary-fg,--kb-bg,--kb-fg,--kb-muted,--kb-muted-fg,--kb-border,--kb-ring,--kb-error,--kb-radius,--kb-space,--kb-font. 每个组件也呈现data-kb="<name>"(form,field,label,input,select,choice,option,yesno,rating,date,consent,submit,error,success,multistep,progress,nav,notice,page,help)用于纯CSS定位。 -
组合和覆盖类 -每个组件
className与…合并tailwind-merge所以你的公用事业赢了:<Form schema={waitlist} client={kibble} className="grid grid-cols-2 gap-4"> <Field name="name" /> <Field name="email" /> <Field name="role" className="col-span-2" /> <Field name="consent" className="col-span-2" /> <Submit className="col-span-2 w-auto justify-self-end">Count me in</Submit> </Form> -
无头 -行为和可访问性,零标记意见;
import { useKibbleForm, FormProvider, useField, Honeypot } from 'kibbleforms/headless'; function Email() { const { field, value, setValue, error, inputProps, errorId } = useField('email'); return ( <label> {field.label} <input {...inputProps} value={(value as string) ?? ''} onChange={(e) => setValue(e.target.value)} /> {error && <p id={errorId}>{error}</p>} </label> ); } export function Custom() { const form = useKibbleForm(waitlist, { client: kibble }); return ( <FormProvider form={form}> <form {...form.formProps}> <Honeypot /> <Email /> <button type="submit" disabled={form.status === 'submitting'}>Send</button> </form> </FormProvider> ); }useKibbleForm给你values,errors,touched,pageIndex,pageCount,status,result,submitError,setValue,setTouched,validatePage,nextPage,prevPage,submit,reset,formProps和更多。useField返回inputProps与id,name,aria-invalid,aria-describedby,aria-required和onBlur(我们使用aria-required而不是required所以显示的是我们的消息,而不是浏览器的)。usePage()和useFormStatus()覆盖导航和状态。
组件
Form (在没有子项的情况下,从图式呈现整个形式; MultiStep 当有超过一页时自动), KibbleProvider, Page, MultiStep, Progress, Field (按类型选择控件), Input, Textarea, Select, Choice (单选或复选框组), YesNo, Rating, DatePicker, Consent, Submit, FieldError, Success, Label, Help, Button。
您可以免费获得的行为:提交时的模式验证(模糊时的格式错误,“required”等待提交),焦点移动到第一个无效控件或新页面的标题,Enter提交单页表单并推进多步骤表单,蜜罐字段,提交时间,访问者来自何处(导致表单的页面,登录页面,入口站点和活动标签;添加 <KibbleAttribution /> 到根布局以覆盖表单之前的页面),可选的Cloudflare Turnstile (settings.turnstileSiteKey),幂等提交,在网络上重试3次/5xx错误,在会话id下保存的每一步部分 sessionStorage,以及成功消息或重定向从 settings.success (服务器的echo获胜)。
使用 <KibbleProvider client={kibble}> 一次(例如在Next.js布局中通过一个小的客户端组件),以便页面可以渲染 <Form schema={…} /> 不通过客户端。在服务器组件框架中,从 kibbleforms/schema 还有来自 kibbleforms/client;默认条目是客户端代码。
客户端SDK
import { createClient, KibbleError } from 'kibbleforms/client';
const kibble = createClient({ projectId: 'prj_…', endpoint: 'https://api.kibbleforms.com' });
const res = await kibble.submit(waitlist, { email: '[email protected]', consent: true }, { startedAt });
// res: { id, status, success?, flags? } — throws KibbleError { code, message, hint, fields, status }
await kibble.savePartial(waitlist, values, { sessionId, pageIndex: 0 }); // never throws, null on failure
服务器总是根据注册的模式版本进行验证;客户机验证是一种便利。提交的文件带有 Idempotency-Key (每个逻辑提交一个,跨重试重用)和模式哈希,以便Kibble知道它们属于哪个版本。
CLI
每个命令都接受 --json (标准输出上的机器可读输出,没有其他)。退出代码: 0 好吧, 1 错误, 2 检查失败。错误总是告诉我们下一步该怎么做。
| 命令 | 它是做什么的 |
|---|---|
kibble init [--name] [--api-url] [--forms-dir kibble/forms] [--force] | 创建沙盒项目。写 kibble.json, .kibble/secret (gitignored), kibble/client.ts、forms目录和 ## Kibble forms 部分 AGENTS.md/CLAUDE.md. 打印索赔链接。 |
kibble push [slug] | 注册forms目录中的每个模式(加载了jiti、TypeScript就可以了)。打印版本、diff和警告。框架插件使得很少需要这样做。 |
kibble sync | 构建步骤:使用 KIBBLE_SECRET_KEY (或 .kibble/secret)注册每个表单标记其来源(Vercel, netflix, Cloudflare Pages, GitHub Actions, KIBBLE_ENV); 没有它,只有在访客被拒绝时才会检查和离开。 |
kibble env vercel|netlify|print | 将密钥放入主机的构建环境中(Vercel的标准输入,不回显),或者打印密钥以进行粘贴。 |
kibble test [slug] | 从localhost发送带有样例值的测试提交,并确认它已被存储。 |
kibble status | 模式、声明状态、起源和具有本地vs远程模式漂移的表单表。 |
kibble check [--allow-sandbox] | 严格本地检查:如果项目未被认领或本地模式未注册,则退出2。 |
kibble claim [--open] [--wait] | 打印(并打开)索赔链接; --wait 投票直到项目上线。 |
kibble submissions [slug] [--status all|complete|partial|spam|test] [--limit 20] | 列出最近的回复,包括类型、日期和第一次回复。 |
kibble destinations list / add slack (为某人打印“添加到Slack”链接)或 add slack <url> / add postgres "<conn>" [--table t] [--schema s] / add email <member addr> / add webhook <url> (每 --form slug 或 --all-forms) / remove <id> / test <id> | 连接Slack, Postgres(包括Supabase pooler),向工作区成员发送电子邮件和签名webhook,而不需要仪表板。连接字符串永远不会回显;Webhook签名秘密打印一次。 |
kibble domains list|add <domain>|remove <domain> | 站点的生产域(允许的来源)。 |
kibble review <slug> [--ideal "…"] [--categories "A,B"] [--off|--on] | 显示或更改表单的分类(理想响应支持适合级别)。 |
配置: kibble.json ({ projectId, apiUrl, formsDir }),秘密地 .kibble/secret (KIBBLE_SECRET_KEY 覆盖(在CI中很有用); KIBBLE_API_URL 为设置默认API init。
文档
https://api.kibbleforms.com/llms.txt 和 /docs/*.md 都是为特工和人类写的。
麻省理工学院