Build a form that files requests

In about ten minutes you’ll build the classic business form end to end: a support-request portal where visitors submit a request, a workflow validates and files it into a table, and your team works a live queue. Every piece is something you can inspect afterwards — the same pattern powers job applications, RSVPs, order intake, feedback, anything.

The finished support portal: page navigation, live stat tiles, and a request form with name, email, topic and priority selects, a details textarea and a file upload
What you're building — a themed, multi-page portal with live stats and a working form. Visitors need no account.

The flow of data, so nothing below is mysterious: the visitor’s form fields → the Nucleus → your workflow’s input ({{ $json.email }} etc.) → a Table row. The page never holds a credential; every hop is server-side.

Step 1 — Create the table

Requests need somewhere to live. In the Nucleus header open TablesNew table:

  • Name: Support requests
  • Columns: name (text), email (text), topic (text), priority (text), details (text), status (text)

That’s the whole schema. Rows automatically carry an id, createdAt and updatedAt; writes are filtered to these declared columns, so posting a whole form at the table just keeps what you declared. (More on Tables →)

Step 2 — Build the intake workflow

Open Studio → new workflow, name it File support request, and wire five nodes:

The intake workflow on the Studio canvas: Form trigger into an If gate; the true branch runs Set, Table and Console nodes, the false branch logs a rejection
The whole intake: Form trigger → If gate → stamp → save → receipt, with a rejection log on the false branch.
  1. Form trigger — the front door. The interface’s form fields arrive as this workflow’s input, so downstream nodes read them as {{ $json.email }}, {{ $json.topic }}, and so on.
  2. If — gate on the one field you can’t live without: Path email, Operator exists. Belt-and-braces server-side validation behind the form’s own required flags.
  3. Edit Fields (Set) on the true branch — add status = new, keeping everything else (Include: all). Every fresh request starts life as new.
  4. TableTable Support requests, Operation insert, and leave Values empty: an empty Values means “insert the whole input”, which is exactly the submitted form (filtered to your declared columns — the file attachment simply doesn’t land in the table).
  5. Console — a receipt you’ll see in the run: Support request filed by {{ $json.email }} — {{ $json.topic }}. Add a second Console on the If’s false branch so rejected submissions are visible too.

Save (Ctrl+S). Test it right here if you like: the Form trigger passes any test input through, so Test workflow with {"name":"Ada","email":"ada@acme.io","topic":"Billing", "details":"trial"} should end green with a new table row.

Step 3 — Compose the page

Open InterfacesNew interface — title Acme Support, slug support-desk. You land in the builder: structure on the left, a live preview on the right that re-renders as you type.

On the first page (rename it Get help), add blocks:

  1. headingHow can we help?
  2. markdown — a sentence of reassurance. **bold** and [links](https://…) work.
  3. stat — three tiles: Open requests pointed at your Support requests table (a live row count), and fixed values like 38m / 98%.
  4. form — the heart of it:
    • Workflow: File support request

    • Fields — each field’s name is the key the workflow reads, so they must match what Step 2 expects:

      namelabeltyperequired
      nameYour nametext
      emailEmailemail
      topicTopicselect (Billing, Bug report, How do I…)
      priorityPriorityselect (Normal, High, Production down)
      detailsWhat’s going on?textarea
      attachmentScreenshot (optional)file
    • Response text: Got it — we're on it. (Or set a Redirect URL to send the visitor to a thank-you page instead.)

Watch the preview build itself as you go. Then add a second page with + — call it Open requests — and give it a table block: your table, mode editable, search on. That page is your team’s queue: search, edit status inline, delete.

Pick an accent color and light/dark at the top, and Save.

Step 4 — Publish and prove it

Hit Open page, fill in your own form, submit. Then prove the whole chain, end to end:

  • Runs (Studio → Runs) shows a run with actor interface:support-desk — open it and read your Console receipt and every node’s envelope.
  • Tables → Support requests — your submission is a row, status = new.
  • The portal’s Open requests page shows it live; edit its status inline right there.
The portal's queue page: a searchable, editable grid of support requests where agents edit the status column inline
The queue page — the same table, live on the site, searchable and editable by your team.

Step 5 — Control who gets in

In the builder header, Access:

  • Public — anyone with the URL (right for a support form).
  • Link with key — the URL only works with its ?k=… key; Rotate key invalidates every shared link instantly (right for the internal queue — or split the queue into its own key-gated interface).
  • Password — visitors get an on-brand password page; correct entry mints a session cookie.

Every run and every visitor table-edit lands in the audit log.

Where to go next

  • The two other seeded demos show the same pattern shaped differently: /if/careers (job applications feeding a hiring-pipeline page) and /if/event-rsvp (an upsert form — re-submitting the same email updates the RSVP instead of duplicating — behind a link key, with an organizer page whose button fires a broadcast workflow).
  • Interfaces reference — every block kind and access mode.
  • React to new rows elsewhere with the Table trigger, or notify Slack from the intake workflow — it’s a normal workflow; extend it like one.

Troubleshooting

SymptomCause
Form submits, table stays emptyThe workflow starts with an Inject trigger (static payload swallows the submission) — use Form; or field names don’t match what the workflow/table expect
”not found” on submitThe form block’s workflow was deleted or never picked
Visitors can’t edit the queueThe table block’s mode is readonly — flip it to editable
The stat tile shows —Its table reference is unset — pick the table, not a fixed value