class: center, middle, inverse # indie what? ??? I assume that most people here use social networks; for me it would be Twitter, Flickr, GitHub, Facebook, and maybe Last.fm. Although I don't "use" them all to the same degree, I have 4 friends on Facebook. But I have profiles and stuff on all of them, and follow friends and internet people on most of them. On the other hand I own a domain, and have a personal site with a few random apps I've made. But this all exists on its own in the world. I don't really interact with any of it, they mostly just display stuff. And anyone apart from me can definitely only look and read. For a while I've been wanting to change this though so that my own stuff is more primary, and the other social networks just exist for the connections or the Android apps. Mainly for browsing, and publishing happens on my site. But I don't want to go out and come up with my own way of doing things, because that would be pointless: it would leave me in the same position as before. A single dot on the internet not connected to anything or one else. --- class: inverse > The IndieWeb is a people-focused alternative to the "corporate web". ??? So I want to talk about the IndieWeb. Which is (I don't really know how to define), a group of people who are trying to make it so the web isn't something San Fransisco does to us? Instead it should be something we all can be involved in and own, at least a part of. It is described as "the people-focused alternative to the corporate web", which is a good aspiration. Especially since over the last few years we have seen a turn from the "nice" Web 2.0 companies, you know things like Flickr were nice and had nice people on them, they even had a business model -- people paid to have accounts! (I mean, I still do, but) -- to now with the current slightly aggressively social networks, full of trolls and misinformation and non-chronological timelines. And when you look for choice it feels a lot like Coke and Pepsi, sure there is more than Facebook and Twitter, but they each own most of the others. And they have both become these, I guess, accidentally bad corporations, in a way. Maybe they just had the bad luck not to do something genuinely useful _first_, like Google did, before becoming the reluctant _slash_ inept police of the world. These are some of the principles and ideas behind it all. -- - _You_ own _your_ content ??? The core idea is that we own our own words and pictures and whatever. We shouldn't be putting these out in places where random companies can by Terms of Service or whatever claim ownership. And you shouldn't lose all of the things you've written or made just because someone can't make a business model based on crappy advertising work. -- - POSSE ??? When you post content it is still useful to have the audiences and groups that exist on sites like Twitter, Facebook, YouTube, etc. So how can we keep that while keeping our content. This, POSSE, stands for "Post On (your) Site, Syndicate Elsewhere". So the idea is just because you post content once somewhere, we can have computers do menial work like post it everywhere else. We don't need to force _everyone_ to abandon the old platforms, but we can give that choice. -- - Backfeeds ??? And the other piece to that is that if someone replies or likes that syndicated content we should be able to bring those interactions back to the "home" site. So anyway, I'm going to go through a few of the IndieWeb standards and how show easy it is to get integrated and started with this stuff. There are a bunch of little demos I want to show, so :pray:... --- class: middle, offset-title ## authentication ??? The first step when wanting to build something people can interact with is to figure out who that person is. And to make sure they are the same person as they were the last time they came along. There are a bunch of ways, too many, to do this. Off the top of my head: -- - Create your own username/password system ??? - Roll your own username/password. Great, now you have to make sure this stores things securely, has a 'lost password' button, and the user has to put another entry in their password store. Not that good. -- - Login with Twitter (or GitHub or ...) ??? - Delegate to Twitter or GitHub or whatever. Great, now you require that person to have an account with whatever provider you choose. -- - OpenID ??? - OpenID. Umm, it's pretty dead looking. -- - Login with Twitter _or_ GitHub _or_ ... ??? - Delegate to multiple providers, so Twitter and GitHub and whatever. Great, now when someone logs in differently, because maybe they forget which of the many options used before, they get a new account. -- - Something else... ??? - So obviously I'm going to talk about the "good" something else way. --- class: center, middle, inverse ## RelMeAuth ??? RelMeAuth basically takes the idea: instead of getting people to log in with an email address, why not log in with their website. So straight away the downside of this approach is that people need to have a website, but ignoring that... How can we prove that someone owns a website, and authenticate without needing yet another password. --- class: middle, offset-title ## rel=me On my website ```html
Twitter
``` On my Twitter ```html
hawx.me
``` ??? Step 1. Prove who you are. If I have access to a website, then I can add links to it. If I can change both sites to point at each other then I can prove they are linked. This is the basis of RelMeAuth. On your homepage add links with the special rel=me, or `link` tags if you don't want it displayed on the page, then on the page it points at do the same but in the opposite direction. Quite simple. Also note, because Twitter the link actually goes through their URL shortener, but eventually we get redirected to my site. --- class: middle ```html
Web Address:
Sign In
``` ??? Now we can find related social accounts for someone, we can delegate auth to a provider they choose, and when they finally get redirected back to our site we can match up whatever provider they chose to a single URL, their homepage! All it takes is a simple HTML form to get started on the log in process. --- class: middle ```js app.get('/redirect', async (req, res) => { const { code, state } = req.query; const { me } = await request({ method: 'POST', uri: 'https://indielogin.com/auth', formData: { code, redirect_uri, client_id }, json: true, }) req.session.me = me res.redirect('/') }) ``` ??? Hand-wave this is express. Then all we need is to capture the callback, and issue some kind of session to the user. If you've ever implemented an OAuth login flow this request-code-verify dance will feel very familiar. That's because this whole thing is OAuth! Its OAuth-ception because we've got this OAuth flow which then delegates to another provider's OAuth flow. --- class: middle, center ## [insert live demo] ??? ``` node example_signin.js ``` So with this I can enter my website and login to a page. Cool. --- class: fullbleed ![](profiles.png) ??? So that demo was good but it isn't _that_ much use to have a person as a URL. Like saying "Hello, http://blah" everywhere is not the friendliest experience. The terrible way to get the usual profile info for the person would be to have a form like the few I've shown here. And if you look closely you might notice some of the info doesn't actually match between them, but that is another problem. Luckily there is a better way of getting this information. --- class: middle, offset-title ## microformats! ```html
Joshua
Hawxwell
``` ??? We can use the website we have just found for the person. All it requires is some well known markup. Microformats have been around for a while now, and are very easy to use. The http://microformats.org/wiki/h-card wiki entries will tell you everything that is possible. Obviously we don't _know_ if things will be marked up that we might want, for example we might want to show a profile picture, so would be looking for u-photo, but it isn't necessarily going to be there. So we need to be smart and have fallback options. The HTML view is what you would publish, but is annoying to work with, luckily there is a specified way of parsing all of this into JSON. --- class: middle ```json { "items": [ { "type": [ "h-card" ], "properties": { "name": [ "Joshua Hawxwell" ], "given-name": [ "Joshua" ], "family-name": [ "Hawxwell" ] } } ] } ``` ??? Now it is really easy to get the values we need. I used https://php.microformats.io/ to parse the previous snippet and got this. So here is another version of login which is a bit friendlier. --- class: middle, center ### [insert another demo] ??? ``` node example_microformats.js ``` --- class: middle ```js const mf = require('microformat-node') // previous authentication stuff... const html = await request(me) mf.get({ html, baseUrl: me }, (err, data) => { const hcard = data.items.find(x => x.type.includes('h-card')) if (hcard && hcard.properties.name.length > 0) { req.session.name = hcard.properties.name[0] } }) ``` ??? The change I made to my app was to pull in the 'microformat-node' package, and parse the value for 'me' we get from the authentication. --- class: middle, offset-title ## comments / replies ??? OK, so it is easy to get people logged in and figure out basic things about them, without duplicating work. But to build a "social" site we need some more things. Ideally some kind of comment system. But we don't want to go and build it ourselves, because we'd like the users to keep control of their data. If we stop running our site it'd be pretty rubbish if everyone's content was lost for ever. So we want a way of allowing people to write things on their own websites, but then tell us about it so we can also display something. The options I guess are: -- - Build a comment system ??? - Build my own comment system, but as I said this has the problem where I kind of end up owning other people's content. -- - Disqus ??? - Now this is even worse since a 3rd party owns the content now. -- - Something else... ??? - Ah, as always... --- class: middle, center, inverse ## webmentions ??? Webmentions are like the simplest way you could possibly imagine this working. --- class: middle ```js await request({ method: 'post', url: 'https://their.host/webmention-endpoint', form: { source: 'https://your.host/your-post', target: 'https://their.host/their-post', }, }) // HTTP/1.1 202 Accepted // // http://their.host/webmentions/1234 ``` ??? (taken from https://github.com/converspace/webmention/blob/master/README.md) No seriously, you send a POST request with the source (i.e. your post) and a target (i.e. the thing you mentioned). Now obviously it makes sense upon recieving one of these requests to verify that the source actually contains a reference to the target, it could just be spam. But even that amount of work is minimal. --- class: middle, center ### [worst demo so far] ??? ``` node example_webmention_bad.js ``` Here is a kind of pointless demo showing a simple app which allows me to send a webmention for a post. I can create a reply on my site, and then view it on the other site. But instead of the "good webpage" showing just my comment, it shows the whole page! We need a way to say what is content. --- class: middle, offset-title ## microformats, again! ```html
In reply to:
some post
by
Josh
on
13 Jan 2019
Blah blah blah
``` ??? If I mark up my reply with a `h-entry`, similar to how we had `h-card` before, then we can just grab the `e-content` bit. Because that is the actual reply, everything else will be metadata. So our comment display on the original post can be nice and clean, and doesn't have to worry about duplicating information. Actually I've been even kinder since I've put a `h-card` in this post too, which links to my homepage, so if we want more info for who commented then that can be looked at too. For the psuedo-twitter experience we need a couple more things. --- class: middle, offset-title likes ```html
Liked:
some post
``` reposts ```html
some post
[The original content]
``` ??? So I guess it looks like I just added classes and then hand-waved to say this will work. But it kind of does. All I have to do is send a webmention and then the consumer of that (i.e. the person who's post I am liking/reposting) can determine the action by checking for a "like-of" or "repost-of" property. If that URL matches the URL of their post then they can display my like or repost however they want. --- class: middle, offset-title ## webmention.io ??? Now since a lot of people, me included, have static blogs this probably all sounds like something we wouldn't bother with. I don't really want to convert it to run on a server or Wordpress or something. Luckily there exist a few hosted webmention endpoints we can use. -- on your blog ```html
``` ??? You can sign up at webmention.io (with your domain naturally), and then copy the `
` it gives you, which will look like this, on to your posts template. -- to get the mentions ```js fetch("https://webmention.io/api/mentions.jf2?target=THE_PAGE") ``` ??? Then you can grab any mentions using some JavaScript and render them on your static webpage. --- class: middle, center ### [mention this demo] ??? So this is an [example of a page](talk-about-me.html) which has the `
` element in the `` that I got from webmention.io, and some JS to display any mentions. [Here is another page](a-mention.html) that mentions the original. I'm now going to send a POST with cURL to send the webmention. And hopefully it shows up in the list. ``` curl -X POST "https://webmention.io/hawx.me/webmention" \ -d "source=https://hawx.me/talks/indie-what/a-mention.html?t=2" \ -d "target=https://hawx.me/talks/indie-what/talk-about-me.html" ``` --- class: inverse, middle, center ## brid.gy ??? Brid.gy is a good but confusing service that links your site to other "silos". --- class: fullbleed ![](bridgy.png) ??? The idea is that once you have a webmention endpoint up and running on your own site, then you can use bridgy to send webmentions whenever someone tweets a URL of that page. Or retweets it, or replies to it. This is the backfeed I mentioned at the beginning. It takes the interactions on other sites and brings it back to your own. --- class: center, middle, bigger can somebody send a tweet to `@hawx` thanks 🙏 ??? Ok, if somebody could do that. Then I can show you how brid.gy works. This is the page I used to show webmentions before. So I can now go in to brid.gy and signin with Twitter. Then force it to poll. Hopefully it doesn't take too long to pull in the tweet(s) and send them off. Because I have rel=me setup on these pages to point to https://hawx.me/, bridgy will look for a webmention endpoint on that page. I've added one which is set to webmention.io. So that collects the webmention and verifies it, and then I can grab it from the API and show it in the list. All kind of simple but not super straight forward to get your head around. It starts to make sense when you think that the rel=me link means the two concepts are the same. So a tweet to @hawx is equivelant to sending a message to https://hawx.me/. --- class: middle, offset-title ## next... ??? I've kind of got to the end of what I wrote down to talk about. That felt like a lot to go through, and with sign-in, webmentions and bridgy set-up that is a lot of work done. But after this there is still more that I didn't cover to look at: -- - micropub ??? This is quite a large thing in and of itself. Even though the actual spec is fairly simple and small. It is a spec for a protocol for making posts on your site. This would then allow you to post to your site using an interface or app provided by someone else, simply by logging in with your homepage. -- - webactions ??? If you have a post on your site maybe you want to provide a way for people to like it on the page, like you'd get with twitter. There is a web component that you can drop onto your page and use to markup relevant buttons. And also wrap existing silo actions so that people who don't have their own site can still interact with it. -- - websub ??? This is another simple spec, once called PubSubHubbub, for subscribing to updates and notifying others of changes. Take a look if you want. There exist things that can read feeds and get updates using this. --- class: middle, center ## thanks for listening any questions? *** https://hawx.me/talks/indie-what