LIVE DEMO
THIS WAITLIST IS A .swirls FILE.
The form below is a real .swirls file powering a live workflow. Fill it out to join the waitlist. Your submission flows through the same pipeline you see in the editor.
waitlist.swirls/file to power the form
form waitlist {
label: "Waitlist"
enabled: true
schema: @json {
{
"type": "object",
"required": ["name", "email"],
"properties": {
"name": { "type": "string", "title": "Name" },
"email": { "type": "string", "title": "Email", "format": "email" }
},
"additionalProperties": false
}
}
}
graph process_waitlist {
label: "Process Waitlist"
description: "Normalize input, submit Google Form, classify lead, store with metadata"
root {
type: code
label: "Normalize"
inputSchema: @json {
{
"type": "object",
"required": ["name", "email"],
"properties": {
"name": { "type": "string" },
"email": { "type": "string" }
},
"additionalProperties": false
}
}
outputSchema: @json {
{
"type": "object",
"required": ["name", "email", "domain"],
"properties": {
"name": { "type": "string" },
"email": { "type": "string" },
"domain": { "type": "string" }
},
"additionalProperties": false
}
}
code: @ts {
const { name, email } = context.nodes.root.input
return {
name: name.trim(),
email: email.toLowerCase().trim(),
domain: email.split("@")[1] ?? "unknown",
}
}
}
node submit_google_form {
label: "Submit Google Form"
type: http
method: POST
url: @ts {
return "https://docs.google.com/forms/d/e/1FAIpQLSeRN7yt5Jh5GYdl2j2IHVxB6_onVNbYTcHjgjSWPMV9NU0vmg/formResponse"
}
headers: @ts {
return {
"Content-Type": "application/x-www-form-urlencoded",
}
}
body: @ts {
const { name, email } = context.nodes.root.output
const params = new URLSearchParams({
'entry.1965937490': name,
'entry.686474847': email,
});
return params.toString()
}
}
node classify {
type: ai
kind: object
label: "Classify Lead"
schema: @json {
{
"type": "object",
"required": ["segment"],
"properties": {
"segment": { "type": "string" }
}
}
}
model: "google/gemini-2.5-flash"
prompt: @ts {
const { domain } = context.nodes.root.output
return `Classify this lead into one of: startup, enterprise, agency, personal. Email domain: ${domain}`
}
}
node store {
type: code
label: "Store"
schema: @json {
{
"type": "object",
"required": ["name", "email", "domain", "segment", "joinedAt"],
"properties": {
"name": { "type": "string" },
"email": { "type": "string" },
"domain": { "type": "string" },
"segment": { "type": "string" },
"joinedAt": { "type": "string" }
}
}
}
code: @ts {
const { name, email, domain } = context.nodes.root.output
const { segment } = context.nodes.classify.output
return {
name,
email,
domain,
segment,
joinedAt: new Date().toISOString(),
}
}
}
flow {
root -> submit_google_form
submit_google_form -> classify
classify -> store
}
}
trigger on_waitlist {
form:waitlist -> process_waitlist
enabled: true
}
Join the waitlist
Get early access when we launch.
HOW IT WORKS
1. Define
Write your form schema, processing graph, and triggers in a single .swirls file. Version it in Git like any other code.
2. Submit
Users fill out the form. Their input is validated against your JSON Schema and sent to the Swirls runtime.
3. Execute
The trigger fires your graph: normalize, classify with an LLM, and store. Each node runs in sequence, automatically.