1 min read
How I built this site
A static personal site in two languages with Astro, Tailwind and Cloudflare, with no framework JavaScript and a contact form running on a Worker.
- #astro
- #tailwind
- #cloudflare
I wanted a place that says more than a PDF can: the projects I run, the work behind the numbers on my CV, and notes I write along the way. This is how it is put together.
The stack
- Astro renders every page to static HTML at build time. The only JavaScript that reaches the browser is the theme toggle and the contact form.
- Tailwind CSS v4 for styling, with colors defined as CSS variables so light and dark themes share the same classes.
- Cloudflare Workers serves the static files and handles the one dynamic route, the contact form.
Two languages from one source
All of the CV content lives in a single TypeScript file, with English and Portuguese side by side. Pages are thin wrappers that pass a locale to a shared component:
---
import Home from '../components/Home.astro';
---
<Home locale="pt-br" />
English lives at / and Portuguese at /pt-br/. Every page declares its alternate with hreflang, so search engines show the right version to each reader.
Contact form without a backend server
The form posts to /api/contact, which runs on a Worker. It checks a Cloudflare Turnstile token, validates the fields and sends me an email through the Email Service binding. No third-party form service and no API keys in the code.
What is next
More posts about the things I work on every day: multi-tenant Laravel, electronic invoicing in Brazil, Flutter apps and shipping small products on my own.