Apps
Turn a PromptRails workflow into a hosted app, presentation, form, portal, or review queue without building a separate frontend.
Apps let you turn agents, prompts, data sources, and records into hosted web surfaces without building a separate frontend.
Use Apps for internal tools, demos, review queues, customer-facing forms, and lightweight portals where the UI needs to run a PromptRails resource and show the result.
Overview
An app is built on a visual canvas. You place widgets, bind them to queries, and wire up interactions without writing frontend code. Widgets cover inputs, buttons, charts, tables, forms, markdown, images, embedded agent chat, prompt runs, and data source runs. Queries fetch or write data, while page parameters and app records keep state.
Builders get an editor with undo/redo, multi-select, guided data binding, version history, and an assistant that can place widgets. End users get a focused app instead of direct access to the full PromptRails workspace. Apps can render as scrolling web pages or full-screen presentation decks, with optional export controls for PDF and PowerPoint deliverables.
Technical detailsApp data model
App Structure
App (slug, access control, version history)
├── Page 1 ("Customer Lookup")
│ ├── Widgets — text inputs, table, agent chat, ... on the canvas
│ ├── Queries — record_list, agent_run, ... data fetchers
│ └── Parameters — shared page inputs ({{params.name}})
├── Page 2 ("Content Generator")
│ └── ...
└── Records — app-scoped JSONB documents, grouped by collection
- Pages define the navigation structure; each owns its own canvas, queries, and parameters.
- Widgets are placed freely on the canvas and can be nested inside Container / Card widgets.
- Queries are page-scoped data fetchers referenced by widgets via
{{queryName.data}}. - Records are app-scoped documents (the persistence target for Form / Table widgets).
- Versions are immutable snapshots of the whole app, restorable from the editor.
The Canvas Editor
The editor lives at /apps/:id/edit and is organized around a left icon rail and contextual panels:
- Components — the widget toolbox; drag a widget onto the canvas.
- Pages — list / add / rename / delete pages, plus per-page Parameters.
- Queries — create and run data fetchers (bottom strip).
- History — save and restore version snapshots.
- Settings — app name, slug, display mode, access control, theme, and export controls.
- Inspector (right) — edits the selected widget's configuration.
Widgets use free placement: drop them where they should appear and adjust the layout visually. The editor also supports zoom, undo/redo, duplicate, copy/paste, delete, multi-select, and a context menu.
Widget Library
Widgets are organized into five categories. Each is configured from the Inspector and can bind its properties to query output or page parameters.
| Category | Widgets |
|---|---|
| Common / Presentation | text, markdown, button, link, alert, tag, code_block, divider, image, statistic |
| Inputs | text_input, number_input, select, checkbox, switch, radio_group, date_input, date_range_input, form |
| Layout | container, card, tabs, modal, spacer |
| Data | table, list, chart, rest_endpoint |
| Agent | agent_chat, prompt_run, data_source |
Highlights:
- Chart — bar, line, area, pie, donut, scatter, and number visualizations with guided query binding, column pickers, and configurable series.
- Markdown — renders Markdown + GFM, ideal for agent / prompt output.
- List — repeats a row template for any bound array, with dotted-path field access (
row.user.email). - Table — renders arrays of objects with a sticky header; bind to a page query, connect a data source directly, or use static/custom data.
- Form — collects inputs and runs a query on submit (typically
record_create). - Container / Card — group child widgets; nesting survives reload via
parent_id. - Tabs — exposes
activeIndex/activeLabelso other widgets can react to the current pane. - Agent chat — embeds a conversational agent surface directly on the page.
- Prompt run / Data source — run a prompt or connected data source from the page and expose its output to other widgets.
Guided Data Binding
Tables and charts can be connected without writing raw {{ ... }} bindings:
- Pick an existing Page query from the widget Inspector.
- Use Connect data source from the same picker to create a page-load
data_sourcequery and bind the widget to{{queryName.data}}automatically. - Switch to Advanced binding only when you need a custom expression or transformed rows.
For charts, PromptRails reads the latest query result and offers field pickers for the X/category field and value series. If the query has not run yet, you can still type field names and run the query once to load real columns.
Technical detailsCanvas data and query details
Widget Bindings
Widgets read dynamic data through {{ ... }} bindings, resolved against page state at runtime:
{{ orders.data }} # output of the "orders" query
{{ params.customer_email }}# value of the page parameter "customer_email"
{{ row.user.email }} # dotted-path field inside a List/Table row
Reactive widgets (those with {{...}} bindings) are flagged in the editor so you can see at a glance what's data-driven.
Queries
Queries are page-scoped data fetchers. Each has a name, a type, type-specific config, and a trigger.
| Type | Purpose |
|---|---|
record_list | Read documents from the app record store |
record_create | Write a document to the app record store |
agent_run | Execute an agent |
prompt_run | Render and execute a prompt template |
data_source | Run a connected data source |
transformer | Derive a value from other query outputs |
js | Sandboxed JavaScript evaluation against page state |
Triggers control when a query runs:
| Trigger | Behavior |
|---|---|
manual | Runs only when explicitly triggered |
page_load | Runs automatically when the page loads |
on_change | Re-runs when an upstream input changes |
Create queries from the dialog; source pickers list your agents, prompts, and data sources. Run a query from the detail panel and the result renders as a table, scalar card, or JSON depending on its shape. Query runs are persisted so page state can be replayed on refresh and public traffic can be audited.
App Records
Records give an app its own document store without a separate database. Each record belongs to a collection (think of it as a table within the app) and holds an arbitrary JSON data payload.
record_createqueries write records (e.g. a Form submission).record_listqueries read them back (e.g. into a Table), with GIN-indexed filtering.- Public widget writes are attributed to the visitor's session; dashboard writes to the user.
Page Parameters
Pages can define parameters that users fill in, then reference anywhere via {{params.name}}.
| Field | Description |
|---|---|
name | Reference name (used in {{params.*}}) |
label | Display label |
param_type | Input type (text, number, select, etc.) |
default_value | Default value |
options | Options for select-type parameters |
required | Whether the parameter is required |
sort_order | Display order |
Add parameters through a guided dialog (Label → Reference name → Type → Options → Default → Required) — no JSON authoring.
Version History
Every save can be snapshotted. The History panel lists versions with a human-readable summary, lets you Save version on demand, and Restore any prior snapshot. Restoring auto-checkpoints the current state first, then atomically rewrites pages, widgets, parameters, and queries inside a transaction — so a restore is fully reversible and Container nesting survives the round-trip.
Presentation Mode and Export
Apps support two display modes:
| Mode | Best for |
|---|---|
| Web page | A scrolling app or portal with page tabs |
| Presentation | A full-screen slide deck with one app page per slide |
Presentation mode is designed for customer demos and reports: app chrome is hidden, slides are preloaded for smooth navigation, and controls stay out of the content area. Web page mode keeps the same clean runtime surface while preserving page navigation.
When export controls are enabled in App Settings, public runtimes can export the current app as:
- PDF — browser print export with app chrome hidden.
- PPTX — PowerPoint export with each app page or slide captured as a deck slide.
Export controls are enabled by default and can be hidden from both web and presentation views.
Locked and Frozen Apps
Locking an app freezes editing for the builder and preserves runtime data for customer-facing presentations. Prompt and data-source widgets serve their frozen result while locked, so published demos do not shift because of fresh LLM or data-source runs. Unlock the app when you want to edit layout, change queries, or refresh frozen outputs.
Access Control
Each app has a single auth_method that gates the public URL:
auth_method | Behavior |
|---|---|
none | Fully public — anyone with the link can use the app |
pin | Requires a shared PIN. The PIN is hashed before storage |
promptrails_login | Requires a Promptrails account with access to the owning workspace |
For promptrails_login, visitors sign in through an inline login flow on the hosted-app domain. The app verifies that the account belongs to the owning workspace before rendering the app.
AI Assistant
The built-in assistant can build the canvas for you. It exposes tools to list, add, update, and delete widgets, and to list and add queries on the current page (list_canvas_widgets, add_canvas_widget, update_canvas_widget, delete_canvas_widget, list_canvas_queries, add_canvas_query). All are gated by a page-ownership check, so the assistant can only edit apps in workspaces you have access to.
Public URLs
Each app has a unique slug that forms its public URL, such as https://your-app-domain.com/internal-tools.
Slugs must be unique across all apps. Depending on the access method, the first visit may show the PIN prompt or the inline login form before the app renders.
Creating an App
Create apps from the PromptRails dashboard:
- Open Apps in your workspace and create a new app — set its name and slug.
- Add one or more pages to define the navigation structure.
- On each page, drag widgets from the Components panel onto the canvas (or start from a template: Dashboard / Form + Table / Agent chat / Single input).
- Add Queries to fetch or write data, and bind widget properties to them with
{{queryName.data}}. - Add Parameters for shared inputs and reference them via
{{params.name}}. - Configure Access Control under Settings (
none/pin/promptrails_login). - Save a version and share the public URL.
Analytics
Apps track execution logs including:
- Which widgets / queries were executed
- Input payloads and output summaries
- Status (success / failure)
- Session tracking
- Error messages
Query runs are persisted separately with per-run duration, input snapshot, and output. Review these from the app detail view to understand how end users are interacting with each page.
Technical detailsApp field reference
App Fields
| Field | Type | Description |
|---|---|---|
id | KSUID | Unique app identifier |
workspace_id | KSUID | Workspace scope |
name | string | Display name |
description | string | Optional description |
slug | string | URL slug (unique) |
status | string | active or inactive |
auth_method | string | none, pin, or promptrails_login |
mode | string | web_page or presentation |
export_enabled | boolean | Shows PDF/PPTX export controls |
grid_columns | integer | Legacy grid column count (default: 12) |
last_published_at | timestamp | Last publish time |
created_at | timestamp | Creation time |
updated_at | timestamp | Last update time |
Related Topics
- Agents -- Agents used in app widgets and queries
- Prompts -- Prompts used in app widgets and queries
- Data Sources -- Data sources used in app widgets and queries