diff --git a/api/funkwhale_api/activity/__init__.py b/api/funkwhale_api/activity/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/api/funkwhale_api/activity/serializers.py b/api/funkwhale_api/activity/serializers.py
new file mode 100644
index 0000000000000000000000000000000000000000..4b40bb0d2804622772aeb5af9d445a75a570779e
--- /dev/null
+++ b/api/funkwhale_api/activity/serializers.py
@@ -0,0 +1,9 @@
+from rest_framework import serializers
+
+
+class ModelSerializer(serializers.ModelSerializer):
+    id = serializers.CharField(source='get_activity_url')
+    # url = serializers.SerializerMethodField()
+
+    def get_url(self, obj):
+        return self.get_id(obj)
diff --git a/api/funkwhale_api/favorites/models.py b/api/funkwhale_api/favorites/models.py
index 899ed9cff7f403bc2089e34cb3ff313ebaceff55..0c6a6b11c6e86083c63a49dfbdf45021554e380c 100644
--- a/api/funkwhale_api/favorites/models.py
+++ b/api/funkwhale_api/favorites/models.py
@@ -1,8 +1,10 @@
+from django.conf import settings
 from django.db import models
 from django.utils import timezone
 
 from funkwhale_api.music.models import Track
 
+
 class TrackFavorite(models.Model):
     creation_date = models.DateTimeField(default=timezone.now)
     user = models.ForeignKey(
@@ -18,3 +20,7 @@ class TrackFavorite(models.Model):
     def add(cls, track, user):
         favorite, created = cls.objects.get_or_create(user=user, track=track)
         return favorite
+
+    def get_activity_url(self):
+        return '{}/favorites/tracks/{}'.format(
+            self.user.get_activity_url(), self.pk)
diff --git a/api/funkwhale_api/favorites/serializers.py b/api/funkwhale_api/favorites/serializers.py
index 57af4570e0df7669bfce087433cdcab245495d5e..01ad2e475a9165253876a029f38d85ebee3725d0 100644
--- a/api/funkwhale_api/favorites/serializers.py
+++ b/api/funkwhale_api/favorites/serializers.py
@@ -1,10 +1,43 @@
+from django.conf import settings
+
 from rest_framework import serializers
 
+from funkwhale_api.activity import serializers as activity_serializers
 from funkwhale_api.music.serializers import TrackSerializerNested
+from funkwhale_api.users.serializers import UserActivitySerializer
 
 from . import models
 
 
+
+
+
+class TrackFavoriteActivitySerializer(activity_serializers.ModelSerializer):
+    type = serializers.SerializerMethodField()
+    object = serializers.CharField(source='track.get_activity_url')
+    actor = UserActivitySerializer(source='user')
+    published = serializers.DateTimeField(source='creation_date')
+
+    class Meta:
+        model = models.TrackFavorite
+        fields = [
+            'id',
+            'object',
+            'type',
+            'actor',
+            'published'
+        ]
+
+    def get_actor(self, obj):
+        return UserActivitySerializer(obj.user).data
+
+    def get_type(self, obj):
+        return 'Like'
+
+    def get_object(self, obj):
+        return obj.track.get_activity_url()
+
+
 class UserTrackFavoriteSerializer(serializers.ModelSerializer):
     # track = TrackSerializerNested(read_only=True)
     class Meta:
diff --git a/api/funkwhale_api/music/consumers.py b/api/funkwhale_api/music/consumers.py
new file mode 100644
index 0000000000000000000000000000000000000000..452346d193328235c56037ae7ba94fb26a7024a1
--- /dev/null
+++ b/api/funkwhale_api/music/consumers.py
@@ -0,0 +1,17 @@
+from funkwhale_api.common.consumers import JsonAuthConsumer
+
+
+class MyConsumer(JsonAuthConsumer):
+    groups = ["broadcast"]
+
+    def receive_json(self, payload):
+        print(payload, self.scope["user"])
+        # Called with either text_data or bytes_data for each frame
+        # You can call:
+        self.send_json({'test': 'me'})
+        # Or, to send a binary frame:
+        # self.send(bytes_data="{Hello} world!")
+        # Want to force-close the connection? Call:
+        # self.close()
+        # # Or add a custom WebSocket error code!
+        # self.close(code=4123)
diff --git a/api/funkwhale_api/music/models.py b/api/funkwhale_api/music/models.py
index 97992fc8f12cafa7af7cb99c7cbfb1cee2b42192..7138dcdd6d51f52568649d06fc34eb655d64e4d0 100644
--- a/api/funkwhale_api/music/models.py
+++ b/api/funkwhale_api/music/models.py
@@ -360,6 +360,12 @@ class Track(APIModelMixin):
                 self.title,
             )
 
+    def get_activity_url(self):
+        if self.mbid:
+            return 'https://musicbrainz.org/recording/{}'.format(
+                self.mbid)
+        return settings.FUNKWHALE_URL + '/tracks/{}'.format(self.pk)
+
 
 class TrackFile(models.Model):
     track = models.ForeignKey(
diff --git a/api/funkwhale_api/users/models.py b/api/funkwhale_api/users/models.py
index 3a0baf11a30c73397b2c31d14fe1ec29d9557a7c..2b0dfa888ca240c49f82574d2a061dd8d8445c21 100644
--- a/api/funkwhale_api/users/models.py
+++ b/api/funkwhale_api/users/models.py
@@ -3,6 +3,7 @@ from __future__ import unicode_literals, absolute_import
 
 import uuid
 
+from django.conf import settings
 from django.contrib.auth.models import AbstractUser
 from django.urls import reverse
 from django.db import models
@@ -43,3 +44,6 @@ class User(AbstractUser):
     def set_password(self, raw_password):
         super().set_password(raw_password)
         self.update_secret_key()
+
+    def get_activity_url(self):
+        return settings.FUNKWHALE_URL + '/@{}'.format(self.username)
diff --git a/api/funkwhale_api/users/serializers.py b/api/funkwhale_api/users/serializers.py
index 8c218b1c28acd2811b208e0a3f4b4f0d788c1aea..2e873d94c6c3e961a3dbad8129ab1473fc55728e 100644
--- a/api/funkwhale_api/users/serializers.py
+++ b/api/funkwhale_api/users/serializers.py
@@ -1,8 +1,26 @@
 from rest_framework import serializers
 
+from funkwhale_api.activity import serializers as activity_serializers
+
 from . import models
 
 
+class UserActivitySerializer(activity_serializers.ModelSerializer):
+    type = serializers.SerializerMethodField()
+    name = serializers.CharField(source='username')
+
+    class Meta:
+        model = models.User
+        fields = [
+            'id',
+            'name',
+            'type'
+        ]
+
+    def get_type(self, obj):
+        return 'Person'
+
+
 class UserBasicSerializer(serializers.ModelSerializer):
     class Meta:
         model = models.User
diff --git a/api/tests/favorites/test_activity.py b/api/tests/favorites/test_activity.py
new file mode 100644
index 0000000000000000000000000000000000000000..b4d76658a8688fd4dc81144e288653186b18e1c2
--- /dev/null
+++ b/api/tests/favorites/test_activity.py
@@ -0,0 +1,28 @@
+from funkwhale_api.users.serializers import UserActivitySerializer
+from funkwhale_api.favorites import serializers
+
+
+def test_get_favorite_activity_url(settings, factories):
+    favorite = factories['favorites.TrackFavorite']()
+    user_url = favorite.user.get_activity_url()
+    expected = '{}/favorites/tracks/{}'.format(
+        user_url, favorite.pk)
+    assert favorite.get_activity_url() == expected
+
+
+def test_activity_favorite_serializer(factories):
+    favorite = factories['favorites.TrackFavorite']()
+
+    actor = UserActivitySerializer(favorite.user).data
+    field = serializers.serializers.DateTimeField()
+    expected = {
+        "type": "Like",
+        "id": favorite.get_activity_url(),
+        "actor": actor,
+        "object": favorite.track.get_activity_url(),
+        "published": field.to_representation(favorite.creation_date),
+    }
+
+    data = serializers.TrackFavoriteActivitySerializer(favorite).data
+
+    assert data == expected
diff --git a/api/tests/test_favorites.py b/api/tests/favorites/test_favorites.py
similarity index 100%
rename from api/tests/test_favorites.py
rename to api/tests/favorites/test_favorites.py
diff --git a/api/tests/music/test_activity.py b/api/tests/music/test_activity.py
new file mode 100644
index 0000000000000000000000000000000000000000..f604874c14e75442b9ba50170107a4aa127497a2
--- /dev/null
+++ b/api/tests/music/test_activity.py
@@ -0,0 +1,17 @@
+from funkwhale_api.users.serializers import UserActivitySerializer
+from funkwhale_api.favorites import serializers
+
+
+
+def test_get_track_activity_url_mbid(factories):
+    track = factories['music.Track']()
+    expected = 'https://musicbrainz.org/recording/{}'.format(
+        track.mbid)
+    assert track.get_activity_url() == expected
+
+
+def test_get_track_activity_url_no_mbid(settings, factories):
+    track = factories['music.Track'](mbid=None)
+    expected = settings.FUNKWHALE_URL + '/tracks/{}'.format(
+        track.pk)
+    assert track.get_activity_url() == expected
diff --git a/api/tests/users/test_activity.py b/api/tests/users/test_activity.py
new file mode 100644
index 0000000000000000000000000000000000000000..3cee4fb4092699125d7ab3bb4a3d32923cb12769
--- /dev/null
+++ b/api/tests/users/test_activity.py
@@ -0,0 +1,21 @@
+from funkwhale_api.users import serializers
+
+
+def test_get_user_activity_url(settings, factories):
+    user = factories['users.User']()
+    assert user.get_activity_url() == '{}/@{}'.format(
+        settings.FUNKWHALE_URL, user.username)
+
+
+def test_activity_user_serializer(factories):
+    user = factories['users.User']()
+
+    expected = {
+        "type": "Person",
+        "id": user.get_activity_url(),
+        "name": user.username,
+    }
+
+    data = serializers.UserActivitySerializer(user).data
+
+    assert data == expected