# Solid Groups App

**URL:** <https://forum.solidproject.org/t/solid-groups-app/2932>\
**Category:** App Testing\
**Created:** [April 19, 2020, 8:19pm UTC](https://forum.solidproject.org/t/solid-groups-app/2932 "2020-04-19T20:19:46Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![aveltens](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/aveltens/32/3987_2.png) [@aveltens](https://forum.solidproject.org/u/aveltens)\
**Post date:** [April 19, 2020, 8:19pm UTC](https://forum.solidproject.org/t/solid-groups-app/2932/1 "2020-04-19T20:19:46Z")

</div>

Hi,

I started developing an App to create groups in Solid. The main idea is to have something like Facebook groups on the distributed Web. The groups should allow people with common interests to find each other.

A Demo installation can be found here:

[https://solid-groups.solid.community/](https://solid-groups.solid.community/)

But it can’t do anything yet, I am primarily working on being able to set up a group initially. The goal is, that anyone can just click a button to deploy the App on her own Pod or a group Pod and the app will then set up a group on that Pod. So app and data will reside on the same pod and groups can spread arround the Web.

The source code is on GitLab: [https://gitlab.com/angelo-v/solid-groups](https://gitlab.com/angelo-v/solid-groups)

---

<div class="post-metadata">

**Author:** ![aveltens](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/aveltens/32/3987_2.png) [@aveltens](https://forum.solidproject.org/u/aveltens)\
**Post date:** [April 24, 2020, 6:13am UTC](https://forum.solidproject.org/t/solid-groups-app/2932/2 "2020-04-24T06:13:36Z")

</div>

What do you think of the following models using activity streams for join requests / proposals sent to group inbox?

Someone asks to join a group:

```auto
@prefix : <#> .
@prefix as: <https://www.w3.org/ns/activitystreams#> .
@prefix c: </profile/card#> .
@prefix group: </groups/main#> .

:it
    a as:Offer ;
    as:actor c:me ;
    as:object :join ;
    as:summary "Angelo asks to join the group" ;
    as:target group:we .

:join
    as:actor c:me ;
    as:object group:we ;
    as:summary "Angelo joins group" ;
    as:type as:Join .

```

Someone proposes to add someone else to a group:

```auto
@prefix : <#> .
@prefix as: <https://www.w3.org/ns/activitystreams#> .
@prefix c: </profile/card#> .
@prefix jane: <https://jane.example/profile/card#> .
@prefix group: </groups/main#> .

:it
    a as:Offer ;
    as:actor c:me ;
    as:object :join ;
    as:summary "Angelo suggests, that Jane joins the group" ;
    as:target group:we .

:join
    as:actor jane:me ;
    as:object group:we ;
    as:summary "Jane joins group" ;
    as:type as:Join .

```

---

<div class="post-metadata">

**Author:** ![aschrijver](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/aschrijver/32/463_2.png) [@aschrijver](https://forum.solidproject.org/u/aschrijver)\
**Post date:** [April 24, 2020, 9:37am UTC](https://forum.solidproject.org/t/solid-groups-app/2932/3 "2020-04-24T09:37:48Z")

</div>

Just a heads up: Tomorrow is the ActivityPub SocialCG meetup, and both Groups (in AP) and AP vs. Solid are agenda items. See:

> **[2020-04-25 SocialCG Meeting](https://socialhub.activitypub.rocks/t/2020-04-25-socialcg-meeting/625)**
>
> See Wiki Page\[1\]. Current Topics Mostly taken from Planning the next SocialCG meeting: when? Introductions Content addressed vocabulary for extensions (@cwebber) E2E Encryption / #software:redaktor-me news (@Sebastian) C2S Widgets...

---

<div class="post-metadata">

**Author:** ![anon36056958](https://avatars.discourse-cdn.com/v4/letter/a/b38774/32.png) [@anon36056958](https://forum.solidproject.org/u/anon36056958)\
**Post date:** [April 24, 2020, 10:40am UTC](https://forum.solidproject.org/t/solid-groups-app/2932/4 "2020-04-24T10:40:49Z")

</div>

Nice!  
For more formal groups, I’m thinking you might have something like

:how  
a as:Question ;  
as:actor c:me ;  
as:object :join ;  
as:summary “Angelo asks how to join the group?” ;  
as:target group:we .

:apply  
a as:Announce ;  
as:actor group:we ;  
as:object :application ;  
as:summary “Group says here is the application” ;  
as:target c:me .

:application  
a as:Object ;  
as:generator group:we ;  
as:audience c:me ;  
as:attachment: \</groups/main#application\> ;  
as:summary “Application to join group” .

---

<div class="post-metadata">

**Author:** ![aveltens](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/aveltens/32/3987_2.png) [@aveltens](https://forum.solidproject.org/u/aveltens)\
**Post date:** [April 24, 2020, 11:04am UTC](https://forum.solidproject.org/t/solid-groups-app/2932/5 "2020-04-24T11:04:33Z")

</div>

This would allow to discover _how_ to join groups? Interesting. But several steps ahead of what I am trying to achieve right now.

But could be interesting to discover wheter a group is open to join for everybody or one needs to send a join request

---

<div class="post-metadata">

**Author:** ![anon36056958](https://avatars.discourse-cdn.com/v4/letter/a/b38774/32.png) [@anon36056958](https://forum.solidproject.org/u/anon36056958)\
**Post date:** [April 24, 2020, 11:33am UTC](https://forum.solidproject.org/t/solid-groups-app/2932/6 "2020-04-24T11:33:55Z")

</div>

Then substitute (?)

:apply  
a as:Announce ;  
as:actor group:we ;  
as:object \<groups/main#openAnnouncement\> ;  
as:summary "This group is open to anyone” ;  
as:target c:me .

---

<div class="post-metadata">

**Author:** ![aveltens](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/aveltens/32/3987_2.png) [@aveltens](https://forum.solidproject.org/u/aveltens)\
**Post date:** [May 2, 2020, 1:29pm UTC](https://forum.solidproject.org/t/solid-groups-app/2932/7 "2020-05-02T13:29:04Z")

</div>

You are able to log in now, and request to join the group. Please give it a try at

[https://solid-groups.solid.community/](https://solid-groups.solid.community/)

The inbox is openly readable for now, so you can check your request data at:

[https://solid-groups.solid.community/groups/inbox/567d00a0-54d2-4977-a0aa-6b8999941bc5/](https://solid-groups.solid.community/groups/inbox/567d00a0-54d2-4977-a0aa-6b8999941bc5/)

Any feedback welcome!

---

<div class="post-metadata">

**Author:** ![Smag0](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/smag0/32/310_2.png) [@Smag0](https://forum.solidproject.org/u/Smag0)\
**Post date:** [May 2, 2020, 2:05pm UTC](https://forum.solidproject.org/t/solid-groups-app/2932/8 "2020-05-02T14:05:47Z")

</div>

Nice I was just asking myself for followers on Agora [https://github.com/scenaristeur/agora](https://github.com/scenaristeur/agora) if I had to ask for request like Instagram or allow automatic followers as Twitter… 👍😊

---

<div class="post-metadata">

**Author:** ![aveltens](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/aveltens/32/3987_2.png) [@aveltens](https://forum.solidproject.org/u/aveltens)\
**Post date:** [May 22, 2020, 9:08pm UTC](https://forum.solidproject.org/t/solid-groups-app/2932/9 "2020-05-22T21:08:17Z")

</div>

Hello everybody, thanks for testing so far. I implemented join acceptance and you should have a such in your inbox.

A list of group members will soon be added to Solid Groups App, until then the list can be seen at [https://solid-groups.solid.community/groups/main#we](https://solid-groups.solid.community/groups/main#we)

Group members are allowed to read the following document, I hope this gives some incentive for more people to test and join 🙂 :

[https://solid-groups.solid.community/private/welcome.html](https://solid-groups.solid.community/private/welcome.html)

---

<div class="post-metadata">

**Author:** ![aveltens](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/aveltens/32/3987_2.png) [@aveltens](https://forum.solidproject.org/u/aveltens)\
**Post date:** [May 29, 2020, 6:37am UTC](https://forum.solidproject.org/t/solid-groups-app/2932/10 "2020-05-29T06:37:39Z")

</div>

Group members are now shown on [the group homepage](https://solid-groups.solid.community/#/)

 ![Bildschirmfoto%20von%202020-05-29%2008-37-13](https://europe1.discourse-cdn.com/flex017/uploads/solidproject/original/2X/c/ca555d0e4c465ce9decb903ddaf61a12115ca9e4.jpeg)

---

<div class="post-metadata">

**Author:** ![aschrijver](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/aschrijver/32/463_2.png) [@aschrijver](https://forum.solidproject.org/u/aschrijver)\
**Post date:** [May 31, 2020, 5:52am UTC](https://forum.solidproject.org/t/solid-groups-app/2932/11 "2020-05-31T05:52:28Z")

</div>

What’s very interesting to me in this discussion is that both Solid and fediverse are investigating how to implement Groups (see [Groups implementation](https://socialhub.activitypub.rocks/t/groups-implementation/591) on SocialHub) and both based on ActivityStreams for that. This is a great opportunity to [combine Solid vs. ActivityPub](http://forum.solidproject.org/t/discussion-solid-vs-activitypub/2685) and, at least, stay as compatible as possible to each other.

How cool would it be if the Solid Groups App would be fediverse-compliant, integrated with the federated web, and showing Solid goodness to the AP audience over there?

The discussion on SocialHub was started by [`@ngerakines`](https://socialhub.activitypub.rocks/u/ngerakines/summary) creator of [Tavern](https://gitlab.com/ngerakines/tavern), a minimalistic Mastodon-compliant AP server implemented in Go. Rather than creating formal descriptions the fediverse recently adopted the practice to have `FEDERATION.md` documents that describe server-to-server federated communication. Tavern has one too, that [describes Group messaging](https://gitlab.com/ngerakines/tavern/-/blob/master/FEDERATION.md#groups).

@aveltens what I find unintuitive is the `Offer{Join}` semantics. To me that says _“I, Angelo **offer** to join the group”_ . I see `Offer` more in terms of _“I offer this Product or Service”_. Also the `Join` in this case refers to an activity that has not happened yet, hence it is not a real activity. Creation of the `Join` should be left to the group after it happened, hence making it a real activity.

Some highlights of SocialHub discussion and `FEDERATION.md` (highly recommended reads):

- As per ActivityStreams spec a `Group` is an Actor-type (in ActivityPub this means it has its own `ldp:inbox`)
- As such the `Group` is the single-source-of-truth of group membership
- Joining a `Group` entails sending a `Follow` activity to its inbox, which is responded with either `Accept` or `Reject`
  - This can be automatic `Accept` for public groups, or a pending operation for private groups, manual approval.
  - A `Reject` includes the reason for rejection e.g. _“Private group, invitation only”_.

- The `Group` notifies its members (including the new member) about membership change with a `Join{Person}` message.
- An `Undo{Follow}` to the `Group` triggers a `Leave` membership change message from the group.
- An `Invite{Person}` to both `Group` and `Person` from an existing member means that a subsequent `Follow` to that group from the person is automatically accepted.

---

<div class="post-metadata">

**Author:** ![aveltens](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/aveltens/32/3987_2.png) [@aveltens](https://forum.solidproject.org/u/aveltens)\
**Post date:** [May 31, 2020, 11:45am UTC](https://forum.solidproject.org/t/solid-groups-app/2932/12 "2020-05-31T11:45:47Z")

</div>

Hey @aschrijver, this is very valuable feedback. Thanks for keeping such a close eye to the relation between ActivityPub and Solid.

I am not committed to the `Offer{Join}` semantics. I did not find a formal specification of group management in the Activity Streams Recommendation, but wanted to start somehow and get a working prototype. `Offer` is used in [a friend-request example](https://www.w3.org/TR/activitystreams-vocabulary/#modeling-friend-requests), so I thought it might fit in for join requests as well.

If now the AS community is working on that part of the spec as well, this is really great and I will dive deeper into it to get on common grounds.

---

<div class="post-metadata">

**Author:** ![aschrijver](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/aschrijver/32/463_2.png) [@aschrijver](https://forum.solidproject.org/u/aschrijver)\
**Post date:** [May 31, 2020, 11:59am UTC](https://forum.solidproject.org/t/solid-groups-app/2932/13 "2020-05-31T11:59:47Z")

</div>

Cool! Note that on SocialHub [`@yvolk`](https://socialhub.activitypub.rocks/u/yvolk) creator of [AndStatus](https://github.com/andstatus/andstatus) fediverse client software also makes a [very valid remark](https://socialhub.activitypub.rocks/t/groups-implementation/591/32?u=aschrijver):

> And thinking further I see that both “Follow a Group” and “Join a Group” activities really make sense in terms of ActivityPub, but they have different meaning:
> 
> - _Join a Group_ - an intent to receive all activities sent to that Group **by members** of the Group.
> - _Follow a Group_ - an intent to receive all activities sent **by the Group** i.e. by the Group as an Actor. This is similar to following a Server’s admin.

The discussion did not follow up from there. I think if I would implement Groups, I would make this distinction.

Also note the word “activities”. In Tavern FEDERATION.md this is currently limited to discussion messages (toots) with `Create{Note}` and `Announce{Note}`. In my implementation this would be a much more broader `Create{Object}` (with restrictions to what `Object` can be, of course). After all groups would be involved in all kinds of activities 🙂

**PS** : Thanks for pointing to this section in the spec… the semantics are very much open to interpretation, so choosing common approaches is a valuable undertaking.

---

<div class="post-metadata">

**Author:** ![anon36056958](https://avatars.discourse-cdn.com/v4/letter/a/b38774/32.png) [@anon36056958](https://forum.solidproject.org/u/anon36056958)\
**Post date:** [June 6, 2020, 4:18pm UTC](https://forum.solidproject.org/t/solid-groups-app/2932/14 "2020-06-06T16:18:36Z")

</div>

Solid Groups App sounds like just the thing to make a group of ontology curators. Unfortunately there is not yet an ontology hub to curate 🙂

---

<div class="post-metadata">

**Author:** ![Smag0](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/smag0/32/310_2.png) [@Smag0](https://forum.solidproject.org/u/Smag0)\
**Post date:** [July 19, 2020, 6:12pm UTC](https://forum.solidproject.org/t/solid-groups-app/2932/15 "2020-07-19T18:12:01Z")

</div>

Hi @aveltens did you try or know if someone try to implement sub-groups ?  
What vocab could we us ? I was thinking of org:subOrganizationOf [https://www.w3.org/TR/vocab-org/#org:subOrganizationOf](https://www.w3.org/TR/vocab-org/#org:subOrganizationOf)

---

<div class="post-metadata">

**Author:** ![aschrijver](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/aschrijver/32/463_2.png) [@aschrijver](https://forum.solidproject.org/u/aschrijver)\
**Post date:** [July 19, 2020, 7:15pm UTC](https://forum.solidproject.org/t/solid-groups-app/2932/16 "2020-07-19T19:15:30Z")

</div>

How do you define a sub-group? Since the group is an `as:Actor` just like `as:Person` it can be part of the members of another group (effectively a nested group). In that case [https://www.w3.org/TR/vocab-org/#org:memberOf](https://www.w3.org/TR/vocab-org/#org:memberOf) also applies.

---

<div class="post-metadata">

**Author:** ![aveltens](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/aveltens/32/3987_2.png) [@aveltens](https://forum.solidproject.org/u/aveltens)\
**Post date:** [July 19, 2020, 7:21pm UTC](https://forum.solidproject.org/t/solid-groups-app/2932/17 "2020-07-19T19:21:52Z")

</div>

I would try to stick to `vcard`. First guess would just to put another group to the `hasMember` list, but did not think this trough yet.

---

<div class="post-metadata">

**Author:** ![aschrijver](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/aschrijver/32/463_2.png) [@aschrijver](https://forum.solidproject.org/u/aschrijver)\
**Post date:** [July 19, 2020, 7:30pm UTC](https://forum.solidproject.org/t/solid-groups-app/2932/18 "2020-07-19T19:30:01Z")

</div>

@Smag0 was looking for an inverse relationship. Vcard has no inverse for `hasMember`. The org vocabulary has both directions, i.e. `org:hasMember`.

---

<div class="post-metadata">

**Author:** ![Smag0](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/smag0/32/310_2.png) [@Smag0](https://forum.solidproject.org/u/Smag0)\
**Post date:** [July 19, 2020, 7:36pm UTC](https://forum.solidproject.org/t/solid-groups-app/2932/19 "2020-07-19T19:36:36Z")

</div>

Thxs @aschrijver @aveltens for your response .  
The aim is to build a gouvernance tool inspired by Holacracy  
With organization ( group) , circles & sub-circles ( groups ) & roles ( also groups? )  
All nested groups in fact, where a member can be a group [https://www.holacracy.org/constitution](https://www.holacracy.org/constitution)

---

<div class="post-metadata">

**Author:** ![aschrijver](https://dub1.discourse-cdn.com/flex017/user_avatar/forum.solidproject.org/aschrijver/32/463_2.png) [@aschrijver](https://forum.solidproject.org/u/aschrijver)\
**Post date:** [July 19, 2020, 7:51pm UTC](https://forum.solidproject.org/t/solid-groups-app/2932/20 "2020-07-19T19:51:27Z")

</div>

Nice! I might start a side-project based on [Sociocracy](http://patterns.sociocracy30.org/map.html) pattern library, if I find the time.  
Is it an open source application?

PS. I’d definitely go for the org ontology in that case. Also I’d make the organization an organization, not a group. In activitystreams there is also an `as:Organization` as a separate Actor type. For Role there is also [`org:Role`](https://www.w3.org/TR/vocab-org/#class-role).

[Next page](https://forum.solidproject.org/t/solid-groups-app/2932.md?page=2)
