Form Capture
Lightweight form capture microservice. ~100 lines, SQLite storage, zero config.
Deploy to Railway
- Create new project on Railway
- Connect this repo
- Add environment variables (optional):
API_KEY- Protect admin endpoints (recommended)ALLOWED_ORIGINS- Comma-separated origins (default:https://chatlabsai.com)
- Add a volume mounted at
/app/datafor persistent storage - Deploy
Environment Variables
| Variable | Default | Description |
|---|---|---|
PORT |
3000 |
Server port |
API_KEY |
none | Protect /emails, /export, /stats |
ALLOWED_ORIGINS |
https://chatlabsai.com |
CORS origins (comma-separated) |
DATABASE_PATH |
./data/forms.db |
SQLite database path |
API Endpoints
Submit Form
POST /submit
Content-Type: application/json
{
"email": "user@example.com",
"form_name": "newsletter", # optional, default: "default"
"source": "homepage" # optional
}
List Submissions (protected)
GET /emails?form_name=newsletter&limit=100&offset=0
Authorization: Bearer YOUR_API_KEY
Export CSV (protected)
GET /export?form_name=newsletter
Authorization: Bearer YOUR_API_KEY
Stats (protected)
GET /stats
Authorization: Bearer YOUR_API_KEY
Health Check
GET /health
Frontend Usage
// Submit form
const response = await fetch('https://your-app.railway.app/submit', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
email: 'user@example.com',
form_name: 'android-waitlist',
source: window.location.pathname
})
});
if (response.ok) {
// Show success message
}
Local Development
npm install
npm start
Test submission:
curl -X POST http://localhost:3000/submit \
-H "Content-Type: application/json" \
-d '{"email": "test@example.com", "form_name": "test"}'
Description
Languages
JavaScript
100%