Yesterday I added a Webmention form at the bottom of my posts. If you used this form, it would show you a "check status" link after accepting the Webmention request. My Webmentions are all handled by webmention.io, and its status URLs return a JSON response. This isn't particularly friendly when someone views one of these URLs in a browser, since they just see a raw JSON blob.
Today I updated webmention.io to return all responses in HTML if they're made from a browser. It checks to see if there is text/html in the Accept header, and returns HTML if so, otherwise returns JSON as normal. Now when you view one of these status links, you'll see something like this.
Since the Webmention spec doesn't define the body of the response, doing this is still considered conformant to the spec. The one non-standard thing I had to do was to return an HTTP 303 response when accepting the Webmention instead of 201, in order to get the browser to redirect to the status URL immediately. I still return 201 to non-browser clients so they won't see any change.
I finally brought back the Webmention form on my website! At the bottom of my posts, you'll see a Webmention form now!
Hopefully soon I'll have realtime comments appearing, so that your comment will appear inline automatically after it's done processing!
Whenever my website receives a comment, like, repost, or other mention, I display those responses on the post's permalink, along with author information if available. For likes and reposts, I show the profile photo in a list, so there are sometimes lots of photos there.
For a while now, I've been archiving these profile photos myself in order to avoid various issues caused by hotlinking these images (mixed-content warnings, potential security issues by including remote images, and having avatars disappear when people change their URLs). It's been great because it speeds up the loading of the images since everything is coming from one domain, and I no longer have broken avatars on old posts. However, there was one problem with this plan, which was sometimes peoples' avatars would be huge! Like over 1000 pixels tall, and I was showing it in a 48px square space.
Today, I updated the code that archives these avatars to resize them to a max of 256 pixels tall.
This code was written in node.js and running on Amazon Lambda. It was the first (and last) project I've run on Lambda, and I did it as a sort of experiment when Lambda first launched. It wasn't too difficult to figure out the ImageMagick commands in Node.js to do the resizing. But... then I went to go and update the code on Lambda, and that was a nightmare. For starters, they're running a new Node.js version now, so I had to update my system to that to ensure I was bundling the right versions of libraries. Then there were some other changes around permissions and things too, which I didn't totally understand. Then I started getting intermittent errors after I tried launching the new version. Ultimately I got fed up and decided to rewrite the project in Ruby and run it on my own server.
It turns out I ended up spending about as much time rewriting the app in Ruby as it took to launch and debug the updated version on Lambda. On the plus side, the code is also way easier to understand now, since it's normal synchronous Ruby instead of async Node code that always turns into a mess. It's also only 100 lines now instead of the previous 150 in Node. Here's the new app.
I didn't change the external facing API, and images are still stored on S3, so my apps that use this project don't have to change at all except for which endpoint they talk to.
Ultimately, this change is only very slightly visible. The end result is now my posts won't be potentially embedding super large images shrunk down to 48px. This code is also used by webmention.io, so if you're using that to receive Webmentions, then you also have this change now!
This is a description of all the pieces and tools that I use to post to my website and handle comments and responses. Many of the pieces are open source and/or based on open protocols that you can implement yourself.
I write posts using an app called Quill. It's an open source application that I wrote. I run a hosted version at quill.p3k.io, and you can run it on your own server if you want as well. Quill provides an interface for posting longer blog posts with embedded images like this, as well as short text notes, and a handful of other kinds of posts like bookmarks.
Quill doesn't actually store any posts itself. It is just an interface for writing posts.
When I click the "post" button in Quill, it sends a Micropub request to my own website, which then creates the post and displays it on my website. Micropub is an API standard for creating short notes and posts, and it supports photos and videos too!
You can start using Quill if your website supports Micropub. There are some Micropub plugins for various CMSs, and it's also not too hard to write an endpoint yourself if you're into that sort of thing.
I never write posts directly on Twitter or Facebook. Instead, I write a post in Quill, and then check the boxes for where I want to syndicate the post.
Providing the text for the buttons is a feature of Micropub, but the actual posting to Twitter and Facebook is done through a tool called silo.pub. Silo.pub exposes a Micropub endpoint for many services, as a way to avoid writing silo-specific code. My server can simply make a Micropub request to the silo.pub endpoint and silo.pub creates the post using the Twitter API. Silo.pub is open source, and is written by Kyle Mahan. I run a copy of it on my server for my own use.
My website CMS is called p3k. It's not open source as a whole, although I have open sourced many of the components that are used to create it. At some point I might open source the whole thing, but when I do, I want to make sure I've built an easy installer for it, as well as a clear path for rolling out updates.
When Quill makes the API request to my website to make the post, it's handled by the Micropub endpoint that is built into p3k. The Micropub endpoint receives the Micropub request, writes the post to the storage file, which is then rendered on my website.
On many of my posts, you'll see comments and other responses. However there is no comment form on my site! Every comment or "like" is actually posted by someone else on their own website, and they sent a Webmention to my site letting me know about it.
Sending a Webmention is just a simple POST request to my Webmention endpoint, with the two URLs in question: the page that links to me, and which of my pages it links to.
My Webmention endpoint is actually a separate service that is open source, and you can use it too! It's at webmention.io or you can install your own copy. Once you sign in, it will give you instructions for adding the endpoint to your site. Basically you just paste an HTML tag into your website header, and that tells Webmention senders where to send the Webmention.
When the endpoint receives a Webmention, it first verifies that the link exists, and then it extracts some data from the web page. It looks for a Microformats 2 h-entry on the page, which tells it where to find the author data, comment text, date, and other properties. This part of the process is also broken out as a separate service I wrote, called X-Ray. You can use the test tool at xray.p3k.io to check what it finds at your own blog's URLs, in order to see what will show up when you send me a Webmention. X-Ray is open source and you're also welcome to use the service or install it yourself.
Since I copy my posts to Twitter and Facebook, I also want to know when people comment or "like" my posts there. There is a fantastic tool called Bridgy, written by Ryan Barrett that helps with this. Once you connect Bridgy to your silo accounts, it will watch when people respond to your posts, and create "proxy" web pages with Microformats markup for each response, and then send you Webmentions.
This means you don't have to write any special code for handling responses from Twitter/Facebook/etc, as long as you've written code that handles Webmentions and the various kinds of h-entry Microformats posts!
If you've made it this far and want more, here are some more links to get you going!