TypeDialog/docs/web/README.md
2025-12-24 03:11:32 +00:00

8.3 KiB

TypeDialog Web Backend

HTTP server with browser-based forms powered by Axum.

Overview

The Web backend (typedialog-web) provides a full-featured HTTP server with browser-based forms. Built with Axum for high performance, supporting REST APIs, WebSockets, and modern web interfaces.

Features

  • HTTP Server: Fast async server with Axum
  • Browser Forms: Responsive HTML forms with JavaScript
  • REST API: JSON endpoints for form submission
  • Real-time Validation: Client-side and server-side validation
  • RepeatingGroups: Inline expandable cards with live counter
  • Mobile-Friendly: Responsive design for all screen sizes
  • HTTPS Support: TLS/SSL for production
  • Session Management: Stateful forms with session persistence

Quick Start

Installation

cargo build --release -p typedialog-web
sudo cp target/release/typedialog-web /usr/local/bin/

# Or use just
just build::web

Basic Usage

# Start server (default: http://localhost:3000)
typedialog-web --config examples/form.toml

# Custom port
typedialog-web --config form.toml --port 8080

# With HTTPS
typedialog-web --config form.toml --tls-cert cert.pem --tls-key key.pem

# From config file
typedialog-web --config config/web/production.toml

Server Endpoints

Form Endpoints

Method Path Description
GET / Render form HTML
POST /submit Submit form data
GET /api/form Get form definition (JSON)
POST /api/validate Validate field
GET /health Health check

Static Assets

Path Description
/static/css/form.css Form styles
/static/js/form.js Form logic
/static/js/repeating-group.js RepeatingGroup handler

Configuration

Server Config

[web]
host = "0.0.0.0"
port = 3000
tls_enabled = false

[web.cors]
allow_origin = "*"
allow_methods = ["GET", "POST"]
allow_headers = ["Content-Type"]

[web.session]
secret_key = "change-me-in-production"
timeout_seconds = 3600

TLS/HTTPS Config

[web.tls]
enabled = true
cert_path = "/path/to/cert.pem"
key_path = "/path/to/key.pem"

Form Config

[form]
title = "Registration Form"
description = "User registration"
submit_text = "Register"
cancel_text = "Cancel"

[[fields]]
name = "email"
field_type = "Text"
label = "Email"
validation = "email"
required = true

API Usage

Get Form Definition

curl http://localhost:3000/api/form

Response:

{
  "form": {
    "title": "Registration",
    "fields": [...]
  }
}

Submit Form

curl -X POST http://localhost:3000/submit \
  -H "Content-Type: application/json" \
  -d '{"name":"John","email":"john@example.com"}'

Response:

{
  "status": "success",
  "data": {
    "name": "John",
    "email": "john@example.com"
  }
}

Validate Field

curl -X POST http://localhost:3000/api/validate \
  -H "Content-Type: application/json" \
  -d '{"field":"email","value":"invalid"}'

Response:

{
  "valid": false,
  "error": "Invalid email format"
}

Frontend Features

JavaScript API

// Form submission
document.getElementById('form').addEventListener('submit', async (e) => {
  e.preventDefault();
  const formData = new FormData(e.target);
  const data = Object.fromEntries(formData);

  const response = await fetch('/submit', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data)
  });

  const result = await response.json();
  console.log('Submitted:', result);
});

// Real-time validation
input.addEventListener('blur', async () => {
  const response = await fetch('/api/validate', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      field: input.name,
      value: input.value
    })
  });

  const result = await response.json();
  if (!result.valid) {
    showError(result.error);
  }
});

RepeatingGroups

The web backend renders RepeatingGroups as inline expandable cards:

<div class="repeating-group" data-min-items="1" data-max-items="10">
  <div class="items-counter">Items: 0/10</div>
  <div class="items-container">
    <!-- Item cards here -->
  </div>
  <button class="add-item-btn">Add Item</button>
</div>

Features:

  • Click "Add Item" to create new items
  • Expand/collapse cards
  • Delete items
  • Live counter updates
  • Min/max validation
  • Duplicate detection (when unique = true)

Styling

Custom CSS for forms:

.form-container {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
}

.field-group {
  margin-bottom: 1.5rem;
}

.field-label {
  font-weight: 600;
  margin-bottom: 0.5rem;
}

.field-input {
  width: 100%;
  padding: 0.5rem;
  border: 1px solid #ccc;
  border-radius: 4px;
}

.field-error {
  color: red;
  font-size: 0.875rem;
  margin-top: 0.25rem;
}

.submit-btn {
  background: #007bff;
  color: white;
  padding: 0.75rem 1.5rem;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

Deployment

Development

typedialog-web --config config/web/dev.toml

Production

# With systemd
sudo systemctl start typedialog-web

# Or directly
typedialog-web \
  --config config/web/production.toml \
  --tls-cert /etc/ssl/cert.pem \
  --tls-key /etc/ssl/key.pem \
  --port 443

Docker

# Build image
docker build -t typedialog-web .

# Run container
docker run -p 3000:3000 \
  -v $(pwd)/config:/config \
  typedialog-web --config /config/web/production.toml

Reverse Proxy (Nginx)

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Use Cases

1. SaaS Applications

Customer onboarding forms with validation:

typedialog-web --config saas/onboarding.toml --port 443 --tls

2. Internal Tools

Admin panels and configuration interfaces:

typedialog-web --config admin/settings.toml --host 0.0.0.0

3. Public Forms

Contact forms, surveys, registrations:

typedialog-web --config public/contact.toml

4. API Integration

Headless forms with JSON API:

curl http://localhost:3000/api/form | jq .

Security

HTTPS

Always use HTTPS in production:

[web.tls]
enabled = true
cert_path = "/etc/ssl/cert.pem"
key_path = "/etc/ssl/key.pem"

CORS

Configure CORS for cross-origin requests:

[web.cors]
allow_origin = "https://example.com"
allow_methods = ["GET", "POST"]
allow_headers = ["Content-Type", "Authorization"]

Session Security

Use strong session secrets:

[web.session]
secret_key = "generate-random-32-byte-key"
timeout_seconds = 1800  # 30 minutes
secure_cookies = true
http_only = true

Input Validation

Always validate on server-side:

[[fields]]
name = "email"
validation = "email"
required = true

[[fields]]
name = "age"
validation = "range(18..120)"

Examples

See examples/04-backends/web/ for:

  • Basic forms
  • REST API integration
  • RepeatingGroups
  • Custom styling
  • HTTPS configuration
  • Multi-page forms

Troubleshooting

"Address already in use"

Port is occupied. Use different port:

typedialog-web --config form.toml --port 8080

"TLS certificate error"

Check cert paths and permissions:

ls -l /path/to/cert.pem /path/to/key.pem

"CORS error"

Configure CORS in config:

[web.cors]
allow_origin = "http://localhost:3000"

"Form not submitting"

Check JavaScript console for errors. Ensure /submit endpoint is reachable.

"Session expired"

Increase session timeout:

[web.session]
timeout_seconds = 7200  # 2 hours

Ready to start? See examples/04-backends/web/