Reacji isn’t itself part of any specific standard. However, it works as part of microformats2 replies. So the idea is just that you compose a reply with a single emoji character. If that is the case, then a person can consider it a reacji rather than a comment. Also, Bridgy translates reacji replies to and from silo emoji reactions. This post has ❤️ reacji from Facebook and This post is me sending a ❤️ to a GitHub issue using Bridgy Publish
{ "type": "entry", "published": "2018-03-14T13:08:14-04:00", "summary": "Reacji isn\u2019t itself part of any specific standard. However, it works as part of microformats2 replies. So the idea is just that you compose a reply with a single emoji character. If that is the case, then a person can consider it a reacji rather than a comment. Also, Bridgy translates reacji replies to and from silo emoji reactions. This post has \u2764\ufe0f reacji from Facebook and This post is me sending a \u2764\ufe0f to a GitHub issue using Bridgy Publish", "url": "https://eddiehinkle.com/2018/03/14/4/reply/", "in-reply-to": [ "https://micro.blog/hjertnes/400333" ], "content": { "text": "Reacji isn\u2019t itself part of any specific standard. However, it works as part of microformats2 replies. So the idea is just that you compose a reply with a single emoji character. If that is the case, then a person can consider it a reacji rather than a comment. Also, Bridgy translates reacji replies to and from silo emoji reactions. This post has \u2764\ufe0f reacji from Facebook and This post is me sending a \u2764\ufe0f to a GitHub issue using Bridgy Publish", "html": "<p>Reacji isn\u2019t itself part of any specific standard. However, it works as part of microformats2 replies. So the idea is just that you compose a reply with a single emoji character. If that is the case, then a person can consider it a reacji rather than a comment. Also, <a href=\"https://brid.gy\">Bridgy</a> translates reacji replies to and from silo emoji reactions. <a href=\"https://eddiehinkle.com/2018/03/10/9/photo/\">This post has \u2764\ufe0f reacji from Facebook</a> and <a href=\"https://eddiehinkle.com/2018/02/22/13/reply/\">This post is me sending a \u2764\ufe0f to a GitHub issue using Bridgy Publish</a></p>" }, "author": { "type": "card", "name": "Eddie Hinkle", "url": "https://eddiehinkle.com/", "photo": "https://aperture-media.p3k.io/eddiehinkle.com/cf9f85e26d4be531bc908d37f69bff1c50b50b87fd066b254f1332c3553df1a8.jpg" }, "refs": { "https://micro.blog/hjertnes/400333": { "type": "entry", "url": "https://micro.blog/hjertnes/400333", "name": "https://micro.blog/hjertnes/400333" } }, "_id": "134833", "_source": "226", "_is_read": true }
Lol! I’m sure this is a joke, but if you ever ACTUALLY want to “facepalm” something, that is where reacji come in. It’s an indieweb way to do flexible reactions similar to a like. Here is an example of clapping.
{ "type": "entry", "published": "2018-03-14T12:31:02-04:00", "summary": "Lol! I\u2019m sure this is a joke, but if you ever ACTUALLY want to \u201cfacepalm\u201d something, that is where reacji come in. It\u2019s an indieweb way to do flexible reactions similar to a like. Here is an example of clapping.", "url": "https://eddiehinkle.com/2018/03/14/3/reply/", "in-reply-to": [ "https://hjertnes.social/posts/2018-03-12-16-11-40/" ], "content": { "text": "Lol! I\u2019m sure this is a joke, but if you ever ACTUALLY want to \u201cfacepalm\u201d something, that is where reacji come in. It\u2019s an indieweb way to do flexible reactions similar to a like. Here is an example of clapping.", "html": "<p>Lol! I\u2019m sure this is a joke, but if you ever ACTUALLY want to \u201cfacepalm\u201d something, that is where <a href=\"https://indieweb.org/reacji\">reacji</a> come in. It\u2019s an indieweb way to do flexible reactions similar to a like. <a href=\"https://eddiehinkle.com/2018/02/20/5/reply/\">Here is an example of clapping</a>.</p>" }, "author": { "type": "card", "name": "Eddie Hinkle", "url": "https://eddiehinkle.com/", "photo": "https://aperture-media.p3k.io/eddiehinkle.com/cf9f85e26d4be531bc908d37f69bff1c50b50b87fd066b254f1332c3553df1a8.jpg" }, "refs": { "https://hjertnes.social/posts/2018-03-12-16-11-40/": { "type": "entry", "url": "https://hjertnes.social/posts/2018-03-12-16-11-40/", "name": "https://hjertnes.social/posts/2018-03-12-16-11-40/" } }, "_id": "134834", "_source": "226", "_is_read": true }
{ "type": "entry", "published": "2018-03-14T15:39:31-07:00", "url": "https://aaronparecki.com/2018/03/14/21/", "category": [ "indieweb", "microblog", "pdx" ], "syndication": [ "https://twitter.com/aaronpk/status/974052448959475712" ], "content": { "text": "\ud83d\udd14 The Homebrew Microblog Meetup is tonight! 6pm at Rogue Eastside! \ud83c\udf89\ud83c\udf7b And a great sunny day for it too! \u2600\ufe0f #indieweb #microblog #pdx https://indieweb.org/events/2018-03-14-homebrew-microblog", "html": "<a href=\"https://aaronparecki.com/emoji/%F0%9F%94%94\">\ud83d\udd14</a> The Homebrew Microblog Meetup is tonight! 6pm at Rogue Eastside! <a href=\"https://aaronparecki.com/emoji/%F0%9F%8E%89\">\ud83c\udf89</a><a href=\"https://aaronparecki.com/emoji/%F0%9F%8D%BB\">\ud83c\udf7b</a> And a great sunny day for it too! <a href=\"https://aaronparecki.com/emoji/%E2%98%80%EF%B8%8F\">\u2600\ufe0f</a> <a href=\"https://aaronparecki.com/tag/indieweb\">#indieweb</a> <a href=\"https://aaronparecki.com/tag/microblog\">#microblog</a> <a href=\"https://aaronparecki.com/tag/pdx\">#pdx</a> <a href=\"https://indieweb.org/events/2018-03-14-homebrew-microblog\">https://indieweb.org/events/2018-03-14-homebrew-microblog</a>" }, "author": { "type": "card", "name": "Aaron Parecki", "url": "https://aaronparecki.com/", "photo": "https://aperture-media.p3k.io/aaronparecki.com/2b8e1668dcd9cfa6a170b3724df740695f73a15c2a825962fd0a0967ec11ecdc.jpg" }, "_id": "134793", "_source": "16", "_is_read": true }
{ "type": "event", "name": "Homebrew Website Club Baltimore", "published": "2018-03-13T11:08:32-0400", "start": "2018-03-20 19:30-0400", "url": "https://martymcgui.re/2018/03/13/110832/", "category": [ "event", "HWC", "IWC", "IndieWeb", "HWCBaltimore" ], "location": [ "https://martymcgui.re/venues/digital-harbor-foundation-tech-center/" ], "syndication": [ "https://upcoming.org/event/homebrew-website-club-baltimore-fw9i7spqmm", "https://www.facebook.com/events/151561025522358/" ], "refs": { "https://martymcgui.re/venues/digital-harbor-foundation-tech-center/": { "type": "card", "name": "Digital Harbor Foundation Tech Center", "url": "https://martymcgui.re/venues/digital-harbor-foundation-tech-center/", "photo": null } }, "_id": "129803", "_source": "175", "_is_read": true }
{ "type": "entry", "author": { "name": "Christian Weiske", "url": "http://cweiske.de/tagebuch/", "photo": null }, "url": "http://cweiske.de/tagebuch/broken-plain-sight.htm", "published": "2018-03-12T22:41:19+01:00", "content": { "html": "<p>\n <a href=\"http://microformats.org/wiki/h-feed\">h-feed</a> is a set of rules to\n add CSS classes to HTML tags so that normal HTML pages can be parsed\n automatically by feed readers.\n <a href=\"https://indieweb.org/\">Indieweb</a> proponents like\n <a href=\"http://tantek.com/\">Tantek \u00c7elik</a> prefer it over\n <a href=\"https://tools.ietf.org/html/rfc4287\">Atom feeds</a>\n and have a <a href=\"https://indieweb.org/feed_file#Criticism\">list of criticisms</a>:\n </p>\n\n\n <h2>Criticism #1: DRY Violations</h2>\n <blockquote>\n <p>\n As a duplicate of information already in the HTML of a web page,\n feed files are an example of the usual DRY violations.\n </p>\n </blockquote>\n <p>\n This tells only half of the story.\n Most websites are split up in two parts:\n <em>Index pages</em> that list articles with their titles and a short summary,\n and <em>article pages</em> that contain the full article text.\n </p>\n <p>\n In that case, the premise of <q>information already [available] in the HTML</q>\n is not correct, and the h-feed is\n <a href=\"http://cweiske.de/tagebuch/atom-vs-hfeed-size.htm\">more than 2 times larger</a>\n then the full-text Atom feed.\n </p>\n\n\n <h2>Criticism #2: Maintenance</h2>\n <blockquote>\n <p>\n Higher maintenance (requiring a separate URL, separate code path to\n generate, separate format understanding)\n </p>\n </blockquote>\n <p>\n This is true for the initial setup/implementation.\n </p>\n <p>\n However, when the site gets a new layout/redesign, the Atom feed can stay\n untouched and will not break,\n while extra care and testing is needed to keep an h-feed working.\n </p>\n\n\n <h2>Criticism #3: Out of date</h2>\n <blockquote>\n <p>\n Feed files become out of date with the visible HTML page\n (often because of broken separate code path), e.g.: [...]\n </p>\n </blockquote>\n <p>\n When reading up the\n <a href=\"https://chat.indieweb.org/\">indieweb chat logs</a> I saw\n <a href=\"https://chat.indieweb.org/dev/2018-03-08\">the following</a>\n and had a very good laugh:\n </p>\n <blockquote>\n <p>\n <a href=\"https://aaronparecki.com/\">aaronpk</a>:\n Whoops tantek the name on your event on your home page is a mess,\n i'm guessing implied p-name? It's fine on your event permalink<br />Following all these indieweb feeds is making these markup\n issues super obvious now.\n </p>\n <p>\n <a href=\"http://tantek.com/\">tantek</a>:\n Even when the data is visible, consuming it and presenting it in a\n different way can reveal issues!<br />If you're still around I think I have a fix for the p-name problem you found.<br />Seems to work locally<br />Alright, deployed<br />!tell aaronpk try tantek.com h-feed again, p-name issue(s) should be fixed. e-content too.\n </p>\n </blockquote>\n <p>\n Tantek\n <a href=\"http://tantek.com/2012/198/t1/added-microformats2-h-feed-h-entry\">added h-feed</a>\n because he feared that the Atom \"side file\" could break silently\n <q>since invisible</q>.\n </p>\n <p>\n Now his h-feed failed silently, and it needed a feed reader user to tell him\n - just like it would have been the case when his Atom feed would have been\n broken\n (except that you can <a href=\"http://cweiske.de/tagebuch/atom-validation.htm\">validate an Atom feed</a>\n automatically).\n </p>\n\n \n <a href=\"https://news.indieweb.org/en\"></a>", "text": "h-feed is a set of rules to\n add CSS classes to HTML tags so that normal HTML pages can be parsed\n automatically by feed readers.\n Indieweb proponents like\n Tantek \u00c7elik prefer it over\n Atom feeds\n and have a list of criticisms:\n \n\n\n Criticism #1: DRY Violations\n \n \n As a duplicate of information already in the HTML of a web page,\n feed files are an example of the usual DRY violations.\n \n \n \n This tells only half of the story.\n Most websites are split up in two parts:\n Index pages that list articles with their titles and a short summary,\n and article pages that contain the full article text.\n \n \n In that case, the premise of information already [available] in the HTML\n is not correct, and the h-feed is\n more than 2 times larger\n then the full-text Atom feed.\n \n\n\n Criticism #2: Maintenance\n \n \n Higher maintenance (requiring a separate URL, separate code path to\n generate, separate format understanding)\n \n \n \n This is true for the initial setup/implementation.\n \n \n However, when the site gets a new layout/redesign, the Atom feed can stay\n untouched and will not break,\n while extra care and testing is needed to keep an h-feed working.\n \n\n\n Criticism #3: Out of date\n \n \n Feed files become out of date with the visible HTML page\n (often because of broken separate code path), e.g.: [...]\n \n \n \n When reading up the\n indieweb chat logs I saw\n the following\n and had a very good laugh:\n \n \n \n aaronpk:\n Whoops tantek the name on your event on your home page is a mess,\n i'm guessing implied p-name? It's fine on your event permalink\nFollowing all these indieweb feeds is making these markup\n issues super obvious now.\n \n \n tantek:\n Even when the data is visible, consuming it and presenting it in a\n different way can reveal issues!\nIf you're still around I think I have a fix for the p-name problem you found.\nSeems to work locally\nAlright, deployed\n!tell aaronpk try tantek.com h-feed again, p-name issue(s) should be fixed. e-content too.\n \n \n \n Tantek\n added h-feed\n because he feared that the Atom \"side file\" could break silently\n since invisible.\n \n \n Now his h-feed failed silently, and it needed a feed reader user to tell him\n - just like it would have been the case when his Atom feed would have been\n broken\n (except that you can validate an Atom feed\n automatically)." }, "name": "Broken in plain sight", "_id": "129415", "_source": "193", "_is_read": true }
{ "type": "entry", "url": "https://realize.be/notes/1241", "content": { "text": "Started working on an android version of Indigenous. The authentication already works and I can post notes from it, yes! (code online soon) #indieweb #drupal #android" }, "_id": "128913", "_source": "213", "_is_read": true }
{ "type": "entry", "published": "2018-03-13T01:56:46+0000", "url": "https://cleverdevil.io/2018/microsub-has-really-been-the-missing-piece", "in-reply-to": [ "https://aaronparecki.com/2018/03/12/17/building-an-indieweb-reader" ], "content": { "text": "Microsub has really been the missing piece of the puzzle. I love using Together + Aperture every single day. Nice work on the spec \ud83d\ude00" }, "author": { "type": "card", "name": "Jonathan LaCour", "url": "https://cleverdevil.io/profile/cleverdevil", "photo": "https://aperture-media.p3k.io/cleverdevil.io/abdf4969f052cb64177f73cda9be6a709931eb55607f8c1fb2c69eb135841acf.jpg" }, "_id": "127784", "_source": "71", "_is_read": true }
{ "type": "entry", "published": "2018-03-12T17:03:57-0700", "url": "https://aaronparecki.com/2018/03/12/17/building-an-indieweb-reader", "category": [ "indieweb", "monocle", "aperture", "microsub", "micropub", "watchtower", "reader" ], "name": "Building an IndieWeb Reader", "content": { "text": "Over the last several months, I've been slowly putting the pieces in place to be able to build a solid indieweb reader. Today, I feel like I finally have enough in place to consider this functional enough that I am now using it every day!\nOne of the major missing pieces of the IndieWeb ecosystem has been having an integrated reading an posting experience that mirrors the ease with which it's possible to post and follow on Twitter and other silo apps. \nWe've seen a few attempts at indieweb readers over the past few years, but nothing has really taken off or stuck around. Even my own attempts at readers have fallen apart, both the previous iteration of Monocle in 2016, and my fork of selfoss in 2014. My suspicion has always been that we haven't seen many people building out this part of the ecosystem because it turns out there are a whole bunch of different parts to building a reader, many of which have no overlap in skillset: managing the subscription list, polling and fetching feeds, parsing feeds, data storage, rendering posts in a UI, providing inline action buttons to be able to reply and favorite posts, etc. \nWhen I'm building out the UI components of a project, the last thing I want to have to think about is the invisible backend stuff like feed polling and parsing. Similarly when I'm tackling the problems with parsing and normalizing data from feeds, the last thing I am thinking about is Javascript button interactions. Not to mention that I am barely an iOS developer, so there's no way I'd be able to build out a full indieweb reader for iOS.\nIn April 2017, I started outlining a spec that draws a hard line between these very different parts of building a reader, and called it Microsub (for subscribing), as a complement to Micropub (for publishing). The basic idea is to separate the feed subscriptions from the UI parts of building a reader. \nI started working from the ground up on building out the various aspects I knew I would need in order to eventually end up with a fully functional reader. \nThe main interface of MonocleI based a lot of these design decisions around my previous experience in building a reader, as well as my documentation of how I use IRC to read content across the web.\nMy goal with this is to use this as my primary online dashboard to follow all kinds of content, as well as being able to interact with the content without leaving the interface. \nChannels\nThe main organization of the reader is laid out in \"channels\". You can also think of these as \"folders\" if you want. Many feeds (or sources) can be added to a channel, and the posts are all combined into a single timeline view.\nDisplaying Posts\nMonocle supports displaying a few different types of content in posts. It has native support for notes, articles, photos, multi-photos, videos, audio clips, checkins, favorites, reposts, and replies.\nSince I follow my Instagram feed in the reader, I wanted to have a good display for photos, especially when there are many photos attached to a single post. I ended up doing a simple custom layout when there are two or three photos. Four or more they just start tiling as half-size photos. With three photos, the first photo appears larger on the left and the other two are stacked to the right.\nI wanted to be able to read full articles in the reader without jumping out to the site, but also didn't want to have to scroll endlessly when I'm just skimming headlines. So if an article has content that is too tall, it gets truncated with a \"read more\" link to expand it.\nIf the post has an audio file, such as podcasts, then there is a simple HTML audio player inline!\nPost Actions\nEach post has a set of buttons to be able to respond to the post. The quickly accessible actions are \"favorite\", \"repost\", and \"reply\". The three dots opens up an expanded menu with some additional options, some of which I have not yet implemented.\nCurrently it's possible to remove a post from a channel, and to open up a debug view showing the raw data behind the post. Eventually this will expand to include muting the author, blocking the author, or unfollowing the source the post came from.\nReplying\nClicking the \"reply\" button drops down a little text box for posting a reply.\nThere is a character counter just so that I have a sense of how long the post is. Since this is posting the reply back to my website, this interface has no idea what sort of character limits there are, so it's just a simple counter. When I click the \"Reply\" button, the app makes a Micropub post to my website to create the post there. \nMy website already has all the logic for adding that to my replies feed and sending webmentions to the post I'm replying to. Since this post I replied to is on Micro.blog, and Micro.blog accepts webmentions, the post showed up there within a few seconds.\nThe same workflow happens for favoriting and reposting things.\nSyndicating to GitHub\nMy website also recognizes when the post I'm replying to is a Twitter or GitHub permalink, and will automatically syndicate my reply or favorite appropriately! Since I added my GitHub notifications to a channel, I can actually reply to GitHub issues directly from the interface!\nReplying to a GitHub issue comment from MonocleMy reply to the GitHub issue on my websiteMy reply automatically syndicated to GitHubRead-State Tracking\nYou may have noticed the little blue dots next to the channel names in some previous screenshots. Those indicate how many unread posts are in the channel.\n \nHowever, some feeds that I follow end up with tons of posts in the channels, so many that the actual number of posts is no longer significant! All I really want to know is whether there is something new or not. To account for this, I can choose whether a channel implements per-item tracking, or just a boolean read/unread indicator, or disables read tracking altogether.\nWhen I'm looking at a timeline, any new posts appear with a yellow glow around them. As the post scrolls out of view, it gets marked as read, and that state is pushed to the server so that other clients will also know it's now read.\nI really enjoy not having to manually mark things as read, instead the interface just handles it all for me without any additional interaction.\nMultiple Website Support\nSince I actually have several different websites I use, I wanted the response buttons to be able to post not just to my website, but also to the other websites I have. For example, my cat Dora, who has her own website is not always the best at using the computer, so sometimes I have to favorite things for her.\nI can choose a alternate default account per channel so that the response buttons will actually post to the alternate website. Notice Dora's cat face in the bottom right corner of the screen. This lets me know that interacting with posts in this channel will be posted to this alternate account.\nI can even temporarily switch to a different account by clicking on the profile icon and choosing another account.\nSimple Posting Interface\nYou may also have noticed the little pen icon in the lower left corner. Clicking that pops up a dialog for writing a new post from the selected account. I chose to keep this interface super simple, providing just a text box and character counter. \nIf I need to write something more complicated, such as including HTML content, adding a photo, or choosing where the post is syndicated, then I'll just pop over to Quill and write the post there instead.\nMultiple Apps\nI mentioned earlier that there were many parts to this, and I haven't talked much about that yet. The most important thing about the architecture of this system is that it is not just a single monolithic app. Instead, there is a server responsible for collecting all the data from the feeds I'm following, and separate apps for displaying them! Since I was documenting everything on the wiki as I was building this out, other people were able to jump in and start writing clients from the beginning! \nThere are already two other great interfaces that work with the same backend server! \nHere is a Javascript app called Together, written by Grant, showing the same posts you saw in a previous screenshot.\nHere is the same content rendered by the iOS app, Indigenous, written by Eddie.\nI'm pretty thrilled that already we've been able to have two people jump in and build readers so quickly already, thanks to the hard work of feed fetching being abstracted away by the server!\nThe Microsub Server\nNow to start getting into the technical bits of how this works. Feel free to skip this section if specs make your eyes glaze over.\nI mentioned before that the main separation going on here is splitting off the feed fetching and parsing from rendering the posts.\nThis accomplishes a few things:\nEnables app developers to focus on the UI aspects of building a reader\n Allows you to choose which service you want to use to manage your subscriptions\n Enables you to use many different reader apps all talking to the same server backend that you control\n Leaves room for servers to do experimental things with feeds and subscriptions (think \"magic\" or \"smart\" feeds) without having to bother with the UI components or needing to get clients to add support\nThe main idea behind this is the Microsub spec. This is the spec that the Microsub server implements so that clients know how they can talk to it. \nIdeally there will eventually be a large ecosystem around the spec, with many clients to choose from, and many servers as well. We'll see some projects build in Microsub support natively, so that they work out of the box, and we'll also see some dedicated feed subscription services support Microsub. The nice thing about using your website identity to tie the pieces together is that you can choose your Microsub server separately from choosing the software that powers your website.\nFor example, I decided early on when building my website that I didn't want to mix the idea of following feeds into the same software that powers my website. So instead, I wrote an external Microsub server called Aperture, which is responsible for all the feed polling and parsing and storing the posts in channels. Aperture is open source, although I still consider it \"in active development\", so I am not officially supporting it right now. You are of course welcome to get it running yourself, but be prepared for things to change quickly.\n(Aperture actually has two components, Watchtower which is a microservice that polls feeds and delivers them to Aperture itself, and Aperture does the actual feed parsing with the content provided by Watchtower. This allows me to scale out the feed polling separately from the Microsub server.)\nIf you want to try to get Aperture and Watchtower running, Daniel did a pretty great writeup of his experience getting things set up in two posts: Part 1 and Part 2.\nIdeally I would love to see some more implementations of Microsub servers, so head over to the spec if that's your thing!\nMonocle\nMonocle is the Microsub client I wrote that's featured in the screenshots above. It is also open source. Since it doesn't do any feed parsing itself, it doesn't even have a storage backend! Everything is fetched on the fly with the exception of the channel list and Micropub config which is persisted in the session data. \nWhen I click on a channel to view it, Monocle first makes a Microsub timeline request to Aperture to fetch the channel data, then renders it in the timeline view. This is analogous to the iOS app Indigenous fetching the timeline data from the Microsub server then rendering it on the phone, except Monocle is doing that server-side to generate HTML for the browser.\nYou might think I'm crazy for having written a PHP app that fetches JSON from an API and then renders --gasp-- static HTML in 2018, but guess what -- it's fast!\nMonocle is open source, but I am also hosting a version online that anyone is welcome to use at monocle.p3k.io. Since it doesn't actually store anything itself, I don't expect it to take up any significant resources any time soon! Of course in order to use it, you'll need to have your website pointing to a Microsub server of your choosing. Since that's where all the actual work is done, I am not making my hosted version of Aperture available for general signups right now. You'll need to either get that running on your own server, or build a Microsub server from scratch!\nPutting the Pieces Together\nThis last section has been a bit of a wall of text, so here is a diagram showing how all the pieces fit together to make this possible!\nMy website contains the IndieAuth and Micropub bits, but others have chosen to use external services for those as well. I've also chosen to outsource sending and receiving webmentions to external services, whereas other people end up handling those within their own website code as well.\nThe reader apps all talk to the Microsub server that I've linked to in order to view posts, and when I tap a \"like\" button or write a reply from the app, they post that to my Micropub server to create a new post.\nI use webmention.io to handle my incoming webmentions, and it is configured to send posts to a channel in Aperture using Aperture's Micropub API.\nFurther Reading\nThis has been a very long read, so congrats if you've made it this far! Here are some links if you're curious about how you can start building out various pieces of the ecosystem as well!\nSpecs\n\n Microsub - a standardized way for apps to consume and interact with feeds collected by a server\n \n\n \nMicropub - a W3C Recommendation for creating, updating and deleting posts using external apps\n \nWebmention - a W3C Recommendation enabling cross-site comments and other interactions\n \nIndieAuth - an OAuth 2.0 extension that enables you to authorize third-party apps to talk to your Micropub or Microsub servers\n \nmp-destination - a Micropub extension allowing a server to designate alternate destinations for creating posts\nOpen Source Projects\n\n Indigenous - an iOS Microsub client\n \n\n \nTogether - a React JS Microsub client\n \nMonocle - a server-side PHP Microsub client\n \nAperture - a PHP Microsub server\n \nWatchtower - a feed fetching microservice\nFuture Work\nWhile this is all a good start, and I do actually use this as my primary online home now, there is still a lot more work to do!\n\n More Microsub servers! I want to see at least two more solid Microsub server implementations in the relatively near future! That will help develop the spec further and ensure we're actually building interoperable tools. I suspect one of the implementations will end up being part of an integrated CMS such as Known or Wordpress, or will be a proxy to an existing feed reader service.\n \n\n \nFollowing private content. Private content has always been a challenge, mainly due to the fact that any time authentication is involved it complicates things a lot. With IndieAuth finally written up as a spec, we now have a solid building block to use to experiment in this area more.\n \nAn Android Microsub app. While both Monocle and Together work pretty well on mobile browsers, there are still many advantages to having a native Android app! And it sounds like one is already in the works.\n \nBetter UI for actually following people. I've kind of taken a shortcut on this front in order to move the rest forward. Right now, you still need to type someone's URL into a Microsub app in order to follow them. There are many challenges with streamlining this process further.\nAs always, I'm happy to chat about any and all of this! It's been a lot of fun already to build this all out and see it working! You can find me in the IndieWeb chat via IRC and Slack, if you send me a Webmention I'll see it in my reader, or find me at an upcoming IndieWeb event!", "html": "<p>Over the last several months, I've been slowly putting the pieces in place to be able to build a solid <a href=\"https://indieweb.org/reader\">indieweb reader</a>. Today, I feel like I finally have enough in place to consider this functional enough that I am now using it every day!</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/52de891fb4d611a704b7da5f71eee3d34c25dd79eedfbbbbfdcea0d16bba922f.jpg\" alt=\"\" /><p>One of the major missing pieces of the IndieWeb ecosystem has been having an integrated reading an posting experience that mirrors the ease with which it's possible to post and follow on Twitter and other silo apps. </p>\n<p>We've seen <a href=\"https://indieweb.org/Woodwind\">a few attempts</a> at indieweb readers over the past few years, but nothing has really taken off or stuck around. Even my own attempts at readers have fallen apart, both the <a href=\"https://aaronparecki.com/2016/04/26/3/monocle\">previous iteration of Monocle</a> in 2016, and <a href=\"https://aaronparecki.com/2014/02/13/1/microformats2-selfoss\">my fork of selfoss</a> in 2014. My suspicion has always been that we haven't seen many people building out this part of the ecosystem because it turns out there are a whole bunch of different parts to building a reader, many of which have no overlap in skillset: managing the subscription list, polling and fetching feeds, parsing feeds, data storage, rendering posts in a UI, providing inline action buttons to be able to reply and favorite posts, etc. </p>\n<p>When I'm building out the UI components of a project, the last thing I want to have to think about is the invisible backend stuff like feed polling and parsing. Similarly when I'm tackling the problems with parsing and normalizing data from feeds, the last thing I am thinking about is Javascript button interactions. Not to mention that I am <a href=\"https://github.com/aaronpk/Overland-iOS\">barely an iOS developer</a>, so there's no way I'd be able to build out a full indieweb reader for iOS.</p>\n<p>In April 2017, I started outlining a spec that draws a hard line between these very different parts of building a reader, and called it <a href=\"https://indieweb.org/Microsub-spec\">Microsub</a> (for subscribing), as a complement to <a href=\"https://www.w3.org/TR/micropub/\">Micropub</a> (for publishing). The basic idea is to separate the feed subscriptions from the UI parts of building a reader. </p>\n<p>I started working from the ground up on building out the various aspects I knew I would need in order to eventually end up with a fully functional reader. </p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/99ee75efacf4ae91c6db73aef62668513da9f4f48917ef2a2c8b0f6204ca76c3.png\" alt=\"\" />The main interface of Monocle<p>I based a lot of these design decisions around my previous experience in building a reader, as well as my documentation of <a href=\"https://aaronparecki.com/2015/08/29/8/why-i-live-in-irc\">how I use IRC</a> to read content across the web.</p>\n<p>My goal with this is to use this as my primary online dashboard to follow all kinds of content, as well as being able to interact with the content without leaving the interface. </p>\n<h3>Channels</h3>\n<p>The main organization of the reader is laid out in \"channels\". You can also think of these as \"folders\" if you want. Many feeds (or sources) can be added to a channel, and the posts are all combined into a single timeline view.</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/effc3ad2eaa08fd813af2d4320b0a011b3e3e722eb5cbe3e641ecec9b79a4c57.png\" alt=\"\" /><h3>Displaying Posts</h3>\n<p>Monocle supports displaying a few different types of content in posts. It has native support for notes, articles, photos, multi-photos, videos, audio clips, checkins, favorites, reposts, and replies.</p>\n<p>Since I follow my Instagram feed in the reader, I wanted to have a good display for photos, especially when there are many photos attached to a single post. I ended up doing a simple custom layout when there are two or three photos. Four or more they just start tiling as half-size photos. With three photos, the first photo appears larger on the left and the other two are stacked to the right.</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/6fcb41083980e0d10b3c6559a093a3ed40e4fe4917c7d69a0ae5a9bba88f950f.png\" alt=\"\" /><p>I wanted to be able to read full articles in the reader without jumping out to the site, but also didn't want to have to scroll endlessly when I'm just skimming headlines. So if an article has content that is too tall, it gets truncated with a \"read more\" link to expand it.</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/09fe59c9bc0da1c7d7472e89ea0ebb32de60513afe685245876c7c270e58458f.png\" alt=\"\" /><p>If the post has an audio file, such as podcasts, then there is a simple HTML audio player inline!</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/dc4e3b3fd82a9c61ee2aacb1775b16f2da0dd781464b5d9148efb13522985252.png\" alt=\"\" /><h3>Post Actions</h3>\n<p>Each post has a set of buttons to be able to respond to the post. The quickly accessible actions are \"favorite\", \"repost\", and \"reply\". The three dots opens up an expanded menu with some additional options, some of which I have not yet implemented.</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/3b31b9f24e0705bb86c0469df946eed46cc005921139d66b7229568a0607c280.png\" alt=\"\" /><p>Currently it's possible to remove a post from a channel, and to open up a debug view showing the raw data behind the post. Eventually this will expand to include muting the author, blocking the author, or unfollowing the source the post came from.</p>\n<h3>Replying</h3>\n<p>Clicking the \"reply\" button drops down a little text box for posting a reply.</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/842aa68de900d648d7c0b344c87af647cd7b0038e64c01e2756adf73a6481980.png\" alt=\"\" /><p>There is a character counter just so that I have a sense of how long the post is. Since this is posting the reply back to my website, this interface has no idea what sort of character limits there are, so it's just a simple counter. When I click the \"Reply\" button, the app makes a <a href=\"https://indieweb.org/Micropub\">Micropub</a> post to my website to create the post there. </p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/8f9dea2403b36d2f299fed8a341847bcd63180f98d3d88e03e26025fe4629491.png\" alt=\"\" /><p>My website already has all the logic for adding that to my replies feed and sending webmentions to the post I'm replying to. Since this post I replied to is on Micro.blog, and Micro.blog accepts <a href=\"https://indieweb.org/Webmention\">webmentions</a>, the post showed up there within a few seconds.</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/9f06eba5d7fad6c17926830d1d93c82befe661124bc9cfa956e4362eccebf2df.png\" alt=\"\" /><p>The same workflow happens for favoriting and reposting things.</p>\n<h3>Syndicating to GitHub</h3>\n<p>My website also recognizes when the post I'm replying to is a Twitter or GitHub permalink, and will automatically syndicate my reply or favorite appropriately! Since I <a href=\"https://aaronparecki.com/2018/03/04/14/\">added my GitHub notifications</a> to a channel, I can actually reply to GitHub issues directly from the interface!</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/723a32d605f36d739381ca4489f1583d8bb3756c4a8ee2cab9a9ef5e03557b50.png\" alt=\"\" />Replying to a GitHub issue comment from Monocle<img src=\"https://aperture-media.p3k.io/aaronparecki.com/830518e753866480790207c063cf72a446bb1a1c171183164d89c4bee1de9619.png\" alt=\"\" />My reply to the GitHub issue on my website<img src=\"https://aperture-media.p3k.io/aaronparecki.com/ef27cc1f2427549f954646ea7cc9b2d046f445c7f47db5bcc0d0409e41b3650f.png\" alt=\"\" />My reply automatically syndicated to GitHub<h3>Read-State Tracking</h3>\n<p>You may have noticed the little blue dots next to the channel names in some previous screenshots. Those indicate how many unread posts are in the channel.</p>\n \n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/7b3d2e17539f5afb19ec8bdd6aa8baf6cf59c58e0a4e331d1d2afe584555c1e8.png\" alt=\"\" /><p>However, some feeds that I follow end up with tons of posts in the channels, so many that the actual number of posts is no longer significant! All I really want to know is whether there is something new or not. To account for this, I can choose whether a channel implements per-item tracking, or just a boolean read/unread indicator, or disables read tracking altogether.</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/b8f14a0a59093186b1c7b66d6b6bc7d6f0efcc57dec6c134945e279b67488376.png\" alt=\"\" /><p>When I'm looking at a timeline, any new posts appear with a yellow glow around them. As the post scrolls out of view, it gets marked as read, and that state is pushed to the server so that other clients will also know it's now read.</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/41e79c5fc0452d779374227b8a0d113accb09da45f020cdcc1e23aed723703c7.gif\" alt=\"\" /><p>I really enjoy not having to manually mark things as read, instead the interface just handles it all for me without any additional interaction.</p>\n<h3>Multiple Website Support</h3>\n<p>Since I actually have several different websites I use, I wanted the response buttons to be able to post not just to my website, but also to the other websites I have. For example, <a href=\"https://indiewebcat.com/\">my cat Dora, who has her own website</a> is not always the best at using the computer, so sometimes I have to favorite things for her.</p>\n<p>I can choose a alternate default account per channel so that the response buttons will actually post to the alternate website. Notice Dora's cat face in the bottom right corner of the screen. This lets me know that interacting with posts in this channel will be posted to this alternate account.</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/0478d169f668d832be219fb1c1f20054f4ad78902c895241d486ceb3e5c8090d.png\" alt=\"\" /><p>I can even temporarily switch to a different account by clicking on the profile icon and choosing another account.</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/dccb30a7daf3711eaa76264fc8bd7b71cfda87eae7b95bc8430757267f397df2.png\" alt=\"\" /><h3>Simple Posting Interface</h3>\n<p>You may also have noticed the little pen icon in the lower left corner. Clicking that pops up a dialog for writing a new post from the selected account. I chose to keep this interface super simple, providing just a text box and character counter. </p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/ff8c12b4b51273786686f38e80b4c5c7fa8103ebb86d675d99e3c48526bee250.png\" alt=\"\" /><p>If I need to write something more complicated, such as including HTML content, adding a photo, or choosing where the post is syndicated, then I'll just pop over to <a href=\"https://quill.p3k.io\">Quill</a> and write the post there instead.</p>\n<h3>Multiple Apps</h3>\n<p>I mentioned earlier that there were many parts to this, and I haven't talked much about that yet. The most important thing about the architecture of this system is that it is not just a single monolithic app. Instead, there is a server responsible for collecting all the data from the feeds I'm following, and separate apps for displaying them! Since I was documenting everything <a href=\"https://indieweb.org/Microsub-spec\">on the wiki</a> as I was building this out, other people were able to jump in and start writing clients from the beginning! </p>\n<p>There are already two other great interfaces that work with the same backend server! </p>\n<p>Here is a Javascript app called Together, written by <a href=\"https://grant.codes/\">Grant</a>, showing the same posts you saw in a previous screenshot.</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/cd9801ee19a21269496f6e53b6022932230c8ebe1fbbadb474b8233f777a6a3f.png\" alt=\"\" /><p>Here is the same content rendered by the iOS app, <a href=\"https://indieweb.org/Indigenous\">Indigenous</a>, written by <a href=\"https://eddiehinkle.com/\">Eddie</a>.</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/76bcae9687181f954feb59e76a0381e3a3283b3a534e255a92d89b6c2327e106.png\" alt=\"\" /><p>I'm pretty thrilled that already we've been able to have two people jump in and build readers so quickly already, thanks to the hard work of feed fetching being abstracted away by the server!</p>\n<h3>The Microsub Server</h3>\n<p>Now to start getting into the technical bits of how this works. Feel free to skip this section if specs make your eyes glaze over.</p>\n<p>I mentioned before that the main separation going on here is splitting off the feed fetching and parsing from rendering the posts.</p>\n<p>This accomplishes a few things:</p>\n<ul><li>Enables app developers to focus on the UI aspects of building a reader</li>\n <li>Allows you to choose which service you want to use to manage your subscriptions</li>\n <li>Enables you to use many different reader apps all talking to the same server backend that you control</li>\n <li>Leaves room for servers to do experimental things with feeds and subscriptions (think \"magic\" or \"smart\" feeds) without having to bother with the UI components or needing to get clients to add support</li>\n</ul><p>The main idea behind this is the <a href=\"https://indieweb.org/Microsub-spec\">Microsub spec</a>. This is the spec that the Microsub server implements so that clients know how they can talk to it. </p>\n<p>Ideally there will eventually be a large ecosystem around the spec, with many clients to choose from, and many servers as well. We'll see some projects build in Microsub support natively, so that they work out of the box, and we'll also see some dedicated feed subscription services support Microsub. The nice thing about using your website identity to tie the pieces together is that you can choose your Microsub server separately from choosing the software that powers your website.</p>\n<p>For example, I decided early on when building my website that I didn't want to mix the idea of following feeds into the same software that powers my website. So instead, I wrote an external Microsub server called <a href=\"https://indieweb.org/Aperture\">Aperture</a>, which is responsible for all the feed polling and parsing and storing the posts in channels. Aperture is open source, although I still consider it \"in active development\", so I am not officially supporting it right now. You are of course welcome to get it running yourself, but be prepared for things to change quickly.</p>\n<p>(Aperture actually has two components, Watchtower which is a microservice that polls feeds and delivers them to Aperture itself, and Aperture does the actual feed parsing with the content provided by Watchtower. This allows me to scale out the feed polling separately from the Microsub server.)</p>\n<p>If you want to try to get Aperture and Watchtower running, <a href=\"https://ascraeus.org/\">Daniel</a> did a pretty great writeup of his experience getting things set up in two posts: <a href=\"https://ascraeus.org/websub-part-i-watchtower/\">Part 1</a> and <a href=\"https://ascraeus.org/websub-part-ii-aperture/\">Part 2</a>.</p>\n<p>Ideally I would love to see some more implementations of Microsub servers, so head over to <a href=\"https://indieweb.org/Microsub-spec\">the spec</a> if that's your thing!</p>\n<h3>Monocle</h3>\n<p><a href=\"https://indieweb.org/Monocle\">Monocle</a> is the Microsub <i>client</i> I wrote that's featured in the screenshots above. It is also <a href=\"https://github.com/aaronpk/Monocle\">open source</a>. Since it doesn't do any feed parsing itself, it doesn't even have a storage backend! Everything is fetched on the fly with the exception of the channel list and Micropub config which is persisted in the session data. </p>\n<p>When I click on a channel to view it, Monocle first makes a Microsub <a href=\"https://indieweb.org/Microsub-spec#Timelines\">timeline request</a> to Aperture to fetch the channel data, then renders it in the timeline view. This is analogous to the iOS app Indigenous fetching the timeline data from the Microsub server then rendering it on the phone, except Monocle is doing that server-side to generate HTML for the browser.</p>\n<p>You might think I'm crazy for having written a PHP app that fetches JSON from an API and then renders --<i>gasp--</i> static HTML in 2018, but guess what -- it's fast!</p>\n<p>Monocle is open source, but I am also hosting a version online that anyone is welcome to use at <a href=\"https://monocle.p3k.io\">monocle.p3k.io</a>. Since it doesn't actually store anything itself, I don't expect it to take up any significant resources any time soon! Of course in order to use it, you'll need to have your website pointing to a Microsub server of your choosing. Since that's where all the actual work is done, I am not making my hosted version of Aperture available for general signups right now. You'll need to either get that running on your own server, or build a Microsub server from scratch!</p>\n<h3>Putting the Pieces Together</h3>\n<p>This last section has been a bit of a wall of text, so here is a diagram showing how all the pieces fit together to make this possible!</p>\n<img src=\"https://aperture-media.p3k.io/aaronparecki.com/ad3d3e8b7eb52515e23c582e490e420a023cd69f35cfc2a8ccf5f1aa73c736c5.png\" alt=\"\" /><p>My website contains the IndieAuth and Micropub bits, but others have chosen to use external services for those as well. I've also chosen to outsource sending and receiving webmentions to external services, whereas other people end up handling those within their own website code as well.</p>\n<p>The reader apps all talk to the Microsub server that I've linked to in order to view posts, and when I tap a \"like\" button or write a reply from the app, they post that to my Micropub server to create a new post.</p>\n<p>I use webmention.io to handle my incoming webmentions, and it is configured to send posts to a channel in Aperture using Aperture's Micropub API.</p>\n<h3>Further Reading</h3>\n<p>This has been a very long read, so congrats if you've made it this far! Here are some links if you're curious about how you can start building out various pieces of the ecosystem as well!</p>\n<p><b>Specs</b></p>\n<ul><li>\n <a href=\"https://indieweb.org/Microsub-spec\">Microsub</a> - a standardized way for apps to consume and interact with feeds collected by a server\n <br /></li>\n <li>\n<a href=\"https://www.w3.org/TR/micropub/\">Micropub</a> - a W3C Recommendation for creating, updating and deleting posts using external apps</li>\n <li>\n<a href=\"https://www.w3.org/TR/webmention/\">Webmention</a> - a W3C Recommendation enabling cross-site comments and other interactions</li>\n <li>\n<a href=\"https://indieauth.spec.indieweb.org/\">IndieAuth</a> - an OAuth 2.0 extension that enables you to authorize third-party apps to talk to your Micropub or Microsub servers</li>\n <li>\n<a href=\"https://indieweb.org/Micropub-extensions#Destination\">mp-destination</a> - a Micropub extension allowing a server to designate alternate destinations for creating posts</li>\n</ul><p><b>Open Source Projects</b></p>\n<ul><li>\n <a href=\"https://github.com/EdwardHinkle/indigenous-ios\">Indigenous</a> - an iOS Microsub client\n <br /></li>\n <li>\n<a href=\"https://github.com/cleverdevil/together\">Together</a> - a React JS Microsub client</li>\n <li>\n<a href=\"https://github.com/aaronpk/Monocle\">Monocle</a> - a server-side PHP Microsub client</li>\n <li>\n<a href=\"https://github.com/aaronpk/Aperture\">Aperture</a> - a PHP Microsub server</li>\n <li>\n<a href=\"https://github.com/aaronpk/Watchtower\">Watchtower</a> - a feed fetching microservice</li>\n</ul><h3>Future Work</h3>\n<p>While this is all a good start, and I do actually use this as my primary online home now, there is still a lot more work to do!</p>\n<ul><li>\n <b>More Microsub servers!</b> I want to see at least two more solid Microsub server implementations in the relatively near future! That will help develop the spec further and ensure we're actually building interoperable tools. I suspect one of the implementations will end up being part of an integrated CMS such as <a href=\"https://indieweb.org/Known\">Known</a> or Wordpress, or will be a proxy to an existing feed reader service.\n <br /></li>\n <li>\n<b>Following private content.</b> Private content has always been a challenge, mainly due to the fact that any time authentication is involved it complicates things a lot. With <a href=\"https://indieauth.spec.indieweb.org/\">IndieAuth</a> finally written up as a spec, we now have a solid building block to use to experiment in this area more.</li>\n <li>\n<b>An Android Microsub app.</b> While both Monocle and Together work pretty well on mobile browsers, there are still many advantages to having a native Android app! And <a href=\"https://chat.indieweb.org/2018-03-12#t1520892075951500\">it sounds</a> like one is already in the works.</li>\n <li>\n<b>Better UI for actually following people.</b> I've kind of taken a shortcut on this front in order to move the rest forward. Right now, you still need to type someone's URL into a Microsub app in order to follow them. There are <a href=\"https://indieweb.org/follow\">many challenges</a> with streamlining this process further.</li>\n</ul><p>As always, I'm happy to chat about any and all of this! It's been a lot of fun already to build this all out and see it working! You can find me in the <a href=\"https://indieweb.org/discuss\">IndieWeb chat</a> via IRC and Slack, if you <a href=\"https://aaronparecki.com/webmention\">send me a Webmention</a> I'll see it in my reader, or find me at an <a href=\"https://indieweb.org/Events\">upcoming IndieWeb event</a>!</p>" }, "author": { "type": "card", "name": "Aaron Parecki", "url": "https://aaronparecki.com/", "photo": "https://aperture-media.p3k.io/aaronparecki.com/2b8e1668dcd9cfa6a170b3724df740695f73a15c2a825962fd0a0967ec11ecdc.jpg" }, "_id": "127431", "_source": "16", "_is_read": true }
{ "type": "entry", "published": "2018-03-12T13:04:55-0400", "url": "https://martymcgui.re/2018/03/12/130455/", "category": [ "IndieWeb", "ghostparty", "glitch", "neocities", "micropub", "IndieAuth" ], "syndication": [ "https://twitter.com/schmarty/status/973249205270704133", "https://www.facebook.com/marty.mcguire.54/posts/10211595313620390?comment_id=10211596218443010" ], "name": "Micropub for a static Neocities website", "content": { "text": "This post gives more technical detail for the recent talk that I gave at Bring-a-Hack NYC. In it, I describe a system that copies posts from Ghost Party's Instagram automatically to the Ghost Party Website at ghostparty.today.\nThis roughly works like so:\n\n OwnYourGram periodically checks our Instagram for new images\n \n\n For each new post, it makes a Micropub request to a service that I wrote for this purpose.\n The endpoint accepts the image files and uploads them to our site using the Neocities API. Then it creates some new HTML from the micropub post data, edits the site's main index.html page to include the content, then uploads it back to Neocities.\nAuthorization with IndieAuth\nOne missing step in that rough outline is the bit where we tell OwnYourGram *how* to post to our site via Micropub, as well as making sure that OwnYourGram can prove that we have given it permission to post there. Many Micropub clients support IndieAuth as a way to do this permission-granting step (known as authorization). With a typical personal website, I'd delegate this process to indieauth.com, which lets you offload the step of \"proving\" that you own the website where you're trying to post by instead letting you log into an existing social network account.\nghostparty.today is a shared website, so I thought a simpler way to approach this would be to create a custom authorization endpoint that accepts a password. I could give this password to other GHOST PARTY folks and they can post whatever they like.\nSome nice folks in the IndieWeb community had already created an authorization endpoint that works this way, called selfauth. I created a pretty simplistic port of selfauth from PHP to JavaScript using NodeJS on the awesome Glitch social code hosting platform. It needs some more robust error checking, and some micropub clients seem to have trouble with it, but it works with OwnYourGram and Quill, so it's Good Enough for now!\nEnter the password to get authorized!If you're interested, you can find the source for this endpoint here: https://glitch.com/edit/#!/befitting-price\nMicropub Endpoint\nFinally, there's the Micropub endpoint itself. I based mine off of this Glitch micropub project, created by Adam Bachman at IndieWebCamp Baltimore this year. Specfically, I took the bits that verify the access token. From there, it was a matter of stumbling through various bits of handling a Micropub post, pulling in extra libraries as I needed them. I slowly added support for saving uploaded files to our Neocities site via the Neocities API, then for generating an HTML snippet for the new post, and finally for adding the post to the site's main page.\nThe process for adding the generated post content to the site itself is extremely retro. The Micropub endpoint actually downloads the HTML from https://ghostparty.today/index.html. Inside there is a comment that looks like:\n<!-- NEW POSTS BELOW -->\nSo the new contents for index.html is everything before the comment, the comment, the new content, and then everything after the comment. Once that's constructed, the endpoint uploads index.html back to Neocities with the new contents.\n\n You can find the source for the Micropub endpoint here: https://glitch.com/edit/#!/prism-dirt\n \n\nIt should be possible to fork the project on Glitch and configure it to work with your own Neocities site! You'll need to use cURL with the Neocities API to generate an authorization token to configure the app, rather than saving username and password info in the project!\nMaking ghostparty.today \"IndieWeb-Readable\"\nThe GHOST PARTY site follows an extremely old-school publishing model where each post only exists as a small section of HTML on a single long page. This complicates things a bit because interacting with posts on the IndieWeb typically requires three things:\n\n A machine-readable \"identity\" h-card that says \"who\" this website is, including a logo, the site name, canonical URL.\n \n\n A machine-readable feed that contains new posts, allowing people to follow our updates in their favorite indie reader.\n A separate permalink URL for each post, containing machine-readable info about that post, allowing other IndieWeb sites to \"understand\" the content when they want to RSVP to events, repost or like photos, and more.\nMicroformats2 parsers like X-Ray do a great job at parsing HTML page into meaningful data, but the programs that use the parsed data usually stop at the first thing they find. So, if I ask X-Ray to parse https://ghostparty.today/, this is what it sees:\n{\n \"data\":{\n \"type\":\"card\",\n \"name\":\"GHOST PARTY\",\n \"url\":\"https://ghostparty.today/\",\n \"photo\":\"https://ghostparty.neocities.org/ghost-party-logo.png\"\n },\n \"url\":\"https://ghostparty.today/\",\n \"code\":200\n}\nThis is great in that it contains the \"identity\" information that we want the page to have. However, that page also has a feed! How can I get at that? By telling X-Ray to only look at a fragment of the page! Here's how X-Ray sees https://ghostparty.today/#feed: \n{\n \"data\":{\n \"type\":\"feed\",\n \"items\":[\n {\n \"type\":\"entry\",\n \"published\":\"2018-03-07T16:44:16+00:00\",\n \"url\":\"https://ghostparty.today/#2018-03-07-181020\",\n \"photo\":[\"https://ghostparty.today/uploads/2018-03-07/181020-ig0LN1JG.jpg\"],\n \"content\":{\"text\":\"snow day selfie #snowday #snowfie #ghoststories\"} \n },\n {\n \"type\":\"entry\",\n ...\n },\n ...\n ],\n \"url\":\"https://ghostparty.today/#feed\",\n \"code\":200,\n \"info\":{\"found_fragment\":true}\n }\n}\n\n Data! Nice! So if we want to follow ghostparty.today with an indie reader, we use https://ghostparty.today/#feed as the URL.\n \n\nLooking at the content of the feed, you'll notice that the individual items have a url property which also has a fragment ID in the URL. This allows IndieWeb sites to interact with a particular post, even though it's one of many on the same page. For example, I was able to create an RSVP post to the most recent Ghost Party show, and (by looking just at the content in the fragment at https://ghostparty.today/#show-2018-02-14) my site was able to pick up the machine-readable details about the event to display them on my own site.\nThe microformats markup for the h-card and h-feed are built into the index.html file itself and don't change very often. However, for each new micropub post we need to convert those properties into a chunk of HTML for the index.html page that also contains the microformats h-entry markup. To do this, I made this Handlebars template:\n<div class=\"h-entry\" id=\"{{ mp-slug }}\">\n <a class=\"u-author\" href=\"/\"></a>\n <a class=\"u-url\" href=\"#{{ mp-slug }}\">{{#if name}}<h2 class=\"p-name\">{{ name }}</h2>{{/if}}</a>\n <time class=\"dt-published\" datetime=\"{{ published }}\"></time>\n {{#if video}}\n {{#each video}}\n <video controls loop class=\"u-video\" src=\"{{ . }}\"></video>\n {{/each}}\n {{ else }}\n {{#each photo}}\n <img class=\"u-photo\" src=\"{{ . }}\" />\n {{/each}}\n {{#each audio}}\n <audio class=\"u-audio\" src=\"{{ . }}\"></audio>\n {{/each}}\n {{/if}}\n <div class=\"e-content\">{{ content }}</div>\n</div>\n<img src=\"ghosts.gif\" />\n\nNot so bad!\nResources\nHere's a collection of some of the other libraries and docs I used to pull this thing together:\n\n Neocities API\n Includes details on using cURL to get an authorization token.\n There\u2019s a Node module for the Neocities API, but it uses username and passwords, so I just used regular HTTP requests to handle talking to Neocities.\n \n \n Node Request HTTP Client\n Verifies the authorization token by querying the token endpoint (I used tokens.indieauth.com for this)\n Handles uploading files like images to Neocities via their API.\n Used to fetch index.html from the site and later to writes it back via Neocities API.\n \n \n ES6 Promises\n There's a lot of asynchronous code that waits for network requests. This code is very Promise-heavy to handle that.\n \n \n Handlebars templating\n Made it easy to take the Micropub properties for a new post and rendered them into HTML content with microformats.\n \n \n Express 4 API\n Glitch uses Node and Express 4 by default, and I got to learn lots about it!\n \n \n Multer Express Middleware\n For handling uploaded files\n \n \n Body Parser Express Middleware\n For handling regular Micropub properties\n \n \n Validator.js\n Half-using this for the authorization endpoint, need to clean it up and finish it up!\n \n \n OwnYourGram API docs\n Shows what properties are sent over Micropub, so you know exactly the kind of data your Micropub endpoint will need to handle.", "html": "<p>This post gives more technical detail for the <a href=\"https://martymcgui.re/2018/03/12/110809/\">recent talk that I gave at Bring-a-Hack NYC</a>. In it, I describe a system that copies posts from <a href=\"https://www.instagram.com/ghostpartyimprov/\">Ghost Party's Instagram</a> automatically to the <a href=\"https://ghostparty.today/\">Ghost Party Website at ghostparty.today</a>.</p>\n<p>This roughly works like so:</p>\n<ul><li>\n <a href=\"https://ownyourgram.com/\">OwnYourGram</a> periodically checks our Instagram for new images\n <br /></li>\n <li>For each new post, it makes a <a href=\"https://indieweb.org/Micropub\">Micropub</a> request to a service that I wrote for this purpose.</li>\n <li>The endpoint accepts the image files and uploads them to our site using the Neocities API. Then it creates some new HTML from the micropub post data, edits the site's main index.html page to include the content, then uploads it back to Neocities.</li>\n</ul><h2>Authorization with IndieAuth</h2>\n<p>One missing step in that rough outline is the bit where we tell OwnYourGram *how* to post to our site via Micropub, as well as making sure that OwnYourGram can prove that we have given it permission to post there. Many Micropub clients support <a href=\"https://indieweb.org/IndieAuth\">IndieAuth</a> as a way to do this permission-granting step (known as authorization). With a typical personal website, I'd delegate this process to <a href=\"https://indieauth.com/\">indieauth.com</a>, which lets you offload the step of \"proving\" that you own the website where you're trying to post by instead letting you log into an existing social network account.</p>\n<p>ghostparty.today is a shared website, so I thought a simpler way to approach this would be to create a custom authorization endpoint that accepts a password. I could give this password to other GHOST PARTY folks and they can post whatever they like.</p>\n<p>Some nice folks in the IndieWeb community had already created an authorization endpoint that works this way, called <a href=\"https://github.com/Inklings-io/selfauth\">selfauth</a>. I created a pretty simplistic port of selfauth from PHP to JavaScript using NodeJS on the awesome <a href=\"https://glitch.com/\">Glitch social code hosting platform</a>. It needs some more robust error checking, and some micropub clients seem to have trouble with it, but it works with OwnYourGram and <a href=\"https://quill.p3k.io/\">Quill</a>, so it's Good Enough for now!</p>\n<img src=\"https://aperture-media.p3k.io/media.martymcgui.re/bdbddadd6e6c4655bdc084b099c73340eefc5caf76d235ba7f403ac47ecc6730.png\" alt=\"Interface displaying text 'You are attempting to login as https://ghostparty.today/ with client https://quill.p3k.io/' along with a password prompt.\" />Enter the password to get authorized!<p>If you're interested, you can find the source for this endpoint here: <a href=\"https://glitch.com/edit/#!/befitting-price\">https://glitch.com/edit/#!/befitting-price</a></p>\n<h2>Micropub Endpoint</h2>\n<p>Finally, there's the Micropub endpoint itself. I based mine off of <a href=\"https://glitch.com/edit/#!/crocus-garlic\">this Glitch micropub project</a>, created by <a href=\"https://adambachman.org/\">Adam Bachman</a> at <a href=\"https://indieweb.org/2018/Baltimore\">IndieWebCamp Baltimore</a> this year. Specfically, I took the bits that verify the access token. From there, it was a matter of stumbling through various bits of handling a Micropub post, pulling in extra libraries as I needed them. I slowly added support for saving uploaded files to our Neocities site via the Neocities API, then for generating an HTML snippet for the new post, and finally for adding the post to the site's main page.</p>\n<p>The process for adding the generated post content to the site itself is extremely retro. The Micropub endpoint actually downloads the HTML from https://ghostparty.today/index.html. Inside there is a comment that looks like:</p>\n<pre><!-- NEW POSTS BELOW --></pre>\n<p>So the new contents for index.html is everything before the comment, the comment, the new content, and then everything after the comment. Once that's constructed, the endpoint uploads index.html back to Neocities with the new contents.</p>\n<p>\n You can find the source for the Micropub endpoint here: <a href=\"https://glitch.com/edit/#!/prism-dirt\">https://glitch.com/edit/#!/prism-dirt</a>\n <br /></p>\n<p>It should be possible to fork the project on Glitch and configure it to work with your own Neocities site! You'll need to use cURL with the Neocities API to generate an authorization token to configure the app, rather than saving username and password info in the project!</p>\n<h2>Making ghostparty.today \"IndieWeb-Readable\"</h2>\n<p>The GHOST PARTY site follows an extremely old-school publishing model where each post <i>only</i> exists as a small section of HTML on a single long page. This complicates things a bit because interacting with posts on the IndieWeb typically requires three things:</p>\n<ul><li>\n A machine-readable \"identity\" <a href=\"https://indieweb.org/h-card\">h-card</a> that says \"who\" this website is, including a logo, the site name, canonical URL.\n <br /></li>\n <li>A machine-readable <a href=\"https://indieweb.org/h-feed\">feed</a> that contains new posts, allowing people to follow our updates in their favorite <a href=\"https://indieweb.org/reader\">indie reader</a>.</li>\n <li>A separate permalink URL for each post, containing <a href=\"https://indieweb.org/h-entry\">machine-readable info about that post</a>, allowing other IndieWeb sites to \"understand\" the content when they want to RSVP to events, repost or like photos, and more.</li>\n</ul><p>Microformats2 parsers like <a href=\"https://xray.p3k.io/\">X-Ray</a> do a great job at parsing HTML page into meaningful data, but the programs that use the parsed data usually stop at the first thing they find. So, if I ask X-Ray to <a href=\"https://xray.p3k.io/parse?url=https%3A%2F%2Fghostparty.today%2F\">parse https://ghostparty.today</a>/, this is what it sees:</p>\n<pre>{\n \"data\":{\n \"type\":\"card\",\n \"name\":\"GHOST PARTY\",\n \"url\":\"https://ghostparty.today/\",\n \"photo\":\"https://ghostparty.neocities.org/ghost-party-logo.png\"\n },\n \"url\":\"https://ghostparty.today/\",\n \"code\":200\n}</pre>\n<p>This is great in that it contains the \"identity\" information that we want the page to have. However, that page also has a feed! How can I get at that? By telling X-Ray to only look at a <a href=\"https://www.w3.org/DesignIssues/Fragment.html\">fragment of the page</a>! Here's how X-Ray <a href=\"https://xray.p3k.io/parse?url=https%3A%2F%2Fghostparty.today%2F%23feed\">sees https://ghostparty.today/#feed</a>: </p>\n<pre>{\n \"data\":{\n \"type\":\"feed\",\n \"items\":[\n {\n \"type\":\"entry\",\n \"published\":\"2018-03-07T16:44:16+00:00\",\n \"url\":\"https://ghostparty.today/#2018-03-07-181020\",\n \"photo\":[\"https://ghostparty.today/uploads/2018-03-07/181020-ig0LN1JG.jpg\"],\n \"content\":{\"text\":\"snow day selfie #snowday #snowfie #ghoststories\"} \n },\n {\n \"type\":\"entry\",\n ...\n },\n ...\n ],\n \"url\":\"https://ghostparty.today/#feed\",\n \"code\":200,\n \"info\":{\"found_fragment\":true}\n }\n}</pre>\n<p>\n Data! Nice! So if we want to follow ghostparty.today with an indie reader, we use <code>https://ghostparty.today/#feed</code> as the URL.\n <br /></p>\n<p>Looking at the content of the feed, you'll notice that the individual items have a url property which <i>also</i> has a fragment ID in the URL. This allows IndieWeb sites to interact with a particular post, even though it's one of many on the same page. For example, I was able to <a href=\"https://martymcgui.re/2018/01/31/224122/\">create an RSVP post to the most recent Ghost Party show</a>, and (by looking just at the content in the fragment at <code>https://ghostparty.today/#show-2018-02-14</code>) my site was able to pick up the machine-readable details about the event to display them on my own site.</p>\n<p>The microformats markup for the h-card and h-feed are built into the index.html file itself and don't change very often. However, for each new micropub post we need to convert those properties into a chunk of HTML for the index.html page that <i>also</i> contains the microformats h-entry markup. To do this, I made <a href=\"https://glitch.com/edit/#!/prism-dirt?path=views/entry.handlebars:1:0\">this Handlebars template</a>:</p>\n<pre><code><div class=\"h-entry\" id=\"{{ mp-slug }}\">\n <a class=\"u-author\" href=\"/\"></a>\n <a class=\"u-url\" href=\"#{{ mp-slug }}\">{{#if name}}<h2 class=\"p-name\">{{ name }}</h2>{{/if}}</a>\n <time class=\"dt-published\" datetime=\"{{ published }}\"></time>\n {{#if video}}\n {{#each video}}\n <video controls loop class=\"u-video\" src=\"{{ . }}\"></video>\n {{/each}}\n {{ else }}\n {{#each photo}}\n <img class=\"u-photo\" src=\"{{ . }}\" />\n {{/each}}\n {{#each audio}}\n <audio class=\"u-audio\" src=\"{{ . }}\"></audio>\n {{/each}}\n {{/if}}\n <div class=\"e-content\">{{ content }}</div>\n</div>\n<img src=\"ghosts.gif\" />\n</code></pre>\n<p>Not so bad!</p>\n<h2>Resources</h2>\n<p>Here's a collection of some of the other libraries and docs I used to pull this thing together:</p>\n<ul><li>\n <a href=\"https://neocities.org/api\">Neocities API</a>\n <ul><li>Includes details on using cURL to get an authorization token.</li>\n <li>There\u2019s a <a href=\"https://github.com/neocities/neocities-node/blob/master/index.js\">Node module</a> for the Neocities API, but it uses username and passwords, so I just used regular HTTP requests to handle talking to Neocities.</li>\n </ul></li>\n <li>\n <a href=\"https://github.com/request/request\">Node Request HTTP Client</a>\n <ul><li>Verifies the authorization token by querying the token endpoint (I used tokens.indieauth.com for this)</li>\n <li>Handles uploading files like images to Neocities via their API.</li>\n <li>Used to fetch index.html from the site and later to writes it back via Neocities API.</li>\n </ul></li>\n <li>\n <a href=\"http://www.datchley.name/es6-promises/\">ES6 Promises</a>\n <ul><li>There's a lot of asynchronous code that waits for network requests. This code is very Promise-heavy to handle that.</li>\n </ul></li>\n <li>\n <a href=\"http://handlebarsjs.com/block_helpers.html\">Handlebars templating</a>\n <ul><li>Made it easy to take the Micropub properties for a new post and rendered them into HTML content with microformats.</li>\n </ul></li>\n <li>\n <a href=\"https://expressjs.com/en/4x/api.html\">Express 4 API</a>\n <ul><li>Glitch uses Node and Express 4 by default, and I got to learn lots about it!</li>\n </ul></li>\n <li>\n <a href=\"https://expressjs.com/en/resources/middleware/multer.html\">Multer Express Middleware</a>\n <ul><li>For handling uploaded files</li>\n </ul></li>\n <li>\n <a href=\"https://expressjs.com/en/resources/middleware/body-parser.html\">Body Parser Express Middleware</a>\n <ul><li>For handling regular Micropub properties</li>\n </ul></li>\n <li>\n <a href=\"https://github.com/chriso/validator.js/tree/9.4.0\">Validator.js</a>\n <ul><li>Half-using this for the authorization endpoint, need to clean it up and finish it up!</li>\n </ul></li>\n <li>\n <a href=\"https://ownyourgram.com/docs\">OwnYourGram API docs</a>\n <ul><li>Shows what properties are sent over Micropub, so you know exactly the kind of data your Micropub endpoint will need to handle.</li>\n </ul></li>\n</ul>" }, "author": { "type": "card", "name": "Marty McGuire", "url": "https://martymcgui.re/", "photo": "https://aperture-media.p3k.io/martymcgui.re/4f9fac2b9e3ae62998c557418143efe288bca8170a119921a9c6bfeb0a1263a2.jpg" }, "_id": "127020", "_source": "175", "_is_read": true }
{ "type": "entry", "published": "2018-03-12T11:11:57-0700", "url": "https://aaronparecki.com/2018/03/12/11/aperture", "category": [ "aperture", "microsub", "indieweb" ], "content": { "text": "Just made Aperture download a cached copy of avatars and other media it finds in posts! Now the images will always be available over https, and images from old posts won't disappear!\n\nIf you're running your own copy of Aperture, it'll take an extra step of setting up a subdomain to serve the images from the storage folder. They're not served from the main domain for security reasons.", "html": "Just made Aperture download a cached copy of avatars and other media it finds in posts! Now the images will always be available over https, and images from old posts won't disappear!<br /><br />If you're running your own copy of Aperture, it'll take an extra step of setting up a subdomain to serve the images from the storage folder. They're not served from the main domain for security reasons." }, "author": { "type": "card", "name": "Aaron Parecki", "url": "https://aaronparecki.com/", "photo": "https://aperture-media.p3k.io/aaronparecki.com/2b8e1668dcd9cfa6a170b3724df740695f73a15c2a825962fd0a0967ec11ecdc.jpg" }, "_id": "126518", "_source": "16", "_is_read": true }
{ "type": "entry", "published": "2018-03-12T10:51:04-0700", "url": "https://aaronparecki.com/2018/03/12/10/homebrew-microblog", "category": [ "indieweb", "microblog" ], "photo": [ "https://aperture-media.p3k.io/aaronparecki.com/ffd5f0365bcc141e2e70069945a6899ac2609ea34965c45820853ddaf9b9962d.jpg" ], "syndication": [ "https://twitter.com/aaronpk/status/973255081519808512" ], "content": { "text": "Homebrew Website Club PDX is back, and joining forces with the Microbrew and Microblog meetup! Come to Rogue Eastside this Wednesday for the first \"Homebrew Microblog\"! https://indieweb.org/events/2018-03-14-homebrew-microblog #indieweb #microblog", "html": "Homebrew Website Club PDX is back, and joining forces with the Microbrew and Microblog meetup! Come to Rogue Eastside this Wednesday for the first \"Homebrew Microblog\"! <a href=\"https://indieweb.org/events/2018-03-14-homebrew-microblog\">https://indieweb.org/events/2018-03-14-homebrew-microblog</a> <a href=\"https://aaronparecki.com/tag/indieweb\">#indieweb</a> <a href=\"https://aaronparecki.com/tag/microblog\">#microblog</a>" }, "author": { "type": "card", "name": "Aaron Parecki", "url": "https://aaronparecki.com/", "photo": "https://aperture-media.p3k.io/aaronparecki.com/2b8e1668dcd9cfa6a170b3724df740695f73a15c2a825962fd0a0967ec11ecdc.jpg" }, "_id": "126467", "_source": "16", "_is_read": true }
{ "type": "entry", "published": "2018-03-12T11:08:09-0400", "url": "https://martymcgui.re/2018/03/12/110809/", "category": [ "IndieWeb", "ghostparty", "micropub", "speaking" ], "syndication": [ "https://twitter.com/schmarty/status/973219715907772416", "https://www.facebook.com/marty.mcguire.54/posts/10211595313620390" ], "name": "A Ghost (Party) is Haunting the Silo'd Web", "content": { "text": "This post is a rough summary of a lightning talk that I gave on February 28th at the Bring-A-Hack NYC with Hackaday + Ultimaker + New Lab. Many thanks to Shayna Gentiluomo for organizing and sometimes co-conspirator Matt Griffin for nudging me to speak!\nI have a lot of distrust for social silos like Facebook and Twitter which draw us in with the promise of connecting with family, friends, and interesting people, but I sometimes have trouble articulating that in a succinct way. Thankfully, I saw a perfect example this morning:\nPosting on the @facebook website is not working in Mac OS today. JavaScript eats CSS & HTML, making data entry field disappear except for a spookily disembodied close-box X. Been this way a few hours. \u2014 @zeldman, 9:53 AM - 28 Feb 2018\n\nSome Facebook team pushed an (untested?) update which broke the website, preventing some users from posting. \"Move fast and break things\". These silos don't value us or our content. So, we should get out. But what is the alternative?\nThe IndieWeb helps us take our content back, by posting to our own websites on our own domains. With some work, we can even get the benefits of these social networks and take our conversations with us. There\u2019s a whole lot of great stuff on the IndieWeb website, so go spend a couple of days reading it. But I\u2019m not here to talk about all those good things today. I\u2019m here to talk about how I used them to do a dumb hack.\n \n\nghostparty.today is a website for Ghost Party \u2013 an improv project that has a ... certain aesthetic. Specifically the website was pitched as \u201cexactly like the Heaven\u2019s Gate website\u201d but we compromised on \u201cextreme Geocities\u201d.\n\nWe have an aesthetic.My Ghost Party co-host (co-ghost) built the first version of the site on Neocities.org, a lovely hosting provider that recaptures the feel of editing raw HTML directly in your browser. However, hand-editing HTML gets exhausting and sometimes you just want to post things to Instagram (and, of course, Ghost Party has an Instagram).\nAnd Instagram is fine as a marketing platform! Lots of people look at it and like the pictures. But what about our website? Our aesthetic?\nMicropub is a standard (and now W3C Recommendation) designed over some years of practice from the IndieWeb community that defines a way for apps and clients to easily make new posts to any website (even yours) if it supports Micropub.\nI used Glitch, an amazing community and JavaScript-server-app hosting service, to make a simple micropub service for ghostparty.today.\n\nIt accepts posts via micropub, including file uploads, and uses the Neocities API (hey, it\u2019s not the 90s! Neocities has an API!) to upload the files to our website. Then, it fetches our site\u2019s index.html, adds the content of the new post, and uploads it back. You can find the source here on Glitch and fork it for your own purposes!\nNow that our site supports micropub, we can make use of a wonderful service called OwnYourGram. Once we give OwnYourGram permission to post to our site and read our Instagram feed, it will poll our Instagram account and copy each new post back to our website, where we can display it however we want.\nAestheticWe can go a step further, using an IndieWeb building block called Webmention and a service called brid.gy, to bring all of those responses, those Instagram and Facebook likes and comments, Twitter retweets, and more, back to our site for display.\nAnd to show how it works, here\u2019s a micropub client call Quill that works for any micropub-enabled site. Let\u2019s make a quick post, now!\nQuill's note interfaceOnce we hit the \"Post\" button and refresh the homepage, we can see the new post on the site!\nAestheticThis was the end of time time. I would have like to further encourage folks to check out Homebrew Website Clubs in their own communities, or to start one if they don't exist. They're part show-and-tell, part support group, and part mad science lab for people who love the web!", "html": "<p>This post is a rough summary of a lightning talk that I gave on February 28th at the <a href=\"https://hackaday.com/2018/02/23/next-week-bring-a-hack-in-nyc/\">Bring-A-Hack NYC with Hackaday + Ultimaker + New Lab</a>. Many thanks to Shayna Gentiluomo for organizing and sometimes co-conspirator <a href=\"https://mfgriffin.com/\">Matt Griffin</a> for nudging me to speak!</p>\n<p>I have a lot of distrust for social silos like Facebook and Twitter which draw us in with the promise of connecting with family, friends, and interesting people, but I sometimes have trouble articulating that in a succinct way. Thankfully, I saw a perfect example this morning:</p>\n<blockquote>Posting on the @facebook website is not working in Mac OS today. JavaScript eats CSS & HTML, making data entry field disappear except for a spookily disembodied close-box X. Been this way a few hours. \u2014 <a href=\"https://twitter.com/zeldman\">@zeldman</a>, <a href=\"https://twitter.com/zeldman/status/968861672541708290\">9:53 AM - 28 Feb 2018</a>\n</blockquote>\n<p>Some Facebook team pushed an (untested?) update which broke the website, preventing some users from posting. \"Move fast and break things\". These silos don't value us or our content. So, we should get out. But what is the alternative?</p>\n<p>The <a href=\"https://indieweb.org/\">IndieWeb</a> helps us take our content back, by posting to our own websites on our own domains. With some work, we can even get the benefits of these social networks and take our conversations with us. There\u2019s a whole lot of great stuff on the IndieWeb website, so <a href=\"https://indieweb.org/Getting_Started\">go spend a couple of days reading it</a>. But I\u2019m not here to talk about all those good things today. I\u2019m here to talk about how I used them to do a dumb hack.\n <br /></p>\n<p><a href=\"https://ghostparty.today/\">ghostparty.today</a> is a website for Ghost Party \u2013 an improv project that has a ... certain aesthetic. Specifically the website was pitched as \u201cexactly like the Heaven\u2019s Gate website\u201d but we compromised on \u201cextreme Geocities\u201d.</p>\n<p></p>\n<img src=\"https://media.martymcgui.re/09/a1/ac/48/9365fceee9147050b56175762179446084558b2611bec008d03146ed.png\" alt=\"Ugly large text says 'Welcome to GHOST PARTY'\" />We have an aesthetic.<p>My Ghost Party co-host (co-ghost) built the first version of the site on <a href=\"https://neocities.org/\">Neocities.org</a>, a lovely hosting provider that recaptures the feel of editing raw HTML directly in your browser. However, hand-editing HTML gets exhausting and sometimes you just want to post things to Instagram (and, of course, <a href=\"https://instagram.com/ghostpartyimprov/\">Ghost Party has an Instagram</a>).</p>\n<p>And Instagram is fine as a marketing platform! Lots of people look at it and like the pictures. But what about our website? <i>Our aesthetic</i>?</p>\n<p><a href=\"https://indieweb.org/Micropub\">Micropub</a> is a standard (and now W3C Recommendation) designed over some years of practice from the IndieWeb community that defines a way for apps and clients to easily make new posts to any website (even yours) if it supports Micropub.</p>\n<p>I used <a href=\"https://glitch.com/\">Glitch</a>, an amazing community and JavaScript-server-app hosting service, to make a simple micropub service for ghostparty.today.</p>\n<p></p>\n<img src=\"https://media.martymcgui.re/9c/e4/3b/6a/2acaa5622a3129066fbe2cccae3e41bbaa56db82ff3d0eff51f9e2ed.png\" alt=\"Screenshot of code in the Glitch UI\" /><p>It accepts posts via micropub, including file uploads, and uses the Neocities API (hey, it\u2019s not the 90s! Neocities has an API!) to upload the files to our website. Then, it fetches our site\u2019s index.html, adds the content of the new post, and uploads it back. <a href=\"https://glitch.com/edit/#!/prism-dirt\">You can find the source here on Glitch and fork it for your own purposes</a>!</p>\n<p>Now that our site supports micropub, we can make use of a wonderful service called <a href=\"https://ownyourgram.com/\">OwnYourGram</a>. Once we give OwnYourGram permission to post to our site and read our Instagram feed, it will poll our Instagram account and copy each new post back to our website, where we can display it however we want.</p>\n<img src=\"https://media.martymcgui.re/2c/fe/90/e7/881eb3e2066c4fe6230eb7f6005921d22ff1691171c389dc92f2527f.png\" alt=\"Super simplified Instagram photo on Ghost Party website\" />Aesthetic<p>We can go a step further, using an IndieWeb building block called <a href=\"https://indieweb.org/Webmention\">Webmention</a> and a service called <a href=\"https://brid.gy/\">brid.gy</a>, to bring all of those responses, those Instagram and Facebook likes and comments, Twitter retweets, and more, back to our site for display.</p>\n<p>And to show how it works, here\u2019s a micropub client call <a href=\"https://quill.p3k.io/\">Quill</a> that works for any micropub-enabled site. Let\u2019s make a quick post, now!</p>\n<img src=\"https://media.martymcgui.re/50/c3/e5/91/56ecb23b74abdd71f8a31a41040a321dbd94b70b8da981dd954a11ae.png\" alt=\"Posting interface with 'Hello from New Lab' typed into note field\" />Quill's note interface<p>Once we hit the \"Post\" button and refresh the homepage, we can see the new post on the site!</p>\n<img src=\"https://media.martymcgui.re/82/0a/5e/fc/19b83c42948ee8517be2677de6f120ba374aeb0ed1d5343ba053409f.png\" alt=\"'Hello from New Lab' text with ghost separator image\" /><em>Aesthetic</em><p>This was the end of time time. I would have like to further encourage folks to check out <a href=\"https://indieweb.org/Homebrew_Website_Club\">Homebrew Website Club</a>s in their own communities, or to start one if they don't exist. They're part show-and-tell, part support group, and part mad science lab for people who love the web!</p>" }, "author": { "type": "card", "name": "Marty McGuire", "url": "https://martymcgui.re/", "photo": "https://martymcgui.re/images/logo.jpg" }, "_id": "126220", "_source": "175", "_is_read": true }
{ "type": "entry", "published": "2018-03-11T23:30:08-0400", "url": "https://kartikprabhu.com/notes/re-citizen-of-indieweb", "category": [ "indieweb", "indiewebcitizen" ], "syndication": [ "https://twitter.com/kartik_prabhu/status/973044439135506432" ], "in-reply-to": [ "https://collect.readwriterespond.com/citizen-of-indieweb/" ], "content": { "text": "To me it means: have a domain name and post content on it. Everything else is a bonus.\n\n#indieweb #indiewebcitizen" }, "author": { "type": "card", "name": "Kartik Prabhu", "url": "https://kartikprabhu.com/about#me", "photo": "https://kartikprabhu.com/static/images/avatar.jpg" }, "_id": "124974", "_source": "204", "_is_read": true }
{ "type": "entry", "published": "2018-03-11T23:47:01-0400", "summary": "Aaron Davis asked the question", "url": "https://eddiehinkle.com/2018/03/11/9/article/", "category": [ "indieweb", "" ], "name": "A Citizen of the IndieWeb", "author": { "type": "card", "name": "Eddie Hinkle", "url": "https://eddiehinkle.com/", "photo": "https://eddiehinkle.com/images/profile.jpg" }, "_id": "124838", "_source": "226", "_is_read": true }
Hey, I’m sorry to hear you’re having a hard time. If you haven’t joined us on Slack/IRC, we love to help talking through things with people that are having a hard time, you can find the chat info here: https://indieweb.org/discuss
{ "type": "entry", "published": "2018-03-11T21:07:19-0400", "summary": "Hey, I\u2019m sorry to hear you\u2019re having a hard time. If you haven\u2019t joined us on Slack/IRC, we love to help talking through things with people that are having a hard time, you can find the chat info here: https://indieweb.org/discuss", "url": "https://eddiehinkle.com/2018/03/11/8/reply/", "in-reply-to": [ "https://twitter.com/downdb/status/972992691301576707" ], "content": { "text": "Hey, I\u2019m sorry to hear you\u2019re having a hard time. If you haven\u2019t joined us on Slack/IRC, we love to help talking through things with people that are having a hard time, you can find the chat info here: https://indieweb.org/discuss", "html": "<p>Hey, I\u2019m sorry to hear you\u2019re having a hard time. If you haven\u2019t joined us on Slack/IRC, we love to help talking through things with people that are having a hard time, you can find the chat info here: <a href=\"https://indieweb.org/discuss\">https://indieweb.org/discuss</a></p>" }, "author": { "type": "card", "name": "Eddie Hinkle", "url": "https://eddiehinkle.com/", "photo": "https://eddiehinkle.com/images/profile.jpg" }, "refs": { "https://twitter.com/downdb/status/972992691301576707": { "type": "entry", "url": "https://twitter.com/downdb/status/972992691301576707", "name": "https://twitter.com/downdb/status/972992691301576707" } }, "_id": "124699", "_source": "226", "_is_read": true }
{ "type": "entry", "published": "2018-03-10T15:37:55-0500", "url": "https://martymcgui.re/2018/03/10/153755/", "category": [ "podcast", "IndieWeb", "this-week-indieweb-podcast" ], "audio": [ "https://media.martymcgui.re/20/fc/78/e8/6ab36bca487d5c2d468116c65cbe05e2f95c0aeeedd6ccf0d1e56371.mp3" ], "syndication": [ "https://huffduffer.com/schmarty/465175", "https://twitter.com/schmarty/status/972572891580682240", "https://www.facebook.com/marty.mcguire.54/posts/10211580886619724" ], "name": "This Week in the IndieWeb Audio Edition \u2022 March 3rd - 9th, 2018", "content": { "text": "Show/Hide Transcript \n \n Audio edition for This Week in the IndieWeb for March 3rd - 9th, 2018.\n\nYou can find all of my audio editions and subscribe with your favorite podcast app here: martymcgui.re/podcasts/indieweb/.\n\nMusic from Aaron Parecki\u2019s 100DaysOfMusic project: Day 85 - Suit, Day 48 - Glitch, Day 49 - Floating, Day 9, and Day 11\n\nThanks to everyone in the IndieWeb chat for their feedback and suggestions. Please drop me a note if there are any changes you\u2019d like to see for this audio edition!", "html": "Show/Hide Transcript \n \n <p>Audio edition for <a href=\"https://indieweb.org/this-week/2018-03-09.html\">This Week in the IndieWeb for March 3rd - 9th, 2018</a>.</p>\n\n<p>You can find all of my audio editions and subscribe with your favorite podcast app here: <a href=\"https://martymcgui.re/podcasts/indieweb/\">martymcgui.re/podcasts/indieweb/</a>.</p>\n\n<p>Music from <a href=\"https://aaronparecki.com/\">Aaron Parecki</a>\u2019s <a href=\"https://100.aaronparecki.com/\">100DaysOfMusic project</a>: <a href=\"https://aaronparecki.com/2017/03/15/14/day85\">Day 85 - Suit</a>, <a href=\"https://aaronparecki.com/2017/02/06/7/day48\">Day 48 - Glitch</a>, <a href=\"https://aaronparecki.com/2017/02/07/4/day49\">Day 49 - Floating</a>, <a href=\"https://aaronparecki.com/2016/12/29/21/day-9\">Day 9</a>, and <a href=\"https://aaronparecki.com/2016/12/31/15/\">Day 11</a></p>\n\n<p>Thanks to everyone in the <a href=\"https://chat.indieweb.org/\">IndieWeb chat</a> for their feedback and suggestions. Please drop me a note if there are any changes you\u2019d like to see for this audio edition!</p>" }, "author": { "type": "card", "name": "Marty McGuire", "url": "https://martymcgui.re/", "photo": "https://martymcgui.re/images/logo.jpg" }, "_id": "121418", "_source": "175", "_is_read": true }
{ "type": "entry", "published": "2018-03-10T05:01:01+0000", "url": "https://cleverdevil.io/2018/started-working-on-a-json-schema-for", "category": [ "indieweb", "microformats2" ], "syndication": [ "https://twitter.com/cleverdevil/status/972336503698460672" ], "content": { "text": "Started working on a JSON Schema for microformats2 about a week ago. Posted the first version on GitHub tonight \u2013 https://github.com/cleverdevil/microformats2 \u2013 Feedback welcome! #indieweb #microformats2", "html": "Started working on a JSON Schema for microformats2 about a week ago. Posted the first version on GitHub tonight \u2013 <a href=\"https://github.com/cleverdevil/microformats2\">https://github.com/cleverdevil/microformats2</a> \u2013 Feedback welcome! <a href=\"https://cleverdevil.io/tag/indieweb\" class=\"p-category\">#indieweb</a> <a href=\"https://cleverdevil.io/tag/microformats2\" class=\"p-category\">#microformats2</a>" }, "author": { "type": "card", "name": "Jonathan LaCour", "url": "https://cleverdevil.io/profile/cleverdevil", "photo": "https://cleverdevil.io/file/fdbc7696a5f73864ea11a828c861e138/thumb.jpg" }, "_id": "120213", "_source": "71", "_is_read": true }
{ "type": "entry", "published": "2018-03-10T00:29:37-0500", "url": "https://kartikprabhu.com/notes/re-snarfed-like-mf2py-backcompat", "category": [ "indieweb", "microformats" ], "in-reply-to": [ "https://snarfed.org/2018-03-09_backcompat-mf2py-parallel-transport" ], "content": { "text": "The irony of this \u201clike post\u201d is that under the new backcompat rules (according to spec) the u-like-of is ignored under a hentry! see: http://microformats.org/wiki/microformats2-parsing#note_backward_compatibility_details\n\nSo it shows up as a mention to my post! :P", "html": "The irony of this \u201clike post\u201d is that under the new backcompat rules (according to spec) the u-like-of is ignored under a hentry! see: <a href=\"http://microformats.org/wiki/microformats2-parsing#note_backward_compatibility_details\">http://microformats.org/wiki/microformats2-parsing#note_backward_compatibility_details</a>\n\nSo it shows up as a mention to my post! :P" }, "author": { "type": "card", "name": "Kartik Prabhu", "url": "https://kartikprabhu.com/about#me", "photo": "https://kartikprabhu.com/static/images/avatar.jpg" }, "_id": "120003", "_source": "204", "_is_read": true }
{ "type": "entry", "published": "2018-03-09T18:19:57-0500", "url": "https://kartikprabhu.com/notes/backcompat-mf2py", "category": [ "python", "microformats", "indieweb" ], "syndication": [ "https://twitter.com/kartik_prabhu/status/972251357443952640" ], "content": { "text": "Took a solid 10 hours but better backcompat parsing rules in mf2py now https://github.com/kartikprabhu/mf2py", "html": "Took a solid 10 hours but better backcompat parsing rules in mf2py now <a href=\"https://github.com/kartikprabhu/mf2py\">https://github.com/kartikprabhu/mf2py</a>" }, "author": { "type": "card", "name": "Kartik Prabhu", "url": "https://kartikprabhu.com/about#me", "photo": "https://kartikprabhu.com/static/images/avatar.jpg" }, "_id": "119741", "_source": "204", "_is_read": true }
{ "type": "entry", "published": "2018-03-09T21:29:02+0000", "url": "http://stream.boffosocko.com/2018/%E3%81%8A%E3%81%AF%E3%82%88%E3%81%86%E3%81%94%E3%81%96%E3%81%84%E3%81%BE%E3%81%99-welcome-to-the-indieweb-im-sure-many-can-help", "in-reply-to": [ "https://www.prjorgensen.com/2018/03/08/949" ], "content": { "text": "\u304a\u306f\u3088\u3046\u3054\u3056\u3044\u307e\u3059. Welcome to the IndieWeb! I'm sure many can help you out with some additional detail about what you're experiencing. Try catching us live in the chat at: https://indieweb.org/discuss", "html": "\u304a\u306f\u3088\u3046\u3054\u3056\u3044\u307e\u3059. Welcome to the IndieWeb! I'm sure many can help you out with some additional detail about what you're experiencing. Try catching us live in the chat at: <a href=\"https://indieweb.org/discuss\">https://indieweb.org/discuss</a>" }, "author": { "type": "card", "name": "Chris Aldrich", "url": "http://stream.boffosocko.com/profile/chrisaldrich", "photo": "http://stream.boffosocko.com/file/600427b81f7785e704eadfe511a9270f/thumb.jpg" }, "_id": "119726", "_source": "192", "_is_read": true }