Custom components

For anyone who needs a component that doesn't exist in the prebuilt palette. You'll have a React component that lives in your funnel and behaves like any other Zellify block. You need familiarity with React + TypeScript, or an AI that does.

What a custom component is#

A custom component is a React + TypeScript component that you (or your AI) write inside the Zellify Component Editor. Once saved, it appears in the funnel builder's palette and your team can drag it onto any page like a prebuilt component.

The runtime injects everything the component needs: a hook-based prop API so non-developers can edit text, colors, options, and layout from the visual props panel; access to the funnel's global design tokens; navigation via useFunnelRouter(); and tracking via the tracker object. Your component reads these and renders normal JSX.

Why custom components are written a specific way#

Custom components do not work like generic React components dropped into a Next.js app. The runtime expects:

  1. Props are declared via Zellify hooks, not via React props. props.useText("headerText", { default: "..." }) registers an editable text field that shows up in the props panel.
  2. A PropEditorLayout static that lays out the props panel: MyComponent.PropEditorLayout = ({ Section, Separator, Control, Label }) => ...
  3. A variants static listing the supported variants: MyComponent.variants = [{ label: "Default", props: { _variant: "default" }, variables: {} }]
  4. The root element must be w-full max-w-[450px] mx-auto so the component fits the mobile viewport.
  5. Colors come from the funnel's global color system via useColor with globalColorKey. Hardcoding #000000 or text-black produces a component that doesn't adapt across funnels.
  6. Bundled imports are limited to @props, @global, @primitives, react-hook-form (for inputs), and @/lib/utils. To use an external library (Rive, Lottie, GSAP, etc.) inject a <script> tag at runtime — load it from a CDN like unpkg, then read the global the script attaches to window.

Get any of these wrong and the component either fails to register, won't show controls in the props panel, or renders broken in the live funnel.

Two ways to build one#

1. In the Zellify Component Editor#

The Component Editor in the dashboard ships with an AI assistant that has the system prompt and props reference pre-loaded. Open the editor, describe what you want, and the AI generates a working component. This is the easiest path.

See Custom success-page component for an example walkthrough that uses funnel hooks (useVariable, tracker, useFunnelRouter).

2. With your own AI (Cursor, Claude, ChatGPT, Gemini)#

If you want to use your own AI tool — Cursor, Claude Code, Claude.ai, ChatGPT, Gemini, anything — you need to give it the same context our internal AI uses. We publish two files for this:

FileWhat's in itRaw URL
System promptRules, conventions, structure, design system, "things that will break"system-prompt.md
Props referenceEvery prop hook (useText, useColor, useOptions, etc.) with full TypeScript signatures and examplesprops-reference.md

Both files are published as plain markdown so you can curl them, attach them to a Cursor .cursorrules file, paste them into a Claude Project, or feed them to any other tool.

Workflow

  1. Fetch both files. From your terminal:

    Code
    1curl -O https://docs.zellify.app/custom-components/system-prompt.md2curl -O https://docs.zellify.app/custom-components/props-reference.md

    Or open them in a browser and copy the text.

  2. Give them to your AI as context. The exact mechanism depends on your tool:

    • Cursor: drop both files in a .cursor/rules/ folder, or attach them to your prompt with @.
    • Claude Projects: upload both as project knowledge.
    • ChatGPT: paste the system prompt as a custom instruction; attach the props reference as a file.
    • Claude Code / CLI: include both file paths in your prompt.
  3. Describe the component you want. Examples that work:

    • "Build a testimonial card with a 5-star rating, a quote, a customer name, and a circular avatar."
    • "Make a quiz component with 4 image-based options that auto-advances when an option is tapped."
    • "Build a countdown timer that shows days, hours, minutes, seconds — with editable end date and labels."
  4. Paste the output into the Zellify Component Editor. Open the editor, create a new component, paste the generated code, save. The editor type-checks the code and shows the live preview.

  5. Iterate. If something looks off, paste the rendered preview screenshot back to your AI along with the current code and describe the change.

Both files are kept in sync automatically: The published files are copied verbatim from the source the platform's AI uses. They update on every docs deploy.

Common pitfalls#

PitfallWhy it happensFix
Props panel shows nothingForgot to declare props with props.use* hooksEvery editable field must be a hook call
Colors don't change with the funnelHardcoded hex or Tailwind color classUse props.useColor with globalColorKey
Component doesn't fit the pageMissing w-full max-w-[450px] mx-auto on the rootAdd it to the outermost div
Form input doesn't submitForgot useFormContext + Controller from react-hook-formWire form inputs through React Hook Form
Auto-navigation breaks on tab backgroundUsed requestAnimationFrame for timersUse setTimeout with absolute offsets
Variant switcher missingNo variants static arrayAdd at minimum a default variant
AI system prompt
The full system prompt our AI uses. Copy into your own AI tool.
Props reference
Every prop hook with TypeScript signatures and examples.
Components overview
Where custom components fit alongside prebuilt ones.
Custom registration component
Worked example using funnel hooks.