{
    "version": "https://jsonfeed.org/version/1",
    "title": "https://grant.codes json feed",
    "home_page_url": "https://grant.codes",
    "feed_url": "https://backend.grant.codes/micropub/plugin/feeds/json",
    "author": {
        "name": "Grant Richmond",
        "url": "https://grant.codes"
    },
    "items": [
        {
            "id": "https://grant.codes/2019/07/08/together",
            "content_html": "<p>Over the last few months I have been completely rebuilding my social reader <a href=\"https://alltogethernow.io\">Together</a>. So I felt I should write a post about it to highlight what&#x27;s changed and show off what Together has to offer.</p><p>First off just a little info on the idea of a <a href=\"https://indieweb.org/reader\">social reader</a>: A social reader is an application that can be used to read and interact with content from all around the web, not just one walled garden.</p><p>In the world of the <a href=\"https://indieweb.org\">#indieweb</a> that means following other websites and owning all your own content on your own website.</p><h2>Features</h2><h3>Layouts</h3><p>The content you follow from around the web comes in all different forms, it doesn&#x27;t make sense to force a photo into the same layout as long form blog post.</p><p>To help with this Together supports a number of views:</p><h4>Timeline View</h4><img alt=\"\" src=\"https://grant.codes/media/2019/07/08/timeline.jpg\" class=\"alignwide\"/><p>The timeline view is similar to what you might find in twitter or facebook.</p><p>Each post has it&#x27;s own card in a scrolling list of cards. Great for shorter format and mixed content.</p><h4>Classic View</h4><img alt=\"\" src=\"https://grant.codes/media/2019/07/08/classic.jpg\" class=\"alignwide\"/><p>Inspired by classic RSS readers such as Google Reader (r.i.p.). The classic view uses a 2 column layout with small post previews on the left and you can click into a single post to view it on the right.</p><p>This view works well for longer form articles or news updates.</p><h4>Gallery View</h4><img alt=\"\" src=\"https://grant.codes/media/2019/07/08/gallery.jpg\" class=\"alignwide\"/><p>The gallery view shows a grid of photos and videos from your feeds.</p><p>You can click into an individual photo or view to view it full screen and swipe through them.</p><p>I use this view to follow my instagram feed and the <a href=\"https://micro.blog/discover/photos\">micro.blog photo feed</a>.</p><h4>Map View</h4><p>A more niche view is the map view that shows where the most recent posts in a channel come from.</p><p>This can be used to have a nice view where your friends have checked in recently.</p><h3>Previews</h3><img alt=\"\" src=\"https://grant.codes/media/2019/07/08/preview.jpg\" class=\"alignnone\"/><p>Something I worked on quite a bit for this release was the feed following and preview UI.</p><p>The preview and search is now contained in one unified box, it&#x27;s now much easier to see exactly what you searched for and what feed you are previewing.</p><h3>Inline actions</h3><p>Inline actions are not new in this version of Together, but have seen an update. The actions let you reply, like or repost to your website via <a href=\"https://indieweb.org/micropub\">micropub</a>, perform admin actions (like blocking and muting sources) and viewing or loading the original content.</p><p>New in v3 is the consistent option to attempt to reload the content again from the source. This is useful for (annoying) feeds that only provide a short preview of a posts content.</p><p>Another new feature in v3 are the improved notifications. When you post a reply or like, notifications now have buttons to view your created post or immediately delete it if your micropub endpoint supports <a href=\"https://www.w3.org/TR/micropub/#delete\">deletes</a>.</p><img alt=\"\" src=\"https://grant.codes/media/2019/07/08/notification.jpg\" class=\"alignnone\"/><h3>Settings management</h3><img alt=\"\" src=\"https://grant.codes/media/2019/07/08/following.jpg\" class=\"alignnone\"/><p>Channel settings have also seen a bit of an upgrade in v3, in particular the list of feeds you are following, or have blocked or muted. You can now more easily see exactly what each feed is and click through to view it.</p><h3>Micropub Queries</h3><p>This one is exciting to me! <a href=\"https://github.com/indieweb/micropub-extensions/issues/4\">Micropub queries</a> are very experimental but if your micropub endpoint supports them it allows Together to query your own website for recently published content that can then be displayed and managed.</p><p>My site also supports various <a href=\"https://indieweb.org/posts#Types_of_Posts\">post types</a>, so I can see my photos, notes, articles or a variety of other content.</p><p>When viewing these posts from your own site you can also edit and delete them all from within Together.</p><img alt=\"\" src=\"https://grant.codes/media/2019/07/08/micropub-query.jpg\" class=\"alignwide\"/><h3>Share Target</h3><p>I constantly find articles and content online that I want to interact with or store on my own website, and the Together share target helps facilitate that. Now if Together is installed as a PWA with chrome, you can natively share content to it, and then interact with that content, like writing a reply or liking the url.</p><h3>Contributions &amp; Donations\r</h3><p>\rWith this new release, I&#x27;ve also added the ability to donate money towards the development of Together if you are so inclined. Payments are handled via my own website at <a href=\"https://pay.grant.codes\">pay.grant.codes\r</a>. At some point I&#x27;d like to make this more obvious in a non-annoying way, but I&#x27;ve not thought of how to do that yet.</p><p>\rNon monetary contributions are also easier now too! In particular opening a GitHub issue is just a click away with error messages being autofilled into the issue.</p><h2>Tech details</h2><p>V3 of Together was a near total rewrite. Now the backend is a <a href=\"https://graphql.org\">GraphQL</a> server writtin in nodejs using Apollo and the frontend is a react app that reads from the server.</p><h3>Backend</h3><p>The <a href=\"https://github.com/alltogethernow/server\">new backend for Together</a> is a GraphQL server. It is totally independent from the frontend, so if you want to run your own version for your own project you are very much welcome to.</p><p>The backend is basically a bridge between <a href=\"https://graphql.org\">GraphQL</a> and <a href=\"https://indieweb.org/microsub\">Microsub</a> and <a href=\"https://indieweb.org/micropub\">Micropub</a>.</p><p>Microsub maps quite well to GraphQL as it is based on JF2 which is a strictly defined format.</p><p>But there are a few transformations that the Together server performs: It converts keys for all properties to camel case, and fills in a few properties with smart defaults, such as feed names are based on their url if there is no name, channels have a number of custom properties that mainly relate to Together settings, these are prefixed with &quot;_t_&quot;</p><p>Micropub on the other hand uses uses the much more fluid microformats2 format, which does not map nearly so well, so there is a bit of passing json strings involved and some conversion between mf2 and jf2.</p><p>For realtime updates, data is pushed from the server using GraphQL <a href=\"https://www.apollographql.com/docs/apollo-server/features/subscriptions\">subscriptions</a> over websockets.</p><p>On the server your microsub endpoint is polled every minute for updates, and if there is new data it is pushed to the client.</p><p>A small amount of persistent data is also stored in a <a href=\"https://www.mongodb.com/\">mongodb</a> database. This is mainly for user data, such as their endpoint info, token, and channel settings.</p><h3>Frontend</h3><p>The <a href=\"https://github.com/alltogethernow/web\">Together frontend</a> has always been built with react, but now it has been updated to be much more performant using newer features. All components have been converted to use <a href=\"https://reactjs.org/docs/hooks-intro.html\">react hooks</a>.</p><h2>Misc</h2><h3>IndieAuth Library</h3><p>A while back I made (with a lot of help from <a class=\"h-card\" href=\"https://martymcgui.re/\">@Marty McGuire</a>) an <a href=\"https://indieweb.org/indieauth\">IndieAuth</a> helper library that improves on a lot of issues with the auth implementation I had used before. So I now use that in together so there should be fewer issues with people trying to log in.</p><h3><a href=\"https://github.com/grantcodes/postrchild-editor-base\">@postrchild/editor-base</a></h3><p>As part of a bunch of my projects I have forms to create mf2 content for micropub posts, I had this extracted into a reusable form, but it previously was not very well made and didn&#x27;t follow a lot of react best practices.</p><p>But I have also rebuilt this to be way more performant and extendable, so now it is ideal for creating both super simple micropub client interfaces as well as far more advanced, customized interfaces.</p><h3><a href=\"https://microsub-middleware.glitch.me/\">Microsub Middleware</a></h3><p>This is another little side project that works independently of Together. It simply watches your microsub channels and then automatically performs actions on the content.</p><p>At the moment I mainly use it to roll up likes and bookmarks in my channels into one post per day instead of cluttering up my feeds.</p><p>It also has an option to only keep the most recent checkin post of all users in a channel, this lets me keep an up to date location map of my indieweb friends.</p><h3>Glitch Indieweb Starter</h3><p>Want to use all these awesome things I have mentioned but don&#x27;t know where to start? I&#x27;ve made something that can maybe help you with that! <a href=\"https://indieweb-starter.glitch.me\">indieweb-starter.glitch.me</a> is a pretty basic indieweb website that you can remix to instantly create your own (quite basic) website that supports IndieAuth, Micropub and Microsub - basically everything you need to get started using Together.</p><p>I wouldn&#x27;t recommend it as your main forever website, but it is a nice place to start out and try out some indieweb functionality before moving to something more permanent.</p><h3>PostrChild Browser Extension</h3><p>With the other updates I also needed to update the <a href=\"https://postrchild.com\">PostrChild browser extension</a>. So there will be a few updates there soon. The one I am currently happiest with is the automatic caching of a new post you are writing, it makes me feel much more comfortable knowing my content isn’t going to be lost.</p><h3>Granary</h3><p>I have to give a shoutout to <a href=\"https://granary.io\">granary</a> and <a href=\"https://snarfed.org\">snarfed</a>! Granary is a useful tool that can be used to convert data from silos such as twitter and instagram into a more friendly formats for the open web. I use this to covert my instagram feed and twitter lists into microformats2 html to follow in Together.<br/></p><p></p>",
            "url": "https://grant.codes/2019/07/08/together",
            "title": "Together v3",
            "summary": "An update on what is new in Together",
            "date_modified": "2019-07-08T20:34:22.043Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2018/06/05/5b1704320402420baf709a8f",
            "content_html": "<p>About to try and sync all my browser bookmarks to my #indieweb site. Let's see if this works...<br></p>",
            "url": "https://grant.codes/2018/06/05/5b1704320402420baf709a8f",
            "title": "<p>About to try and sync all my browser bookmarks …",
            "date_modified": "2018-06-05T21:44:18.792Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2018/05/17/5afce1d7310c2519f662a7b5",
            "content_html": "<p>Hmm, looks like my new inline micropub browser extension is just about ready for testing! #indieweb</p>",
            "url": "https://grant.codes/2018/05/17/5afce1d7310c2519f662a7b5",
            "title": "<p>Hmm, looks like my new inline micropub browser …",
            "date_modified": "2018-05-17T01:58:47.356Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/10/18/59e7a46c8191f2590727801a",
            "content_html": "<p class=\"text-style-pre\">Got a colourful new refresh of my #indieweb site online: <a href=\"https://grant.codes\">https://grant.codes</a></p>",
            "url": "https://grant.codes/2017/10/18/59e7a46c8191f2590727801a",
            "title": "Got a colourful new refresh of my #indieweb site o…",
            "date_modified": "2017-10-18T18:58:52.541Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/04/12/58ee3fd79f99400e56703317",
            "content_html": "<p class=\"text-style-pre\">Day 94 of #100DaysOfCode: Added RSVP support to my #indieweb chatbot and site 👋 with automatic webmention sending. <a href=\"https://grant.codes/2017/04/12/58ee3c3a9f99400e56703316\">https://grant.codes/2017/04/12/58ee3c3a9f99400e56703316</a></p>",
            "url": "https://grant.codes/2017/04/12/58ee3fd79f99400e56703317",
            "title": "Day 94 of #100DaysOfCode: Added RSVP support to my…",
            "date_modified": "2017-04-12T14:55:19.931Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/04/05/58e56d2ca59bf96b9f97acda",
            "content_html": "<p class=\"text-style-pre\">Day 86 of #100DaysOfCode: Added a method to verify access tokens to my #indieweb micropub helper: <a href=\"https://github.com/grantcodes/micropub\">https://github.com/grantcodes/micropub</a></p>",
            "url": "https://grant.codes/2017/04/05/58e56d2ca59bf96b9f97acda",
            "title": "Day 86 of #100DaysOfCode: Added a method to verify…",
            "date_modified": "2017-04-05T22:18:20.045Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/04/02/58e0a3c80f8ff246f68a41d5",
            "content_html": "<p class=\"text-style-pre\">Day 82 of #100DaysOfCode: I now correctly append query variables to urls in my #indieweb micropub helper <a href=\"https://github.com/grantcodes/micropub\">https://github.com/grantcodes/micropub</a></p>",
            "url": "https://grant.codes/2017/04/02/58e0a3c80f8ff246f68a41d5",
            "title": "Day 82 of #100DaysOfCode: I now correctly append q…",
            "date_modified": "2017-04-02T07:10:00.775Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/03/31/58dea94c0f8ff246f68a41c4",
            "content_html": "<p class=\"text-style-pre\">Day 81 of #100DaysOfCode: Updated my #indieweb like feed. So many embeded animals 😻 <a href=\"https://grant.codes/likes\">https://grant.codes/likes</a></p>",
            "url": "https://grant.codes/2017/03/31/58dea94c0f8ff246f68a41c4",
            "title": "Day 81 of #100DaysOfCode: Updated my #indieweb lik…",
            "date_modified": "2017-03-31T19:09:00.291Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/03/30/58dcbfae86fa5e195003616e",
            "content_html": "<p class=\"text-style-pre\">Day 79 of #100DaysOfCode: Updated the omibear #indieweb chrome extension to use my micropub library</p>",
            "url": "https://grant.codes/2017/03/30/58dcbfae86fa5e195003616e",
            "title": "Day 79 of #100DaysOfCode: Updated the omibear #ind…",
            "date_modified": "2017-03-30T08:19:58.951Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/03/23/58d416860f86c0358d9dd09d",
            "content_html": "<p class=\"text-style-pre\">Day 75 of #100DaysOfCode: Updated my #indieweb photo gallery micropub client. It's better in every way now <a href=\"http://photopostr.tpxl.io/\">http://photopostr.tpxl.io/</a></p>",
            "url": "https://grant.codes/2017/03/23/58d416860f86c0358d9dd09d",
            "title": "Day 75 of #100DaysOfCode: Updated my #indieweb pho…",
            "date_modified": "2017-03-23T18:40:06.703Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/03/15/58c9a8cd1e60b04ed55c4e44",
            "content_html": "<p class=\"text-style-pre\">Day 71 of #100DaysOfCode: Improved the handling of photos, reposts and reply syndication on my #indieweb site</p>",
            "url": "https://grant.codes/2017/03/15/58c9a8cd1e60b04ed55c4e44",
            "title": "Day 71 of #100DaysOfCode: Improved the handling of…",
            "date_modified": "2017-03-15T20:49:17.326Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/03/11/58c48c3da12e682d685ee695",
            "content_html": "<p class=\"text-style-pre\">Day 67 of #100DaysOfCode: Updated my #indieweb micropub chatbot to use my updated micropub-helper library <a href=\"http://postrchildbot.tpxl.io/\">http://postrchildbot.tpxl.io/</a></p>",
            "url": "https://grant.codes/2017/03/11/58c48c3da12e682d685ee695",
            "title": "Day 67 of #100DaysOfCode: Updated my #indieweb mic…",
            "date_modified": "2017-03-11T23:46:05.752Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/03/11/58c343470d6bdb1dcdc71f46",
            "content_html": "<p class=\"text-style-pre\">Day 66 of #100DaysOfCode: Look at all those ticks for my #indieweb micropub helper library ✅ <a href=\"https://www.npmjs.com/package/micropub-helper\">https://www.npmjs.com/package/micropub-helper</a></p>",
            "url": "https://grant.codes/2017/03/11/58c343470d6bdb1dcdc71f46",
            "title": "Day 66 of #100DaysOfCode: Look at all those ticks …",
            "image": "https://backend.grant.codes/media/2017/03/11/923n4rnffl6slsqvvx6r.jpg",
            "date_modified": "2017-03-11T00:22:31.537Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/03/09/58c12a485a1dad401d2ccdc0",
            "content_html": "<p class=\"text-style-pre\">Day 65 of #100DaysOfCode: Updated my micropub helper. It's now passes most available tests on <a href=\"http://micropub.rocks\">micropub.rocks</a> in node mode #indieweb</p>",
            "url": "https://grant.codes/2017/03/09/58c12a485a1dad401d2ccdc0",
            "title": "Day 65 of #100DaysOfCode: Updated my micropub help…",
            "date_modified": "2017-03-09T10:11:20.774Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/03/08/58c093a5bee67f4f042ce8e0",
            "content_html": "<p class=\"text-style-pre\">Loving the new client tests on <a href=\"http://micropub.rocks\">micropub.rocks</a>! It's making testing a breeze! #indieweb</p>",
            "url": "https://grant.codes/2017/03/08/58c093a5bee67f4f042ce8e0",
            "title": "Loving the new client tests on micropub.rocks! It'…",
            "date_modified": "2017-03-08T23:28:37.347Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/03/06/58bddedebee67f4f042ce8ce",
            "content_html": "<p class=\"text-style-pre\">Day 63 of #100DaysOfCode: I made a basic #JavaScript micropub helper <a href=\"https://github.com/terminalpixel/micropub\">https://github.com/terminalpixel/micropub</a> #indieweb</p>",
            "url": "https://grant.codes/2017/03/06/58bddedebee67f4f042ce8ce",
            "title": "Day 63 of #100DaysOfCode: I made a basic #JavaScri…",
            "date_modified": "2017-03-06T22:12:46.810Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/03/05/58bc9f5bbee67f4f042ce8c6",
            "content_html": "<p class=\"text-style-pre\">Day 62 of #100DaysOfCode: Added support for config queries on my #indieweb micropub endpoint</p>",
            "url": "https://grant.codes/2017/03/05/58bc9f5bbee67f4f042ce8c6",
            "title": "Day 62 of #100DaysOfCode: Added support for config…",
            "date_modified": "2017-03-05T23:29:31.297Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/02/05/589789c526ae7f0dcfa0fb1d",
            "content_html": "<p class=\"text-style-pre\">Day 34 of #100DaysOfCode: 💥 Added emojicode conversion to my #indieweb #chatbot 🎉 So slack emoji should work better now 😀</p>",
            "url": "https://grant.codes/2017/02/05/589789c526ae7f0dcfa0fb1d",
            "title": "Day 34 of #100DaysOfCode: 💥 Added emojicode conve…",
            "date_modified": "2017-02-05T20:23:33.727Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/01/27/588b5db2f9fe4f3f59e8f1d9",
            "content_html": "<p class=\"text-style-pre\">Day 024 of #100DaysOfCode: My #indieweb #chatbot now has a little intro message to get you started <a href=\"https://postrchildbot.tpxl.io/\">https://postrchildbot.tpxl.io/</a></p>",
            "url": "https://grant.codes/2017/01/27/588b5db2f9fe4f3f59e8f1d9",
            "title": "Day 024 of #100DaysOfCode: My #indieweb #chatbot n…",
            "date_modified": "2017-01-27T14:48:18.330Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        },
        {
            "id": "https://grant.codes/2017/01/02/586a7cc61b79dd6fe2efd6d5",
            "content_html": "<p class=\"text-style-pre\">Day 001 of #100DaysOfCode: Got embeds working on my #indieweb site. See <a href=\"https://grant.codes/likes\">https://grant.codes/likes</a> for a nice example</p>",
            "url": "https://grant.codes/2017/01/02/586a7cc61b79dd6fe2efd6d5",
            "title": "Day 001 of #100DaysOfCode: Got embeds working on m…",
            "date_modified": "2017-01-02T16:16:06.630Z",
            "author": {
                "name": "Grant Richmond",
                "url": "https://grant.codes"
            }
        }
    ]
}