Why I use Astro for my blog when Umbraco is my default
I spend most of my working day building Umbraco websites. When I decided to move my blog to my own domain, using Umbraco would have been the obvious choice.
I chose a folder of Markdown files instead.
That is not because Umbraco is bad at blogs. Umbraco is very good at them. It just does not fit the way I want to work on this particular blog.
The choice came down to what I wanted to achieve. I wanted to own the site, work on posts as files, and publish them without going through a backoffice. I did not want to pay more than necessary for hosting either. Once I had decided that the posts would be files and the pages did not need a running application or database, a static site generator was the obvious fit. The specific generator is almost incidental.
I wanted to own the publishing platform
Before this site, I published on DEV. Its editor uses Markdown, so the writing format was already familiar. The difference was where the authoritative version lived.
On DEV, I edited posts in a web interface. DEV does offer exports and an API, so the content was not locked away. It still meant that the normal editing and publishing flow happened on somebody else’s platform. I could not decide how the rest of the site should look or behave either.
I wanted the repository to hold the authoritative copy of every post. That gives me the files, their history, the URLs, the rendering, and the design. If I want to move the site later, I do not need to start by exporting my own writing.
Owning the platform does mean leaving DEV’s built-in distribution behind. In practice, that has not bothered me much. This is a fairly specific Umbraco blog, and its RSS feed is included on the Umbraco Community blogs page. New posts also reach the Umbraco Discord server and UMB.FYI. I share them myself on LinkedIn, X, Bluesky, and Mastodon.
I can still cross-post an article to DEV and set my own version as the canonical URL. DEV supports canonical URLs in its editor, so owning the original does not prevent me from using its audience as well.
The workflow came first
A blog post in this repository is an ordinary Markdown file. I can start with a rough idea, discuss it with an AI agent, check claims, and turn it into a draft without leaving the project.
Markdown also makes the writing itself faster for me. I do not have to select some text and find the right formatting control. I type ## A heading or [link text](https://example.com) and keep writing. It is a small difference, but it suits the way I work.
I have written skills that guide the agent through the process. One interviews me about the subject, challenges vague answers, checks technical claims against primary sources, proposes an outline, and only then writes the draft. Other instructions cover the tone and structure I use on the blog.
AI is useful here because it can work on the same files as the rest of the site. It can read an existing post, find related material, update the draft, and show me the changes as a diff. I can correct the text like any other change in the repository.
That flow has made it much easier for me to get from an idea to a reasonably complete article. The AI is not just producing text. I use it as an editor and sparring partner to validate, test, and explore the idea before I publish it.
An Umbraco backoffice would give me a good editing experience, but it would still put an administration interface between the repository and the post. I do not need that layer when I am the only author and the content is mostly text.
What actually runs the site
The content model for a blog post is deliberately small. A file starts with a little frontmatter followed by normal Markdown.
---
title: "Post title"
description: "A short description"
date: 2026-09-14
draft: true
tags: ["umbraco", "architecture"]
---
Astro validates those values through a content collection and turns each Markdown file into a page. The site configuration tells Astro to generate static output.
export default defineConfig({
output: "static",
});
Astro’s documentation describes static output as prerendering pages into a completely static site. The blog also builds its search index with Pagefind and generates Open Graph images during the build.
Publishing is a Git operation. A push to main starts a GitHub Actions workflow, which installs the dependencies, builds the site, and sends the generated dist directory to Cloudflare Pages.
- name: Build site
run: npm run build
- name: Deploy to Cloudflare Pages
uses: cloudflare/wrangler-action@v3
with:
command: pages deploy dist --project-name=skttldev
The pages served to readers do not require a running .NET application or a SQL database. Cloudflare states that requests for static assets are free and unlimited on both free and paid plans. Its free plan also allows 20,000 files per Pages site, which leaves plenty of room for this blog.
There are still moving parts. Node packages need updates, builds can fail, and the deployment workflow needs maintenance. Static does not mean maintenance-free. It means that the published blog has fewer runtime components for me to look after.
What Umbraco would add
If I built the blog in Umbraco today, I would choose the most recent version, which is currently Umbraco 18. The Umbraco system requirements specify .NET 10 and either SQLite or SQL Server.
The simplest hosting option would be Umbraco Cloud. At the time of writing, Umbraco Cloud Starter costs €45 per month. That includes Azure hosting, automatic security updates, a CDN, and other services that I would otherwise have to arrange myself.
That price is not actually a blocker for me. As an Umbraco MVP, I have access to a free Cloud project for a personal or community-related site. I could use it for this blog. I would still be adding a CMS and changing a workflow that already does what I need.
I might be able to host it for less on Azure App Service, but then I would need to choose and configure the application hosting, database, deployment, backups, and updates. Neither option is unreasonable. Both are more than this blog currently needs.
The extra pieces buy something useful. Umbraco gives me a backoffice where I can model content, manage media and relationships, add validation, schedule publishing, and query the result through its APIs. Those features matter on many of the sites I build. They are the reason Umbraco remains my default CMS.
For this blog, most of them would sit unused while I continued wishing I could edit the source file directly.
Where a CMS would fit better
Not every part of my planned site fits Markdown equally well.
I want a portfolio with links to packages, tools, and other things I have made. I already have an early attempt using another Astro content collection. Each item is a flat Markdown file with frontmatter for its type, image, URL, repository, and tags.
That is workable, but I have spent a while circling around the data model and the frontend presentation without finding the right shape. Portfolio items are more structured than blog posts. I want to group and filter them, relate them to other content, and present different project types sensibly.
That data would be more pleasant to maintain in a point-and-click CMS. Umbraco would make the data modelling easier and give me editors for each field, validation, and better tools for managing relationships.
It would not design or implement the frontend filtering for me. That is currently the larger unresolved problem. Moving the whole site to a CMS would add infrastructure without solving the part I am actually stuck on.
Why I am not building a hybrid
There are ways to combine the two approaches.
An Umbraco site could retrieve the blog posts from this GitHub repository and keep Markdown as the source. Astro could retrieve the portfolio through Umbraco’s Delivery API. Either approach would let each type of content live in the system that suits it.
It would also give me two systems to develop, deploy, and understand. The integration would need rules for caching, failures, previews, and updates. I would still have to build the portfolio presentation.
That is a lot of machinery for a personal site whose current blog workflow already works. It might make an interesting technical experiment, but it would be more than the job needs.
Final thoughts
I did not choose Astro because it beats Umbraco at blogging. I chose a static, file-based site because it matches how I want to write and publish right now.
The result is simple. The content and website live in the same repository. AI can help me work on both. A Git push publishes static files to hosting that is sufficient for the site and currently costs me nothing.
Umbraco remains my default when a site benefits from structured content and a real editing interface. My planned portfolio may eventually push this site further in that direction. It has not done so yet.
For now, changing the architecture would give me more platform and no better blog. I am quite happy with the folder of Markdown files.