Back to all skills

form-builder

Build stylish, Typeform-like multi-step forms and surveys using the Rebyte Forms library (Composer API). Outputs standalone HTML files. Triggers include "create a form", "build a survey", "make a questionnaire", "feedback form", "contact form", "signup form", "onboarding flow", "multi-step form", "typeform-style", "data collection form". Do NOT use for simple single-field inputs or backend form processing.

Featured Design

Run this skill in the cloud

No local installation needed
All dependencies pre-installed
Secure isolated VM environment

Skill Documentation

# Rebyte Forms Builder

Build production-ready, Typeform-style forms using the Composer API.

## ⚠️ CRITICAL: Completion Requirements

**A form task is NOT complete until:**
1. ✅ Form backend created (POST /api/forms/create)
2. ✅ HTML file saved as `index.html`
3. ✅ **Invoke the `rebyte-app-builder` skill** to deploy the form
4. ✅ BOTH URLs shared with user: **Form URL** (from deployment) AND **Admin URL** (from form creation API)

**NEVER tell the user the form is "done" without completing ALL steps.**

## Authentication

**IMPORTANT:** All API requests require authentication. Get your auth token and API URL by running:

```bash
AUTH_TOKEN=$(/home/user/.local/bin/rebyte-auth)
API_URL=$(python3 -c "import json; print(json.load(open('/home/user/.rebyte.ai/auth.json'))['sandbox']['relay_url'])")
```

Include the token in all API requests as a Bearer token, and use `$API_URL` as the base for all API endpoints.

## Boilerplate Template

```html
<!DOCTYPE html>
<html lang="en" spellcheck="false" class="fmd-root" data-fmd-color-scheme="light">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{TITLE}}</title>
    <link rel="stylesheet" type="text/css" href="https://unpkg.com/rebyte-forms@1.0.1/dist/css/formsmd.min.css">
</head>
<body class="fmd-body">
    <noscript>Please turn on JavaScript to see this page.</noscript>
    <div class="fmd-main">
        <div class="fmd-main-container">
            <div class="fmd-loader-container">
                <div class="fmd-loader-spinner" role="status" aria-label="Loading"></div>
            </div>
        </div>
    </div>

    <script src="https://unpkg.com/rebyte-forms@1.0.1/dist/js/composer.bundle.min.js"></script>
    <script src="https://unpkg.com/rebyte-forms@1.0.1/dist/js/formsmd.bundle.min.js"></script>
    <script>
        const composer = new Composer({
            title: "{{TITLE}}",
            colorScheme: "light",
            accent: "#6366f1",
            accentForeground: "#ffffff",
            backgroundColor: "#fafafa",
            color: "#18181b",
            fontFamily: "Inter, sans-serif",
            pageProgress: "show",
        });

        // Start slide
        composer.startSlide({ buttonText: "Get Started" });
        composer.h1("Welcome");
        composer.p("Introduction text here.");

        // Form slides go here...

        // End slide
        composer.endSlide();
        composer.h1("Thank you!");
        composer.p("Your response has been recorded.");

        // Initialize
        const formsmd = new Formsmd(composer.template, document, { isFullPage: true });
        formsmd.init();
    </script>
</body>
</html>
```

## Composer Settings

| Setting | Type | Description |
|---------|------|-------------|
| `title` | string | Page title |
| `colorScheme` | `"light"` \| `"dark"` | Default color scheme |
| `accent` | string | Primary color (hex) for buttons, fields |
| `accentForeground` | string | Text color on accent background |
| `backgroundColor` | string | Page background color |
| `color` | string | Text color |
| `backgroundImage` | string | CSS background-image (gradient or url) |
| `backdropOpacity` | string | Overlay opacity on background image (e.g., "0.4") |
| `fontFamily` | string | Font family |
| `fontSize` | `"sm"` \| `"lg"` | Font size |
| `rounded` | `"none"` \| `"pill"` | Button/UI rounding |
| `pageProgress` | `"hide"` \| `"show"` \| `"decorative"` | Progress bar style |
| `formStyle` | `"classic"` | Classic form field appearance |
| `postUrl` | string | URL to POST form responses |

## Field Types

### Text Input
```javascript
composer.textInput("fieldName", {
    question: "What's your name?",
    placeholder: "John Doe",
    required: true,
    description: "Optional helper text",
    multiline: true,  // for textarea
    maxlength: 500,
    autofocus: true,
    subfield: true,   // smaller label (for grouping)
});
```

### Email Input
```javascript
composer.emailInput("email", {
    question: "Your email address?",
    placeholder: "you@example.com",
    required: true,
});
```

### Phone Input
```javascript
composer.telInput("phone", {
    question: "Phone Number",
    country: "US",  // default country code
    required: true,
});
```

### URL Input
```javascript
composer.urlInput("website", {
    question: "Your website",
    placeholder: "https://example.com",
});
```

### Number Input
```javascript
composer.numberInput("salary", {
    question: "Expected salary (USD)",
    placeholder: "100000",
    unit: "$",
    min: 50000,
    max: 500000,
});
```

### Choice Input (Radio/Checkbox)
```javascript
// Simple choices
composer.choiceInput("role", {
    question: "What's your role?",
    choices: ["Developer", "Designer", "Manager", "Other"],
    required: true,
});

// With custom values
composer.choiceInput("ticket", {
    question: "Select ticket type",
    choices: [
        { label: "General - $99", value: "general" },
        { label: "VIP - $299", value: "vip" },
    ],
    required: true,
});

// Multiple selection
composer.choiceInput("skills", {
    question: "Select your skills",
    description: "Choose all that apply",
    choices: ["JavaScript", "Python", "Go", "Rust"],
    multiple: true,
});

// Horizontal layout
composer.choiceInput("size", {
    question: "T-Shirt Size",
    choices: ["S", "M", "L", "XL"],
    horizontal: true,
});
```

### Select Box (Dropdown)
```javascript
composer.selectBox("country", {
    question: "Select your country",
    placeholder: "Choose one",
    options: ["USA", "Canada", "UK", "Germany", "Other"],
});
```

### Rating Input
```javascript
composer.ratingInput("satisfaction", {
    question: "How satisfied are you?",
    outOf: 5,
    icon: "star",
    required: true,
});
```

### Opinion Scale (NPS)
```javascript
composer.opinionScale("nps", {
    question: "How likely are you to recommend us?",
    startAt: 0,
    outOf: 10,
    labelStart: "Not likely",
    labelEnd: "Very likely",
    required: true,
});
```

### File Upload
```javascript
composer.fileInput("resume", {
    question: "Upload your resume",
    description: "PDF format, max 10MB",
    sizeLimit: 10,
    required: true,
});
```

### Date/Time Inputs
```javascript
composer.dateInput("startDate", { question: "Start date" });
composer.timeInput("preferredTime", { question: "Preferred time" });
composer.datetimeInput("appointment", { question: "Select date and time" });
```

## Slide Structure

```javascript
// Start slide (intro)
composer.startSlide({ buttonText: "Begin" });
composer.h1("Title");
composer.p("Description");

// Regular slide
composer.slide();
composer.textInput("name", { question: "Your name?", required: true });

// Another slide with multiple fields
composer.slide();
composer.h2("Contact Details");
composer.emailInput("email", { question: "Email", required: true });
composer.telInput("phone", { question: "Phone", subfield: true });

// End slide
composer.endSlide();
composer.h1("Thanks!");
```

## Conditional Display

Show a field only when a condition is met:

```javascript
composer.choiceInput("wantFollowUp", {
    question: "Can we follow up?",
    choices: [
        { label: "Yes", value: "yes" },
        { label: "No", value: "no" },
    ],
});

composer.emailInput("followUpEmail", {
    question: "Your email for follow-up",
    displayCondition: {
        dependencies: ["wantFollowUp"],
        condition: "wantFollowUp == 'yes'",
    },
});
```

## Theme Presets

### Light Professional
```javascript
const composer = new Composer({
    colorScheme: "light",
    accent: "#18181b",
    accentForeground: "#fafafa",
    backgroundColor: "#fafafa",
    color: "#18181b",
    fontFamily: "DM Sans, sans-serif",
    formStyle: "classic",
    pageProgress: "show",
});
```

### Dark Modern
```javascript
const composer = new Composer({
    colorScheme: "dark",
    accent: "#a855f7",
    accentForeground: "#ffffff",
    backgroundColor: "#0f0a1e",
    color: "#e2e8f0",
    backgroundImage: "linear-gradient(135deg, #1a0a2e 0%, #16213e 50%, #0f0a1e 100%)",
    fontFamily: "Space Grotesk, sans-serif",
    rounded: "pill",
    pageProgress: "show",
});
```

### Warm Feedback
```javascript
const composer = new Composer({
    colorScheme: "light",
    accent: "#f97316",
    accentForeground: "#ffffff",
    backgroundColor: "#fffbeb",
    color: "#451a03",
    backgroundImage: "linear-gradient(180deg, #fef3c7 0%, #fffbeb 50%, #fff7ed 100%)",
    fontFamily: "Outfit, sans-serif",
    fontSize: "lg",
    pageProgress: "show",
});
```

### With Background Image
```javascript
const composer = new Composer({
    colorScheme: "dark",
    accent: "#f472b6",
    accentForeground: "#ffffff",
    backgroundColor: "#1e1b4b",
    color: "#f8fafc",
    backgroundImage: "url('https://images.unsplash.com/photo-xxx?w=1920&q=80')",
    backdropOpacity: "0.4",
    fontFamily: "Plus Jakarta Sans, sans-serif",
    rounded: "pill",
});
```

## Collecting Form Submissions

To collect responses, you need to:
1. Create a form backend (stores submissions)
2. Add `postUrl` to your HTML form
3. Save HTML as `index.html`
4. **Invoke the `rebyte-app-builder` skill** to deploy

### Complete Workflow

#### Step 1: Create Form Backend

Call the Forms API to create a backend that stores submissions:

```bash
curl -X POST "$API_URL/api/forms/create" \
  -H "Authorization: Bearer $AUTH_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "My Survey",
    "fields": ["name", "email", "rating", "feedback"]
  }'
```

**IMPORTANT:** The `fields` array must contain the exact field names you use in your form (e.g., `composer.textInput("name", ...)` means `"name"` goes in fields).

Response:
```json
{
  "formId": "abc123def456",
  "submitUrl": "https://.../api/forms/submit/abc123def456",
  "adminUrl": "https://.../forms/abc123def456",
  "fields": ["name", "email", "rating", "feedback"]
}
```

**Save these URLs:**
- **`submitUrl`**: Where form data is POSTed (use as `postUrl` in Composer)
- **`adminUrl`**: Spreadsheet UI to view all submissions (**share with form creator**)

#### Step 2: Configure Form HTML

Add the `submitUrl` as `postUrl` in your Composer settings:

```javascript
const composer = new Composer({
    title: "My Survey",
    postUrl: "<submitUrl from API response>",
    // ... other settings
});
```

#### Step 3: Save and Deploy

1. Save the form HTML as `index.html`
2. **Invoke the `rebyte-app-builder` skill** to deploy it
3. The skill will handle ZIP creation, upload, and deployment

### Final URLs to Share

After deployment, you'll have:
- **Form URL**: From the `rebyte-app-builder` skill output - Share with respondents
- **Admin URL**: From the form creation API response (Step 1) - View responses in spreadsheet

### Viewing Results

**Admin UI (Recommended)**: Open `adminUrl` in a browser to view responses in a spreadsheet interface with CSV/JSON export.

**API Endpoints** (for programmatic access):
- **JSON**: `GET $API_URL/api/forms/results/{formId}`
- **CSV**: `GET $API_URL/api/forms/results/{formId}/csv`

## IMPORTANT: Always Return Both URLs

When you finish building and deploying a form, you **MUST** tell the user both URLs:

1. **Form URL** (for respondents): From the `rebyte-app-builder` skill output
2. **Admin URL** (for viewing results): From the form creation API response (Step 1)

**Never forget the Admin URL** - without it, the user cannot see their form submissions!

Published by rebyteai

This skill works with Claude Code, Cursor, Windsurf, Gemini CLI, and other AI coding agents.

rebyte.ai - The only skill marketplace where you can run skills directly in the cloud

No downloads. No configuration. Just sign in and start using AI skills immediately.