How-To Guide

How to Build Forms with AI: From Prompt to Working Calculator in Minutes

February 2026 · 12 min read

Building a pricing calculator used to mean hours of coding or fighting with drag-and-drop limitations. Now you open a chat, describe what you want, and get working code with real-time calculations. No templates. No limitations. Just describe it.

FormTs has an AI assistant built into the code editor. You describe a form in plain English - field types, pricing logic, conditional behavior - and it writes TypeScript code that compiles into a live, interactive form. The preview updates as the code streams in.

This isn't "AI fills in a template." The AI writes actual form logic: multipliers, tiered pricing, conditional visibility, computed totals. The same code you'd write by hand, generated from a description.

How It Works

The workflow is four steps:

  1. Open the editor and click the AI chat panel
  2. Describe your form - what fields, what pricing, what logic
  3. Watch it generate - code streams in, preview updates live
  4. Refine if needed - edit the code or ask AI to adjust

The AI has full knowledge of FormTs types and API. It knows about dropdowns, sliders, radio buttons, price displays, subforms, multi-page wizards, PDF generation - everything. You describe the result you want, it picks the right components.

Pro tip

The AI chat keeps conversation history per form. You can say "add a discount field" or "change the deep clean multiplier to 1.6" and it modifies the existing code. You don't have to start over.

Example: Cleaning Quote Calculator

Let's start with a real example. You run a cleaning business and want a calculator that shows instant prices based on apartment size, cleaning type, and add-on services.

Here's what you'd type in the AI chat:

Build a cleaning quote calculator:

- Property types: Studio ($60), 1-Bed ($80), 2-Bed ($110), 3-Bed ($140)
- Cleaning types: Standard (1x), Deep Clean (1.5x), Move-Out (1.8x)
- Add-ons: Inside Fridge ($30), Inside Oven ($30),
  Interior Windows ($40), Laundry ($25)
- Show total price updating in real-time
- Don't send to server, calculator only

And here's what AI generates - a complete, working calculator:

export function cleaningCalculator(form: FormTs) {
    const rates: Record<string, number> = {
        'studio': 60, 'one-bed': 80, 'two-bed': 110, 'three-bed': 140
    };
    const typeMultipliers: Record<string, number> = {
        'standard': 1.0, 'deep': 1.5, 'move-out': 1.8
    };

    const details = form.addSubform('details', { title: 'Property Details' });

    details.addRow(row => {
        row.addDropdown('size', {
            label: 'Apartment Size',
            options: [
                { id: 'studio', name: 'Studio' },
                { id: 'one-bed', name: '1 Bedroom' },
                { id: 'two-bed', name: '2 Bedrooms' },
                { id: 'three-bed', name: '3 Bedrooms' }
            ],
            isRequired: true,
            defaultValue: 'one-bed'
        });

        row.addRadioButton('type', {
            label: 'Cleaning Type',
            options: [
                { id: 'standard', name: 'Standard' },
                { id: 'deep', name: 'Deep Clean' },
                { id: 'move-out', name: 'Move-Out' }
            ],
            defaultValue: 'standard',
            orientation: 'vertical'
        });
    });

    const addons = form.addSubform('addons', { title: 'Add-Ons' });

    addons.addRow(row => {
        row.addCheckboxList('extras', {
            label: 'Extra Services',
            options: [
                { id: 'fridge', name: 'Inside Fridge (+$30)' },
                { id: 'oven', name: 'Inside Oven (+$30)' },
                { id: 'windows', name: 'Interior Windows (+$40)' },
                { id: 'laundry', name: 'Laundry (+$25)' }
            ],
            orientation: 'vertical'
        });
    });

    const quote = form.addSubform('quote', {
        title: 'Your Quote',
        isCollapsible: false
    });

    quote.addRow(row => {
        row.addPriceDisplay('total', {
            label: 'Estimated Price',
            computedValue: () => {
                const size = details.dropdown('size')?.value() || 'one-bed';
                const type = details.radioButton('type')?.value() || 'standard';
                const extras = addons.checkboxList('extras')?.value() || [];

                const base = rates[size] || 80;
                const multiplier = typeMultipliers[type] || 1.0;

                let addonsTotal = 0;
                if (extras.includes('fridge')) addonsTotal += 30;
                if (extras.includes('oven')) addonsTotal += 30;
                if (extras.includes('windows')) addonsTotal += 40;
                if (extras.includes('laundry')) addonsTotal += 25;

                return Math.round(base * multiplier + addonsTotal);
            },
            variant: 'large',
            currency: '$'
        });
    });

    form.configureSubmitButton({ label: 'Get Quote' });
    form.configureSubmitBehavior({ sendToServer: false });
}

That's the full output. The form has three sections: property details with a dropdown and radio buttons, add-on checkboxes, and a live price display. Select "2 Bedrooms" + "Deep Clean" + "Inside Fridge" and you instantly see: $110 × 1.5 + $30 = $195.

Every calculation updates in real time. No submit button needed for the price - users see it change as they make selections. The sendToServer: false flag means this is a pure calculator. No backend, no submissions, no database.

Try it yourself - open the editor and describe your calculator.

Writing Better Prompts

The quality of the output depends directly on the quality of your prompt. Vague prompts produce generic forms. Specific prompts produce production-ready calculators.

Bad Prompt

Make me a cleaning form with pricing

This gives AI almost nothing to work with. It will guess at field types, make up prices, and probably miss your business logic entirely.

Good Prompt

Build a cleaning quote calculator:

- Property types: Studio ($60), 1-Bed ($80), 2-Bed ($110), 3-Bed ($140)
- Cleaning types: Standard (1x), Deep Clean (1.5x), Move-Out (1.8x)
- Add-ons: Inside Fridge ($30), Inside Oven ($30),
  Interior Windows ($40), Laundry ($25)
- Show total price updating in real-time
- Don't send to server, calculator only

This tells AI exactly what options exist, what each costs, how multipliers work, and what the form should do. The output matches your actual pricing.

What to Include in Your Prompt

  • Actual prices and rates - don't say "with pricing", say "Studio $60, 1-Bed $80"
  • Multipliers and discounts - "Deep clean costs 1.5x the base rate"
  • Field types you want - dropdowns, sliders, checkboxes, radio buttons
  • Conditional logic - "Show pet fee only if they select pet hair removal"
  • What happens on submit - calculator only, or collect contact info and send to server
  • Currency and formatting - "$", suffix like "/month" or "/visit"

Pro tip

You don't need to know the FormTs API to write good prompts. Say "sliding scale from 10 to 300" instead of "addSlider with min 10 max 300". The AI translates your intent into the correct API calls.

Example: Event Pricing Calculator

Here's a more complex example. An event planning company wants a calculator where customers pick event type, guest count, catering tier, and extras - with venue fees that change based on event type.

The prompt:

"Build an event pricing calculator. Event types: Corporate Meeting (venue $500), Wedding Reception (venue $2000), Birthday Party (venue $300), Charity Gala (venue $1500). Guest slider 10-300. Catering: Basic Buffet $25/person, Premium Plated $55/person, Luxury Tasting $95/person. Add-ons: DJ $500, Photographer $800, Floral $400, Valet $600. Show venue fee separately plus grand total. Calculator only, no submission."

The generated code:

export function eventPricingCalculator(form: FormTs) {
    const event = form.addSubform('event', { title: 'Event Details' });

    event.addRow(row => {
        row.addDropdown('type', {
            label: 'Event Type',
            options: [
                { id: 'corporate', name: 'Corporate Meeting' },
                { id: 'wedding', name: 'Wedding Reception' },
                { id: 'birthday', name: 'Birthday Party' },
                { id: 'gala', name: 'Charity Gala' }
            ],
            isRequired: true
        });
    });

    event.addRow(row => {
        row.addSlider('guests', {
            label: 'Number of Guests',
            min: 10,
            max: 300,
            step: 10,
            defaultValue: 50,
            unit: 'guests'
        });
    });

    event.addRow(row => {
        row.addRadioButton('catering', {
            label: 'Catering Tier',
            options: [
                { id: 'basic', name: 'Basic Buffet ($25/person)' },
                { id: 'premium', name: 'Premium Plated ($55/person)' },
                { id: 'luxury', name: 'Luxury Tasting ($95/person)' }
            ],
            orientation: 'vertical',
            defaultValue: 'basic'
        });
    });

    event.addRow(row => {
        row.addCheckboxList('extras', {
            label: 'Add-Ons',
            options: [
                { id: 'dj', name: 'DJ & Sound System (+$500)' },
                { id: 'photo', name: 'Photographer (+$800)' },
                { id: 'flowers', name: 'Floral Arrangements (+$400)' },
                { id: 'valet', name: 'Valet Parking (+$600)' }
            ],
            orientation: 'vertical'
        });
    });

    // Venue fee depends on event type
    event.addRow(row => {
        row.addPriceDisplay('venueFee', {
            label: 'Venue Fee',
            computedValue: () => {
                const type = event.dropdown('type')?.value();
                const fees: Record<string, number> = {
                    'corporate': 500, 'wedding': 2000,
                    'birthday': 300, 'gala': 1500
                };
                return fees[type || 'corporate'] || 500;
            },
            currency: '$'
        });
    });

    const pricing = form.addSubform('pricing', {
        title: 'Event Estimate',
        isCollapsible: false
    });

    pricing.addRow(row => {
        row.addPriceDisplay('total', {
            label: 'Total Estimate',
            computedValue: () => {
                const guests = event.slider('guests')?.value() || 50;
                const type = event.dropdown('type')?.value() || 'corporate';
                const catering = event.radioButton('catering')?.value() || 'basic';
                const extras = event.checkboxList('extras')?.value() || [];

                // Venue fee
                const venueFees: Record<string, number> = {
                    'corporate': 500, 'wedding': 2000,
                    'birthday': 300, 'gala': 1500
                };
                const venue = venueFees[type] || 500;

                // Catering
                const perPerson: Record<string, number> = {
                    'basic': 25, 'premium': 55, 'luxury': 95
                };
                const cateringCost = guests * (perPerson[catering] || 25);

                // Add-ons
                let addonsCost = 0;
                if (extras.includes('dj')) addonsCost += 500;
                if (extras.includes('photo')) addonsCost += 800;
                if (extras.includes('flowers')) addonsCost += 400;
                if (extras.includes('valet')) addonsCost += 600;

                return venue + cateringCost + addonsCost;
            },
            variant: 'large',
            currency: '$'
        });
    });

    form.configureSubmitButton({ label: 'Get Estimate' });
    form.configureSubmitBehavior({ sendToServer: false });
}

Notice how the AI:

  • Used a slider for guest count (not a text input) because the prompt said "slider 10-300"
  • Created a separate venue fee display that changes based on event type
  • Built the total calculation with three cost components: venue + per-person catering + flat-rate add-ons
  • Set variant: 'large' on the total to make it visually prominent
  • Used Record lookups instead of if/else chains for clean pricing logic

Select "Wedding Reception" + 150 guests + "Premium Plated" + Photographer and you see: $2,000 + (150 × $55) + $800 = $11,050. All updating live as the guest slider moves.

Refining AI Output

AI gets you 80-90% of the way. The structure, field types, and core logic are usually right. What you might want to tweak:

  • Add recurring discounts that AI didn't know about
  • Adjust styling - custom colors, section titles, layout tweaks
  • Add PDF generation for downloadable quotes
  • Fine-tune edge cases in pricing formulas

You can either edit the code directly in the editor (it has full TypeScript IntelliSense) or ask AI to make changes: "Add a 15% discount for recurring weekly bookings."

Example: Adding a Recurring Discount

AI generated a flat price calculation:

quote.addRow(row => {
    row.addPriceDisplay('total', {
        label: 'Estimated Price',
        computedValue: () => {
            const base = rates[size] || 80;
            const multiplier = typeMultipliers[type] || 1.0;
            return Math.round(base * multiplier + addonsTotal);
        },
        variant: 'large',
        currency: '$'
    });
});

You want to add frequency discounts - 20% off weekly, 15% bi-weekly, 10% monthly. You tell AI "add recurring frequency options with those discounts" or edit the code yourself:

quote.addRow(row => {
    row.addPriceDisplay('total', {
        label: 'Estimated Price',
        computedValue: () => {
            const base = rates[size] || 80;
            const multiplier = typeMultipliers[type] || 1.0;
            const subtotal = base * multiplier + addonsTotal;

            // Recurring discount
            const freq = options.radioButton('frequency')?.value() || 'one-time';
            const discounts: Record<string, number> = {
                'one-time': 0, 'weekly': 20, 'bi-weekly': 15, 'monthly': 10
            };
            const discount = subtotal * ((discounts[freq] || 0) / 100);

            return Math.round(subtotal - discount);
        },
        variant: 'large',
        currency: '$',
        suffix: () => {
            const freq = options.radioButton('frequency')?.value();
            if (freq === 'weekly') return '/week';
            if (freq === 'bi-weekly') return '/visit';
            if (freq === 'monthly') return '/month';
            return '';
        }
    });
});

The suffix function dynamically shows "/week", "/visit", or "/month" next to the price based on the selected frequency.

Adding PDF Quotes

Once the calculator works, ask AI: "Add a PDF quote that shows all selections and the total price." It generates the PDF configuration:

form.configurePdf('quote', (pdf) => {
    pdf.configure({
        filename: 'event-quote.pdf',
        allowUserDownload: true,
        header: {
            title: 'Event Quote',
            subtitle: 'Your Personalized Estimate'
        }
    });

    pdf.addSection('Event Details', (section) => {
        section.addRow((row) => {
            row.addField('Event Type', eventType);
            row.addField('Guests', guestCount.toString());
        });
        section.addRow((row) => {
            row.addField('Catering', cateringTier);
        });
    });

    pdf.addSection('Pricing', (section) => {
        section.addRow((row) => {
            row.addField('Venue Fee', '$' + venueFee);
            row.addField('Catering', '$' + cateringTotal);
        });
        section.addDivider();
        section.addRow((row) => {
            row.addField('TOTAL', '$' + grandTotal);
        });
    });
});

After submission, customers can download a professional PDF with their quote details. This works on the free plan.

See how PDF generation works with calculators.

From Prompt to Live Website

The full workflow from idea to embedded calculator takes about five minutes:

  1. Describe your calculator in the AI chat with specific prices, options, and logic. AI generates the code and you see the preview immediately.
  2. Test it by clicking through the preview. Try different combinations, check the math, make sure conditional logic works.
  3. Refine - ask AI to adjust ("make the deep clean multiplier 1.6 instead of 1.5") or edit the code directly.
  4. Create a submission link in the Links tab. This generates a unique URL and embed code for your form.
  5. Embed on your site - paste two lines of HTML. Works on WordPress, Wix, Shopify, Squarespace, or any custom site.

The calculator runs on your website as a lightweight web component. No iframes, no slow loads, no style conflicts. It adapts to mobile automatically.

What AI Handles Well

  • Pricing logic - base rates, multipliers, add-on calculations, tiered discounts
  • Form structure - sections, field types, column layouts, conditional visibility
  • Common patterns - quote calculators, booking forms, product configurators, intake forms
  • Multi-page flows - step-by-step wizards with validation per page
  • PDF generation - structured quote documents from form data

What You'll Want to Tweak

  • Exact pricing formulas - AI might round differently than you want
  • Edge cases - what happens at zero quantity, or when nothing is selected
  • Brand-specific copy - section titles, labels, tooltip text
  • Advanced conditional logic - complex business rules with multiple dependencies
  • Custom styling - colors, fonts, spacing specific to your brand

The split-screen editor makes this easy. Code on the left, live preview on the right. Change a number, see the result instantly.

Beyond the Browser: API and Local AI Tools

The built-in AI chat is the fastest way to get started. But FormTs also exposes a REST API that lets you create and deploy forms programmatically - from your terminal, CI/CD pipeline, or any AI coding assistant.

This means you can use tools like Claude Code, GitHub Copilot, Cursor, or any local LLM to write FormTs code in your own editor, then deploy it via a single API call. The workflow:

  1. Grab the type definitions from formts.com/types. You can copy them to clipboard or download the .d.ts file directly. Feed these types to your AI tool so it knows the full FormTs API.
  2. Write form code locally using your preferred AI assistant. With the types loaded, Claude Code or any other tool can generate valid FormTs code with full type safety.
  3. Deploy via API - one POST request creates or updates your form on FormTs:
curl -X POST https://formts.com/api/forms \
  -H "Authorization: ApiKey sk_formts_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "versionNo": 1,
    "name": "Cleaning Quote Calculator",
    "code": "export function cleaningCalculator(form: FormTs) { ... }",
    "aiInterviewerSettings": null
  }'

That's it. Your form is live. Create a submission link, embed it, and you're done - without ever opening the FormTs editor.

Pro tip

The API is available on the PRO plan. You can generate up to 10 API keys per account in User Settings.

Check the full API Documentation for all endpoints, error codes, and rate limits.

This is particularly powerful for teams that manage many forms. Store your form code in Git, update it locally with AI, deploy via API. Version control, code review, and AI-assisted development - all with your existing workflow.

See all API endpoints and integration examples.

Common Questions

Does the AI understand complex pricing logic?

Yes. It handles tiered pricing, percentage discounts, conditional multipliers, per-unit calculations, and multi-variable formulas. Include your actual numbers in the prompt for best results.

Can I edit the code after AI generates it?

Absolutely. The editor has full TypeScript IntelliSense with autocomplete and error highlighting. You can modify any part of the generated code, or ask AI to make specific changes through the chat.

Does AI work for multi-page forms?

Yes. Describe the steps in your prompt - 'Page 1: property details. Page 2: service options. Page 3: quote summary' - and AI creates a multi-page wizard with navigation and per-page validation.

What if AI generates incorrect code?

The editor validates the code automatically and shows errors. You can ask AI to fix specific issues ('the total doesn't include add-ons, fix that') or edit the code yourself. AI learns from the conversation context.

Do I need to know TypeScript?

Not to generate forms. Write your prompt in plain English and AI handles the code. But basic TypeScript knowledge helps when you want to fine-tune formulas or add custom logic beyond what the prompt covers.

Build Your Calculator in Minutes

Describe what you need. AI writes the code. You get a live calculator.