<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Mdtzlm</title>
    <description>The latest articles on Forem by Mdtzlm (@mdtzlm).</description>
    <link>https://forem.com/mdtzlm</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3870047%2F4e2faa0d-7687-4e75-ac52-bac2b944ebab.png</url>
      <title>Forem: Mdtzlm</title>
      <link>https://forem.com/mdtzlm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mdtzlm"/>
    <language>en</language>
    <item>
      <title>I built a directory of EU software alternatives. Then HN pointed out I was running it on Cloudflare.</title>
      <dc:creator>Mdtzlm</dc:creator>
      <pubDate>Thu, 09 Apr 2026 14:42:35 +0000</pubDate>
      <link>https://forem.com/mdtzlm/i-built-a-directory-of-eu-software-alternatives-then-hn-pointed-out-i-was-running-it-on-cloudflare-1cem</link>
      <guid>https://forem.com/mdtzlm/i-built-a-directory-of-eu-software-alternatives-then-hn-pointed-out-i-was-running-it-on-cloudflare-1cem</guid>
      <description>&lt;p&gt;&lt;a href="https://only-eu.eu" rel="noopener noreferrer"&gt;only-eu.eu&lt;/a&gt; is a directory of verified European alternatives to common US software and products. Proton instead of Gmail, Filen instead of Dropbox, Fairphone instead of iPhone. 332 pages, EN and DE, 130+ products across 20+ categories.&lt;/p&gt;

&lt;p&gt;This is about how it's built. Some decisions I'd make again. One I had to fix while 6,100 people were on the site.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why Astro
&lt;/h3&gt;

&lt;p&gt;The site is content: product pages, category pages, a landing page. No user accounts, no dynamic feeds, nothing that needs a server at render time. Astro was the obvious fit. Static output, fast builds, and you only ship client-side JS where you explicitly add it.&lt;/p&gt;

&lt;p&gt;In practice the site has three interactive elements: a search bar (Fuse.js, client-side, indexes product names and the US tools they replace), a "switch tool" grid on the homepage (pick a US tool, see the EU alternative), and a suggestion modal for submitting new products. All three are Astro islands. Everything else is plain HTML from the build.&lt;/p&gt;

&lt;p&gt;Build time for 332 pages is around 8 seconds. That includes generating both language variants for every product and category page from a single TypeScript data source. Astro's file-based routing made the i18n structure straightforward: &lt;code&gt;/kategorien/[category]/[product]&lt;/code&gt; for German, &lt;code&gt;/en/categories/[category]/[product]&lt;/code&gt; for English. One &lt;code&gt;products.ts&lt;/code&gt; file drives everything.&lt;/p&gt;




&lt;h3&gt;
  
  
  Hosting: from Cloudflare Pages to Bunny.net
&lt;/h3&gt;

&lt;p&gt;The site launched on Cloudflare Pages. It works fine: zero config, fast deploys, generous free tier. But after a Show HN post got traction (326 upvotes, ~6,100 visitors in a day), I decided to migrate.&lt;/p&gt;

&lt;p&gt;The reason was not performance. It was consistency. A directory arguing "use European software" probably should not run on US infrastructure. Cloudflare is registered in San Francisco.&lt;/p&gt;

&lt;p&gt;I moved to &lt;strong&gt;Bunny.net&lt;/strong&gt; for hosting, CDN, and DNS. Bunny is registered in Slovenia, runs its edge network across EU regions first, and the developer experience is comparable to Cloudflare. Maybe a bit more config upfront, but nothing unreasonable.&lt;/p&gt;

&lt;p&gt;The migration itself was mostly a DNS exercise. Bunny has a Storage Zone for static files and a Pull Zone for CDN delivery. You point your DNS at Bunny, configure the Pull Zone to serve from the Storage Zone, set up the custom hostname, and deploy via their API. I wrote a Node.js deploy script that uploads the &lt;code&gt;dist/&lt;/code&gt; folder with 20 parallel uploads and purges the CDN cache afterward.&lt;/p&gt;

&lt;p&gt;One thing to watch: Bunny's DNS API uses numeric type codes. Type 0 for A records, Type 2 for CNAME, Type 3 for TXT. The docs are a bit sparse on this. I created two TXT records by accident before I found the right values.&lt;/p&gt;




&lt;h3&gt;
  
  
  API and analytics: Hetzner VPS + self-hosted Plausible
&lt;/h3&gt;

&lt;p&gt;The site has a small backend: a suggestion API (collects product submissions from users), a contact form endpoint, and a Plausible analytics proxy. All of that runs on a single Hetzner VPS in Nuremberg.&lt;/p&gt;

&lt;p&gt;Analytics is self-hosted Plausible on the same VPS. The tracking script is served as a static file from the site itself, and events are proxied through the API. No external requests visible to the browser. No cookie banner, no third-party JS, no fingerprinting. For a site about EU software, that felt like the only reasonable option.&lt;/p&gt;




&lt;h3&gt;
  
  
  What broke during the HN launch
&lt;/h3&gt;

&lt;p&gt;When the Show HN post went live, the first substantive comment pointed out that Ente Photos, which I had listed as Norwegian, is actually incorporated in Delaware, USA. I removed it within the hour.&lt;/p&gt;

&lt;p&gt;That comment prompted a full pricing audit across all products. I found 19 incorrect prices. Corrected all of them the same day.&lt;/p&gt;

&lt;p&gt;And then there was the comment that stung a little more. Someone noted that a directory promoting European alternatives was running on Cloudflare, a US company headquartered in San Francisco. They were right. The HN community did not let that one slide quietly, and honestly I deserved it. That is part of why the Bunny.net migration happened: not just because of the principle, but because the irony had been pointed out publicly and I had no good counterargument.&lt;/p&gt;

&lt;p&gt;None of these were catastrophic. But they were visible. A community of thorough people will find the things you missed, including the things you were already a little uncomfortable about.&lt;/p&gt;




&lt;h3&gt;
  
  
  The badge system
&lt;/h3&gt;

&lt;p&gt;Every product on the site gets an embeddable badge: a small SVG that says "Listed on only-eu.eu". Providers can copy an HTML snippet and put it on their own site. The snippet links back with a &lt;code&gt;?ref=badge&lt;/code&gt; parameter, so Plausible tracks it as its own traffic source.&lt;/p&gt;

&lt;p&gt;One provider already did it. Abfahrt!, a German real-time transit API, embedded the badge in their footer. When someone clicks it, it shows up in my analytics as source "badge". No custom event setup needed, Plausible recognizes the &lt;code&gt;ref&lt;/code&gt; parameter automatically.&lt;/p&gt;

&lt;p&gt;The idea is simple: if a listed product links back, both sides benefit. They get a trust signal, I get a backlink and a way to measure which partnerships actually drive traffic.&lt;/p&gt;




&lt;h3&gt;
  
  
  What's next
&lt;/h3&gt;

&lt;p&gt;The site works. The basics are solid. But there are things that need to get better.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Search is getting a full rewrite.&lt;/strong&gt; The current Fuse.js search does fuzzy matching, but the results are not always useful. If you search "cloud storage", you get results, but the ranking is not great. The new version will weight exact category matches higher and show results grouped by category.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Switch Grid needs an overhaul.&lt;/strong&gt; Right now it maps US tools to EU alternatives by use case, but the matching is too broad. If you click "Notion", you should see project management tools, not every product that vaguely overlaps. The rewrite will make the mapping more precise and add support for products that replace multiple US tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;More categories are coming.&lt;/strong&gt; The site started with software. It now includes hardware (Fairphone, Canyon), fashion (Panama Jack, Shmutke), and services (FlixBus, BlaBlaCar). New categories like grocery, furniture, and education are in progress. The goal is a comprehensive directory, not just a software list.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;67 product suggestions from the HN launch&lt;/strong&gt; are still in the queue. They are being reviewed and added on a rolling basis.&lt;/p&gt;




&lt;h3&gt;
  
  
  Current state
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;332 pages (EN + DE)&lt;/li&gt;
&lt;li&gt;130+ products, 20+ categories&lt;/li&gt;
&lt;li&gt;Hosting: Bunny.net (Slovenia, EU)&lt;/li&gt;
&lt;li&gt;DNS: Bunny DNS (EU)&lt;/li&gt;
&lt;li&gt;Analytics: self-hosted Plausible on Hetzner (Nuremberg, DE)&lt;/li&gt;
&lt;li&gt;API: Hetzner VPS, Node.js&lt;/li&gt;
&lt;li&gt;Build: Astro, deployed via Bunny Storage API&lt;/li&gt;
&lt;li&gt;No cookies, no third-party JS, no CDN outside EU&lt;/li&gt;
&lt;li&gt;Embeddable badge with backlink tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're building something similar, happy to discuss the specifics in the comments.&lt;/p&gt;

&lt;p&gt;If you think a product is missing, use the "suggest" button on the site. I review submissions weekly.&lt;/p&gt;

&lt;p&gt;Cheers,&lt;br&gt;
Manuel&lt;/p&gt;

&lt;p&gt;PS: I used AI to spellcheck and sharpen the tone. I hope that's OK here.&lt;/p&gt;

</description>
      <category>astro</category>
      <category>webdev</category>
      <category>privacy</category>
      <category>marketing</category>
    </item>
  </channel>
</rss>
