When I decided to start my own blog, I faced a classic dilemma: WordPress, Ghost, Hugo, or maybe something custom? I chose to create my own solution that ultimately generates a static HTML page. Why? Because I follow a principle: the simpler something is built, the easier it is for me to maintain.
TL;DR
| Aspect | My solution |
|---|---|
| Framework | Symfony 7.3 |
| Generation | StaticContentGeneratorBundle |
| Hosting | Mikrus (VPS) |
| Deploy | GitHub Actions |
| Migration | ~30 minutes |
Why static pages?
Simplicity first. Static pages mean:
- No backend - nothing to break
- Lightning-fast loading - server sends ready HTML
- Cheap hosting - nginx serving files is enough
In Patoarchitekci podcast episode #155 (Polish) about "budget hosting", there was a quote that summarizes my approach well:
There are things in life that are worth doing and things that pay off. Not always what's worth doing pays off, not always what pays off is worth doing.
How does it work?
I use the StaticContentGeneratorBundle package by Norbert Orzechowicz. Real-world examples can be found in the norbert.tech repo (author's site) and in the Flow PHP documentation site.
Here's how it works:
- I write code like a normal Symfony app - controllers, Twig, routing
- Run the build - the bundle iterates through all routes and saves rendered HTML
- Output is a folder with static files - ready to deploy anywhere
# The entire build process
composer build
Under the hood, magic happens:
# Clear cache
APP_ENV=prod bin/console cache:clear
# Build assets (Tailwind, JS)
APP_ENV=prod bin/console tailwind:build --minify
APP_ENV=prod bin/console asset-map:compile
# Generate static HTML
APP_ENV=prod bin/console static-content-generator:generate:routes
# Sitemap for SEO
APP_ENV=prod bin/console presta:sitemaps:dump
# Copy assets to output
APP_ENV=prod bin/console static-content-generator:copy:assets
Content structure
I keep articles as Markdown files with frontmatter:
content/
├── static-site-symfony/
│ ├── pl.md # Polish version
│ └── en.md # English version
└── helm-vs-kustomize/
├── pl.md
└── en.md
Each article is plain Markdown with a YAML header. I process it through league/commonmark with extensions like GFM, tables, and automatic heading anchors.
Hosting and deploy
I host everything on Mikrus - a Polish VPS for pennies. I use Mikrus 3.5 (4 GB RAM, 40 GB disk) because besides the blog I run several other apps and a company website there.
For the blog alone, much less is needed - Mikrus 1.0 or even the free Frog tier would easily handle static files.
Looking for a cheap VPS for your own projects? I recommend it - referral link.
Deploy? Push to main triggers GitHub Actions, which builds the site and rsyncs it to the server:
name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build static site
run: composer build
- name: Deploy to server
run: rsync -avz output/ user@server:/var/www/blog/
Migration? 30 minutes
This is my favorite part. Want to move the blog to another server? Here's the entire process:
- Set up nginx on the new server (~5 min)
- Generate SSH keys and update secrets in GitHub Actions (~5 min)
- Run the deploy action to the new server (~1 min)
- Switch DNS (~20 min for propagation)
No database to migrate. No PHP environment to configure. No dependency on specific hosting.
If I were using WordPress, migration would be: export database, import database, configure wp-config, test if everything works, pray that plugins don't cause problems...
Why Symfony and not Hugo/Jekyll?
I could use a dedicated static site generator. But:
- I know Symfony - no need to learn a new tool
- Full control - I can add any logic in PHP
- Reusability - same components as in commercial projects
- Twig - powerful templating system I know by heart
Downsides?
To be fair:
- No comments out-of-the-box - I'd need to add Disqus or similar
- No CMS - I write in Markdown in a code editor
For me, these tradeoffs are acceptable. I'd rather write in an IDE than maintain WordPress.
Summary
Boring solutions are an investment in peace of mind. Static HTML may not be sexy, but over months and years it pays off handsomely – it runs stable, maintains itself, and I can move it anywhere in 30 minutes.
If you're building a blog and know PHP - consider this approach. You don't need Kubernetes, a database, or complex infrastructure. Sometimes nginx serving HTML files is all you need.
Have questions? Reach out on LinkedIn.