Professional
Kaizen Apps | Corporate site
The company's bilingual site, with the product demonstrations under the same domain and a booking form that reaches a person.
- Development
- 2026-01 — Present
Stack
- Astro
- TypeScript
- React
- Tailwind CSS
- Cloudflare Turnstile
- Resend
- Render
Context
Kaizen Apps sells bespoke software, so its site is the first commercial contact and the place where a prospect sees the product running before speaking to anyone.
The assignment was to rebuild it entirely: the marketing pages in Spanish and English, the application demonstrations under the same domain, and a booking channel that does not depend on someone checking a shared inbox.
Problem
The previous site carried no search metadata. There were no per-page titles or descriptions, and no declared relationship between the Spanish and English versions, so a search engine had no way of knowing they were the same page in two languages.
The applications the company sells each live at their own address, off the site. A prospect who wanted to see them running left the commercial site, and once outside had no way back and no way across to the next one.
Technical decisions
Routes are declared in a single file. Every page carries its identifier, its two routes and its metadata there, and both the menu and the language equivalence map behind the language switch come out of that same table. Adding a page means adding an entry, not walking through six files.
The site is static except where it cannot be. Only the booking needs a server, so only the booking is served as a server route; the rest is generated at build time. That made moving it from one host to another a matter of swapping the adapter, without touching the pages.
The eight pages that wrap a demonstration were eight copies of the same HTML. They were reduced to one shared function each route delegates to: the floating menu and the frame policy are edited in one file, not eight.
The anti-bot challenge is validated against Cloudflare from the server, not in the browser, and the public response does not distinguish between an invalid token, a malformed field and a failure of the email service. The real code is recorded server-side.
Architecture
The site has three classes of page. The marketing pages are static and bilingual, generated from the route table. The demonstration wrappers are HTML responses that mount the corresponding application inside the site. And there is a single server endpoint, the booking one.
The form obtains a Cloudflare Turnstile token and the server validates it against Cloudflare before looking at the rest of the submission. The browser does not decide whether the challenge was passed.
The type, presence and length of every field are verified on the server. A submission that fails those checks reaches neither the challenge verification nor the email.
The public response says the submission failed and nothing more. The real error code stays in the server log, where it gives no guidance to anyone probing the form blind.
Only the challenge's public key travels in the HTML. The secret key and the email service key exist only in the server environment.
Result
The site publishes in Spanish and English from a single route definition, with each page’s metadata and the correspondence between languages declared where the page itself is declared.
The demonstrations ended up under the same domain and share navigation, so a prospect can walk through them without going back in the browser.
A meeting request now arrives as a formatted email in the commercial inbox, and the sender gets their confirmation in the language they wrote in.
What I learned
A bilingual site breaks on duplication, not on translation. While routes lived in the menu, in the language switch and in every page, each new section cost three edits and produced at least one broken link. With a single table, language stopped being a special case.
The other lesson is commercial. The form is not a detail of the contact page: it is the one point on the site where a visitor leaves something behind. It received the most security attention, and it was the only thing that justified having a server at all.