{"version":"https://jsonfeed.org/version/1.1","title":"Stephen Ajulu","home_page_url":"https://ajulu.netlify.app/","feed_url":"https://ajulu.netlify.app/tags/indieweb/feed.json","description":"Hello, I'm Stephen Ajulu, a seasoned multidisciplinary tech professional with over a decade of experience. I build impactful solutions using design, tech, and engineering in the pursuit of impact.","icon":"https://ajulu.netlify.app/images/me.jpg","authors":[{"name":"Stephen Ajulu","url":"https://stephenajulu.com","avatar":"https://ajulu.netlify.app/images/me.jpg"}],"items":[{"id":"https://ajulu.netlify.app/posts/indieweb-webmention-hugo-guide/","url":"https://ajulu.netlify.app/posts/indieweb-webmention-hugo-guide/","title":"Implementing Webmentions on Hugo: An IndieWeb Guide","summary":"Webmentions are a cornerstone of the IndieWeb movement. They allow you to \u0026ldquo;own your data\u0026rdquo; while still participating in the broader social web. Instead of having a centralized comment system (like Disqus), Webmentions allow you to receive notifications whenever someone links to your post from their own site, or even from social networks like Mastodon or Twitter.\nHow it Works The workflow typically follows the POSSE principle: Publish (on) Own Site, Syndicate Elsewhere.\n","content_html":"\u003cp\u003eWebmentions are a cornerstone of the IndieWeb movement. They allow you to \u0026ldquo;own your data\u0026rdquo; while still participating in the broader social web. Instead of having a centralized comment system (like Disqus), Webmentions allow you to receive notifications whenever someone links to your post from their own site, or even from social networks like Mastodon or Twitter.\u003c/p\u003e\n\u003ch2 id=\"how-it-works\"\u003eHow it Works\u003c/h2\u003e\n\u003cp\u003eThe workflow typically follows the \u003cstrong\u003ePOSSE\u003c/strong\u003e principle: \u003cstrong\u003eP\u003c/strong\u003eublish (on) \u003cstrong\u003eO\u003c/strong\u003ewn \u003cstrong\u003eS\u003c/strong\u003eite, \u003cstrong\u003eS\u003c/strong\u003eyndicate \u003cstrong\u003eE\u003c/strong\u003elsewhere.\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003eSyndication:\u003c/strong\u003e You publish a post here and share it on Mastodon or Twitter.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eInteraction:\u003c/strong\u003e Someone likes or replies to your syndicated post on social media.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eBridge:\u003c/strong\u003e A service like \u003ca href=\"https://bridgy.gy\"\u003eBridgy\u003c/a\u003e sees that interaction and sends a \u0026ldquo;Webmention\u0026rdquo; to your site\u0026rsquo;s endpoint.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eInbox:\u003c/strong\u003e Your site\u0026rsquo;s endpoint (configured via \u003ca href=\"https://webmention.io\"\u003eWebmention.io\u003c/a\u003e) receives the mention.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDisplay:\u003c/strong\u003e Your Hugo templates fetch these mentions via JavaScript and display them at the bottom of your post.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"member-gate\" data-role=\"premium\"\u003e\n    \u003cdiv class=\"unlocked-content\" style=\"display:none;\"\u003e\n        \u003ch2 id=\"step-by-step-implementation\"\u003eStep-by-Step Implementation\u003c/h2\u003e\n\u003ch3 id=\"1-setup-your-identity-indieauth\"\u003e1. Setup your Identity (IndieAuth)\u003c/h3\u003e\n\u003cp\u003eEnsure your site has \u003ccode\u003erel=\u0026quot;me\u0026quot;\u003c/code\u003e links to your social profiles in the \u003ccode\u003e\u0026lt;head\u0026gt;\u003c/code\u003e. This proves you own the domain.\u003c/p\u003e\n\u003ch3 id=\"2-configure-webmentionio\"\u003e2. Configure Webmention.io\u003c/h3\u003e\n\u003cp\u003eLog in to Webmention.io with your domain. Add the following to your \u003ccode\u003eextend-head.html\u003c/code\u003e:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e2\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nt\"\u003elink\u003c/span\u003e \u003cspan class=\"na\"\u003erel\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;webmention\u0026#34;\u003c/span\u003e \u003cspan class=\"na\"\u003ehref\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;https://webmention.io/ajulu.netlify.app/webmention\u0026#34;\u003c/span\u003e \u003cspan class=\"p\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"nt\"\u003elink\u003c/span\u003e \u003cspan class=\"na\"\u003erel\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;pingback\u0026#34;\u003c/span\u003e \u003cspan class=\"na\"\u003ehref\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;https://webmention.io/ajulu.netlify.app/xmlrpc\u0026#34;\u003c/span\u003e \u003cspan class=\"p\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003ch3 id=\"3-display-the-mentions\"\u003e3. Display the Mentions\u003c/h3\u003e\n\u003cp\u003eAdd a container and a script to your post template. We\u0026rsquo;ve already implemented a themed version of this in our \u003ccode\u003ewebmention.html\u003c/code\u003e partial, which uses CSS Grid to display likes and a threaded list for replies.\u003c/p\u003e\n\n    \u003c/div\u003e\n    \u003cdiv class=\"locked-message\"\u003e\n        \u003cdiv class=\"gate-overlay\"\u003e\n            \u003cspan class=\"gate-icon\"\u003e🔒\u003c/span\u003e\n            \u003ch3\u003ePremium Insight\u003c/h3\u003e\n            \u003cp\u003eThis deep-dive is exclusive to \u003cstrong\u003ePremium Members\u003c/strong\u003e.\u003c/p\u003e\n            \u003cdiv class=\"gate-actions\"\u003e\n                \u003ca href=\"/membership\" class=\"btn\"\u003eUnlock Access\u003c/a\u003e\n                \u003cbutton class=\"btn-secondary\" onclick=\"netlifyIdentity.open('login')\"\u003eAlready a member? Log in\u003c/button\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\n\u003cscript\u003e\n    (function() {\n        function checkAccess() {\n            const user = window.netlifyIdentity \u0026\u0026 netlifyIdentity.currentUser();\n            const isPremium = user \u0026\u0026 user.app_metadata \u0026\u0026 user.app_metadata.roles \u0026\u0026 user.app_metadata.roles.includes('premium');\n            \n            document.querySelectorAll('.member-gate').forEach(gate =\u003e {\n                const unlocked = gate.querySelector('.unlocked-content');\n                const locked = gate.querySelector('.locked-message');\n                if (isPremium) {\n                    unlocked.style.display = 'block';\n                    locked.style.display = 'none';\n                } else {\n                    unlocked.style.display = 'none';\n                    locked.style.display = 'block';\n                }\n            });\n        }\n\n        if (window.netlifyIdentity) {\n            netlifyIdentity.on('init', checkAccess);\n            netlifyIdentity.on('login', checkAccess);\n            netlifyIdentity.on('logout', checkAccess);\n        }\n    })();\n\u003c/script\u003e\n\n\u003cstyle\u003e\n.locked-message {\n    padding: 40px;\n    background: var(--base-offset-color);\n    border-radius: 8px;\n    border: 1px dashed var(--highlight-color);\n    text-align: center;\n    margin: 30px 0;\n}\n\n.gate-icon {\n    font-size: 2rem;\n    display: block;\n    margin-bottom: 10px;\n}\n\n.gate-actions {\n    display: flex;\n    gap: 15px;\n    justify-content: center;\n    margin-top: 20px;\n}\n\n.btn-secondary {\n    background: transparent;\n    border: 1px solid var(--highlight-color);\n    color: var(--highlight-color);\n    padding: 10px 20px;\n    border-radius: 6px;\n    cursor: pointer;\n    font-weight: 600;\n}\n\u003c/style\u003e\n\n\u003ch2 id=\"why-bother\"\u003eWhy Bother?\u003c/h2\u003e\n\u003cp\u003eBy using Webmentions, you become a first-class citizen of the open web. You aren\u0026rsquo;t just a \u0026ldquo;user\u0026rdquo; on a platform; you are a node in a distributed social network.\u003c/p\u003e\n\u003cp\u003eHappy hacking!\u003c/p\u003e\n","date_published":"2026-04-27T10:00:00Z","image":"https://images.unsplash.com/photo-1516259762381-22954d7d3ad2?q=80\u0026w=1000\u0026auto=format\u0026fit=crop","tags":["indieweb","hugo","webmentions","posse"]}]}