Marty McGuire

Posts Tagged indieweb

2018
Mon Mar 12

Micropub for a static Neocities website

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.

This roughly works like so:

  • OwnYourGram periodically checks our Instagram for new images
  • For each new post, it makes a Micropub request to a service that I wrote for this purpose.
  • 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.

Authorization with IndieAuth

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 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.

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.

Some 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!

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!

If you're interested, you can find the source for this endpoint here: https://glitch.com/edit/#!/befitting-price

Micropub Endpoint

Finally, 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.

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:

<!-- NEW POSTS BELOW -->

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.

You can find the source for the Micropub endpoint here: https://glitch.com/edit/#!/prism-dirt

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!

Making ghostparty.today "IndieWeb-Readable"

The 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:

  • A machine-readable "identity" h-card that says "who" this website is, including a logo, the site name, canonical URL.
  • A machine-readable feed that contains new posts, allowing people to follow our updates in their favorite indie reader.
  • 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.

Microformats2 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:

{
  "data":{
    "type":"card",
    "name":"GHOST PARTY",
    "url":"https://ghostparty.today/",
    "photo":"https://ghostparty.neocities.org/ghost-party-logo.png"
  },
  "url":"https://ghostparty.today/",
  "code":200
}

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 fragment of the page! Here's how X-Ray sees https://ghostparty.today/#feed

{
  "data":{
    "type":"feed",
    "items":[
      {
        "type":"entry",
        "published":"2018-03-07T16:44:16+00:00",
        "url":"https://ghostparty.today/#2018-03-07-181020",
        "photo":["https://ghostparty.today/uploads/2018-03-07/181020-ig0LN1JG.jpg"],
        "content":{"text":"snow day selfie #snowday #snowfie #ghoststories"} 
      },
      {
        "type":"entry",
        ...
      },
      ...
    ],
    "url":"https://ghostparty.today/#feed",
    "code":200,
    "info":{"found_fragment":true}
  }
}

Data! Nice! So if we want to follow ghostparty.today with an indie reader, we use https://ghostparty.today/#feed as the URL.

Looking 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.

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 also contains the microformats h-entry markup. To do this, I made this Handlebars template:

{% raw %}<div class="h-entry" id="{{ mp-slug }}">
  <a class="u-author" href="/"></a>
  <a class="u-url" href="#{{ mp-slug }}">{{#if name}}<h2 class="p-name">{{ name }}</h2>{{/if}}</a>
  <time class="dt-published" datetime="{{ published }}"></time>
  {{#if video}}
    {{#each video}}
      <video controls loop class="u-video" src="{{ . }}"></video>
    {{/each}}
  {{ else }}
    {{#each photo}}
      <img class="u-photo" src="{{ . }}" />
    {{/each}}
    {{#each audio}}
      <audio class="u-audio" src="{{ . }}"></audio>
    {{/each}}
  {{/if}}
  <div class="e-content">{{ content }}</div>
</div>
<img src="ghosts.gif" />
{% endraw %}

Not so bad!

Resources

Here's a collection of some of the other libraries and docs I used to pull this thing together:

  • Neocities API
    • Includes details on using cURL to get an authorization token.
    • There’s 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.
  • Node Request HTTP Client
    • Verifies the authorization token by querying the token endpoint (I used tokens.indieauth.com for this)
    • Handles uploading files like images to Neocities via their API.
    • Used to fetch index.html from the site and later to writes it back via Neocities API.
  • ES6 Promises
    • There's a lot of asynchronous code that waits for network requests. This code is very Promise-heavy to handle that.
  • Handlebars templating
    • Made it easy to take the Micropub properties for a new post and rendered them into HTML content with microformats.
  • Express 4 API
    • Glitch uses Node and Express 4 by default, and I got to learn lots about it!
  • Multer Express Middleware
    • For handling uploaded files
  • Body Parser Express Middleware
    • For handling regular Micropub properties
  • Validator.js
    • Half-using this for the authorization endpoint, need to clean it up and finish it up!
  • OwnYourGram API docs
    • Shows what properties are sent over Micropub, so you know exactly the kind of data your Micropub endpoint will need to handle.

A Ghost (Party) is Haunting the Silo'd Web

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!


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:

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. — @zeldman, 9:53 AM - 28 Feb 2018

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?

The 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’s a whole lot of great stuff on the IndieWeb website, so go spend a couple of days reading it. But I’m not here to talk about all those good things today. I’m here to talk about how I used them to do a dumb hack.

ghostparty.today is a website for Ghost Party – an improv project that has a ... certain aesthetic. Specifically the website was pitched as “exactly like the Heaven’s Gate website” but we compromised on “extreme Geocities”.

Ugly large text says 'Welcome to GHOST PARTY'
We 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).

And Instagram is fine as a marketing platform! Lots of people look at it and like the pictures. But what about our website? Our aesthetic?

Micropub 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.

I used Glitch, an amazing community and JavaScript-server-app hosting service, to make a simple micropub service for ghostparty.today.

Screenshot of code in the Glitch UI

It accepts posts via micropub, including file uploads, and uses the Neocities API (hey, it’s not the 90s! Neocities has an API!) to upload the files to our website. Then, it fetches our site’s 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!

Now 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.

Super simplified Instagram photo on Ghost Party website
Aesthetic

We 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.

And to show how it works, here’s a micropub client call Quill that works for any micropub-enabled site. Let’s make a quick post, now!

Posting interface with 'Hello from New Lab' typed into note field
Quill's note interface

Once we hit the "Post" button and refresh the homepage, we can see the new post on the site!

'Hello from New Lab' text with ghost separator image
Aesthetic

This 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!

Sat Mar 10

This Week in the IndieWeb Audio Edition • March 3rd - 9th, 2018

Show/Hide Transcript

Audio edition for This Week in the IndieWeb for March 3rd - 9th, 2018.

You can find all of my audio editions and subscribe with your favorite podcast app here: martymcgui.re/podcasts/indieweb/.

Music from Aaron Parecki’s 100DaysOfMusic project: Day 85 - Suit, Day 48 - Glitch, Day 49 - Floating, Day 9, and Day 11

Thanks to everyone in the IndieWeb chat for their feedback and suggestions. Please drop me a note if there are any changes you’d like to see for this audio edition!

Sat Mar 3

This Week in the IndieWeb Audio Edition • February 24th - March 2nd, 2018

Show/Hide Transcript

Audio edition for This Week in the IndieWeb for February 24th - March 2nd, 2018.

You can find all of my audio editions and subscribe with your favorite podcast app here: martymcgui.re/podcasts/indieweb/.

Music from Aaron Parecki’s 100DaysOfMusic project: Day 85 - Suit, Day 48 - Glitch, Day 49 - Floating, Day 9, and Day 11

Thanks to everyone in the IndieWeb chat for their feedback and suggestions. Please drop me a note if there are any changes you’d like to see for this audio edition!

Mon Feb 26

This Week in the IndieWeb Audio Edition • February 17th - 23rd, 2018

Show/Hide Transcript

Audio edition for This Week in the IndieWeb for February 17th - 23rd, 2018.

You can find all of my audio editions and subscribe with your favorite podcast app here: martymcgui.re/podcasts/indieweb/.

Music from Aaron Parecki’s 100DaysOfMusic project: Day 85 - Suit, Day 48 - Glitch, Day 49 - Floating, Day 9, and Day 11

Thanks to everyone in the IndieWeb chat for their feedback and suggestions. Please drop me a note if there are any changes you’d like to see for this audio edition!

Tue Feb 20

🗓️ Homebrew Website Club Baltimore

📆 Add to Calendar: iCal | Google Calendar

Reminder: We are now meeting on Tuesdays instead of the usual Wednesdays. Be sure to double-check your calendars!

Join us for an evening of quiet writing, IndieWeb demos, and discussions!

  • Create or update your personal web site!
  • Finish that blog post you’ve been writing, edit the wiki!
  • Demos of recent IndieWeb breakthroughs, share what you’ve gotten working!
  • Join a community with like-minded interests. Bring friends that want a personal site!

Any questions? Join the #indieweb chat!

Optional quiet writing hour starts at 6:30pm. Meetup begins at 7:30pm.

More information: https://indieweb.org/events/2018-02-20-homebrew-website-club

Facebook event: https://www.facebook.com/events/178990332710536/

Sat Feb 17

This Week in the IndieWeb Audio Edition • February 10th - 16th, 2018

Show/Hide Transcript

Audio edition for This Week in the IndieWeb for February 10th - 16th, 2018.

You can find all of my audio editions and subscribe with your favorite podcast app here: martymcgui.re/podcasts/indieweb/.

Music from Aaron Parecki’s 100DaysOfMusic project: Day 85 - Suit, Day 48 - Glitch, Day 49 - Floating, Day 9, and Day 11

Thanks to everyone in the IndieWeb chat for their feedback and suggestions. Please drop me a note if there are any changes you’d like to see for this audio edition!

Mon Feb 12

This Week in the IndieWeb Audio Edition • February 3rd - 9th, 2018

Show/Hide Transcript

Audio edition for This Week in the IndieWeb for February 3rd - 9th, 2018.

You can find all of my audio editions and subscribe with your favorite podcast app here: martymcgui.re/podcasts/indieweb/.

Music from Aaron Parecki’s 100DaysOfMusic project: Day 85 - Suit, Day 48 - Glitch, Day 49 - Floating, Day 9, and Day 11

Thanks to everyone in the IndieWeb chat for their feedback and suggestions. Please drop me a note if there are any changes you’d like to see for this audio edition!

Tue Feb 6

HWC Baltimore 2018-02-06 Wrap-Up

Baltimore's first Homebrew Website Club of February met at the Digital Harbor Foundation Tech Center on February 6th.

Here are some notes from the "broadcast" portion of the meetup:

jonathanprozzi.net – Productive 2 weeks! Has a personal notes site running on Hugo on a subdomain after some adventures with git publishing hooks and a bug with themes that was causing it to render only as XML. Set up a separate site with Hugo and Reveal.JS and might be interested in that for IndieWeb-related learning activities going forward. Has been tracking everything he is writing, taking notes in his personal notes site as he goes so he can either clean them up for real posts, or just publish the notes. Worked tonight on more activity content on his personal notes site. Troubleshooting microformats on his main site WP theme. Also interested in GatsbyJS plus a WordPress backend... maybe? Also working with Gulp to make a build tool for P5.js sketches.

dariusmccoy.com – Tonight moved his domain from WordPress.com to Hover. Waiting on that to finish so he can set up new hosting and move his site in general off of WordPress.com onto a WordPress.org site which has more flexibility. Thinking about the direction of his site - resume / portfolio, or blogging, or posting his photography. Could blog personal projects, maybe sports blogging but worried about trolls.

derekfields.is – Set up his GitHub pages site to serve from his custom domain. Also put up a post about serving A-Frame virtual worlds from an ESP8266 microcontroller on Medium. Working on a PESOS copy of his post back to his site. Wants to work on a couple more posts for next time.

bouhmad.com – Working on bringing his site back up. Something went wrong on the virtual server running it and he is reinstalling and reconfiguring things. Has a blog post ready to go once the site is back up. (He got it back up before the end of HWC!)

martymcgui.re – Been working on IndieWeb-ifying some project websites, most recently ghostparty.today. It's a single HTML page hosted on Neocities that his improv partner created at IndieWebCamp Baltimore. It's an experiment in nesting microformats and permalinks, making use of links with anchors (example event, example RSVP). Also added mf2 markup to the site for his D&D livestreaming show (example, example reply) so he could reshare things on his site. Is excited about making a micropub server for the Neocities site as a goof, probably running on Glitch. Something like "IndieWeb like it's 1999".

Other things: 

  • The Falcon Heavy test launch happened today and wow! We could not find a reference for the projected final orbit of the payload (a Tesla with a mannequin wearing a SpaceX space suit)
    • The livestream video was interesting. It offered multiple camera views, switchable with a "Switch Camera" button in the YouTube UI. The main view was the public facing talking-head discussion, telemetry displays, etc. The other was a static camera with audio direct from mission control.
  • Transferring domains from WordPress.com is interesting. Apparently the registrar is listed as wildwestdomains.com?
  • Managing DigitalOcean droplets is hard when you lose your SSH private keys.
  • Glitch as a fun way to sketch in code. Neocities has an API.
  • Really clever onboarding process on Glitch. Log in with your GitHub and it shows a welcome page with "Start New Project" and "Resume Coding" buttons. Even if you have never used Glitch before, clicking "Resume Coding" will take you to a new Hello World project. Nice!
  • DigitalOcean recently(?) updated their pricing so that lower tiers are much better! You have to walk through a process to stop each droplet, resize it, and start it back up.
  • The Brackets editor has a Confetti plugin and it is very eye-catching.
  • .meme is a pending TLD??? Also talked .bot premiums on shorter domain names.
  • GitHub Security Alerts now send out weekly emails. Maybe only for some accounts or types of vulnerability, but Marty has been receiving them about some old projects.
  • JAMstack, the attractive bits about "reusable APIs" the dangers of those same APIs belonging to third-parties out of your control.
Left-to-right: jonathanprozzi.net, dariusmccoy.com, bouhmad.com, derekfields.is, martymcgui.re

Thanks to everybody who came out! We hope to see you all again at our next meeting on February 20th, which is a Tuesday!

🗓️ Homebrew Website Club

📆 Add to Calendar: iCal | Google Calendar

Reminder: We are now meeting on Tuesdays instead of the usual Wednesdays. Be sure to double-check your calendars!

Join us for an evening of quiet writing, IndieWeb demos, and discussions!

  • Create or update your personal web site!
  • Finish that blog post you’ve been writing, edit the wiki!
  • Demos of recent IndieWeb breakthroughs, share what you’ve gotten working!
  • Join a community with like-minded interests. Bring friends that want a personal site!

Any questions? Join the #indieweb chat!

Optional quiet writing hour starts at 6:30pm. Meetup begins at 7:30pm.

Have you got a domain name, but aren’t sure where to go next? We’ll be running a short activity from 6:30pm-7:30pm to get started with website hosting!

More information: https://indieweb.org/events/2018-02-06-homebrew-website-club

Facebook event: https://www.facebook.com/events/1560371894031190/