Unify Logo Footer.svg
Unify Applications
Logo
Dev Tools & Debugger

Dev Tools & Debugger

Logo

13 mins READ

What Is Dev Tools?

Dev Tools is a floating debugging window built into the UnifyApps page builder. It gives you live visibility into everything happening inside your app as you interact with it — events firing, actions executing, data sources fetching, state changing, and errors occurring.

Dev Tools is a builder-only tool. It is completely invisible in the published app and has no effect on your app's production behavior. It exists solely to help you understand, trace, and debug your app's logic during development.

Note: Builder-only Dev Tools never appears in your published app. End users will never see it. You can leave Dev Tools open while you build without any concern about it affecting what your users experience.

Opening Dev Tools

There are two ways to open Dev Tools:

  • Click the Dev Tools icon in the left icon rail of the page builder.

  • Use the keyboard shortcut Alt + Shift + D from anywhere in the builder.

Window Management

The Dev Tools window is a freely floating panel that sits in front of the canvas. It does not dock to any edge of the builder.

ActionHow to do it
Move the windowClick and drag the window's header bar to reposition it anywhere over the canvas.
Resize the windowClick and drag the grip handle in the bottom-right corner of the window to resize it.
Reset positionA "Reset window to default position" option is available in the Dev Tools menu, returning it to the default center position and size.
MinimizeCollapse the window to just its header bar. Pulse continues recording events while minimized — no data is lost.
CloseFully close the Dev Tools window. Closing stops event recording and clears all captured events. The next time you open Dev Tools, the stream starts fresh.

The window's dock state — its position, size, and which tab was last open — persists across page refreshes within the same session. If you navigate to a different page in the builder, Dev Tools reopens in the same position showing the last tab you used.

Warning: Minimize vs. Close These two actions have very different consequences. Minimize keeps recording running silently — Pulse captures all events even while the window is collapsed. Close stops recording entirely and discards all captured events. Choose Close only when you are done debugging a particular issue.

The Four Tabs

Dev Tools has four tabs, each providing a different lens on your app's runtime behavior:

TabDescription
PulseThe app-level event stream. Shows a chronological, readable log of everything that happens as you interact with the app — events, actions, state changes, data fetches, errors, and custom log messages.
ConsoleMirrors the browser's developer console output. Useful for seeing console.log output from custom JavaScript in your app and for browser-level warnings and errors.
NetworkShows raw network requests made by the app — API calls, data source fetches, and other HTTP traffic. Useful for verifying request payloads and response bodies.
StateA browsable, real-time snapshot of all page state. Shows variables, data source results, component outputs, and global context values at the current moment.

Pulse — The Event Stream

The Pulse tab is the most powerful debugging tool in Dev Tools. It captures every significant thing that happens in your app and presents it as a readable, structured feed you can trace step by step.

The 7 event kinds Pulse records

KindWhat it representsExample message
EventA user interaction or system event that fired on a component (e.g., On Click, On Change, On Load)."On Click fired on submitButton"
ActionAn action that ran as part of an event handler chain — API call, navigate, show modal, set variable, etc."Set variables.isLoading to true"
Component methodA method called on a specific component instance — e.g., table1.refresh() or form1.reset()."Called refresh() on table1"
State changeA change to the app's state store — a variable updated, a data source result stored, etc."Changed from false to true" / "Set selectedRow to {id: 42, name: 'Alice'}"
Data sourceA data source fetch lifecycle event — fetch started, completed, or skipped. Combines what would otherwise be two separate rows (fetch + store update) into one."Fetch completed — 24 rows returned" / "Fetch skipped — run condition evaluated to false"
ErrorAn error that occurred during event processing, action execution, or a data source fetch. Highlighted in red."Script error in onSubmit: Cannot read properties of undefined"
LogA custom log message emitted by a Log action in your app's event handlers. Used for developer-authored debug output."[DEBUG] form submitted with payload: {…}"

Stream columns

Each row in the Pulse stream has several columns. The columns are resizable — drag the column header divider to adjust column widths.

ColumnDescription
#Sequence position of the event in the current capture session. Useful for referencing specific events in discussion.
ScopeWhere in the app the event originated. This column is only shown when there are events from multiple scopes in the stream — for example, events from different pages or embedded components. Drag to resize.
TimeThe timestamp when the event was captured, relative to when Dev Tools was opened. Drag to resize.
KindThe event type — one of the 7 kinds listed above, shown as a colored badge. Drag to resize.
EntityThe component, variable, data source, or function involved in the event. Drag to resize.
MessageA human-readable description of what happened. Written as a complete sentence: "Changed from {old} to {new}", "Set {field} to {value}", "Fetch skipped — run condition evaluated to false". This is the primary column for understanding what occurred.

Filtering and searching the stream

The filter bar above the stream accepts both structured filters and free-text search. The placeholder text reads: "Filter by scope, kind, entity — or search messages…"

Click in the filter bar to open a dropdown showing available filter keys (scope, kind, entity) grouped under "Filters", with specific values listed as "Suggestions". Selecting a filter adds a chip to the bar. Multiple chips narrow the stream to rows matching all applied filters simultaneously.

Typing text that does not match a filter key performs a free-text search across event messages. Press Enter to apply the search as a chip. Each applied filter or search term appears as a dismissible chip in the filter bar.

A Clear filters button appears when any filters or searches are active, removing all chips at once.

Keyboard-driven filtering

The filter bar is fully keyboard-navigable:

  • Arrow keys — Navigate through suggestions in the dropdown.

  • Enter — Apply the selected suggestion as a filter chip, or apply typed text as a free-text search chip.

  • Escape — Close the suggestion dropdown without applying a filter.

  • Backspace — Remove the last applied chip when the input field is empty.

Pause and resume capture

The Pulse stream captures events continuously by default. A Pause/Resume toggle in the toolbar lets you freeze the stream when you want to examine the current state without new events scrolling past. While paused, events are still captured internally — resuming replays all events that arrived during the pause.

A Clear button discards all currently captured events and resets the stream to empty.

The footer bar at the bottom of the Pulse tab shows the current state: either "Live" (capturing) or "Paused", along with the total count of captured events.

Consecutive event grouping

When the same event fires repeatedly in rapid succession — within one second — Pulse groups consecutive identical events into a single row rather than flooding the stream. The row shows the most recent instance. Hovering over the grouped row reveals a tooltip: "N identical consecutive events grouped", where N is the total count including the grouped ones.

Tip: Event grouping and debounced inputs If you are debugging a text input's On Change event and notice only one row in Pulse where you expected many, it may be grouped. Hover the row to check the grouped count, confirming the event fired as expected.

Event Details Panel

Clicking any row in the Pulse stream opens the Event Details panel on the right side of the Dev Tools window. This panel provides deep context about the selected event through four tabs:

TabWhat it shows
PayloadThe data carried by the event — the event arguments, action inputs, or component output values at the moment the event fired. Shown as an expandable JSON tree.
ErrorError details if the event resulted in a failure. The tab header is visually highlighted (red indicator) when an error is present, making failed steps immediately visible without needing to click. Shows the error message, source, and full stack trace with a Copy button.
StateA snapshot of all page state at the exact moment this event was captured. Identical in structure to the dedicated State tab but frozen to this point in time — useful for seeing what state values were when the event fired.
ChangesA before/after diff of state changes that resulted from this event. A badge on the tab header shows the count of changed state fields. If no state changed, shows "No store change for this step". If state was not captured for this step, shows "No state captured".

Data Source Event Messages

Data source events appear as a single row in Pulse (rather than separate "fetch started" and "store updated" rows). The message follows a consistent format based on the outcome:

OutcomeMessage format
Success — no count"Fetch completed successfully" — shown when the data source returns a result that is not a countable array.
Success — with count"Fetch completed — N rows returned" — shown when the result is an array. The duration of the fetch is shown alongside (e.g., "in 342 ms").
Failure"Fetch failed" — the row is marked as an error. Click to open the Error tab in the Event Details panel for the full error message and stack trace.
Skipped — run condition"Fetch skipped — run condition evaluated to false" — the data source was configured with a run condition that evaluated to false, so no network request was made.

Error Events

When something goes wrong, Pulse captures an Error event. Errors are visually highlighted in the stream with a red indicator so they stand out immediately. There are three categories of errors:

Error typeDescription
Script errorAn unhandled JavaScript exception in custom JavaScript code in your app (e.g., in a JS action, a custom function, or a computed expression).
Page function errorAn error in a page-level function defined in the page's function library.
Action errorAn error that occurred during the execution of an action in an event handler — for example, an API call that returned an error status, or a navigate action that failed to resolve the target.

Clicking an error row opens the Event Details panel. The Error tab shows:

  • The full error message.

  • A Copy button to copy the error to the clipboard.

  • The Source — the event handler, function, or action where the error originated.

  • The full stack trace for JavaScript errors.

Note: Error count badge on the rail icon Even when the Dev Tools window is closed, the Dev Tools icon in the left rail shows a red badge with the count of errors that have occurred in the current session. This means you can detect errors without keeping Dev Tools open — the badge will alert you. The count resets when you navigate away from the app or reload the builder. Each app maintains its own error count.

State Tab — App State Snapshot

The State tab provides a real-time, browsable snapshot of all state in your app at the current moment. Unlike the State sub-tab in Event Details (which is frozen to a past event), the State tab always reflects the current live state.

State is organized into groups

The left sidebar of the State tab groups state into logical categories:

GroupWhat it contains
VariablesAll page-level and global variables, with their current values.
FunctionsPage-level functions defined in the function library.
Data sourcesThe current results, loading state, and error state of every data source configured on the page.
BlocksThe output values and state of reusable block components on the page.
GlobalApp-wide context that is available on every page. Includes: environment variables, the logged-in user's profile, the current location (URL, page, params), the app record, and session storage values.

Browse and Raw views

A Browse / Raw toggle at the top of the State tab switches between two display modes:

  • Browse — An expandable tree view of state, formatted for readability. Expand nested objects and arrays to inspect individual fields.

  • Raw — The full state as a raw JSON string. Useful when you want to copy the entire state snapshot or search for a specific value with the browser's find function.

Empty State Messages

The Pulse stream shows contextual messages when no events are visible, depending on the reason:

  • "No events yet — Interact with your app to generate events" — Dev Tools has just been opened and nothing has happened yet. This is the initial state. Click buttons, fill forms, or trigger any interaction on the canvas to start the stream.

  • "No events found — Try adjusting filters" — Events have been captured, but the current filter/search combination matches nothing. Clear or adjust your filters to see events.

Event Capacity

Pulse keeps the most recent 500 events in memory. When the stream reaches capacity, the oldest events are dropped as new ones arrive. For long debugging sessions with high event volume, periodically clear the stream (using the Clear button) and repro the specific issue you are investigating to keep the relevant events in view.

Warning: 500-event limit If you have actions that fire frequently (for example, On Mouse Move or On Scroll handlers), the stream can fill up quickly. Consider adding a filter for the specific event kind or entity you are debugging so the stream only shows relevant events and does not fill with noise.

Debugging Workflow Tips

Tracing an action chain

When a button click should trigger multiple actions in sequence, use Pulse to verify each step ran:

  1. Open Dev Tools and go to the Pulse tab: Press Alt + Shift + D to open Dev Tools. Confirm Pulse is selected and recording ("Live" shows in the footer).

  2. Trigger the interaction: Click the button (or trigger the event) on the canvas. Enable Interactive Canvas mode with Cmd/Ctrl + Shift + E if needed to allow click-throughs.

  3. Review the event sequence in Pulse: Look for the Event row that matches your trigger, then trace the Action rows that follow. Each action should appear in order. If the chain stops early, the last row before the gap (or the first Error row) identifies where it failed.

  4. Click any row for details: Click the row before the gap to open Event Details. Check the Changes tab to see what state was when that step ran, and the Error tab if the row is highlighted in red.

Debugging data source issues

Filter the Pulse stream by Kind = "Data source" to see only data source events. Look for:

  • Skip messages — If a fetch is being skipped unexpectedly, the message will say "Fetch skipped — run condition evaluated to false". Open Event Details to check the payload, which will show the state values that were evaluated.

  • Zero rows returned — "Fetch completed — 0 rows returned" confirms the request succeeded but the query returned no data. This narrows the issue to the data source query itself rather than a connection or action problem.

  • Fetch failed — An Error row with the response body in the Error tab. Check the status code, error message, and whether the API credentials or endpoint URL are correct.