The Stream Blog

Designing an Activity Stream? Yeah, There’s a W3C Spec For That

Introduction

The activity stream (also known as the “news feed”) is a nearly ubiquitous feature in apps these days. The odd thing is how little information is out there for developers trying to build streams into their own applications.

There are several decent resources when it comes building activity streams – including this valuable Quora post. However, most of what is out there focuses on aspects like infrastructure setup (Redis, Cassandra, etc.) and the various publishing methods (Push versus Pull, etc). Scalability has always been the big difficulty with building a feed – so it isn’t too surprising we see the majority of material relating to that facet. At Stream, we have built a product and a company to serve as a solution to pain points like scalability.

But what about the design of an activity stream? In other words, how do we design our serialized data that makes up our stream?

Well, the good news is, groups of smart people has been figuring these questions out for several years – and there is now a W3C specification that is completely dedicated to the activity stream.

History of the Activity Streams Specification

Atom

In early 2008, Martin Atkins started to work on an HTML microformat for representing social objects. He would later team up with hashtag inventor Chris Messina, Will Norris, David Recordon to come up with a first draft of the Atom Activity Streams specification.

JSON (Yay!)

Later, when Atom waned as a serialization format, Martin again teamed up with Will Norris, Chris Messina, Monica Wilkinson, and Rob Dolin to design JSON Activity Streams in 2009. James Snell would end up doing the final rewrite – which would be released in 2011.

Here’s an awesome piece of news feed history – an episode of Social Web TV from the Activity Streams meetup on the Stanford campus back in September of 2009:

Defining An Activity

Version 1.0 lays out the basics of what makes an activity stream, starting by defining an activity. And an activity stream is just essentially a collection of these activities.

So, then, the important, billion dollar question is: What is an activity?

From the JSON Activity Streams 1.0 spec:

“In its simplest form, an activity consists of an actor, a verb, an object, and a target. It tells the story of a person performing an action on or with an object.”

The 2.0 specification (more on this later) goes on to clarify a bit:

“In the most basic sense, an “Activity” is a semantic description of an action. It is the goal of this specification to provide a JSON-based syntax that is sufficient to express metadata about activities in a rich, human-friendly but machine-processable and extensible manner.”

Simplest Example

Okay, that makes sense. So, let’s take a look at a very simple example of an activity:

“Jack went up the hill.”

In its simplest form, our serialized data could look like:


  {
  "actor": “Jack”,
  "verb": “went”,
  "object": “The Hill”
  }

Using Target

Next, let’s add target into the fold. Here’s an example:

“Jack added a photo of The Hill to Great Hill Pics photo album.”

Here is our serialized data:


  {
  "actor": “Jack”,
  "verb": “added”,
  "object": “the_hill1.jpg”,
  "target": “Great Hill Photos”
  }

Complex Example

A more complex, more real-world example might look like:


  {
   "@context": "http://www.w3.org/ns/activitystreams",
   "type": "added",
   "published": "2015-02-10T15:04:55Z",
   "actor": {
    "type": "Person",
    "id": "http://www.test.example/jack",
    "name": "Jack Hill",
    "url": "http://example.org/jack",
    "image": {
      "type": "Link",
      "href": "http://example.org/jack/profile.jpg",
      "mediaType": "image/jpeg"
    }
   },
   "object" : {
    "id": "http://www.test.example/jack/hill_photos/the_hill1.jpg",
    "type": "Photo",
    "label": "Great Photo of The Hill"
   },
   "target" : {
    "id": "http://example.org/jack/albums/great_hill_pics",
    "type": "OrderedCollection",
    "name": "Great Hill Pics"
   }
  }

Audience Targeting

One extension to the JSON Activity Streams 1.0 is Audience Targeting.  Audience Targeting defines a format that allows for explicitly targeting specific audiences. One use case of this is to notify users. Perhaps they are “following” a user, have set up specific alerts, or are mentioned in an activity.

For example, at Stream we use the “to” property. One way to think of “to” is as “cc” is to email. “To” allows us to support @mentions and notify users, two vital parts of modern activity streams.

Note: Activity Streams 2 (AS2) also has “Mention” type as part of Object class.

Activity Targeting Example

Here’s a simple example of what might be expressed using “to”:

“Jack added a photo of The Hill to Great Hill Photos – with @Jill.”


  {
  "actor": “user:Jack”,
  "verb": “added”,
  "object": “the_hill.jpg”,
  "target": “photo_albums:1”,
  "to": [“notifications:Jill”]
  }

Check out more on targeting in the Stream documentation.

What’s New in 2.0

Now that the W3C Social Web Working Group has taken over the specification – they have introduced some changes for 2.0 – which is now in draft.

Activity Streams 2 (AS2) expands upon the original JSON Activity Streams spec – for example, adding a whole standard vocabulary, while maintaining the the core idea of an activity from the original spec.

Here’s a quick breakdown of some of what’s new with Activity Streams 2 (AS2):

– New MIME Type
– JSON-LD Compatible
– Different Property Names
– Built-In Vocabulary
– Multi-Language Support

Take a look at the Core and the Vocabulary documents. There’s even a validator you can check out over at https://as2.rocks.

Conclusion

Building an activity stream can be difficult – with a lot of thought having to go into infrastructure.

Luckily, one thing we as developers do have is an elegantly designed specification for serialization that has been getting some serious depth thanks to the good people at the W3C.

At Stream, we have incorporated the basic specification design into our product – and urge you to give it a try for free.


Also published on Medium.