---
url: /tutorials/01-first-interface.md
---
# Building Your First Interface
> **Type:** Tutorial | **Audience:** New end-user | **Goal:** Create and save a simple interface with Title and Paragraph blocks
## Opening the Application
Interface Builder is accessed from Pipedrive via a OneClick button. When the app loads, you land on the **Interface Selection Page**, which lists all views belonging to this button. You will see two tabs at the top: **Views** and **Variables**.
## Creating a New Interface
1. On the Interface Selection Page, click the **Create New** button next to the **Your Views** heading.
2. The **Create new view** dialog opens.
3. Enter a descriptive **Name** — this name is how you will reference it later when setting up navigation between views. The optional **Description** and **Default view** toggle can be left at their defaults.
4. Click **Create**. The new view opens in the Builder.
## Understanding the Builder
When you open a view, the Builder loads with three main areas:
* **Canvas** (left side) — the main working area where you build your interface by arranging rows and blocks.
* **Sidebar** (right side) — shows configuration options for whatever is selected. It has two main tabs at the top: the current selection tab (Block Settings, Row Settings, etc.) and **View settings**.
* **Top Bar** — a navigation bar at the top of the canvas with the interface name, a back arrow to return to the view list, and three buttons on the right: **Preview**, **Test**, and **Sample data**.
The top bar also shows a **Saving...** spinner indicator whenever your changes are being auto-saved.
## Adding a Row
Before you can place any content blocks, you need a row. Rows define the column layout of your interface.
1. On an empty canvas, click the **Add first row** button. On a non-empty canvas, hover the gap between two rows and click the `+` button that appears.
2. The **Add row** dialog opens.
3. Pick a layout:
* **Full width** — a single column at 100% width
* **Two columns** — two equal 50/50 columns
* **Three columns** — three equal 33/33/33 columns
* **Sidebar left** — 25/75 split
* **Sidebar right** — 75/25 split
* **Form** — adds a Form Start + Form End marker pair (covered in [Building a Form](03-building-a-form.md))
4. The dialog closes and the new row appears on the canvas as an empty container with a grey column placeholder.
## Adding a Title Block
1. Click an empty column inside the row you just created. The **Add block** dialog opens.
2. Pick **Title** from the list.
3. The block appears on the canvas with an empty text value.
## Editing Block Content
1. Click on the Title block in the canvas to select it.
2. The sidebar switches to the **Block Settings** tab.
3. You will see a **Text** field. This is a Data-Picker-enabled input that supports both static text and dynamic data placeholders.
4. Type your title text, for example: `Welcome to My Interface`.
5. The canvas updates in real-time to reflect your changes.
## Adding a Paragraph Block
1. Add another row using the `+` button (or use a multi-column row from before).
2. Click an empty column to open **Add block** and pick **Paragraph**.
3. Click the new Paragraph block to select it.
4. In the **Block Settings** tab you will see a **Value** field — the same Data-Picker-enabled input as the Title block's **Text** field.
5. Type your paragraph text, for example: `This is my first interface built with Interface Builder.`
## Previewing Your Interface
1. Click the **Preview** button in the top bar.
2. The view switches from the Builder to Preview mode.
3. In Preview mode, you see your interface rendered as it will appear to end users. Click the **Pipedrive resource** button at the top to pick a specific deal, person, or organization to test with.
4. To return to the Builder, click the back arrow at the top-left of the Preview screen.
## Saving
Your work is saved automatically. After a brief pause in editing, the Builder saves your latest changes to the server. You will see a **Saving...** indicator with a spinner in the top bar while the save is in progress.
There is no manual save button — just keep building and your changes are persisted.
## Summary
In this tutorial you learned to:
* Open Interface Builder from the Interface Selection Page
* Create a new view via the **Create New** button and the **Create new view** dialog
* Understand the Builder layout: canvas, sidebar, and top bar
* Add rows from the **Add row** dialog and pick column layouts
* Add Title and Paragraph blocks from the **Add block** dialog
* Edit block content via the sidebar
* Preview your interface
* Rely on auto-save for persisting your work
---
---
url: /tutorials/02-data-binding-basics.md
---
# Displaying Pipedrive Data in Your Interface
> **Type:** Tutorial | **Audience:** End-user | **Goal:** Bind Pipedrive resource data to blocks using the Data Picker
## What is Data Binding?
Interfaces display data from Pipedrive resources -- deals, persons, organizations, and more. Instead of typing fixed text, you bind a block's text input to a field through the **Data Picker**, and the field's current value is rendered at run time.
The Data Picker inserts each field as a small **blue tag** into the editor. The compiled syntax behind the tag is `{{resource.field}}` (for example `{{deal.title}}`), but in the builder you do not type that syntax yourself -- you click the tag you want and the editor renders it as a tag.
## Opening the Data Picker
1. Select a block on the canvas (for example, a Title or Paragraph block).
2. In the Block Settings panel, find a **Data Picker-enabled input**: Title's **Text** field, Paragraph's **Value** field, and similar fields on other blocks.
3. Click inside the input. A **Data Picker tooltip** appears next to the field.
4. The tooltip's top bar contains an icon-only row of tabs:
* **Deal** -- deal fields (title, value, currency, owner, ...)
* **Organization** -- organization fields (name, address, ...)
* **Person** -- person fields (name, email, phone, ...)
* **User** -- the current logged-in user
* **Custom** -- the JSON payload returned by your view's API endpoint or your saved Sample data
* **Search Params** -- URL parameters passed in from another view
* **Variable** -- interface-level variables you define in the Variables tab
* **Functions** -- built-in helper functions
## Browsing Available Data
1. Click a tab to see the fields for that resource.
2. Simple fields (such as `title` or `value`) can be clicked directly to insert them as a tag.
3. Nested fields are expandable. For example, the deal's owner is an object -- expand it to pick `owner_id.name`.
4. The Data Picker remembers which tab you last opened.
## Binding a Deal Title to a Title Block
1. Add a **Title** block to your canvas (or select an existing one).
2. In Block Settings, click the **Text** field. The Data Picker opens.
3. Select the **Deal** tab.
4. Click on **Title**.
5. A blue **Title** tag is inserted into the Text field. The compiled value is `{{deal.title}}`, but you don't see the curly-brace syntax -- you see the tag.
## Combining Static Text and Dynamic Data
You can mix typed text with multiple tags in a single field.
1. Add a **Paragraph** block and select it.
2. In the **Value** field, type: `Deal: `
3. Open the Data Picker and insert the deal **Title** tag.
4. Insert the deal **Currency** tag right after it (or with a space between them).
The editor now shows: `Deal:` followed by a Title tag and a Currency tag. The compiled output is `Deal: {{deal.title}} {{deal.currency}}`.
This technique works in any Data Picker-enabled field across all block types.
## Testing with Real Data
1. Click **Preview** in the top bar to switch to Preview mode.
2. In the Preview top bar, next to the **Preview** title, there is a **Pipedrive resource** button labelled with the active resource (for example `Deal #1995`). Click it to open the **Pipedrive resource** dialog and pick a different deal, person, or organization from your account.
3. The system fetches the real data for the selected resource and replaces every Data Picker tag with the actual value.
4. Your Title and Paragraph blocks render with live Pipedrive data.
If a tag references a resource that is not present (for example a person tag when no person is linked), the rendered value may be empty.
## Understanding Data Types
The Data Picker organises fields by data type:
* **String** -- text values such as names, titles, emails.
* **Number** -- numeric values such as deal amounts and phone numbers.
* **Object** -- nested structures (for example `deal.owner_id` containing `name`, `email`, ...). Expand the object to pick a sub-field; the resulting tag follows the path.
* **Array** -- lists of items (for example deal products). Arrays are used by blocks that iterate, such as the Table block (covered in a later tutorial).
When you pick a sub-field of an object, the Data Picker creates a tag that renders the dotted path (for example `owner_id.name`).
## Summary
In this tutorial you learned to:
* Bind block fields by inserting Data Picker tags instead of typing placeholder syntax
* Browse the eight Data Picker tabs (Deal, Organization, Person, User, Custom, Search Params, Variable, Functions)
* Mix static text and multiple tags in a single field
* Preview your interface with a chosen Pipedrive resource via the Preview top-bar dialog
* Work with nested object fields by expanding them in the Data Picker
---
---
url: /tutorials/03-building-a-form.md
---
# Building a Form
> **Type:** Tutorial | **Audience:** End-user | **Goal:** Create a complete form with inputs and a submit button
## How Forms Are Structured
A form in Interface Builder is defined by two marker rows on the canvas -- **Form Start** at the top and **Form End** at the bottom -- with your content rows in between. Every input placed between those markers belongs to the form. A **Submit button** links to the form by its **Form Identifier** and is what users click to send their answers.
The screenshot below shows the finished tutorial form on the canvas: Form Start carries the `contact-form` identifier badge, and the Submit button shows the same `contact-form` badge — that match is how the button knows which form to send.
## Step 1: Add a Form Element
1. Hover the canvas (or the gap between two rows) to reveal a small `+` button.
2. Click `+` to open the **Add row** dialog.
3. Pick **Form** from the layout list.
Two marker rows appear on the canvas: **Form Start** on top and **Form End** at the bottom, with empty space between them.
## Step 2: Give the Form an Identifier
1. Click the **Form Start** row (Form End works too).
2. The sidebar switches to **Form Settings**.
3. In the **Form Identifier** field, enter a descriptive name. For this tutorial, use `contact-form`.
The identifier shows up as a badge on Form Start on the canvas, and it is how the Submit button (added later) will find the correct form.
## Step 3: Add a Full-Name Input
1. Hover the area between Form Start and Form End — a `+` button appears.
2. Click `+`, pick a one-column **Full** layout in the **Add row** dialog.
3. Click the empty column inside that new row to open the **Add block** dialog and pick **Input**.
4. Click the new Input block to open its settings. You will see fields for **Label**, **Type**, **Placeholder**, **Help text**, **Default Value**, **Required**, and **Disabled**.
5. Set **Label** to `Full Name`.
6. Leave **Type** as **Text**.
## Step 4: Add an Email Input
1. Repeat the same steps to add another row inside the form.
2. Add a second Input block in the new column.
3. Set **Label** to `Email Address`.
4. Change **Type** to **Email**.
5. Turn on the **Required** switch.
## Step 5: Add a Selection Input (Optional)
If you want a drop-down or multi-choice field, pick one of these selection types for **Type**: **Single Select**, **Multi Select**, **Checkbox**, or **Radio**. An **Options Type** selector then appears with two choices:
* **Static** -- you define label/value pairs manually. Use the options editor that appears to add each pair.
* **Dynamic** -- options come from data at render time using the Data Picker. Enter Data Picker expressions for **Labels** and **Values**.
## Step 6: Add Pattern Validation (Optional)
For the simple input types (Text, Email, Number, URL, Date) you can add regex validation:
1. In the input settings, scroll to the **Pattern** field and enter a regex (for example, `^[A-Za-z ]+$`).
2. Optionally fill **Pattern Error** with a custom message shown when the pattern fails.
Test your regex at [regex101.com](https://regex101.com/) before pasting it in.
## Step 7: Add a Submit Button
1. Add a new row using the `+` button. It can be inside or outside the form boundaries — both work.
2. Click an empty column in the new row, then pick **Button** in the **Add block** dialog.
3. Click the new Button to open its settings. Set **Button Type** to **Form Submit Button**.
4. A **Form** dropdown appears. Pick `contact-form` from the list.
## Step 8: Configure Submission
Once Button Type is Form Submit Button, extra settings appear. You will set **Form Type**, **Submit URL**, and an **After submission** behavior.
### Form Type
* **JSON** (default) -- posts form values as a JSON payload to the Submit URL.
* **Multipart/Form-Data** -- use this whenever any input has **Type = File**.
* **Open view with form data** -- instead of posting anywhere, navigates to another view and passes input values as URL search parameters.
### Submit URL
For **JSON** and **Multipart/Form-Data**, enter the endpoint in **Submit URL**. Opening the URL input reveals an advanced dialog where you can also add:
* **Headers** -- custom HTTP headers (key/value pairs; values support the Data Picker).
* **Query parameters** -- additional query string pairs.
### After submission
Pick one of:
* **Wait for response** -- waits up to **Timeout (s)** seconds (10--60) for the server to reply. You can turn on **Disable form after submission** (prevents double-submits) and **Show message after submission** (displays the server's confirmation).
* **Select view** -- immediately navigates to a chosen **View ID** after sending. You can pass static parameters, and optionally forward every input value as search parameters to the target view.
## Step 9: Add a Reset Button (Optional)
To let users clear the form:
1. Add another Button block (use the `+` button to add a row, then **Add block** → **Button**).
2. Set **Button Type** to **Form Reset Button**.
3. In the **Form** dropdown, pick `contact-form`.
## Step 10: Test the Form
1. Click **Preview** in the top bar. The form renders with live inputs.
2. Fill in the fields and click the submit button to see the behavior you configured.
3. For an end-to-end test, click **Test** in the top bar -- test mode runs the interface closer to production.
## Summary
In this tutorial you learned how to:
* Pick **Form** in the **Add row** dialog and work with the **Form Start** / **Form End** markers on the canvas
* Set a **Form Identifier** to name the form
* Add **Input** blocks with different **Types** (Text, Email, and selection types)
* Configure selection inputs with **Options Type** (Static or Dynamic)
* Add **Pattern** validation with a custom **Pattern Error** message
* Add a **Form Submit Button** and link it to the form
* Configure **Form Type**, **Submit URL**, **Headers**, and **After submission**
* Add a **Form Reset Button** to clear the form
* Test the form in Preview and Test modes
---
---
url: /tutorials/04-multi-view-app.md
---
# Building a Multi-View Application
> **Type:** Tutorial | **Audience:** End-user (intermediate) | **Goal:** Create an app with multiple views and navigation
## What are Views?
An interface can contain multiple **views** (pages). Each view is a separate canvas with its own rows and blocks. One view is marked as the **default view** -- it carries a green **Start** badge in the views list and is the view displayed by default when the interface loads.
Users navigate between views using:
* **Action buttons** with the "go to view" action
* **Navbar blocks** with interface-type links
Views are managed from the **Interface Views** page, where every view in the current interface is shown as a card.
## Creating a Second View
1. Go back to the **Interface Views** page by clicking the back arrow in the top bar of the Builder.
2. Click **Create New** to open the **Create new view** dialog.
3. Give it a descriptive name (for example `Order summary`) and click **Create**.
4. Back on the Interface Views list, click the **Edit** button on the new view's card to open it in the Builder.
## Building the Second View
1. With the new view open in the Builder, add rows and blocks as needed.
2. For example, add a Title block bound to `{{deal.title}}` and a Paragraph block showing deal details.
3. This view will serve as a detail page that users navigate to from the first view.
## Adding Navigation with an Action Button
On the first view, set up a button that navigates to the second view:
1. Go back to the Interface Views page and open your first view.
2. Add a **Button** block to the canvas.
3. In Button settings, set the **Button Type** to `Action Button`.
4. A new **Action Type** dropdown appears with two options:
* **back** -- navigates to the previous view
* **go to view** -- navigates to a specific view
5. Select **go to view**.
6. A **View Name** dropdown appears, listing all views in this interface. Select the second view you just created.
7. The button now navigates users to that view when clicked.
## Adding a Back Button
On the second view, add a way to return to the first view:
1. Open the second view in the Builder.
2. Add a **Button** block.
3. Set the **Button Type** to `Action Button`.
4. Set the **Action Type** to **back**.
5. This button returns users to whatever view they came from.
The settings panel looks the same as for "go to view" — just without the **View Name** dropdown.
## Passing Parameters Between Views
Action buttons can pass data from one view to another using parameters. The receiving view accesses these values via the **Search Params** tab in the Data Picker.
1. On the first view, select your "go to view" Action Button.
2. Below the View Name dropdown, you will see a **Parameters** section.
3. Click to open the parameters dialog.
4. Add key-value pairs. For example:
* Key: `deal_id`, Value: a Data Picker tag pointing to the deal's **ID** field.
* Key: `deal_title`, Value: a Data Picker tag pointing to the deal's **Title** field.
5. Values support Data Picker expressions, so you can pass dynamic data.
On the receiving view:
1. Select a block (for example, a Title block).
2. Open the Data Picker and switch to the **Search Params** tab (the icon-only tab in the picker's top bar).
3. You will see the parameter keys you defined. Selecting one inserts a tag that compiles to `{{searchparams.deal_id}}`.
## Using Navbar for Navigation
For persistent navigation across your interface, use a **Navbar** block:
1. Add a **Navbar** block to a row on your view. It typically goes in a full-width row at the top.
2. Click the Navbar block to open its settings. The settings are divided into sections.
### Brand
* Toggle **Show title** to display a text title in the navbar. Configure **Title Text**, **Font Size (px)** (12–48), **Font Weight** (Normal, Medium, Semibold, Bold), and **Title Color**.
* Toggle **Show logo** to display a logo image. Provide the **Image URL**, **Alt Text**, and **Width / Height (px)**.
### Aria Label
Below the Brand section, set the **Aria Label** for the navigation element (defaults to "Navigation menu"). This helps screen readers identify the navigation purpose.
### Layout
* **Layout Direction** — Horizontal or Vertical
* **Alignment** — Left, Center, Right, or Space Between
* **Spacing (px)** — pixel spacing between nav items (0–50)
### Navigation Links
1. Click the **Manage Links** button to open the links dialog.
2. Click **Add** to create a new link. Each link has:
* **Label** — the text displayed in the navbar
* **Link Type** — choose between:
* **Interface** — navigates to another view within this interface. Select the target view from the **Target Interface** dropdown. You can also add **Parameters** (key-value pairs) that are passed to the target view.
* **External URL** — opens an external URL (supports Data Picker expressions)
3. Add links for each view you want in your navigation.
4. Reorder links by dragging the grip handle on each link card.
5. Delete links using the trash icon.
## Summary
In this tutorial you learned to:
* Create multiple views from the Interface Views page
* Use Action Buttons with the "go to view" action to navigate between views
* Add "back" buttons for return navigation
* Pass parameters between views using key-value pairs and Data Picker expressions
* Access passed parameters on the receiving view via the Search Params tab
* Set up a Navbar block with interface-type links for persistent navigation
* Configure navbar Brand, Aria Label, Layout, and link settings
---
---
url: /tutorials/05-table-view.md
---
# Building a Table View
> **Type:** Tutorial | **Audience:** End-user | **Goal:** Create a data table with columns and actions
## When to Use Tables
The **Table** block displays array data in a structured grid with rows and columns. Common use cases include:
* Displaying deal products or line items
* Showing lists of related contacts or organizations
* Rendering any array data from Pipedrive or custom sources
Tables support configurable columns, per-row actions, sorting, conditional visibility, and custom styling.
## Adding a Table Block
1. Hover the canvas (or the gap between rows) to reveal the `+` button. Click it and pick **Full** in the **Add row** dialog — full-width works best for tables.
2. Click the empty column inside the new row to open **Add block**, then pick **Table**.
3. Click the Table block to open its settings in the sidebar.
## Setting the Data Source
The table needs an array data source to iterate over.
1. In Table settings, find the **Target Array** field. This is a Data Picker input that specifies which array to display.
2. Click the Target Array field to open the Data Picker.
3. Navigate to an array field. For example, under the **Deal** tab, find a field that contains array data (such as deal products or a custom field that returns a list).
4. You can also use the **Custom** tab if your data comes from a custom JSON source.
5. Select the array field. The placeholder is inserted into the Target Array field.
The table renders one row per item in the array.
## Table Header (Optional)
Above the data source, the sidebar exposes:
* **Table Title** — optional text rendered above the table, for example `Deal Products`. It is plain text: the Data Picker is not available here.
* **Title Alignment** — Left, Center, or Right alignment for the title text.
* **Default Cell Alignment** — fallback alignment applied to every column that does not set its own alignment. Choose Left, Center, or Right.
* **Empty table text** — text shown when the Target Array resolves to an empty list. This is a Data Picker input and supports dynamic values.
## Configuring Columns
Columns define what data appears in each table column. Use the **Manage Columns** dialog to add and configure them.
1. Click the **Manage Columns** button in Table settings.
2. The dialog opens with a column list on the left and a settings panel on the right.
3. Click the **Add** dropdown to add a new column. You can choose between:
* **Add value column** — displays data from each array item.
* **Add action column** — displays clickable action icons.
* **Add subrow** — displays an extra row of text rendered below each row (useful for descriptions or secondary info).
4. Select a column on the left to edit its settings on the right.
Columns can be reordered by dragging the grip handle, duplicated with the copy icon, or deleted with the trash icon. Subrow columns cannot be reordered — they always render below the main row.
Each column has its settings split across four tabs in the right panel:
* **General** — the data fields that drive the column.
* **Styling** — width, cell alignment, and cell padding.
* **Sorting** — whether the column is sortable and how.
* **Conditional** — when the column is visible.
### Value Columns: General Tab
For each value column, fill in:
* **Header** — the column header text. This is a Data Picker input, so you can use static text or dynamic values.
* **Value(s)** — the data field to display for each row. This is a Data Picker input that resolves relative to each array item. For example, if your array contains objects with a `name` property, enter `name` or use the Data Picker to select the field.
### Value Columns: Styling Tab
* **Cell Alignment** — Left, Center, or Right for the cell content.
* **Column Width** — pick **Auto**, or set a fixed width in `%` or `px`.
* **Cell padding** — toggle to override the table default. When enabled, you can set Top, Right, Bottom, and Left padding individually.
### Value Columns: Sorting Tab
* **Allow sorting** — toggle to let end-users click the column header to reorder rows.
* **Sort by this column** — when enabled, this column is the table's default sort. Only one column can hold this flag.
* **Sort direction** — **Ascending** or **Descending** for the default sort.
* **Custom sort value** — when enabled, sort rows by a different value than the displayed one. Provide a Data Picker path for **Sort value**.
### Value Columns: Conditional Tab
* **Enable conditional visibility** — toggle to hide the column based on a condition.
* **Condition** — Data Picker expression. The column is hidden when the value resolves to empty or `"false"`. Any other value shows the column.
## Action Columns
Action columns add clickable buttons to each row, allowing users to perform operations on individual items. A button can show an icon, a text label, or both.
1. In the Manage Columns dialog, click **Add** and select **Add action column**.
2. The General tab shows the column's **Header** plus an accordion of **actions**. Each action has:
* **Icon** — choose from grouped **Actions**, **Communication**, **Files**, and **Status** icons. The set includes View, Edit, Delete, Add, Copy, Play, Refresh, External link, Mail, Send, Phone, Message, Bell, User, File, Folder, Download, Upload, Image, Attachment, Print, Archive, Check, Close, Warning, Info, Clock, Star, Heart, Lock, and Unlock. Select **Custom** to fill **Custom Icon** with an image URL through the Data Picker.
* **Action Type** — pick **Go to view** to navigate within the interface, **Go to URL** to open a URL, or **Send request** to send a POST without leaving the table.
* **Label** — optional button text, shown after you pick an Action Type. It supports the Data Picker and resolves per row. With a Label set, **Icon position** chooses which side the icon sits on, and the Icon picker offers **No icon** for a text-only button.
* **View Name** — when Action Type is **Go to view**, pick the destination from the dropdown. Optionally configure **Parameters** (key-value pairs passed to the target view; values reference fields from the current row).
* **URL** — when Action Type is **Go to URL**, fill the address. The URL field supports Data Picker expressions, so you can construct URLs with row data.
* **Request URL** — when Action Type is **Send request**, enter an absolute HTTP or HTTPS endpoint. Use the Data Picker to include row values.
* **Body Data** — optionally configure a JSON payload as JSON or key-value pairs. Include the row's identifier because OneClick metadata identifies the view resource, not the row. Leave it empty for no configured body.
* **Omit OneClick metadata envelope** — leave off to send Body Data alongside OneClick metadata; turn on to send only Body Data. Test requests in the Test view; Preview shows them disabled.
* **Require confirmation** — when Action Type is **Send request**, turn this on to ask before the request is sent. The **Title** and **Description** support the Data Picker, so the dialog can name the row it acts on.
3. Click **Add Action** to add more actions to the same column.
4. Each action can be duplicated or deleted from the action's accordion menu.
The Styling, Sorting, and Conditional tabs apply to action columns in the same way as value columns.
### Passing Row Data to Another View
When an action navigates to a view, you can pass data from the current table row:
1. Set the action's **Action Type** to **Go to view**.
2. Choose the target view from **View Name**.
3. Expand the **Parameters** section.
4. Add key-value pairs where the values reference fields from the current array item. The Data Picker context is scoped to the current row, so you can directly select fields from the row item.
## Subrow Columns
A **subrow** column adds a second line of text below each main row — useful for descriptions, hints, or secondary details that do not need their own column.
* **Path** — the data field rendered as the subrow's text (Data Picker).
* The Styling tab supports **Cell Alignment** and **Cell padding** for the subrow text. Conditional visibility is not available for subrow columns.
## Customizing Appearance
In addition to per-column styling, the Table block uses the standard block style settings:
* **Background color**
* **Font size and color**
* **Borders** — top, right, bottom, and left borders with width, style, and color
The table renders with structured headers and data rows. When the array is empty, the **Empty table text** (if configured) is shown.
## Summary
In this tutorial you learned to:
* Add a Table block and set its data source via the **Target Array** field
* Configure the **Table Title**, **Title Alignment**, **Default Cell Alignment**, and **Empty table text** at the table level
* Add **value**, **action**, and **subrow** columns from the **Manage Columns** dialog
* Configure each column across the **General**, **Styling**, **Sorting**, and **Conditional** tabs
* Add **Go to view**, **Go to URL**, and **Send request** actions with per-row data
* Toggle **Allow sorting**, set a default sort column and direction, and use a custom sort value
* Hide columns conditionally using the **Conditional** tab
---
---
url: /how-to/blocks/alert-and-badge.md
---
# How to Use Alert and Badge Blocks
> **Type:** How-to | **Audience:** End-user | **Goal:** Add notification alerts and status badges
## Alert Block
1. Hover the gap between two rows and click the `+` button to add a row, then click an empty column and pick **Alert** in the **Add block** dialog.
2. Click the new block to open its settings in the sidebar.
### Setting the Variant
The variant controls the alert's visual style. The Variant card has two tabs:
**Select tab** (default): Pick a variant from the dropdown:
* **Default** -- neutral style
* **Destructive** -- red, for errors
* **Info** -- blue, for informational messages
* **Success** -- green, for confirmations
* **Warning** -- yellow/amber, for caution
**Data tab**: Use the Data Picker to bind the variant to a data field. The field value must be one of: `default`, `destructive`, `info`, `success`, `warning`.
### Title and Description
* **Title (Optional)**: Use the Data Picker to set the alert title. You can type static text or pick a dynamic value from your data source using `{{resource.field}}` syntax.
* **Description**: Use the Data Picker to set the alert body text. Same static/dynamic options as title.
***
## Badge Block
1. Hover the gap between two rows and click the `+` button to add a row, then click an empty column and pick **Badge** in the **Add block** dialog.
2. Click the new block to open its settings in the sidebar.
### Setting the Variant
Like Alerts, Badges have **Select** and **Data** tabs in the Variant card.
Static variants available:
* Default, Destructive, Info, Success, Warning, Secondary, Outline, Pink, Violet, Light Blue, Disabled
In the Data tab, use the Data Picker to bind the variant to a data field. Valid values: `default`, `destructive`, `info`, `success`, `warning`, `secondary`, `outline`, `pink`, `violet`, `lightBlue`, `disabled`.
### Setting the Value
Use the **Text** field to set the badge text. You can type static text or use the Data Picker with `{{resource.field}}` to pull values dynamically from your data source.
---
---
url: /how-to/blocks/avatar.md
---
# How to Add Avatars
> **Type:** How-to | **Audience:** End-user | **Goal:** Display profile/avatar images
## Adding an Avatar Block
1. Hover the gap between two rows and click the `+` button to add a row (pick any layout in the **Add row** dialog).
2. Click an empty column inside the row, then pick **Avatar** in the **Add block** dialog.
3. Click the new block to open its settings in the sidebar.
## Image Source
Use the **Image URL** field to set the avatar image URL. Typically you bind this to a dynamic data field such as a Pipedrive user photo or person photo URL using `{{resource.field}}` syntax.
If the URL resolves to a valid image, the avatar displays that image.
## Fallback Text
Use the **Fallback Name** field to define fallback text shown when no image is available. This is typically a person's name -- the avatar automatically extracts initials from the first two words (e.g., "John Doe" becomes "JD").
You can use static text or bind it dynamically via the Data Picker.
## Size Selection
Choose the avatar size from the dropdown:
* **Small (32px)**
* **Medium (40px)** — default
* **Large (56px)**
---
---
url: /how-to/blocks/button.md
---
# How to Add and Configure Buttons
> **Type:** How-to | **Audience:** End-user | **Goal:** Configure all button types
## Adding a Button Block
1. Add a row if you do not have one yet — hover the gap between two rows to reveal the `+` button, click it, and pick a layout.
2. Click an empty column inside the row to open the **Add block** dialog.
3. Pick **Button** from the list.
4. Click the new block to open its settings in the sidebar.
5. Choose a **Button Type**: **URL Button**, **Action Button**, **Form Submit Button**, or **Form Reset Button**.
***
## URL Button
Opens a URL or makes an API call when clicked.
1. Set **Button Type** to **URL Button**.
2. Optionally fill **Button Identifier** -- a unique identifier for tracking this button.
3. Choose the **Button URL** mode:
* **Use view base url** -- appends a path to your view's base URL.
* **Use custom url** -- a fully custom URL.
4. For **Use view base url**, set **Path**. For **Use custom url**, set **Custom URL**. Both support the Data Picker for dynamic values.
5. Optionally configure:
* **Button Body Data** -- JSON or form-encoded body sent with the request.
* **Headers** -- custom HTTP headers (key/value pairs). If the OneClick button this interface is attached to has its **Headers** toggle enabled, those headers are merged into the URL button's request automatically — see [OneClick-Level Headers](../../explanation/architecture.md#oneclick-level-headers).
* **Query parameters** -- URL query parameters (key/value pairs).
* **Wait page transition** -- enable to wait for interstitial messages and redirects from your backend (see below).
* **Page Transition Timeout** -- how long to wait for the backend (in seconds).
### How a URL button handles the response
For the request shape your endpoint receives and the polling loop that runs while **Wait page transition** is on, see [URL Button Flow](../../explanation/url-button-flow.md).
When the user clicks a URL button, Interface Builder calls your backend and then:
* **If Wait page transition is off**, the response is used once: a string body becomes a success toast, an `oneclick_data` response can show a toast and/or navigate the user. Nothing else happens.
* **If Wait page transition is on**, Interface Builder keeps polling for updates from your backend for up to **Page Transition Timeout** seconds. Every time your backend writes a new message, the user sees it as a toast. If your backend eventually returns a redirect, the user is navigated there.
Use **Wait page transition** when the action behind the button takes time to complete and you want to show progress (for example, "Validating…", "Charging card…", "Creating invoice…") and then jump the user to a result page when done.
**Response shapes:**
```json
{ "oneclick_data": { "message": "Item added to cart" } }
```
Shown as a success toast.
```json
{
"oneclick_data": {
"message": "Payment successful",
"redirect_view": { "id": "receipt-view", "params": { "order_id": "4321" } }
}
}
```
Shown as a toast, then user is navigated to `receipt-view`.
```json
"Thanks!"
```
A plain string response is shown as a success toast.
See [HTTP Response Format](../../reference/data-binding/http-response-format.md) for every shape the button accepts, and [Messages & Toasts](../data/messages-and-toasts.md) for how to format the message text.
If the backend times out or returns an error, the user sees an error toast. No navigation happens.
***
## Action Button
Navigates between views in your interface.
1. Set **Button Type** to **Action Button**.
2. Choose the **Action Type**:
* **go to view** -- navigate to a specific view.
* **back** -- go to the previous view.
3. For **go to view**, select the target view from the **View Name** dropdown.
4. Optionally add **Parameters** -- key-value pairs passed to the target view.
***
## Form Submit Button
Submits a form's data.
1. Set **Button Type** to **Form Submit Button**.
2. Select the target form from the **Form** dropdown. This links to the **Form Identifier** set on the form.
3. Choose the **Form Type**:
* **JSON** (default) -- sends form data as JSON. Requires a Submit URL.
* **Multipart/Form-Data** -- sends as multipart data (use for file uploads). Requires a Submit URL.
* **Open view with form data** -- passes form data to another view without making an HTTP request. Submit URL is not required.
4. For **JSON** and **Multipart/Form-Data**, set the **Submit URL** -- the endpoint that receives the data.
5. Configure **After submission**:
* **Select view** -- navigate to a chosen view after submission. Optionally pass parameters or forward input values as search params.
* **Wait for response** -- wait for the server response (timeout: 10-60 seconds). Optionally enable **Disable form after submission** to prevent double-submits, or **Show message after submission** to display a confirmation.
6. Optionally configure **Headers** and **Query parameters** for the request.
See [Configuring Form Submission](../forms/form-submission.md) for full details on submission behavior.
***
## Form Reset Button
Clears all fields in a form back to their default values.
1. Set **Button Type** to **Form Reset Button**.
2. Select the target form from the **Form** dropdown.
***
## Asking for Confirmation
Use a confirmation when a click deletes, sends, approves, or clears something. The button then opens a dialog and runs its action only after the user confirms. It works on all four button types.
1. Select the button and scroll to the **Confirmation** section at the bottom of the **Configuration** tab.
2. Turn on **Require confirmation**. The dialog is filled in for you: "Are you sure?", **Confirm**, and **Cancel**, with the Confirm choice copying the button's own variant.
3. Write the **Title** as the question the user answers, for example `Delete {{deal.title}}?`. It supports the Data Picker, so a button inside an Area loop asks about that iteration's record.
4. Optional: add a **Description** with what will happen. It also supports the Data Picker and keeps its line breaks.
5. Optional: adjust **Confirm Button Label** and **Confirm Button Variant** — pick **Destructive** for a delete — and the matching **Cancel** fields.
6. Test the button in the Test view: the dialog must open, and the action must run only after **Confirm**.
Cancel and Escape close the dialog and change nothing. Turning **Require confirmation** back off keeps the texts you wrote, so removing the gate for a test costs nothing.
### On a Form Submit Button
The dialog opens before the form is validated, so a user can confirm and then meet "field required". This is expected: the submission runs unchanged after the confirmation, validation and all. Keep the Title about the action ("Send the application?") rather than about the data being complete.
Pressing Enter in a text input opens the dialog too — the form clicks the gated button for you, so Enter cannot skip the question.
***
## Button Appearance
Variant and size live on the **Style** tab in Block Settings (next to **Configuration** and **Visibility**).
### Button Variant
Choose a visual style from the **Button Variant** selector:
* **Default** -- primary filled button
* **Destructive** -- red/danger style
* **Outline** -- bordered, no fill
* **Secondary** -- muted/secondary fill
* **Ghost** -- no border or fill, text only
* **Link** -- styled as a hyperlink
* **Custom** -- unlocks the rest of the Block Style panel (font size/weight/colours, etc.) so you can build your own look. The other variants ignore those custom style fields.
### Button Size
Choose from: **Small**, **Default**, or **Large**.
### Icons
Both icon slots sit on the same **Style** tab, between **Button Size** and **Button Variant**.
1. Open **Icon before text** and pick a glyph, or **Icon after text** for a trailing one.
2. Pick from the groups **Actions**, **Navigation**, **Communication**, **Files** and **Status**.
3. Choose **No icon** to clear a slot again.
The glyph takes the button's text colour and is always 16 px, so every Button Variant works.
### Making a button icon-only
Use this for a dense row of controls where the words cost more width than they earn.
1. Pick a glyph in **Icon before text**.
2. Turn **Show text** off.
The button becomes a square of the height its **Button Size** already had, keeping its variant colours.
What to expect:
* **Show text** stays unavailable until you pick an icon, and a note below it tells you so. A button with no text and no glyph would be empty.
* **Icon after text** becomes unavailable while the text is hidden. If your only glyph was in that slot, it moves to **Icon before text** when you hide the text.
* The block name is still the button's name: a screen reader announces it, and it appears as a tooltip on hover.
* Your service still receives the block name as the button name in the URL Button metadata.
* On a **Form Submit Button** with **Show error indicator on submit**, the hover reports the invalid field count while the form has errors; the name tooltip returns once the errors are fixed. The badge and the loading spinner are unaffected.
---
---
url: /how-to/blocks/chart.md
---
# How to Add Charts
> **Type:** How-to | **Audience:** End-user | **Goal:** Create bar, line, area, or pie charts
## Adding a Chart Block
1. Hover the gap between two rows and click the `+` button to add a row (pick any layout in the **Add row** dialog).
2. Click an empty column inside the row, then pick **Chart** in the **Add block** dialog.
3. Click the new block to open its settings in the sidebar.
## Selecting Chart Type
Choose the chart type from the **Chart Type** dropdown:
* **Bar** -- vertical bar chart (default)
* **Line** -- line chart
* **Area** -- filled area chart
* **Pie** -- pie/donut chart
## Configuring Data Source
Use the **Data Source** field to bind the chart to an array data source. The Data Picker only allows array-typed values here; pick the array field that holds your data points (it will appear as a blue tag, for example a custom field that resolves to a list of invoices).
Each item in the array must be an object whose properties supply the values and labels for the chart.
## Setting Keys
* **Data Keys** -- comma-separated list of property names to plot as values. For a single series, enter one key (for example `amount`). For multi-series charts, separate with commas (for example `paid,open,overdue`).
* **Name Key** -- the property used for labels on the X-axis or pie segments. Defaults to `name`.
Example data structure (matching the screenshot):
```json
[
{ "invoice_number": "INV-2026-001", "customer": "Acme Corporation Ltd", "amount": 12500, "status": "Paid" },
{ "invoice_number": "INV-2026-002", "customer": "Nordic Solutions AB", "amount": 2400, "status": "Paid" },
{ "invoice_number": "INV-2026-003", "customer": "TechVenture GmbH", "amount": 8750, "status": "Open" },
{ "invoice_number": "INV-2026-004", "customer": "Greenfield Industries","amount": 15000, "status": "Open" }
]
```
With **Data Keys** = `amount` and **Name Key** = `customer`, each row becomes one bar/segment labelled by customer name.
## Visual Options
* **Height** -- chart height in pixels (100--800, default `300`)
* **Show Grid** -- toggle background grid lines on/off (default on)
* **Show Tooltip** -- toggle hover tooltips on/off (default on)
* **Show Legend** -- toggle the chart legend on/off (default off)
---
---
url: /how-to/blocks/hover-card.md
---
# How to Use Hover Cards
> **Type:** How-to | **Audience:** End-user | **Goal:** Add tooltip-style hoverable cards
## Adding a Hover Card Block
1. Hover the gap between two rows and click the `+` button to add a row (pick any layout in the **Add row** dialog).
2. Click an empty column inside the row, then pick **Hover Card** in the **Add block** dialog.
3. Click the new block to open its settings in the sidebar.
## Trigger Type
Choose what the user hovers over to reveal the card. Set **Trigger Type** to:
* **Text Only** — displays trigger text only (default)
* **Icon Only** — displays an icon only
* **Text + Icon** — displays both text and an icon
When the trigger includes text, fill the **Trigger Text** field. You can use static text or bind it dynamically with the Data Picker.
## Icon Configuration
When the trigger type includes an icon (**Icon Only** or **Text + Icon**), the sidebar shows two extra fields:
* **Icon Type** — pick the icon style: **Warning (Triangle)**, **Info (Exclamation)**, or **Question (Help)**. Default: **Question (Help)**.
* **Icon Color** — pick the icon color: **Gray**, **Red**, **Yellow**, **Blue**, or **Green**. Default: **Gray**.
## Content, Width, Alignment
* **Content** — the hover card body content. Use static text or the Data Picker for dynamic values.
* **Width** — set the card width in pixels (100–600). Default: 320.
* **Alignment** — set card alignment relative to the trigger: **Start**, **Center**, or **End**. Default: **Center**.
---
---
url: /how-to/blocks/html.md
---
# How to Use the HTML Block
> **Type:** How-to | **Audience:** Advanced end-user | **Goal:** Embed custom HTML content
## Adding an HTML Block
1. Hover the gap between two rows and click the `+` button to add a row (pick any layout in the **Add row** dialog).
2. Click an empty column inside the row, then pick **HTML** in the **Add block** dialog.
3. Click the new block to open its settings in the sidebar.
## Writing HTML Content
Enter your HTML markup in the **HTML** field. The field accepts whatever you paste -- there is no validation in the builder itself.
> **Pasting from ChatGPT or similar tools**
> Pasted content is normalised before it is saved: smart quotes (`"` `"` `'` `'`) become straight quotes, en/em dashes (`–` `—`) become hyphens, non-breaking spaces become regular spaces, and zero-width characters and Windows line endings are stripped. This prevents invisible artefacts from breaking your markup. Valid HTML entities like `&` are left untouched.
When the view renders, the HTML is run through a sanitiser. Only a fixed allowlist of tags survives:
`p`, `span`, `div`, `br`, `hr`, `h1`--`h6`, `ul` / `ol` / `li`, `dl` / `dt` / `dd`, `table` / `thead` / `tbody` / `tfoot` / `tr` / `th` / `td` / `caption` / `colgroup` / `col`, `a`, `img`, `figure`, `figcaption`, `details`, `summary`, plus inline-formatting tags (`strong`, `b`, `em`, `i`, `u`, `s`, `strike`, `del`, `ins`, `sub`, `sup`, `small`, `mark`, `abbr`, `code`, `pre`, `blockquote`).
Allowed attributes: `href`, `src`, `alt`, `title`, `width`, `height`, `colspan`, `rowspan`, and `style` (so inline CSS is supported).
Anything else -- `ok"` → `"ok"`
## Allowed attributes
* `` accepts `href`. All other attributes are dropped.
* Event-handler attributes (`onclick`, `onerror`, and so on) are stripped from every tag.
* `
`, `