Activity Streams 2.0
Introduction
Storyfeed can serve each activity as a W3C Activity Streams 2.0 JSON-LD document, using AS2 names for all seven roles.
The Activity Streams document is separate from the normal feed payload.
Serving Activity Documents
Enabling the Route
Enable the read-only route in config/storyfeed.php:
'routes' => [
'enabled' => true,
'prefix' => 'storyfeed',
'middleware' => [], // Add your application's access middleware.
],Route Middleware and Identifiers
| Route | Returns |
|---|---|
GET /{prefix}/activities/{uid} | one Activity document, identified by its ULID |
Add authentication or throttling to middleware.
WARNING
The prefix is part of every activity's ID. Choose it before sharing documents, since changing it changes all their IDs.
Serving Collections
Use CollectionSerializer::collection() to convert cursor-paginated activities into an OrderedCollection or an OrderedCollectionPage with a next link. Your application selects the activities and serves the route:
use Storyfeed\Models\Activity;
use Storyfeed\Serialization\CollectionSerializer;
$page = Activity::query()
->published()
->involving($project) // without a scope, this is every activity
->orderBy('published_at', 'desc')
->orderBy('id', 'desc')
->cursorPaginate(20);
$document = app(CollectionSerializer::class)
->collection($page, route('projects.activity', $project), $request->query('cursor'));Pass the collection's absolute URL as the second argument and the incoming cursor as the third. Use null for the first page.
Activity Streams Fields
Origin, Result and Instrument
| Role | AS2 Meaning |
|---|---|
origin | the source; Move, Remove and Delete can identify the source container |
result | an entity produced by the activity |
instrument | the means used, such as a service |
Mapping Activity Types
Verb Mappings
Map verbs to Activity Streams types in your verb enum:
<?php
namespace App\Enums;
use Storyfeed\ActivityStreams\ActivityType;
use Storyfeed\Concerns\AsFeedVerb;
use Storyfeed\Contracts\FeedVerb;
enum OrderActivity: string implements FeedVerb
{
use AsFeedVerb;
case Placed = 'place';
case Confirmed = 'confirm';
case Ready = 'ready';
public function activityType(): ActivityType|string|null
{
return match ($this) {
self::Placed => ActivityType::Create,
self::Confirmed => ActivityType::Accept,
default => null,
};
}
}- The mapping sets the document's
typeand affects default deletion rules.Delete,Remove,Undo, andRejecthave no constitutive roles by default; other types use the object. Explicit rules can override this. See Deleted Models for how missing roles make an activity redundant. - Without an app or built-in AS2 mapping, the type is
Activityandsf:verbholds the verb. The document's JSON-LD context,https://ns.storyfeed.dev, definessf:verb. Intransitive types also fall back toActivitywhen an object is present. - Composite objects serialize as
OrderedCollection. - Entity media serialize as AS2
Linkobjects undericon,image, andpreview. During serialization,$context->feed()infeedMedia()returnsnull.
Type Overrides
On a Story class, import Storyfeed\ActivityStreams\ActivityType and set $type:
public ActivityType|string|null $type = ActivityType::Create;On a model, implement Storyfeed\Contracts\HasActivityStreamsType.
Reading Activity Documents
Storyfeed\Serialization\Reader::activity() parses a Storyfeed document, preserving its uid, verb, type, roles, and published_at to the whole second. Other document properties are not returned.