Shipping This Blog — Astro, Tailwind, and Self-Hosted with Coolify
How this site was built: static generation with Astro and deployments via GitHub Actions on a self-hosted Coolify instance.
I wanted this blog to be small infrastructure: easy to understand, cheap to run, and boring once deployed. This post is a quick walkthrough of the stack and the few choices that make it practical for me.
Why Astro
The requirements were simple: fast static pages, control over the generated output, and MDX support so I could write technical articles in Markdown while still embedding interactive components when useful.
Astro fits that well. It pre-renders pages to plain HTML at build time and ships no client-side JavaScript unless a component explicitly needs it.
Posts are written in MDX. The text stays readable in the editor, but I can still drop Astro components into an article. The diagrams on this page use a small <Mermaid> wrapper: the diagram definition lives in the .mdx file, Mermaid renders it as SVG, and the wrapper deals with dark mode and zooming.
Build Pipeline
Astro builds the site into a plain dist/ directory. That directory is all nginx needs to serve the blog.
Design System
The design uses Tailwind v4 with a small set of CSS variables for color, spacing, borders, and dark mode.
I also used Impeccable as a design assistant. The useful part was not asking it to “make it beautiful”, but giving it constraints. I kept a design.md file with the palette, typography, spacing, and the general feel I wanted. When the result drifted, I changed the directions instead of accepting the output blindly. Git made the experiments cheap to revert.
Self-Hosted Deployment
The hosting setup is intentionally small: one Hetzner VPS managed by Coolify. Coolify gives me a practical way to deploy services as Docker Compose applications without adding a managed platform on top.
For this blog, Coolify clones the private GitHub repository, runs a two-stage Docker build, and replaces the running container. Node builds the static files; nginx serves them.
CI/CD Pipeline
A GitHub Actions workflow runs on every push to master. Before deployment, it installs dependencies and runs a production build. If that fails, the workflow stops there.
If the build passes, the workflow calls the Coolify webhook. That keeps the deploy path simple while avoiding the worst case: asking Coolify to deploy a commit that cannot even build. The Coolify API token and deploy endpoint URL are stored as GitHub repository secrets, so they are available to the workflow without being committed to the repository.
Conclusion
This setup is not complicated, and that is the point. The site builds fast, deploys from Git, and leaves me with very little to maintain.
I will use it to write about the projects I build on the side, especially around video, IoT, and web platforms: edge capture, device orchestration, inference, real-time dashboards, and the glue needed to make those pieces work together.