Widget Categories
Key Capabilities
Quick Links
Getting Started
Build your first interactive app in a few minutes. No prior experience required.
The Builder Interface
Your First App — Step by Step
Open the Widgets tab in the left panel. Find a widget (e.g. Button) and drag it onto the canvas. It appears at your drop position.
Click the widget to select it. The right Properties Panel shows all configurable properties — change the label text, colours, size, and font directly.
In Properties Panel, scroll to Events and click the script icon next to onClick. The Script Editor opens — write your first script:
show toast "Hello, World!"
Click the ▶ Preview button in the top bar. Your app goes live in an interactive preview. Click your button to see the toast message appear.
Click the + next to the Card Tabs at the top of the canvas to add new pages/screens. Use go to card CardName in scripts to navigate between them.
When ready, click Publish in the top bar. The app appears in the App Library for regular users to launch. Or use Export to download a standalone HTML file.
Essential Script Patterns
Show / Hide Widgets
show widget MyPanel
hide widget LoadingSpinner
show loading -- full-screen overlay
hide loading
Read and Set Widget Properties
-- Read the current value of a widget
set variable userName to the text of widget NameField
-- Set a widget property
set the text of widget StatusLabel to "Welcome, " + userName + "!"
set the bgColor of widget MyButton to "#10b981"
set the value of widget VolumeSlider to 75
Variables
set variable count to 0
set variable message to "Hello"
set variable total to variable price * variable quantity
-- Variables persist across card navigations automatically
Navigation
go to card Dashboard
go to card SettingsPage
go back
-- Open an external URL (same tab or new tab)
open url "https://example.com"
open url "https://docs.example.com" in new tab
-- Print / PDF (single card)
print card as pdf
-- Batch print (multi-record — one page per DB record)
start print batch
-- ... loop updating widgets ...
add current card to batch
-- ... end loop ...
print batch as pdf
Conditions
if the text of widget EmailField is empty then
show toast "Please enter your email" with background color "#ef4444"
else if the text of widget EmailField contains "@" then
show toast "Valid email!"
else
show toast "Enter a real email address" with background color "#f59e0b"
end if
HTTP Requests
-- GET request
get url "https://api.example.com/products"
set variable products to result
-- POST request
set variable payload to "{\"name\":\"" + the text of widget NameField + "\"}"
post payload to url "https://api.example.com/users" as json
-- After any HTTP call, these variables are set:
-- result → response body
-- httpStatus → "200", "404", etc.
-- httpError → error message or "" on success
Tip: Watch variables update in real-time during preview. Switch to the Variables tab in the left panel while preview is running — every variable shows its live value.
Show Toast Notifications
show toast "Saved!"
show toast "Error saving" with background color "#ef4444"
show toast "Info message" with duration 5000 with position "top-right"
Loop Over Data
for each item in myList
print item
end for
repeat 3 times
set variable count to count + 1
end repeat
Undo / Redo & Snapshots
Use Ctrl+Z / Ctrl+Shift+Z to undo and redo canvas changes. Click the 📸 button in the top bar to save a named snapshot — restore it any time to jump back to that exact state.
SMART Script Reference
A plain-English scripting language. Attach scripts to widget events, card loads, or run them from other scripts.
Scripts are case-insensitive for keywords. Widget names are case-sensitive. Lines starting with -- are comments.
Variables
set variable myVar to "Hello World"
set variable count to 42
set variable price to 9.99
set variable isActive to true
set variable items to ["apple", "banana", "cherry"]
-- Math
set variable total to variable price * variable quantity
set variable pct to variable correct / variable total * 100
-- String concatenation
set variable greeting to "Hello, " + variable userName + "!"
-- String interpolation (use curly braces)
set variable msg to "Order #{orderId} is ready!"
Reading Widget Properties
-- Text inputs
set variable name to the text of widget NameField
-- Other properties
set variable checked to the checked of widget AgreeBox
set variable rating to the value of widget StarRating1
set variable tags to the tags of widget TagInput1
set variable data to the data of widget MyTable
Setting Widget Properties
set the text of widget MyLabel to "Updated!"
set the bgColor of widget MyCard to "#3b82f6"
set the value of widget MySlider to 75
set the data of widget MyTable to variable rows
set the visible of widget MyPanel to "false"
show widget MyPanel -- shorthand for visible = true
hide widget MyPanel -- shorthand for visible = false
Conditions
if variable count is greater than 10 then
show toast "Count exceeded!"
end if
if the text of widget Input is empty then
show toast "Required"
else if the text of widget Input contains "@" then
show toast "Looks like an email"
else
show toast "Text entered"
end if
-- Boolean conditions
if variable isActive is "true" then ... end if
if variable status is not "error" then ... end if
if variable name contains "Smith" then ... end if
if variable list is not empty then ... end if
-- AND / OR
if variable age is greater than 18 and variable country is "UK" then ... end if
if variable type is "admin" or variable type is "superadmin" then ... end if
Loops
-- Count loop
repeat 5 times
set variable total to total + 1
end repeat
-- For each loop
for each item in myList
print item
end for
-- While loop
set variable attempts to 0
repeat while attempts is less than 3
set variable attempts to attempts + 1
call webhook "TryConnect"
if webhookStatus is "200" then
break
end if
wait 1 seconds
end repeat
-- Until loop (inverse of while)
repeat until variable done is "true"
call webhook "PollStatus"
set variable done to webhookResponse
wait 2 seconds
end repeat
-- Loop control
break -- exit loop immediately
continue -- skip to next iteration
HTTP Requests
-- GET request
get url "https://api.example.com/data"
set variable data to result
set variable status to httpStatus
-- POST with JSON
set variable payload to "{\"name\":\"Alice\",\"age\":30}"
post payload to url "https://api.example.com/users" as json
-- POST with a variable as body
post variable formData to url "https://api.example.com/submit" as json
-- Custom headers
set header "Authorization" to "Bearer " + variable token
set header "X-Api-Key" to "my-key"
get url "https://api.example.com/protected"
clear headers
-- After any HTTP call:
-- result → raw response body
-- httpStatus → "200", "404", etc.
-- httpError → "" on success, error message on failure
-- Error handling
try
get url "https://api.example.com/data"
set the data of widget Table1 to result
on error
show toast "Failed: {httpError}" with background color "#ef4444"
end try
JSON Handling
-- Read a field from a JSON string
set variable name to json field "name" of result
set variable price to json field "data.product.price" of result
set variable first to json field "items[0].title" of result
-- Build JSON manually
set variable obj to "{\"key\":\"" + variable val + "\"}"
-- Parse JSON array
set variable list to result
for each row in list
set variable id to json field "id" of row
print id
end for
Math Functions
round(x) or round of Xfloor(x) or floor of Xceiling(x) or ceiling of Xabs(x) or abs of Xmin(x,y) or min of X and Ymax(x,y) or max of X and Ypow(x,n)sqrt(x)random(min,max) or random between X and YString Functions
length(x) or length of Xuppercase(x) or uppercase of Xlowercase(x) or lowercase of Xtrim(x) or trim of Xreplace(x,old,new)split(x,delim) or split X by Yindexof(str,search)substring(str,start,len)number(x) / tonumber(x)text(x) / totext(x)List / Array Operations
-- Create a list
set variable colors to ["red", "green", "blue"]
-- Add / remove items
add "yellow" to list colors
remove "red" from list colors
-- Read items
set variable first to item 1 of colors
set variable last to item last of colors
set variable count to count of colors
-- Sort and filter
set variable sorted to sort colors by "name" ascending
set variable active to filter myList where "status" equals "active"
set variable top5 to limit myList to 5
-- In-place mutations
sort list myList by "date"
reverse list myList
shuffle list myList
-- Aggregate
set variable total to sum of priceList
set variable avg to avg of scoreList
set variable unique to unique of tagList
-- Pluck and group
set variable names to pluck "name" from userList
set variable grouped to group userList by "department"
-- Multi-condition filter
set variable result to filter orders where "status" equals "open" and "amount" is greater than 100
Date & Time
set variable now to date now -- current date/time as string
set variable today to date today -- today's date (YYYY-MM-DD)
set variable ts to timestamp now -- Unix timestamp in ms
Storage (Persistent Variables)
-- Save a variable to localStorage (persists after page refresh)
save variable myData to storage
-- Load it back
load variable myData from storage
-- Clear a specific key
clear storage myData
Navigation
go to card HomePage
go to card OrderSummary
go back
-- Open an external URL
open url "https://example.com"
open url "https://example.com" in new tab
Print / PDF
-- Print the current card (opens browser Save as PDF dialog)
print card as pdf
-- Conditional print
if patientName is not empty then
print card as pdf
end if
Batch Print (multi-record PDF)
Loop through database records and render each as a page in one PDF — for run sheets, meal cards, client summaries, etc.
-- 1. Reset the collector
start print batch
-- 2. Loop through records, updating widgets and snapshotting each
open table "Meals"
go to first record
set variable i to 1
repeat while i <= total
set the mealName of widget MealTitle to db field "mealName"
set the value of widget NutritionFacts to db field "nutritionJson"
add current card to batch
go to next record
set variable i to i + 1
end repeat
-- 3. Open one print dialog with all collected pages
print batch as pdf
Timers
-- Repeating timer
every 5 seconds run script UpdateFeed
every 1 seconds run script TickClock
-- One-shot delay
after 3 seconds run script ShowWelcome
after 0.5 seconds run script AnimateIn
-- Stop all timers
stop timer
Media & Animation
-- Video (Video widget)
play video MyPlayer
pause video MyPlayer
-- Sound (PlaySound widget / audio URL)
play sound "success"
stop sound "success"
-- Lottie Animation (LottieAnimation widget)
play animation widget MyAnim
pause animation widget MyAnim
stop animation widget MyAnim
-- Change animation properties at runtime
set the src of widget MyAnim to "https://assets.lottiefiles.com/lf20_xyz.json"
set the speed of widget MyAnim to 2
set the loop of widget MyAnim to false
-- Audio Player (AudioPlayer widget)
play audio widget MyAudio
pause audio widget MyAudio
stop audio widget MyAudio -- pause + reset to beginning
-- Set source and volume at runtime
set the src of widget MyAudio to "https://example.com/track.mp3"
set the volume of widget MyAudio to 0.5
-- Read current playback position (seconds — updated during playback)
set variable elapsed to audioCurrentTime
Webhooks
-- Call a named webhook (configured in App Settings → Webhooks)
call webhook "SubmitOrder"
-- Call with specific variables as payload
call webhook "SubmitOrder" with data "orderId,total,email"
-- After call:
-- webhookStatus → HTTP status code
-- webhookResponse → raw response body
Send Email (Resend)
-- Configure API key in App Settings → Email first
send email to "user@example.com" subject "Welcome" body "Thanks for signing up!"
send email to recipient subject "Receipt #{orderId}" body "Total: £{total}" as html
-- After sending:
-- emailStatus → "200" = sent, other = error
-- emailResult → raw Resend API response
User-Defined Commands
-- Define a reusable command (in any script)
command RefreshDashboard
get url "https://api.example.com/stats"
set the data of widget StatsTable to result
set the value of widget RevGauge to json field "revenue" of result
end command
-- Call it anywhere
RefreshDashboard
Validation
validate widget EmailField as email
validate widget PhoneField as required
validate widget AgeField as min-value 18
validate widget DescriptionField as max-length 500
-- After validation:
-- validationPassed → "true" or "false"
-- validationError → error message or ""
if validationPassed is "false" then
show toast validationError with background color "#ef4444"
end if
clear validation widget EmailField
Form Groups
-- Collect all child inputs at once
submit form widget ContactForm -- triggers onSubmit with formData variable
reset form widget ContactForm -- clears all child inputs
Phone, Currency & Time Inputs
-- PhoneInput — read combined value (e.g. "+44 7700 900000")
set variable phone to phoneNumber -- set via outputVariable property
set the value of widget PhoneField to "7700 900123"
set the countryCode of widget PhoneField to "+44"
-- CurrencyInput — value is always a number
set variable amount to currencyValue -- set via outputVariable property
set the value of widget PriceBox to 99.99
-- TimePicker — value is always HH:MM (24-hour internally)
set variable t to the value of widget StartTime
set the value of widget StartTime to "09:00"
-- timeValue variable is also set automatically on every selection
-- Combine date + time for an appointment
set variable appointment to dateValue + " " + timeValue
File Download
-- Trigger a browser download from any variable — no server needed
save file "results.csv" with content csvData
save file "export.json" with content jsonString
save file "photo.png" with content croppedImageData -- base64 data URLs auto-decoded
-- Dynamic filename
set variable today to "2025-06-20"
save file "report-" + today + ".csv" with content reportCsv
-- MIME type is inferred from the extension:
-- .csv → text/csv .json → application/json .txt / .md → text/plain
-- .html → text/html .xml → application/xml
-- .png / .jpg / .gif / .svg → image/* .pdf → application/pdf
Push Notifications
-- OS-level browser notification (appears in system tray / notification centre)
send notification "Title"
send notification "Order ready" with message "Your order #4821 is ready to collect."
send notification "Alert" with message "Low stock warning" with icon "https://yourapp.com/icon.png"
-- notificationStatus is set automatically:
-- "sent" → notification fired successfully
-- "denied" → user blocked permission
-- "unsupported" → browser doesn't support Notification API
if notificationStatus is not "sent"
show toast "Notifications blocked: " + notificationStatus
end if
Geolocation
-- Get device position (async — waits for browser permission + GPS fix)
get current location
-- Variables set automatically:
-- locationLat e.g. "51.5074"
-- locationLng e.g. "-0.1278"
-- locationAccuracy metres, e.g. "18"
-- locationStatus "ok" or error message
if locationStatus is "ok"
set the text of widget LatLabel to "Lat: " + locationLat
set the text of widget LngLabel to "Lng: " + locationLng
else
set the text of widget Status to "Error: " + locationStatus
end if
-- Build a map link
get current location
set variable mapUrl to "https://maps.google.com/?q=" + locationLat + "," + locationLng
Script Output (Print / Toast)
print "Debug message" -- shows in Console (Variables panel)
show toast "Success!"
show toast "Warning" with background color "#f59e0b" with duration 3000 with position "top-right"
Run Other Scripts
run script MyHelperScript
run script ValidateAndSubmit
Auth (Published Apps)
login user with variable credentials
logout user
restore session
-- After login:
-- sessionToken → JWT access token
-- userEmail → logged-in email
-- userRole → user's role
WebSockets & SSE
-- WebSocket
connect to websocket "wss://api.example.com/live"
-- Messages arrive as onMessage events (set on the script)
-- wsMessage contains the incoming text
-- Server-Sent Events
subscribe to sse "https://api.example.com/stream"
-- sseMessage contains the incoming data
Signature Pad
-- Get the signature as a base64 PNG data URL
get signature of widget SigPad into mySig
-- Clear the canvas
clear signature of widget SigPad
-- Stamp HH:MM DD/MM/YYYY onto the signature
stamp widget SigPad with timestamp
Temperature Logging
-- Record a temperature reading (fires onLog / onFail)
log temperature 4.2 for widget TempLog
log temperature currentTemp for widget TempLog
-- Retrieve full log as JSON array string
get temperature log of widget TempLog into myLog
Row Status
-- Set the status of a row in any list widget
set row status of widget MyList row 2 to "complete"
-- Count all rows, or rows matching a status
get row count of widget MyList into total
get row count of widget MyList where status is "pending" into pendingCount
Row Colour Coding (DataTable)
Apply a background colour to individual rows in a DataTable. Row numbers are 1-based. Accepts any CSS colour string.
-- Colour a specific row
set row color of widget ClientTable row 1 to "#fee2e2"
set row color of widget ClientTable row 3 to "#dcfce7"
-- Clear one row's colour
set row color of widget ClientTable row 1 to ""
-- Clear all custom row colours
clear row colors of widget ClientTable
Welfare Alerts — Push to Coordinators
Broadcasts a push notification to all coordinator-role devices in the organisation. Coordinator must call subscribe to push after login. Alert auto-includes driver name, wellness indicators, and GPS.
-- Coordinator setup (once, after login)
subscribe to push
-- Driver: escalate a welfare concern
send welfare alert for client "Mrs Johnson"
send welfare alert for client clientName with notes wellnessNotes
-- Variables set:
-- welfareAlertStatus → "sent" | "error" | "unavailable"
-- welfareAlertRecipients → number of coordinator devices notified
-- WellnessCheckPanel onSubmit — send alert if concerns noted
on widget WellnessCheck onSubmit
if concernsNoted is "yes"
send welfare alert for client currentClientName with notes wellnessNotes
show toast "⚠️ " & welfareAlertRecipients & " coordinator(s) notified"
end if
end on
Data Layer
Connect REST APIs to your widgets without writing a single script line. Define sources, model their fields, then bind those fields to widget properties.
How It Works
Open the 🔌 Data tab in the left panel. Click Add Data Source. Paste a URL, choose GET/POST method, add optional headers and body, and toggle Auto-fetch if you want it to run when the card loads.
Click Test to make the actual API call and see the raw JSON response inline. Verify the shape of the data before moving on.
Click Add Data Model. Pick the source, then add fields using dot-notation paths to extract values from the JSON:
title → data.product.title
price → data.product.price
stock → data.inventory[0].qty
Click Test Model — each field lights up green showing its resolved value, or red if the path is wrong.
Select a widget on the canvas. Scroll to Data Bindings in the Properties Panel. Click Bind next to any property and choose a model field.
Press Preview — bound widgets populate automatically. No scripts needed.
Using Data Sources in Scripts
-- Trigger a fetch manually in a script
fetch data from ProductsAPI
-- After fetch, model field values are available as variables:
-- ModelName_fieldKey
set the text of widget PriceLabel to variable ProductModel_price
set the text of widget TitleLabel to variable ProductModel_title
Tip: Use Auto-fetch on your data source for data you always want loaded when the card appears. Use the script command fetch data from SourceName for on-demand or triggered fetches.
Real-Time Data
WebSocket
-- Open a persistent WebSocket connection
connect to websocket "wss://api.example.com/live"
-- The script's onMessage event fires for each message
-- wsMessage variable contains the incoming text or JSON
Server-Sent Events (SSE)
-- Subscribe to an SSE stream
subscribe to sse "https://api.example.com/stream"
-- The script's onMessage event fires for each event
-- sseMessage variable contains the event data
Webhooks (Outbound)
Configure outbound webhooks in App Settings → Webhooks. Add a name and URL, then call from any script:
call webhook "SubmitOrder"
call webhook "NotifySlack" with data "orderId,customerName,total"
-- After call:
-- webhookStatus → HTTP status code ("200" = success)
-- webhookResponse → raw response body
Email (Resend API)
Configure your Resend API key in App Settings → Email. Set the From Address and From Name.
send email to "customer@example.com" subject "Order Confirmed" body "Your order is on its way!"
send email to variable emailAddr subject "Invoice #{num}" body htmlContent as html
-- emailStatus → "200" on success
-- emailResult → raw API response
User Authentication (Published Apps)
-- Login
login user with variable credentials
-- Logout
logout user
-- Restore session on card load
restore session
-- After login:
-- sessionToken → JWT access token
-- userEmail → logged-in user's email
-- userRole → "admin" / "builder" / "viewer"
Authentication calls go directly from the browser to the backend. Ensure your backend is running and CORS is configured for the app's domain when using web exports.
Widget Reference
All 119 widgets available in Sentrix. Click any widget to see its full property reference and example scripts.
Keyboard Shortcuts
All shortcuts are active while the canvas has focus. They're automatically disabled when a text input or the script editor has focus.
Press ? at any time on the canvas to open the interactive shortcuts reference directly inside the app.