IndieWebCamp is a 2-day creator camp focused on growing the independent web

How to set up your realtime feed

Setting up an Atom feed for realtime publishing.

The goal of this post is to collect information on how to prepare your website and Atom feed to publish realtime content.

You can subscribe to your feed in http://identi.ca, or using a PubSubHubbub client. There is a great PuSHBot for testing which will send a message over Jabber when a feed is updated.

Set up the HTML Page

First, you need to set up your HTML page to reference the Atom file. When subscribing from identi.ca, you'll be entering someone's web page address, not an Atom feed directly.

The main tag you need to add to the <head> section is this:

<link rel="alternate" type="application/atom+xml" href="/updates.atom" />

Atom Feed

Live examples:

Header

You will need at least these elements as the basis of the Atom feed.

<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
  <title>Tantek Çelik</title>
  <link href="http://tantek.com/" rel="alternate" title="Tantek Çelik" type="text/html"/>
  <link href="http://tantek.com/updates.atom" rel="self"/>
  <link rel="hub" href="http://pubsubhubbub.appspot.com/"/>
  <id>http://tantek.com/updates.atom</id>
  <author>
    <name>Tantek</name>
    <uri>http://tantek.com/</uri>
  </author>
  <updated>2012-08-17T10:48:00-07:00</updated>

For the author tag, you must include a name and URI, otherwise identi.ca won't recognize it as a valid feed.

By linking to the pubsubhubbub.appspot.com hub, you'll be taking advantage of the free hub service Google provides. Anyone will be able to subscribe to your realtime content from that hub. Anecdotal evidence has also shown that Google will actually index content posted there as well, so you can end up having real-time results in Google by using their hub.

Entries

Entry elements must have at least the following tags: title, content, published, updated, link, and id. Here are two examples you can reference.

  <entry>
    <updated>2012-08-17T10:48:00-07:00</updated>
    <published>2012-08-17T10:48:00-07:00</published>
    <link href="http://tantek.com/2012/230/t1/tweetcc-cc-license-tweets-quote-embed-indieweb" rel="alternate" title=" use tweetcc.com to CC license tweets so others may quote/embed yours independent of Twitter's TOS. #indieweb " type="text/html"/>
    <id>http://tantek.com/2012/230/t1/tweetcc-cc-license-tweets-quote-embed-indieweb</id>
    <title type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">
use tweetcc.com to CC license tweets so others may quote/embed yours independent of Twitter's TOS. #indieweb
</div>
    </title>
    <content type="xhtml" xml:base="http://tantek.com/2012/" xml:space="preserve">
      <div xmlns="http://www.w3.org/1999/xhtml">
use <a class="auto-link" href="http://tweetcc.com">tweetcc.com</a> to CC license tweets so others may quote/embed yours independent of Twitter's TOS. #indieweb
</div>
    </content>
    <object-type xmlns="http://activitystrea.ms/spec/1.0/">http://activitystrea.ms/schema/1.0/note</object-type>
  </entry>
  <entry>
    <title>Children, though they are good tax deductions, can be an expensive hobby.</title>
    <content type="xhtml" xml:base="http://aaronparecki.com/2012/222/note/3/" xml:space="preserve"><div xmlns="http://www.w3.org/1999/xhtml"> Children, though they are good tax deductions, can be an expensive hobby. </div></content>
    <published>2012-08-09T14:04:11-07:00</published>
    <updated>2012-08-09T14:04:11-07:00</updated>
    <link href="http://aaronparecki.com/2012/222/note/3" rel="alternate" type="text/html" title="Children, though they are good tax deductions, can be an expensive hobby." />
    <id>http://aaronparecki.com/2012/222/note/3</id>
    <object-type xmlns="http://activitystrea.ms/spec/1.0/">http://activitystrea.ms/schema/1.0/note</object-type>
  </entry>

As shown in these two examples, the <title> tag can be either plain text, or can have a type="xhtml" attribute.


Statusnet/identi.ca Integration Notes

Statusnet/identi.ca (referred to as statusnet in this doc for brevity) is probably the most mature and most widely deployed OStatus implementation. If you're implementing any part of ostatus, you should aim for integration with statusnet.

statusnet won't understand a <content> element of this format:

<content type="html"><![CDATA[ <p>Example Content</p> ]]></content>

It must use xhtml, as such:

<content type="xhtml" xml:base="http://aaronparecki.com/2012/222/note/3/" xml:space="preserve">
  <div xmlns="http://www.w3.org/1999/xhtml"><p>Example Content</p></div>
</content>

The xhtml must be well-formed in order for statusnet and many feed readers to be able to successfully consume it. statusnet seems to be rather more picky compared to most feed readers, and won't give you useful error messages. If in doubt, validate!

Another thing to watch out for is elements from the activitystreams spec, e.g. activity:object-type or activity:verb. The values of these elements must be complete, well formed URLs and not just the bit on the end (e.g. 'post', 'edit', 'article', 'note' etc)!

Follow the examples above and examples in the wild that are known to be supported by statusnet instead of the examples in the activitystreams schema, which will not work with statusnet.

Checking Your Work

There are a few ways to test if this worked.

First you can use a feed validator to check for major errors such as XML errors or missing elements. feedvalidator.org does a pretty good job.

Assuming you don't get many errors there, you can try subscribing to the feed in a traditional RSS reader, such as Vienna.

Try using the PuSHBot service to send Jabber messages to you when your feed is updated. You can use this easily if you have a Jabber account, and don't forget that Google Chat accounts are Jabber.

  1. Add push-bot@appspot.com to your contact list.
  2. Send it a subscription message by using the /subscribe command: /subscribe http://example.com/updates.atom
  3. If all goes well, you should see a confirmation message like Subscribed to http://example.com/updates.atom

Then you just need to send the publish message to the appspot hub. You can do this from cURL on the command line like this:

$ curl -i -d hub.mode=publish -d hub.url=http://example.com/updates.atom https://pubsubhubbub.appspot.com/publish

If it worked, you will get a 204 No Content response.