Form ID

shadcn/ui component

Install a form component that renders your Ikiform fields with your own shadcn/ui components.

If your project uses shadcn/ui, you can install a ready-made form instead of writing the markup. It is one option among several: the same form keeps working with plain HTML and fetch.

Install

Terminal
npx shadcn@latest add https://ikiform.com/r/form.json

This copies components/ikiform/form.tsx into your project and installs the shadcn/ui components it uses: button, checkbox, input, label, radio-group and textarea. The file is yours to edit. Selects use a native <select>, so it works with both the Radix and Base UI flavours of shadcn/ui.

Usage

app/contact/page.tsx
import { IkiForm } from "@/components/ikiform/form";

export default function Contact() {
  return <IkiForm form="frm_xxxxxxxxxxxxxxxx" />;
}

On mount the component fetches the form's public schema and renders one control per field, using the labels, placeholders, help text and options you set in the dashboard. Define fields first on the Fields tab of the form; a form without fields renders no inputs.

  • It validates in the browser with the same rules and messages as the server.
  • It posts JSON with the honeypot and a signed render timestamp, which helps spam scoring.
  • Server field errors appear under their fields; other errors appear above the button.
  • On success it replaces the form with the form's success message.

Props

PropTypeDescription
formstringRequired. The form id.
fieldsIkiFormField[]Replaces the fetched fields. Uses the same shape as field definitions.
onSuccess({ id, values }) => voidCalled after a successful submit.
submitLabelstringButton text. Defaults to the form's submit label.
successMessageReactNodeShown after submit. Defaults to the form's success message.
turnstileSiteKeystringOnly for forms with your own Turnstile keys and no site key saved in Ikiform.
classNamestringClass names for the form element.
baseUrlstringDefaults to https://ikiform.com.
app/waitlist/page.tsx
import { IkiForm } from "@/components/ikiform/form";

export default function Waitlist() {
  return (
    <IkiForm
      form="frm_xxxxxxxxxxxxxxxx"
      submitLabel="Join the waitlist"
      successMessage="You're on the list."
      onSuccess={({ id }) => console.log("Submitted", id)}
    />
  );
}

Fields in code

Pass fields to render without the dashboard definition. The server still validates against the form's published fields, so keep the two in sync.

Fields in code
<IkiForm
  form="frm_xxxxxxxxxxxxxxxx"
  fields={[
    { id: "email", type: "email", label: "Work email", required: true },
    { id: "team_size", type: "number", label: "Team size", validation: { min: 1, integer: true } },
  ]}
/>

Human check

With the spam check set to Ikiform, the component embeds a small ikiform.com frame that stays hidden until Turnstile needs a click, and asks for a fresh token after every attempt. If the frame can't load, it offers to open the check in a new window. With your own Turnstile keys, it renders the Turnstile widget with the form's site key.

The schema endpoint

The component reads GET https://ikiform.com/f/<formId>/schema. You can call it yourself to build your own renderer, or use getSchema from the SDK.

GET /f/:formId/schema
{
  "id": "frm_xxxxxxxxxxxxxxxx",
  "title": "Contact",
  "description": null,
  "fields": [{ "id": "email", "type": "email", "label": "Email", "required": true }],
  "settings": { "submit_label": "Send", "success_message": "Thanks!" },
  "honeypot_field": "_gotcha",
  "turnstile_required": false,
  "turnstile_site_key": null,
  "challenge": null,
  "ts": "1792300000000.signature"
}
  • Open to any origin (Access-Control-Allow-Origin: *) and never cached.
  • Paused, disabled and unknown forms all return the same 404.
  • Only the published fields and display settings leave the server. Allowed domains, the redirect URL, spam settings and rate limits stay private.
  • challenge is { "provider": "ikiform", "url": ... }, { "provider": "custom", "site_key": ... } or null. ts is a fresh signed render timestamp to send back as _ikiform_ts.
  • It allows 60 requests a minute per visitor and form, separate from the submit allowance.
The component source is plain React and Tailwind. Read it, restyle it, or delete the parts you don't need.