Minimal serverless contact backend
A simple, serverless contact backend using Cloudflare Workers and KV, designed for reliability, clarity, and full operator control.
Project created on: 25 Nov. 2025 | Last updated: 26 Nov. 2025
This project is a deliberately simple contact backend built to avoid third-party form services, frameworks, and unnecessary complexity.
Messages are submitted via a Cloudflare Worker, validated and normalized, and stored directly in KV as structured JSON. There is no encryption beyond transport security, and the operator is explicitly trusted with message contents.
The goal was not privacy by cryptography, but operational clarity: understanding exactly how data flows, where it is stored, and how administrative access is controlled.
Overview
Problem
Hosted form services introduce external dependencies, opaque storage, pricing limits, and long-term availability risks for a simple requirement: receiving messages.
Solution
A small Cloudflare Worker that validates submissions, normalizes timestamps, and stores messages in KV, paired with a private admin view for reading entries.
Core Stack
Cloudflare Workers · KV Storage · One-time admin URLs · Server-rendered HTML · No frameworks
Architecture
The architecture is intentionally straightforward: accept input, normalize data, store records, and render results. There are no sessions, accounts, or background processes.
- Client submission: Captures message, email, timezone, and an invisible honeypot to block bots.
- Worker endpoint: Validates input, normalizes timestamps to UTC, extracts IP, and generates a unique sortable ID.
- KV storage: Each submission becomes a structured JSON record with full metadata.
- Renderer: Converts KV entries into an Excel-style table UI inside a hidden admin route.
- Admin access: A single-use, long URL token limits exposure without introducing session state or persistent credentials.
Key Features
Minimal by design
Eliminates sessions, accounts, and frameworks to reduce moving parts.
UTC normalization
Every entry is stored in YYYY-MM-DD HH:MM:SS UTC, guaranteeing consistent ordering.
Anti-spam honeypot
Invisible field + rate limiting blocks automated submissions without CAPTCHAs.
KV storage model
Durable, globally replicated, schema-free structured storage.
Admin renderer
Server-rendered sorting table with no external dependencies.
Screenshots
Sample code snippet
This snippet shows how each message is normalized to UTC and safely stored in KV:
// Normalize current time to UTC const now = new Date(); const utc = now.toISOString().replace("T", " ").replace("Z", " UTC"); // Store structured message in KV await MESSAGES.put(id, JSON.stringify({ name, email, message, ip, client_tz, client_time, utc_time: utc }));
Possible future improvements
- Filtering (Email / IP / Date)
- CSV export
- Time-based token expiration
- Encrypted KV values
- Webhook alerts
- E2EE Variant (See FormSeal)
Links
GitHub: https://github.com/grayguava/contactform-backend/
Live Demo: No Live demo or deployments available