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
Related Documentation
- Installation - Setup guide
- Configuration - Web configuration options
- Field Types - Available field types
- Encryption - Secure field handling
- Examples - Working examples
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/