<?xml version="1.0" encoding="UTF-8"?>
<rss
  version="2.0"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:media="http://search.yahoo.com/mrss/"
>
<channel>
<title><![CDATA[Writing - Joachim Zeelmaekers]]></title>
<description><![CDATA[Articles tagged "Writing" on Joachim Zeelmaekers.]]></description>
<link>https://joachimz.me/tag/writing/</link>
<image>
<url>https://joachimz.me/favicon.svg</url>
<title><![CDATA[Writing - Joachim Zeelmaekers]]></title>
<link>https://joachimz.me/tag/writing/</link>
</image>
<generator>Astro</generator>
<lastBuildDate>Mon, 23 Feb 2026 06:00:00 GMT</lastBuildDate>
<atom:link href="https://joachimz.me/tag/writing/rss.xml" rel="self" type="application/rss+xml"/>
<ttl>60</ttl>
<language>en-us</language>
<item>
<title><![CDATA[Rebuilding My Blog From the Ground Up]]></title>
<description><![CDATA[Leaving Ghost for Astro and Cloudflare Pages: owning my blog stack]]></description>
<link>https://joachimz.me/blog/rebuilding-my-blog-from-the-ground-up/</link>
<guid isPermaLink="true">https://joachimz.me/blog/rebuilding-my-blog-from-the-ground-up/</guid>
<category>software-engineering</category><category>writing</category>
<dc:creator><![CDATA[Joachim Zeelmaekers]]></dc:creator>
<pubDate>Mon, 23 Feb 2026 06:00:00 GMT</pubDate>
<media:content url="https://joachimz.me/images/blog/rebuilding-my-blog-from-the-ground-up.webp" medium="image"/>
<content:encoded><![CDATA[<p>My blog ran on <a href="https://ghost.org/">Ghost</a> for years and felt fast enough. Then I rebuilt it with Astro and Cloudflare Pages.</p>
<p>Page load dropped from about one second to under 300 ms, the stack cost went to zero, and I finally owned every part of the experience.</p>
<p>This is why I left Ghost and rebuilt the blog from the ground up.</p>
<h2>Why I Left Ghost</h2>
<p>Ghost is a great product. If you want a managed blogging platform with a clean editor and built-in newsletter support, it does the job well.</p>
<p>My reasons for leaving were not about quality. They were about control and fit.</p>
<p>Since my goal this year is to start publishing weekly, I wanted my blog to feel completely mine: faster, simpler, and shaped exactly to my preferences. Ghost did not allow the level of customization I wanted without workarounds.</p>
<p>The bigger issue was scope. Ghost Pro is not cheap, and self-hosting Ghost means running a server, a database, and ongoing upgrades. For a personal blog with one post a week, that stack felt like overkill.</p>
<p>I expected the newsletter to be the hardest part to replace. It turned out not to be.</p>
<h2>Choosing the Stack</h2>
<p>I did not spend weeks evaluating frameworks, like I would in the past. The decision was pretty simple.</p>
<p>Lately I heard a lot about <strong><a href="https://astro.build/">Astro</a></strong> and I wanted to try it out. It ships hardly any Javascript by default, supports Markdown and MDX natively, and gives you full control over the output. No hydration overhead, no client-side routing unless you explicitly opt in. Just HTML and CSS.</p>
<p><strong><a href="https://pages.cloudflare.com/">Cloudflare Pages</a></strong> for hosting. Free tier, global CDN, automatic deployments using GitHub Actions. The site builds in seconds and deploys to edge locations worldwide. No servers to manage, no bills to worry about.</p>
<p><strong>Markdown files</strong> instead of a database. Like we all know, lately everything has been about Markdown files, so why not put every post in a Markdown file in a Git repository. I can make changes to it in any editor, preview locally, and publish by pushing to main. Version history comes for free.</p>
<p>For my newsletter, with the full 12 subscribers, I first thought to not include it anymore. But then I found <a href="https://kit.com/">Kit</a>, 10 000 subscribers for free. Perfect for my use case.</p>
<p>The entire stack costs me nothing beyond the domain name, and my time of course.</p>
<h2>Performance Results</h2>
<p>The page load numbers are the clearest win.</p>
<p>In real usage the Ghost site felt reasonably fast, around one second to visible content. However, Lighthouse mobile simulation revealed much heavier rendering costs, especially LCP. The Astro rebuild reduces both perceived and measured performance costs.</p>
<p>The architecture shift from dynamic rendering to static edge delivery shows up clearly in performance metrics.</p>
<p>Lighthouse snapshot (single run, mobile emulation, default throttling).</p>
<p>Here is a Lighthouse snapshot (single run, mobile emulation) comparing the old Ghost site with the new Astro build:</p>
<table>
<thead>
<tr>
<th>Metric</th>
<th>Ghost (before)</th>
<th>Astro (after)</th>
</tr>
</thead>
<tbody><tr>
<td>Performance score</td>
<td>63</td>
<td>77</td>
</tr>
<tr>
<td>Accessibility score</td>
<td>80</td>
<td>100</td>
</tr>
<tr>
<td>Best Practices score</td>
<td>81</td>
<td>100</td>
</tr>
<tr>
<td>SEO score</td>
<td>100</td>
<td>100</td>
</tr>
<tr>
<td>FCP</td>
<td>2,597 ms</td>
<td>1,049 ms</td>
</tr>
<tr>
<td>LCP</td>
<td>23,758 ms</td>
<td>4,792 ms</td>
</tr>
<tr>
<td>Speed Index</td>
<td>7,857 ms</td>
<td>1,296 ms</td>
</tr>
<tr>
<td>Total page weight</td>
<td>7.71 MB</td>
<td>0.42 MB</td>
</tr>
<tr>
<td>Requests</td>
<td>36</td>
<td>28</td>
</tr>
</tbody></table>
<p>The largest improvements come from removing heavy images and client-side scripts. Total page weight dropped by over 18x, which directly improved Speed Index and LCP.</p>
<h2>Design + UX Updates</h2>
<p>The better question would be, what did not change. Well, the content.</p>
<p>The homepage moved from a stock template to a focused, branded entry point with clear hierarchy and fewer distractions.</p>
<p>Beyond speed, the design is entirely mine. The goal was a calmer, more intentional experience with room to grow. I can now iterate quickly and add new features without fighting the platform.</p>
<p>The new list view trades heavy thumbnails and whitespace for tighter hierarchy and faster scanning. Smaller images, consistent metadata, and clearer contrast mean you can find a post at a glance without hunting for it.</p>
<p>The reading view moves from a template-heavy page to a focused editorial layout. Better line length, calmer typography, and fewer competing elements keep attention on the text and reduce cognitive load.</p>
<p>The CTA experience is now integrated into the reading flow instead of floating over it. Recommendations feel like a natural next step, not an interruption, which keeps the page focused while still nudging the next click.</p>
<p>The newsletter now feels like part of the site, not a third-party embed. The form is lighter, the spacing is calmer, and the CTA matches the rest of the system, so it reads as an invitation rather than a modal ad.</p>
<p><img src="/images/blog/rebuild/new-features.webp" alt="Site features overview in the new blog"></p>
<p>The benefit of building this site myself is being able to introduce more features to improve the experience:</p>
<ul>
<li>Search across every post (full text, fast).</li>
<li>An About page that actually explains what I write about.</li>
<li>Dark/light mode that preserves the brand tone.</li>
<li>One-click code copy for snippets.</li>
<li>Dedicated tag pages so topics are easy to follow.</li>
<li>Posts grouped by year for quick scanning.</li>
</ul>
<h2>The Takeaway</h2>
<p>If you are a developer blogging on a managed platform, ask yourself what you are getting in return for that convenience. If the answer is &quot;less control and a monthly bill,&quot; it might be time to build your own.</p>
<p>It does not need to be complicated. A static site generator, a CDN, and Markdown files will take you further than most platforms. And the process of building it will teach you more than any blog post about blogging ever could.</p>
<p>Including this one.</p>
]]></content:encoded>
</item>
<item>
<title><![CDATA[One Month of Writing in Public: What the Numbers Say]]></title>
<description><![CDATA[I committed to publishing one article weekly. The hardest part wasn't the writing, but the engagement. Here's what the numbers revealed.]]></description>
<link>https://joachimz.me/one-month-of-writing-in-public-what-the-numbers-actually-say/</link>
<guid isPermaLink="true">https://joachimz.me/one-month-of-writing-in-public-what-the-numbers-actually-say/</guid>
<category>writing</category><category>personal-growth</category>
<dc:creator><![CDATA[Joachim Zeelmaekers]]></dc:creator>
<pubDate>Mon, 26 Jan 2026 00:00:00 GMT</pubDate>
<media:content url="https://joachimz.me/images/blog/one-month-of-writing-in-public-what-the-numbers-actually-say.webp" medium="image"/>
<content:encoded><![CDATA[<p>I’ve been at this for a month now. One month of trying something that, honestly, made me awkward at first.</p>
<p>If you know me, you know I measure things. Not obsessively. I’m not tracking my sleep cycles or optimizing my morning routine. But I’ve learned that if you don’t measure anything, you’re just guessing. And guessing gets old fast.</p>
<p>This year I rediscovered something I’d forgotten I loved: writing. And that interest pulled me into territory I’d mostly avoided for years. Social media. “Personal branding.”</p>
<p>I know. I felt the cringe too.</p>
<p>But here’s the thing about curiosity, it doesn’t care about any of that. Once the experiment took shape in my head, I couldn’t let it go.</p>
<h2 id="the-plan-was-simple">The Plan Was Simple</h2>
<p>Write and publish one article every week. No exceptions. Or at least, not yet. Life has a way of interrupting even the best intentions.</p>
<p>The writing part? That came naturally. The distribution part? That’s where things got interesting.</p>
<p>LinkedIn was always my default. I’d post something, it would disappear into the void, and I’d move on. But this time I wanted to understand how the platform actually worked. So I started reading. And one concept kept surfacing over and over again.</p>
<p>Commenting.</p>
<h2 id="the-thirty-minute-comment">The Thirty-Minute Comment</h2>
<p>Sounds easy, right? Leave a thoughtful comment on a relevant post. Show genuine interest. Engage with your network.</p>
<p>I thought the same thing. Then I tried it.</p>
<p>Finding a post that actually resonated with me. Something worth responding to beyond “Great insights!”, took longer than I expected. Sometimes thirty minutes or more. Thirty minutes of scrolling through doom-and-gloom AI predictions and recycled productivity advice, looking for something that sparked a genuine thought.</p>
<p>When I finally found one, I had to truly understand it. Then craft something valuable for me and for the person who wrote it.</p>
<p>This “simple” daily habit turned out to be one of the hardest parts of the whole experiment. And I have to say, I missed two days when I was sick.</p>
<h2 id="the-domain-problem">The Domain Problem</h2>
<p>Somewhere in the first week, I realized my blog URL was working against me.</p>
<p><a href="https://blog.webtric.be">https://blog.webtric.be</a> isn’t exactly memorable. Try telling someone that URL over coffee and hope they remember. So I switched to joachimz.me shorter, cleaner and actually writable.</p>
<p>But now I had a new problem: how do you redirect traffic without breaking everything?</p>
<p>If you’ve ever migrated a site, you know this can be a nightmare if not done properly. Fortunately, Cloudflare’s free tier makes it almost trivial. One redirect rule, and all the old traffic flows to the new domain. Done.</p>
<p>If you’re interesting in knowing how, reach out and I’ll gladly help you!</p>
<h2 id="actually-measuring-what-matters">Actually Measuring What Matters</h2>
<p>Next step: tracking. I went with Heap, which offers a generous free tier (up to 10,000 sessions per month). For a blog my size, that’s more than enough. And if I ever exceed it? That would be a wonderful problem to have.</p>
<p>Integration took about five minutes. Add a few lines of code, similar to Google Search Console, and you’re capturing data. (No, I’m not sponsored. I’m just showing you that this stuff isn’t as complicated as it seems. If you’ve been putting off starting a blog because the technical side intimidates you, it shouldn’t.)</p>
<h2 id="the-numbers">The Numbers</h2>
<p>Now the part you’re actually here for.</p>
<p>I had no baseline. I hadn’t posted anything meaningful on LinkedIn in months. So these numbers exist in a vacuum, but they still surprised me.</p>
<p><strong>LinkedIn Performance:</strong></p>
<ul>
<li>~8,500 impressions (I’m discounting some repost noise)</li>
<li>~4,000 members reached</li>
<li>Posts published weekly, typically Monday through Wednesday</li>
</ul>
<p>I didn’t expect this. I expected some growth, sure. But not this trajectory. The curve kept climbing in a way that felt almost suspicious.</p>
<p>Of course, comparing this to “nothing” isn’t exactly scientific. But it’s a start.</p>
<p><strong>Blog Traffic (since December 21st, when the new domain went live):</strong></p>
<ul>
<li>213 unique visitors</li>
<li>294 page views</li>
<li>233 sessions</li>
</ul>
<p>These are fine, but they’re not what I actually cared about. I wanted to know: are people reading?</p>
<p>Time on page by article</p>
<p>The longer posts held attention longer. No surprise there. But seeing actual minutes spent on something I wrote? That landed differently than I expected. In a positive way!</p>
<p>The last one stings a little. Zero newsletter signups. But it’s also honest data. People visited, some of them read, but nobody was compelled to stick around for more. That’s useful information. It tells me the content might be interesting enough to click, but not yet valuable enough to subscribe. Another learning.</p>
<h2 id="what-one-month-actually-taught-me">What One Month Actually Taught Me</h2>
<p>Here’s what I didn’t anticipate: the hardest part wasn’t the writing. It wasn’t the technical setup. It wasn’t even maintaining the weekly cadence.</p>
<p>The hardest part was engaging authentically in a space that is unknown to me for the most part.</p>
<p>Thirty minutes to find one post worth commenting on. That ratio tells you something about the signal-to-noise problem on LinkedIn, or maybe my feed is the problem. But it also tells you something about the opportunity.</p>
<p>If most people are leaving “Great post!” or AI-generated comments, the bar for standing out isn’t actually that high. It just requires effort most people aren’t willing to give.</p>
<p>The numbers are encouraging, but ultimately they don’t matter too much. Also, one month is nothing. It’s a spark, not a trend. The real question is whether I can sustain this through month three, month six, month twelve, when the novelty wears off and the weekly deadline starts feeling like a weight instead of a challenge.</p>
<p>What I can say: I’m writing more than I have in years. I’m thinking more carefully about what I want to say. And for the first time in a long time, I’m actually clicking publish consistently instead of letting it sit in drafts because the posts might not be perfect.</p>
<p>That alone feels like progress worth measuring.</p>]]></content:encoded>
</item>
<item>
<title><![CDATA[Why you should consider using a publishing platform for your blog]]></title>
<description><![CDATA[When you consider a blog as one of your side projects, you might want to pick an existing platform and here's why.]]></description>
<link>https://joachimz.me/why-you-should-consider-using/</link>
<guid isPermaLink="true">https://joachimz.me/why-you-should-consider-using/</guid>
<category>writing</category>
<dc:creator><![CDATA[Joachim Zeelmaekers]]></dc:creator>
<pubDate>Sun, 03 Jan 2021 00:00:00 GMT</pubDate>
<media:content url="https://joachimz.me/images/blog/why-you-should-consider-using.webp" medium="image"/>
<content:encoded><![CDATA[<p>After a couple of months of writing on Medium and Dev, I started to think about building my own blog. As a developer, I love to build things myself. But after a while of building my own blog, I realised that this approach would take a huge amount of time. Certainly, when I compared the functionality that I was building with existing platforms.</p>
<p>After some advice that I received from another developer, who also has a blog, I started to use Ghost. Ghost is a full-stack, modern publishing platform to create your personal blog. With their Medium-like editor, one-click mailing list feature, optional paid subscriptions for members and much more Ghost offers a complete solution for building your audience.</p>
<p>Now let me explain why I chose Ghost and why I did not continue using Strapi headless CMS with Gatsby.</p>
<h2 id="editor">Editor</h2>
<p>I used to write my blogs in Markdown, which is a formatting language often used by developers. And I love Markdown, don’t get me wrong. But editors, like the ones from Medium or Ghost, offer easy solutions to drag and drop images, add code-snippets, embed external media, etc…</p>
<p>By using this editor, I have the ability to schedule posts for a future date without having to be online. This approach allows you to write multiple posts and schedule them for the upcoming weeks. Of course, this is also possible when you build your own blog, but this will cost you some time to make sure it works properly.</p>
<h2 id="integrations">Integrations</h2>
<p>Speaking of time, I love publishing my content on Dev and Medium. And I used to write my articles in Markdown, and copy-paste them to all the platforms. This is fine in the beginning, but it’s pretty time-consuming and prone to error.</p>
<p>This hassle is solved by using the Zapier integration from Ghost. Zapier is a platform that helps you automate workflows by creating a Zap. An example of a Zap is tweeting your published article automatically on Twitter. By creating these workflows, you can automate a lot of the process, and focus simply on creating new articles. Zapier has about 2000 integrations with other apps, so this is a powerful tool to use. It’s also free for the first 5 zaps, which is all you need!</p>
<p>Ghost also offers about 30 events to listen on. If you want to create custom integrations, you can easily set up a service and configure your webhook in the platform. If you want more information about the available events, visit the docs.</p>
<h2 id="subscribers">Subscribers</h2>
<p>When you try to start a mailing list, there are a couple of questions that pop up. My main question was, which tool do I use, and how do I manage the list easily?</p>
<p>Well, Ghost offers a solution to this problem. By toggling on the member-functionality, you get a subscribe option on your website. When anyone subscribes, they are added to your member list. Once someone is subscribed, you can send your new articles via mail on publishing without extra costs.</p>
<p>You can also export your members into another tool like MailerLite or Mailchimp so you can send additional emails that are not linked to your articles. For example, sending an email with your newest podcast or a survey!</p>
<h2 id="customisation">Customisation</h2>
<p>As a developer, I find it important to be able to customise the theme. In the beginning, it’s not that important. But when you progress, you have to be able to change the design, improve user experience and add some additional features.</p>
<p>When you use Ghost, you can buy a theme that fits you or create your own theme. Ghost uses a combination of Javascript and handlebars. This allows you to customise the whole theme and add features on the go. You can integrate your Github with Ghost to keep track of your versions, and you could even sell your theme if you like.</p>
<p>Don’t want to use handlebars and Javascript? No problem! Ghost offers an API to use the platform as a headless CMS. This means that you can connect any frontend to the platform without using the themes provided by Ghost or the community. This allows you to use the powerful features from Ghost together with your preferred frontend platform.</p>
<h2 id="maintainability">Maintainability</h2>
<p>When you create your own blog, you will always have to maintain the code. Some APIs will change over time and some of your integrations will stop working for some reason. When you use Ghost, you pay the monthly fee to maintain the platform and add additional features. If your blog is very successful, you might also want to create other content. Using a platform like Ghost will save you time in the long run by simplifying the process.</p>
<p>When you have some experience as a developer, you will know that building a great application takes time. In my case, I don’t have the amount of time to work on a platform and put out content. When you’re already working as a full-time developer and run a side business, it’s challenging to maintain the code for your personal blog without sacrificing all your time.</p>
<h2 id="metadata-configuration-and-seo">Metadata configuration and SEO</h2>
<p>In creating a publishing platform, SEO and metadata configuration is important. You have to be able to configure the title and the description and make sure it’s properly displayed in Google. It takes some time to configure this, and platforms like Ghost already have this in place. You get the configuration options for every post with a preview available.</p>
<h2 id="conclusion">Conclusion</h2>
<p>I know I focused on Ghost as the go-to platform. The reason for this is that it’s the platform that I use and I know most about. There are other platforms out there, which might be even better, but for this article, I wanted to focus on this platform.</p>
<p>I could go on and on about why you should consider using a platform like Ghost. But it’s all a matter of the amount of effort you want to put it. If you have no other projects except for your own blog, you might want to consider building your own platform because you will learn a lot in doing so!</p>
<p>But when you consider a blog as one of your side projects, you might want to pick an existing platform. You do have to take into account that you have to pay the monthly fee of 36$/month or 29$/month if you pay annually. But in my case, it’s more than worth it. When you build your own platform you also have to pay for monitoring, hosting, some paid integrations and other things. So before you start building, consider all the options. One of them being Ghost!</p>]]></content:encoded>
</item>
</channel>
</rss>