Learn the Good Patterns
Real-world engineering guide on how top e-commerce websites achieve sub-1.0s LCP, zero layout shifts, impenetrable checkout security, and effortless scale.
Strict Form Validation: Phone, Email, Passwords & Double-Submit
Validating shopping inputs (E.164 phone numbers, RFC email, strong passwords), preventing double-submit charges with disabled states, and accessible error handling.
Masked Inputs, Robust Regex & Anti-Double-Charge Guards
Production checkout forms validate customer input immediately in the browser while guaranteeing duplicate validation on the server. Phone fields enforce international E.164 standards with numeric keypads, emails are normalized and validated, and the "Pay Now" button is disabled with a loading spinner upon first click to prevent shoppers from being double-charged.
// Accessible Checkout Form with Anti-Double-Submit Guard (React / Next.js)
import { useState } from 'react';
export function CheckoutForm() {
const [phone, setPhone] = useState('');
const [email, setEmail] = useState('');
const [isSubmitting, setIsSubmitting] = useState(false);
const [errorMsg, setErrorMsg] = useState('');
const handleSubmit = async (e) => {
e.preventDefault();
if (isSubmitting) return; // Prevent double click
// 1. Phone validation: E.164 (10 to 15 digits)
const phoneRegex = /^\+?[1-9]\d{9,14}$/;
if (!phoneRegex.test(phone.replace(/\s+/g, ''))) {
setErrorMsg('Please enter a valid 10-digit phone number with country code');
return;
}
// 2. Email normalization
const cleanEmail = email.trim().toLowerCase();
setIsSubmitting(true);
try {
await processOrderPayment({ email: cleanEmail, phone });
} catch (err) {
setErrorMsg(err.message);
setIsSubmitting(false); // Re-enable on error
}
};
return (
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label htmlFor="customer-phone" className="block text-xs font-bold text-slate-700">
Mobile Number (for Order SMS Tracking)
</label>
<input
id="customer-phone"
type="tel"
inputMode="tel"
required
placeholder="+1 555 019 2834"
value={phone}
onChange={(e) => setPhone(e.target.value)}
className="w-full rounded-lg border border-slate-300 p-2 text-sm"
/>
</div>
<button
type="submit"
disabled={isSubmitting}
className="w-full rounded-xl bg-emerald-600 py-3 text-sm font-bold text-white hover:bg-emerald-500 disabled:opacity-50 flex items-center justify-center gap-2"
>
{isSubmitting ? (
<>
<span className="h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent" />
<span>Processing Payment... Do Not Refresh</span>
</>
) : (
<span>Pay $129.00 Securely</span>
)}
</button>
</form>
);
}Key Engineering & Business Benefits:
- Eliminates duplicate credit card authorization charges from impatient customer double-clicks.
- Triggers the native telephone keypad on iOS and Android devices via inputmode="tel".
- Reduces delivery failures caused by malformed phone numbers or mistyped delivery emails.
The Horror Site: Zero Validation & 5x Double Charge Bug
The bad site accepted random letters ("abcde") for phone numbers, allowed negative quantities ("-5 pairs of shoes"), and left the "Pay" button clickable indefinitely. Rapid clicking submitted multiple requests to the payment processor, charging customers multiple times!
<input type="text" name="phone" placeholder="Enter anything" />
<!-- Zero disabled state on click: -->
<button onclick="payOrder()">Pay Now (Click 5 times for 5 charges!)</button>How to Implement / Fix in 3 Practical Steps
Use inputmode="tel" and regex /^\+?[1-9]\d{9,14}$/ to validate phone numbers accurately.
Disable the payment submission button immediately upon click and render an accessible processing spinner.
Sanitize text inputs to eliminate cross-site scripting (XSS) in delivery instructions and review comments.
Fill in checkout fields with invalid characters ("abcd" in phone) and click the Pay button rapidly. Verify validation blocks submission and button enters disabled state.
Finished reading this lesson?
Mark it as mastered below, or click Next Lesson to auto-complete.