Skip to content
All projects

Amex Roofing

I built a bilingual website and inspection-request workflow for a Bay Area roofing contractor, connecting the public form to serverless scheduling routes and making failure states part of the interface.

Client project · English and Chinese · 2026

My role
Independent developer
Year
2026

HTML · CSS · JavaScript · Vercel Serverless · Google Calendar API

Amex Roofing inspection-request receipt showing a fictional address and preferred arrival window.
Sample inspection receipt with a simulated success response. View full-size image

Make the next step clear

A homeowner arrives with a roof problem and needs a practical next step: call the contractor or request an inspection. The site puts those choices beside the service explanation. The booking flow collects a property address, contact details, preferred date, and one-hour arrival window. Its receipt says “Inspection requested” and explains that the crew will call to confirm. That distinction keeps a successful form submission from promising a completed appointment.

My work covers the public interface, the bilingual page structure, and the serverless booking integration. This is client delivery, separate from the independent products elsewhere in my portfolio.

Keep both languages on one workflow

English and Chinese pages use a shared visual system and booking behavior. Build scripts generate the translated homepage and service-area pages from maintained source content. That keeps layout and interaction changes from turning into two unrelated implementations. The language choice also travels with the inspection request, giving the crew useful context for the follow-up.

The front end uses HTML, CSS, and JavaScript, while provider credentials stay in serverless routes. A form can still submit through its native POST path when the enhanced browser flow is unavailable. The tradeoff is maintaining consistent validation and messages across both the browser and server.

Validate before touching the calendar

The booking route checks the request source and validates contact, address, date, and time fields before delivery. The browser shows errors near the field that needs attention. Date selection and availability requests also need to handle responses arriving out of order: changing the selected date must not let an older response overwrite the current choice.

Local booking-contract checks exercised rejected origins, invalid inputs, accepted date windows, and the native-form fallback. Separate calendar-sync checks confirmed that a failed notification does not advance the synchronization checkpoint. Holding that checkpoint until delivery succeeds gives a later retry a chance to recover the missed notification.

Recover when a time is taken

An available slot can become unavailable between selection and submission. The interface handles the server’s conflict response by clearing the selected time, marking busy windows unavailable, and placing an explanation beside the time field. The address and contact fields remain populated so the user can choose another window without starting over.

A controlled browser check reproduced this sequence with a simulated slot-conflict response. The deployed interface kept the contact information, cleared the unavailable time, and moved attention to the field that needed correction. This makes recovery part of the normal form flow.

Amex Roofing booking form preserves sample contact information and asks the user to choose another arrival window after a simulated conflict.
Simulated slot conflict: contact details stay in place while the user chooses another arrival window. View full-size image

Delivered scope and remaining limits

The delivered site joins service information, bilingual content, and an inspection-request flow in one customer-facing experience. The important boundary is between receiving a request and completing the crew’s scheduling process. The public receipt reflects that distinction, while the integration handles validation and delivery behind it.

The next engineering step is to exercise the complete scheduling lifecycle in a controlled environment, including duplicate requests, delayed provider responses, and notification retries. Those checks would extend the existing contracts from individual boundaries to the whole workflow.

Screenshots use the deployed UI with fictional inputs and simulated API responses. Local contract checks used mocked dependencies; no bookings were sent. Captured September 5, 2026.