Pre-1.0. Not intended for public use yet. The API is subject to undocumented change, and these pages may already be wrong about it.

Skip to content

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:

config/storyfeed.php
php
'routes' => [
    'enabled' => true,
    'prefix' => 'storyfeed',
    'middleware' => [], // Add your application's access middleware.
],

Route Middleware and Identifiers ​

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

A controller that serves the collection
php
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 ​

RoleAS2 Meaning
originthe source; Move, Remove and Delete can identify the source container
resultan entity produced by the activity
instrumentthe means used, such as a service

Mapping Activity Types ​

Verb Mappings ​

Map verbs to Activity Streams types in your verb enum:

app/Enums/OrderActivity.php
php
<?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 type and affects default deletion rules. Delete, Remove, Undo, and Reject have 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 Activity and sf:verb holds the verb. The document's JSON-LD context, https://ns.storyfeed.dev, defines sf:verb. Intransitive types also fall back to Activity when an object is present.
  • Composite objects serialize as OrderedCollection.
  • Entity media serialize as AS2 Link objects under icon, image, and preview. During serialization, $context->feed() in feedMedia() returns null.

Type Overrides ​

On a Story class, import Storyfeed\ActivityStreams\ActivityType and set $type:

app/Stories/OrderWasPlaced.php
php
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.

Released under the MIT License.