What Typeform Actually Does
Typeform is a form and survey builder that presents one question at a time with smooth transitions between them. This single-question-per-screen approach dramatically increases completion rates compared to traditional forms that show everything at once. Beyond the UX pattern, Typeform offers a drag-and-drop form builder for creators, multiple question types (text, multiple choice, rating, file upload, etc.), conditional logic that shows different questions based on previous answers, response collection and analytics, and integrations that push form data to other tools.
The product has two distinct sides: the builder experience where form creators design their forms, and the respondent experience where people fill them out. Both need to be well-built for the product to work.
Core Features Worth Cloning
A viable form builder needs a form creation interface with question management, support for multiple question types (short text, long text, multiple choice, checkboxes, rating scale, date, number, email, file upload, yes/no), the one-question-at-a-time presentation, conditional logic (if answer to Q1 is X, skip to Q5), a progress indicator showing how far through the form the respondent is, a thank-you or completion screen, response collection in a structured database, a basic analytics dashboard showing completion rate and answer distributions, and shareable form URLs. Skip the integration marketplace, payment collection within forms, advanced theming and custom CSS, workspaces with team permissions, and the logic map visual editor. Build integrations case-by-case and add themes after you have a working builder.
Data Architecture in Bubble
The data model needs to handle dynamic form structures. You are essentially building a tool that lets users create database schemas without knowing what databases are.
The Form data type stores form_title (text), description (text), creator (User), slug (text, for the public URL), is_published (yes/no), theme_colour (text), welcome_screen_title (text), welcome_screen_description (text), thank_you_title (text), thank_you_description (text), redirect_url (text, optional redirect after completion), total_responses (number, denormalised for quick display), and created_date (date).
The Question data type needs form (Form), question_text (text), question_type (option set: short_text, long_text, multiple_choice, checkboxes, rating, date, number, email, file_upload, yes_no, dropdown, opinion_scale), description (text, helper text shown below the question), is_required (yes/no), position (number with gaps), placeholder_text (text), and settings specific to each type. For rating questions, add max_rating (number). For opinion scale, add scale_min (number), scale_max (number), label_min (text), label_max (text). You can either add all type-specific fields to the Question type (simpler, some fields will be unused per question) or create separate settings types per question type (cleaner, more complex).
The Choice data type handles multiple choice and checkbox options. It stores question (Question), choice_text (text), position (number), and image (image, for picture choice questions). Keep choices as separate records rather than a comma-separated list. This makes reordering, editing, and deleting individual choices much cleaner.
The Conditional Logic Rule data type stores source_question (Question), condition_type (option set: equals, not_equals, contains, greater_than, less_than), condition_value (text), and target_question (Question, the question to jump to if the condition is met). When the respondent answers the source question and the condition is true, skip to the target question instead of the next one in sequence.
The Response data type represents a single form submission. It stores form (Form), respondent_email (text, if collected), started_at (date), completed_at (date), is_complete (yes/no), and ip_address (text, optional). Each response is one person's complete (or partial) form submission.
The Answer data type stores the individual answers. It needs response (Response), question (Question), text_value (text, for text inputs), number_value (number), date_value (date), selected_choices (list of Choices, for multiple choice and checkboxes), file_value (file, for uploads), and boolean_value (yes/no). Similar to Notion's cell value pattern, one answer record per question per response. The appropriate value field is populated based on the question type.
Building the Form Builder
The builder interface is where form creators add and configure questions. Display a repeating group of Questions sorted by position. Each question in the list shows a preview of the question with its type icon, the question text, and action buttons (edit, duplicate, delete, reorder). When the creator clicks to edit a question, show the configuration panel. This can be a popup, a sliding panel, or an inline expansion. The configuration panel shows the question text input, question type dropdown (changing this adjusts which settings are visible), the is_required toggle, description text input, and type-specific settings.
For multiple choice questions, the configuration includes a repeating group of Choices with add, edit, and delete functionality for each option. For rating and scale questions, show number inputs for min, max, and text inputs for labels. Use conditional visibility on the configuration panel to show only the relevant settings for the selected question type.
Adding a new question creates a Question record with the form reference, a default type (short text), and a position value higher than the current last question. Deleting a question either removes the record or marks it as deleted (soft delete is safer if you want undo functionality).
For reordering, implement move-up and move-down buttons that swap position values between adjacent questions. This is much simpler than drag-and-drop and works reliably in Bubble.
The Respondent Experience
This is where Typeform's magic happens. Show one question at a time on a full-screen card. The respondent answers and clicks "Next" (or presses Enter) to advance. Here is how to build it.
Use a custom state on the page called "current_question_index" (number, starting at 0 for the welcome screen). Load all questions for this form into a repeating group (hidden) or use a custom state that holds the list of questions. Display the current question by filtering to the question at the current index position. Show the appropriate input element based on question_type using conditional visibility: a text input for short_text, a multiline input for long_text, a repeating group of choice buttons for multiple_choice, and so on.
When the respondent clicks "Next," first validate the answer (check if required, validate email format, etc.). If valid, save the answer by creating an Answer record linked to the current Response and Question. Then check conditional logic: search for Conditional Logic Rules where source_question is the current question. Evaluate the condition against the given answer. If a matching rule exists, jump to the target question's position. If no rule matches, increment current_question_index by 1.
Animate the transition between questions using Bubble's animation workflows. Fade out the current question group and fade in the next one. Add a progress bar at the top that shows current_question_index divided by total questions as a percentage. The completion screen triggers when current_question_index exceeds the total number of questions. Display the thank-you message and optionally redirect to the redirect_url.
Response Analytics
The analytics dashboard shows form-level metrics: total responses, completion rate (completed divided by started), average completion time, and responses over time. For individual questions, show answer distributions. For multiple choice, display a bar chart of how many respondents selected each choice. For rating questions, show the average rating and distribution. For text answers, display them in a scrollable list. Use Bubble's charting plugins (Chart Element or a third-party chart plugin) for visual displays. Calculate metrics using Bubble's aggregation operators: count, average, and grouped-by on the Response and Answer data types.
Privacy Rules
Published forms should be publicly accessible (the form structure, not the responses). Form builder and settings should only be accessible to the creator. Response data should only be accessible to the form creator. Individual respondents should not see other people's answers. Answer records should inherit their response's visibility rules. Draft forms should only be visible to the creator.
Cost and Timeline
A form builder with the one-at-a-time UX takes 6 to 10 weeks for an experienced Bubble developer. Conditional logic adds complexity but is manageable. Analytics with charts adds 1 to 2 weeks. Bubble's Growth plan at $119 per month handles the backend workflows for response processing. Annual costs run $1,500 to $3,000 including charting plugins.
Build or Hire
A form builder is a strong intermediate Bubble project. The data model is the entity-attribute-value pattern, which takes planning but is well-documented. The one-question-at-a-time UX is mostly custom states and conditional visibility, which are core Bubble concepts. Conditional logic adds complexity but is manageable if you keep the condition types simple initially.
Related guides:
Bubble zapier integration guide
how to build a directory with Bubble
Building a form tool, survey platform, or quiz app? Talk to Goodspeed Studio about building it efficiently on Bubble.
Forms Are a Solved Problem, But Niches Are Not
Typeform proved that UX matters in forms. Your clone should prove that a specific audience needs a form experience Typeform does not offer. Maybe it is HIPAA-compliant intake forms, interactive product configurators, or quiz-based lead qualification. Build the core one-question-at-a-time engine, then specialise for your audience. Talk to our Bubble developers.

Harish Malhi
Founder of Goodspeed
Harish Malhi is the founder of Goodspeed, one of the top-rated Bubble agencies globally and winner of Bubble’s Agency of the Year award in 2024. He left Google to launch his first app, Diaspo, built entirely on Bubble, which gained press coverage from the BBC, ITV and more. Since then, he has helped ship over 200 products using Bubble, Framer, n8n and more - from internal tools to full-scale SaaS platforms. Harish now leads a team that helps founders and operators replace clunky workflows with fast, flexible software without writing a line of code.
Frequently Asked Questions (FAQs)
How do I build the one-question-at-a-time experience in Bubble?
Use a custom state to track the current question index. Display the question at that index using conditional visibility. On Next, save the answer, check conditional logic, and increment the index. Add fade animations between transitions for the Typeform feel.
Can Bubble handle conditional logic in forms?
Yes. Create a Conditional Logic Rule data type linking source questions to target questions with conditions. After each answer, check if any rules match. If a rule matches, jump to the target question. If not, go to the next question in sequence.
How do I store responses for different question types?
Use an Answer data type with separate value fields for each data type: text_value, number_value, date_value, selected_choices, file_value, and boolean_value. Populate the appropriate field based on the question type.
Can I add analytics and charts to a Bubble form builder?
Yes. Use Bubble's Chart Element plugin or integrate a charting library. Calculate metrics using Bubble's aggregation operators on the Response and Answer data types. Show completion rates, answer distributions, and response trends.
How long does it take to build a Typeform clone on Bubble?
Six to 10 weeks for an experienced Bubble developer. Conditional logic and analytics charts each add one to two weeks. The form builder interface and respondent experience are roughly equal in development effort.
Can respondents save partial form responses?
Yes. Create the Response record when the respondent starts the form and save each Answer as they progress. Mark the response as incomplete until they reach the end. They can return via a unique link to continue where they left off.
