Good Morning
danielwonder.com
Marketing technologist, decentralised web builder, practical AI operator.
Good Morning
Good Morning
Working on a Nostr plugin for WordPress 👀
Working on a Nostr plugin for WordPress 👀
The Right to Exit I’ve had a personal blog on WordPress in one form or another since about 2008. However after watching much of the community getting disrupted by power struggles last…
I’ve had a personal blog on WordPress in one form or another since about 2008. However after watching much of the community getting disrupted by power struggles last year, I decided it was time to try something new for my personal blog.
Rather than simply jumping to another platform with the same structural risks, I decided to see just how far I could go in building my own decentralised publishing stack.

Traditional blog publishing features three key layers:
My goal was to decentralise every layer.

I’d already been playing with some of these ideas in my head, so these were ultimately the tools I chose:
| Layer | Tool | Why I Chose It |
|---|---|---|
| CMS | Nostr | Signed portable content served via relays |
| Host | IPFS + Fleek | Censorship-resistant, globally mirrored |
| Domain | ENS (.eth + eth.link) | Human-readable decentralised domains |
Nostr (Notes and Other Stuff Transmitted by Relays) is a decentralised messaging protocol that uses public key cryptography, similar to Bitcoin and Ethereum. At its core, you sign messages, and broadcast them to a network of relays, which mirror the content. While the primary way most people use Nostr is through apps such as Primal that offer a Twitter-like experience, the protocol has been expanded through a series of NIPs (Nostr Implementation Possibilities) that specify several other content “kinds” which can represent other data.
To use Nostr as a CMS, I make use of several message kinds:
Instead of using an existing Nostr client, I built a static frontend that fetches and renders the content directly in the browser with help from the Cursor IDE. The entire site was written in vanilla TypeScript with zero frameworks to avoid as many dependencies as possible.

IPFS (InterPlanetary File System) is a peer-to-peer protocol for storing and sharing data. Instead of using location-based naming, e.g., danielwonder.com, it uses content addressing via file and folder hashes. Due to the nature of hash functions, the same hash will always resolve to the same content as long as someone on the network is hosting a copy of the content. It first gained wider recognition as a protocol for hosting NFT media. However it can be used to host entire websites.
To host a file or collection of files, users must pin content on their node, which keeps serving it through the network. However, I don’t want to rely on others altruistically pinning and serving my site, so I host my own node that serves the site from my personal server.
Additionally, I pay for hosting from a company called Fleek, which pins my site across their network, including globally distributed IPFS nodes and gateways served through an edge network. Fleek connects directly to my GitHub, so that every push to `main` deploys an updated version of the site, which generates and pins a new IPFS hash.
As every update generates a new hash, it typically wouldn’t be ideal for a blog. You would need to re-pin and update your domain records every time you publish a new update. To address this, I designed my website as a static template that dynamically pulls the content from the Nostr network. By separating dynamic content (via Nostr) from the static website (served by IPFS), I can make frequent content updates without changing the website hash.
If you’ve ever seen an IPFS hash, you know it’s not something that most people will remember, especially if it changes often. On the traditional web, we use domains like .com to solve that problem for IP addresses. And in fact, I do still serve my blog through a .com domain as well for convenience. But ENS (Ethereum Name Service) provides the final layer of my decentralising stack.
ENS allows you to store an IPFS content hash in the `contenthash` field. This lets anyone with an ENS-compatible browser access your site through a human-readable address such as `danielwonder.eth`.

For broader compatibility, there are also HTTP gateway services that let `.eth` domains resolve using the traditional DNS system. You can use these by simply appending `.link` or `.limo` to the end of the domain. The end result is a single domain, e.g. `danielwonder.eth.link`, that works in traditional browsers and can also be accessed through the `.eth` name without relying on centralised DNS infrastructure.
One final note is that I could have used ENS as the profile layer instead of Nostr. I chose not to, as it would have introduced additional dependencies and I was already pulling content from Nostr, which also includes profile fields such as name, avatar, and social links. That said, I’ve added my Nostr pubkey to my ENS profile as an additional layer of verification.
While the structure I’ve chosen optimises for decentralisation and true ownership, there are some downsides.
Right now, the static site template has a few creative shortcuts that allowed me to ship fast, e.g. fallback assets. However, it already features a simple config file to allow for alternative identities and custom Nostr relays. I plan to open source it and allow anyone to use the template with their own Nostr key and host it however they want.
Sometimes we test things.
Sometimes we test things.
gm
gm
Hi
Hi
The challenge with Nostr identity is a single key point of failure. I want to try a new app, but have to spend 20 minutes trying to verify it isn’t just out…
The challenge with Nostr identity is a single key point of failure. I want to try a new app, but have to spend 20 minutes trying to verify it isn’t just out there collecting keys.
In a world where any question can be answered, the stand out skill is asking the right questions.
In a world where any question can be answered, the stand out skill is asking the right questions.
Move with wonder. Act with intent.
Move with wonder. Act with intent.
A Tale of Two Blogs During today’s “internet” outage, my old personal blog went down. It’s running WordPress on Kinsta, which relies on both Google Cloud and Cloudflare, so it got caught…
A Tale of Two Blogs
During today’s “internet” outage, my old personal blog went down. It’s running WordPress on Kinsta, which relies on both Google Cloud and Cloudflare, so it got caught in the disruption.
Meanwhile, my newer personal site stayed online. It’s powered by Nostr, hosted on distributed IPFS nodes, and accessible via Ethereum Name Service. Even though the .com version uses Cloudflare, the underlying setup doesn’t depend on Google.
Neither site is critical, but the difference is worth noting. This is exactly why decentralisation matters. A single bug from one provider shouldn’t take down half the web.