Overview
Advanced elements provide complex functionality like dynamic lists, third-party integrations, and conditional forms. These elements unlock powerful features for sophisticated LinkApps.
Element Use Case arrayDynamic lists of structured items (FAQs, links, products) integrationConnect third-party services (email marketing, etc.) conditionalDisplayShow/hide elements based on other values fileUpload images or documents buttonTrigger actions or workflows
Array
Dynamic array of structured inputs for collecting lists of items. Perfect for FAQs, social links, product lists, or any repeating data.
Properties
Property Type Description idstringUnique identifier (becomes prop name) inputType'array'Must be 'array' titlestringField title descriptionstringHelp text labelstringLabel for the array defaultValuearrayInitial array values array_optionsobjectArray UI configuration array_elementsarrayElement definitions for each item validationobjectValidation rules
Array Options
Configure the array UI in the admin:
Property Type Description minnumberMinimum items required maxnumberMaximum items allowed add_item_button_textstring”Add” button text (empty array) add_second_item_button_textstring”Add” button text (after first item) add_item_titlestringAdd dialog title edit_item_titlestringEdit dialog title item_formatstringDisplay template (e.g., {{question}})
Validation
Rule Type Description requiredbooleanArray must have at least one item maxSizenumberMaximum items (alternative to array_options.max)
Example: Social Links
{
id : "socialLinks" ,
inputType : "array" ,
title : "Social Links" ,
description : "Add your social media profiles" ,
label : "Social profiles" ,
array_options : {
min : 1 ,
max : 5 ,
add_item_button_text : "Add social link" ,
add_second_item_button_text : "Add another link" ,
item_format : "{{platform}}: {{url}}"
},
array_elements : [
{
id: "platform" ,
inputType: "select" ,
title: "Platform" ,
label: "Social platform" ,
options: [
{ label: "Twitter" , value: "twitter" },
{ label: "Instagram" , value: "instagram" },
{ label: "TikTok" , value: "tiktok" },
{ label: "LinkedIn" , value: "linkedin" }
],
validation: { required: true }
},
{
id: "url" ,
inputType: "url" ,
title: "Profile URL" ,
label: "URL" ,
placeholder: "https://twitter.com/username" ,
validation: { required: true }
}
],
validation : {
required : true
}
}
Usage in layout:
type SocialLink = {
platform : 'twitter' | 'instagram' | 'tiktok' | 'linkedin'
url : string
}
type Settings = {
socialLinks : SocialLink []
}
export default function ClassicLayout ({ socialLinks } : AppProps < Settings >) {
return (
< div className = "social-links" >
< h2 > Follow me: </ h2 >
{ socialLinks . map (( link , index ) => (
< a key = { index } href = { link . url } className = { `social- ${ link . platform } ` } >
{ link . platform }
</ a >
)) }
</ div >
)
}
Example: FAQ List
{
id : "questions_list" ,
inputType : "array" ,
title : "Questions" ,
validation : {
required : true ,
maxSize : 20
},
array_options : {
add_item_button_text : "Add a question" ,
add_item_title : "Add question" ,
add_second_item_button_text : "Add another question" ,
edit_item_title : "Edit question" ,
item_format : "{{question}}" // Shows question text in list
},
array_elements : [
{
id: "question" ,
title: "Question" ,
inputType: "text" ,
validation: {
required: true ,
minLength: 1 ,
maxLength: 200
}
},
{
id: "answer" ,
title: "Answer" ,
inputType: "textarea" ,
validation: {
required: true ,
minLength: 1 ,
maxLength: 800
}
}
]
}
Usage in layout:
type Question = {
question : string
answer : string
}
type FAQSettings = {
questions_list : Question []
}
export default function ClassicLayout ({ questions_list } : AppProps < FAQSettings >) {
return (
< div className = "faq" >
< h1 > Frequently Asked Questions </ h1 >
{ questions_list . map (( item , index ) => (
< details key = { index } >
< summary > { item . question } </ summary >
< p > { item . answer } </ p >
</ details >
)) }
</ div >
)
}
Use item_format with {{fieldId}} syntax to show a preview of each item in the admin list view.
Conditional Display
Show or hide elements based on the value of other elements. Creates dynamic forms that adapt to user choices.
Properties
Property Type Description dependsOnstringID of the element this depends on valuestring | booleanValue that triggers display operator'equals' | 'notEquals' | 'contains'Comparison operator (default: 'equals')
Add conditionalDisplay to any element to control its visibility.
elements : [
{
id: "enableNotifications" ,
inputType: "switch" ,
title: "Notifications" ,
label: "Enable email notifications" ,
defaultValue: false
},
{
id: "notificationEmail" ,
inputType: "text" ,
title: "Email Address" ,
label: "Email" ,
placeholder: "you@example.com" ,
validation: {
required: true
},
// Only show if enableNotifications is true
conditionalDisplay: {
dependsOn: "enableNotifications" ,
value: true ,
operator: "equals"
}
}
]
Example: Conditional Based on Select
elements : [
{
id: "integrationProvider" ,
inputType: "select" ,
title: "Integration Provider" ,
options: [
{ label: "Mailchimp" , value: "mailchimp" },
{ label: "SendGrid" , value: "sendgrid" },
{ label: "Custom API" , value: "custom" }
]
},
{
id: "customApiEndpoint" ,
inputType: "url" ,
title: "Custom API Endpoint" ,
placeholder: "https://api.example.com/notify" ,
validation: { required: true },
// Only show if integrationProvider is 'custom'
conditionalDisplay: {
dependsOn: "integrationProvider" ,
value: "custom"
}
},
{
id: "customApiKey" ,
inputType: "text" ,
title: "API Key" ,
placeholder: "Enter your API key" ,
// Also only show for custom
conditionalDisplay: {
dependsOn: "integrationProvider" ,
value: "custom"
}
}
]
Operators
Operator Description Example equalsExact match (default) value: true shows when field is truenotEqualsDoes not match value: "none" shows when field is not “none”containsArray contains value value: "advanced" shows if array includes “advanced”
Use conditional display to reduce form complexity and show users only relevant fields.
Integration
Connect to third-party services like email marketing platforms. Requires users to have the integration already set up in their Linktree account.
Properties
Property Type Description idstringUnique identifier inputType'integration'Must be 'integration' capabilitystringRequired integration capability vendorstringSpecific vendor identifier (optional) titlestringField title descriptionstringHelp text
Example
{
id : "emailIntegration" ,
inputType : "integration" ,
title : "Email Marketing" ,
description : "Connect your email marketing service to collect subscribers" ,
capability : "MANAGE_EMAIL_SUBSCRIBERS" ,
vendor : "mailchimp" // Optional: specific vendor
}
Users must have the integration already connected in their Linktree account. This element lets them select which integration to use with your LinkApp.
File Upload
Upload images, documents, or other file types.
Properties
Property Type Description idstringUnique identifier inputType'file'Must be 'file' titlestringField title descriptionstringHelp text labelstringInput label acceptstring[]Accepted file types multiplebooleanAllow multiple files validationobjectValidation rules
Example
{
id : "bannerImage" ,
inputType : "file" ,
title : "Banner Image" ,
description : "Upload a banner image for your LinkApp" ,
label : "Choose image" ,
accept : [ "image/png" , "image/jpeg" , "image/webp" ],
multiple : false ,
validation : {
required : true
}
}
Interactive button element that triggers actions.
Properties
Property Type Description idstringUnique identifier inputType'button'Must be 'button' labelstringButton text actionobjectAction configuration
Action Properties
Property Type Description on'click'Interaction event type'update-link'Action type data.link_typestringLink type to update to
Example
{
id : "upgradeButton" ,
inputType : "button" ,
label : "Upgrade to Pro Version" ,
action : {
on : "click" ,
type : "update-link" ,
data : {
link_type : "pro-version-app"
}
}
}
Complete Example: Advanced FAQ App
Here’s a complete example using arrays and conditional display:
export default {
settings: {
title: "FAQ Manager" ,
icon: "question-mark" ,
uses_url: false ,
elements: [
// Array of FAQ items
{
id: "questions_list" ,
inputType: "array" ,
validation: {
required: true ,
maxSize: 20
},
array_options: {
add_item_button_text: "Add a question" ,
add_item_title: "Add question" ,
item_format: "{{question}}"
},
array_elements: [
{
id: "question" ,
title: "Question" ,
inputType: "text" ,
validation: { required: true , maxLength: 200 }
},
{
id: "answer" ,
title: "Answer" ,
inputType: "textarea" ,
validation: { required: true , maxLength: 800 }
}
]
},
// Enable search toggle
{
id: "enableSearch" ,
inputType: "switch" ,
title: "Search Options" ,
label: "Enable question search" ,
defaultValue: false
},
// Search placeholder (conditional)
{
id: "searchPlaceholder" ,
inputType: "text" ,
title: "Search Placeholder" ,
label: "Placeholder text" ,
defaultValue: "Search questions..." ,
conditionalDisplay: {
dependsOn: "enableSearch" ,
value: true
}
},
// Enable categories toggle
{
id: "enableCategories" ,
inputType: "switch" ,
title: "Organization" ,
label: "Group questions by category" ,
defaultValue: false
},
// Category list (conditional)
{
id: "categories" ,
inputType: "array" ,
title: "Categories" ,
description: "Define question categories" ,
conditionalDisplay: {
dependsOn: "enableCategories" ,
value: true
},
array_options: {
add_item_button_text: "Add category" ,
item_format: "{{name}}"
},
array_elements: [
{
id: "name" ,
inputType: "text" ,
title: "Category Name" ,
validation: { required: true , maxLength: 50 }
}
]
}
]
}
}
Validation Strategies
Required Arrays
{
id : "items" ,
inputType : "array" ,
validation : {
required : true // At least one item required
}
}
Array Size Limits
{
id : "items" ,
inputType : "array" ,
array_options : {
min : 1 , // Minimum items
max : 10 // Maximum items
}
}
Or use validation.maxSize:
{
id : "items" ,
inputType : "array" ,
validation : {
maxSize : 10
}
}
Nested Validation
Array elements can have their own validation:
array_elements : [
{
id: "email" ,
inputType: "text" ,
validation: {
required: true ,
pattern: "^[^@]+@[^@]+ \\ .[^@]+$" // Email format
}
}
]
Best Practices
Array Design
// ✅ Good - clear item format
array_options : {
item_format : "{{question}}" // Shows question text
}
// ✅ Good - descriptive button text
array_options : {
add_item_button_text : "Add a social link" ,
add_second_item_button_text : "Add another social link"
}
Conditional Display
// ✅ Good - progressive disclosure
{
id : "advancedMode" ,
inputType : "switch" ,
label : "Show advanced options"
},
{
id : "advancedSettings" ,
inputType : "text" ,
conditionalDisplay : {
dependsOn : "advancedMode" ,
value : true
}
}
Array Element Names
// ✅ Good - descriptive IDs
array_elements : [
{ id: "question" , inputType: "text" },
{ id: "answer" , inputType: "textarea" }
]
// ❌ Avoid - unclear
array_elements : [
{ id: "q" , inputType: "text" },
{ id: "a" , inputType: "textarea" }
]
Type Safety
Define array item types:
type Question = {
question : string
answer : string
}
type SocialLink = {
platform : string
url : string
}
type Settings = {
questions_list : Question []
socialLinks : SocialLink []
enableSearch : boolean
searchPlaceholder : string // Only shown if enableSearch is true
}
export default function ClassicLayout ( props : AppProps < Settings >) {
const { questions_list , socialLinks , enableSearch , searchPlaceholder } = props
return < div > ...</ div >
}
Next Steps
Text Inputs Text, textarea, URL, and number inputs
Selection Controls Select, radio, and checkbox elements
Toggles Switch and link behavior elements
Back to Reference Return to settings reference overview