Skip to content

Commit a6a27b3

Browse files
committed
feat(deployed-form): added deployed form input
1 parent c3adcf3 commit a6a27b3

File tree

39 files changed

+13054
-16
lines changed

39 files changed

+13054
-16
lines changed
Lines changed: 357 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,357 @@
1+
---
2+
title: Form Deployment
3+
---
4+
5+
import { Callout } from 'fumadocs-ui/components/callout'
6+
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
7+
8+
Deploy your workflow as an embeddable form that users can fill out on your website or share via link. Form submissions trigger your workflow with the `form` trigger type, and results appear in your execution logs.
9+
10+
## Overview
11+
12+
Form deployment turns your workflow's Input Format into a beautiful, responsive form that can be:
13+
- Shared via a direct link (e.g., `https://sim.ai/form/my-survey`)
14+
- Embedded in any website using an iframe
15+
- Customized with your brand colors and messages
16+
17+
When a user submits the form, it triggers your workflow with the form data, executing all downstream blocks automatically.
18+
19+
<Callout type="info">
20+
Forms derive their fields directly from your workflow's Start block Input Format. Each field you define becomes a form input with the appropriate type (text, number, checkbox, etc.).
21+
</Callout>
22+
23+
## Creating a Form Deployment
24+
25+
1. Open your workflow in the editor
26+
2. Click the **Deploy** button in the top-right corner
27+
3. Select the **Form** tab
28+
4. Configure your form settings:
29+
- **Identifier**: A unique URL slug (e.g., `contact-form` creates `https://sim.ai/form/contact-form`)
30+
- **Title**: The form's heading displayed to users
31+
- **Description**: Optional subtitle explaining the form's purpose
32+
5. Click **Launch** to deploy
33+
34+
## Input Format Mapping
35+
36+
Your Start block's Input Format fields map to form inputs:
37+
38+
| Input Format Type | Form Field |
39+
|------------------|------------|
40+
| `string` | Text input (or textarea for fields named "message", "description", etc.) |
41+
| `number` | Number input with validation |
42+
| `boolean` | Toggle switch |
43+
| `object` | JSON editor |
44+
| `array` | JSON array editor |
45+
| `files` | File upload dropzone |
46+
47+
<Callout type="warn">
48+
Make sure your Start block has at least one Input Format field defined. Forms with no fields will display a message indicating no inputs are configured.
49+
</Callout>
50+
51+
## Customization Options
52+
53+
### Branding
54+
55+
- **Primary Color**: Hex color for buttons and accents (e.g., `#3972F6`)
56+
- **Logo URL**: Your logo displayed in the form header
57+
- **"Powered by Sim" Branding**: Toggle to show/hide the footer branding
58+
59+
### Messages
60+
61+
- **Welcome Message**: Introductory text shown above the form
62+
- **Thank You Title**: Heading displayed after successful submission
63+
- **Thank You Message**: Body text shown after submission
64+
65+
## Access Control
66+
67+
Forms support three authentication modes:
68+
69+
| Mode | Description |
70+
|------|-------------|
71+
| **Public** | Anyone with the link can submit |
72+
| **Password** | Users must enter a password to access the form |
73+
| **Email Whitelist** | Only specified emails or domains can submit |
74+
75+
For email whitelist, you can specify:
76+
- Exact emails: `[email protected]`
77+
- Domain wildcards: `@example.com` (allows all emails from that domain)
78+
79+
## Embedding Your Form
80+
81+
### Direct Link
82+
83+
Share the form URL directly:
84+
85+
```
86+
https://sim.ai/form/your-identifier
87+
```
88+
89+
### Iframe Embed
90+
91+
Embed the form in any webpage:
92+
93+
```html
94+
<iframe
95+
src="https://sim.ai/form/your-identifier"
96+
width="100%"
97+
height="600"
98+
frameborder="0"
99+
style="border: none; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);"
100+
></iframe>
101+
```
102+
103+
## Programmatic Form Submission
104+
105+
You can also submit forms programmatically without using the UI.
106+
107+
<Tabs items={['cURL', 'Python', 'TypeScript', 'Go']}>
108+
<Tab value="cURL">
109+
```bash
110+
curl -X POST https://sim.ai/api/form/your-identifier \
111+
-H "Content-Type: application/json" \
112+
-d '{
113+
"formData": {
114+
"name": "John Doe",
115+
"email": "[email protected]",
116+
"message": "Hello from the API!"
117+
}
118+
}'
119+
```
120+
</Tab>
121+
<Tab value="Python">
122+
```python
123+
import requests
124+
125+
url = "https://sim.ai/api/form/your-identifier"
126+
payload = {
127+
"formData": {
128+
"name": "John Doe",
129+
"email": "[email protected]",
130+
"message": "Hello from the API!"
131+
}
132+
}
133+
134+
response = requests.post(url, json=payload)
135+
result = response.json()
136+
137+
if result.get("success"):
138+
print("Form submitted successfully!")
139+
print(f"Execution ID: {result['data']['executionId']}")
140+
else:
141+
print(f"Error: {result.get('error')}")
142+
```
143+
</Tab>
144+
<Tab value="TypeScript">
145+
```typescript
146+
interface FormSubmissionResult {
147+
success: boolean;
148+
data?: {
149+
executionId: string;
150+
thankYouTitle: string;
151+
thankYouMessage: string;
152+
};
153+
error?: string;
154+
}
155+
156+
async function submitForm(
157+
identifier: string,
158+
formData: Record<string, unknown>
159+
): Promise<FormSubmissionResult> {
160+
const response = await fetch(
161+
`https://sim.ai/api/form/${identifier}`,
162+
{
163+
method: 'POST',
164+
headers: {
165+
'Content-Type': 'application/json',
166+
},
167+
body: JSON.stringify({ formData }),
168+
}
169+
);
170+
171+
return response.json();
172+
}
173+
174+
// Usage
175+
const result = await submitForm('your-identifier', {
176+
name: 'John Doe',
177+
178+
message: 'Hello from TypeScript!',
179+
});
180+
181+
if (result.success) {
182+
console.log('Submitted! Execution ID:', result.data?.executionId);
183+
}
184+
```
185+
</Tab>
186+
<Tab value="Go">
187+
```go
188+
package main
189+
190+
import (
191+
"bytes"
192+
"encoding/json"
193+
"fmt"
194+
"net/http"
195+
)
196+
197+
type FormPayload struct {
198+
FormData map[string]interface{} `json:"formData"`
199+
}
200+
201+
type FormResponse struct {
202+
Success bool `json:"success"`
203+
Data struct {
204+
ExecutionID string `json:"executionId"`
205+
ThankYouTitle string `json:"thankYouTitle"`
206+
ThankYouMessage string `json:"thankYouMessage"`
207+
} `json:"data"`
208+
Error string `json:"error"`
209+
}
210+
211+
func submitForm(identifier string, formData map[string]interface{}) (*FormResponse, error) {
212+
payload := FormPayload{FormData: formData}
213+
jsonData, err := json.Marshal(payload)
214+
if err != nil {
215+
return nil, err
216+
}
217+
218+
url := fmt.Sprintf("https://sim.ai/api/form/%s", identifier)
219+
resp, err := http.Post(url, "application/json", bytes.NewBuffer(jsonData))
220+
if err != nil {
221+
return nil, err
222+
}
223+
defer resp.Body.Close()
224+
225+
var result FormResponse
226+
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
227+
return nil, err
228+
}
229+
230+
return &result, nil
231+
}
232+
233+
func main() {
234+
result, err := submitForm("your-identifier", map[string]interface{}{
235+
"name": "John Doe",
236+
"email": "[email protected]",
237+
"message": "Hello from Go!",
238+
})
239+
if err != nil {
240+
fmt.Printf("Error: %v\n", err)
241+
return
242+
}
243+
244+
if result.Success {
245+
fmt.Printf("Submitted! Execution ID: %s\n", result.Data.ExecutionID)
246+
} else {
247+
fmt.Printf("Error: %s\n", result.Error)
248+
}
249+
}
250+
```
251+
</Tab>
252+
</Tabs>
253+
254+
### Password-Protected Forms
255+
256+
For password-protected forms, include the password in your request:
257+
258+
```bash
259+
curl -X POST https://sim.ai/api/form/your-identifier \
260+
-H "Content-Type: application/json" \
261+
-d '{
262+
"password": "your-password",
263+
"formData": {
264+
"name": "John Doe"
265+
}
266+
}'
267+
```
268+
269+
### Email-Protected Forms
270+
271+
For email-protected forms, include the email:
272+
273+
```bash
274+
curl -X POST https://sim.ai/api/form/your-identifier \
275+
-H "Content-Type: application/json" \
276+
-d '{
277+
"email": "[email protected]",
278+
"formData": {
279+
"name": "John Doe"
280+
}
281+
}'
282+
```
283+
284+
## Execution Logs
285+
286+
Form submissions appear in your workflow's execution logs with:
287+
- **Trigger Type**: `form`
288+
- **Input Data**: The submitted form values
289+
- **Execution ID**: Unique identifier for tracking
290+
291+
Filter your logs by trigger type `form` to see all form submissions.
292+
293+
## React Component Example
294+
295+
Embed forms in React applications:
296+
297+
```tsx
298+
import { useEffect, useRef } from 'react';
299+
300+
interface SimFormProps {
301+
identifier: string;
302+
height?: number;
303+
className?: string;
304+
}
305+
306+
export function SimForm({ identifier, height = 600, className }: SimFormProps) {
307+
const iframeRef = useRef<HTMLIFrameElement>(null);
308+
309+
return (
310+
<iframe
311+
ref={iframeRef}
312+
src={`https://sim.ai/form/${identifier}`}
313+
width="100%"
314+
height={height}
315+
frameBorder="0"
316+
style={{
317+
border: 'none',
318+
borderRadius: '8px',
319+
boxShadow: '0 2px 8px rgba(0,0,0,0.1)',
320+
}}
321+
className={className}
322+
title="Sim Form"
323+
/>
324+
);
325+
}
326+
327+
// Usage
328+
function ContactPage() {
329+
return (
330+
<div className="max-w-2xl mx-auto p-4">
331+
<h1>Contact Us</h1>
332+
<SimForm identifier="contact-form" height={700} />
333+
</div>
334+
);
335+
}
336+
```
337+
338+
## Best Practices
339+
340+
1. **Keep forms focused** - Include only the fields you need to trigger your workflow
341+
2. **Use descriptive field names** - Field names are converted to labels (e.g., `customerEmail` becomes "Customer Email")
342+
3. **Set field types appropriately** - Use `number` for numeric inputs, `boolean` for yes/no questions
343+
4. **Test before sharing** - Use the preview in the deploy modal to verify your form looks correct
344+
5. **Monitor submissions** - Check your execution logs regularly to ensure forms are working
345+
346+
## Troubleshooting
347+
348+
### Form shows "No input fields configured"
349+
Ensure your Start block has at least one Input Format field defined.
350+
351+
### Form not loading in iframe
352+
Check that your website's Content Security Policy allows iframes from `sim.ai`.
353+
354+
### Submissions failing
355+
- Verify the form identifier is correct
356+
- Check that required fields are filled
357+
- For protected forms, ensure credentials are correct
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
"pages": ["index", "basics", "api", "logging", "costs"]
2+
"pages": ["index", "basics", "api", "form", "logging", "costs"]
33
}

apps/docs/content/docs/en/triggers/start.mdx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Reference structured values downstream with expressions such as <code>&lt;start.
4444

4545
## How it behaves per entry point
4646

47-
<Tabs items={['Editor run', 'Deploy to API', 'Deploy to chat']}>
47+
<Tabs items={['Editor run', 'Deploy to API', 'Deploy to chat', 'Deploy to form']}>
4848
<Tab>
4949
When you click <strong>Run</strong> in the editor, the Start block renders the Input Format as a form. Default values make it easy to retest without retyping data. Submitting the form triggers the workflow immediately and the values become available on <code>&lt;start.fieldName&gt;</code> (for example <code>&lt;start.sampleField&gt;</code>).
5050

@@ -64,6 +64,13 @@ Reference structured values downstream with expressions such as <code>&lt;start.
6464

6565
If you launch chat with additional structured context (for example from an embed), it merges into the corresponding <code>&lt;start.fieldName&gt;</code> outputs, keeping downstream blocks consistent with API and manual runs.
6666
</Tab>
67+
<Tab>
68+
Form deployments render the Input Format as a standalone, embeddable form page. Each field becomes a form input with appropriate UI controls—text inputs for strings, number inputs for numbers, toggle switches for booleans, and file upload zones for files.
69+
70+
When a user submits the form, values become available on <code>&lt;start.fieldName&gt;</code> just like other entry points. The workflow executes with trigger type <code>form</code>, and submitters see a customizable thank-you message upon completion.
71+
72+
Forms can be embedded via iframe or shared as direct links, making them ideal for surveys, contact forms, and data collection workflows.
73+
</Tab>
6774
</Tabs>
6875

6976
## Referencing Start data downstream

0 commit comments

Comments
 (0)