MoodleNet in 2018: a retrospective

Captain Hindsight


This year, MoodleNet has gone from idea to code. In fact, we’ll be launching a Minimum Viable Product in January 2019 to gather feedback from around a hundred testers. That process will start in the New Year.

In a world of agile development, where speed-to-market is everything, why has it taken a year for MoodleNet to emerge? Hopefully, this post (and its many links) will help explain some of that. We agree with Abraham Lincoln’s philosophy when he said: “Give me six hours to chop down a tree and I will spend the first four sharpening the axe.”

MoodleNet is a new open social media platform for educators, focused on professional development and open content. It aims to sustainably empower communities of educators to share and learn from each other to improve the quality of education, and will be an integral part of the Moodle ecosystem.

If we were building a centralised system such as Twitter, if we wanted to “move fast and break things” like Facebook famously does, then we could have launched months ago. But what we’re building with MoodleNet is, just like Moodle Core has proven to be, for the long haul. We’re building something to last.

Batman thinking


Back in January, we began by scoping out what we wanted to achieve in a white paper that included feedback and suggestions from a whole raft of people who are credited at the end of the document. We based it on scenarios that, while fictional, are based on the real-world situations faced by different groups within the millions of people who make up the Moodle community.

Realising that it’s important to build Open Source projects upon strong principles, we defined what we meant when we said that MoodleNet is:

search-refine-curateBryan Mathers began helping us visualise some of what we were trying to achieve with the project, bringing it to life beyond mere words. At this point, the MoodleNet team consisted of a single person – me, Doug Belshaw. To quote another American President, this time Woodrow Wilson, I decided to use “not only all the brains I have, but all I can borrow”. As an educator and a technologist, I got in touch with experts in my network to ask for their advice. They are listed at the bottom of this post, and their input was invaluable for refining what we wanted MoodleNet to be.

In February, at a management meeting in Perth Australia, I ran a couple of MoodleNet workshops based on what I’d heard from the experts in my network, and also what Martin Dougiamas, Moodle’s Founder and CEO, had requested. This was a very positive experience, as it was clear that MoodleNet was going to be vital to the whole Moodle ecosystem.

While still in nascent form, and in the run up to the implementation of the European General Data Protection Regulation (GDPR), we focused in on compliance, and testing some ideas around using the very new ActivityPub protocol. We tested various approaches, such as those taken by Hubzilla and Mastodon.

Once we knew that MoodleNet was going to be a federated social network – one that could be installed just like Moodle Core, but with each MoodleNet instance connected together – it was time to focus in on what people would be doing with this social network. Work in March involved gathering inspiration from different types of social networks that involved resource-sharing. We felt that, in 2018, asking people to join yet another generic social network would be fighting an uphill battle.

At the MoodleMoot UK & Ireland in March, we gave a presentation and ran a workshop on MoodleNet, soliciting feedback on the ideas we had come up with. Feedback was positive, with the community tweeting about the soft spot between pedagogy and technology, and seeming to get why we had decided to start by focusing on building something small.



By the time the OER18 and OE Global conferences came around in April, we felt that we were ready to plan what MoodleNet would look like in more detail. Conversations at these two events really helped us explain what we hoped to be the value proposition, and fed into a series of blog posts aimed at winnowing the project down to MVP size.

It was at this time that we also began running the MoodleNet community calls. Having run many of these before with other Open Source projects, I was delighted that many people gave up their time to join us. Unfortunately, we had to give these up after the first three, as the way we were collecting user data wasn’t GDPR compliant. It’s still something we’d like to do, so we’re still looking for a better way to run these in 2019.

MoodleNet - a resource-centric social networkOne extremely important feature of any social network, but particularly one focused on resource-sharing, is search functionality. Get it right, and nobody notices. Get it wrong, and everyone complains. I asked Mike Larsson, who I’d worked with at Mozilla, to do some thinking around this for us. He came up with several approaches, including a custom search index. As we prepare for the MVP, we’re currently building upon these ideas.

In May, as the project began to need more technical input, I asked for some input from Phil Barker around metadata, schemas, and standards relating to Open Educational Resources (OER). We also started looking for a Technical Architect to join the team. After going through 80 applications, and interviewing many diverse candidates from around the world, we offered the position to Mayel de Borniol.

Mayel’s first day at Moodle was also the first day of a week-long sociocratic design sprint with Outlandish, a tech co-op based in London. Martin Dougiamas flew in from Australia to be with us and, based on information we’d gathered – including a pre-sprint community survey – we designed a prototype which we then tested with members of the Moodle community. Bryan Mathers again helped us visualise proceedings.

The design sprint gave us a real impetus and mandate to get started in June with the technical architecture of MoodleNet. Mayel outlined some options for how we could set up and run MoodleNet, and we established a code base in GitLab. By the time we both presented in Barcelona at MoodleMoot Spain, we had a clear idea of where we were heading, both conceptually and technically. We received great feedback and questions, both in person and via Twitter.



After the design sprint, we engaged the services of Outlandish to continue designing MoodleNet. UX Milestone 1 in July demonstrated our thinking around the potential look and feel of the user experience on mobile. At the same time, given what the community had told us, we began planning for how MoodleNet could integrate with Moodle Core.

I flew over to the US for the MountainMoot of which I’d heard so much. I ran a workshop on MoodleNet, gaining some extremely useful insights both during the session and in conversation during the event. It was at this time we also started thinking about the use of Open Badges in MoodleNet. Although we have de-scoped them from the MVP release, it’s still something we’re looking to integrate as soon as possible in 2019! We also started thinking about identity in decentralised social networks.

moodlenet-betaWhile I spent most of August on holiday interrailing around Europe with my family, work continued on MoodleNet in my absence. Mayel settled on a technical architecture for the project, and decided to use Elixir for the backend code base. This led to questions both within Moodle HQ and the community, and to Mayel presenting to Moodle Core developers.

Outlandish continued their work through UX Milestone 2, which resulted in four screencasts to show the community the work we’d done. By the time September came around, we were ready to accelerate development of the project. I presented at ALT-C, Mayel and I participated in a front-end development workshop with Outlandish in London (leading to a demo and draft style guide), and after a several-week search, we welcome Alex Castaño to the team as backend developer.

It’s good practice in open source to avoid reinventing the wheel and to instead use shared libraries of code for functionality that exists in more than one project. When we didn’t find a suitable code library for creating federated apps, we decided to build a generic ActivityPub backend server. This was for several reasons, but the most important is that the more ActivityPub-enabled services there are, the better for the entire decentralised application ecosystem. We’ve already seen the resulting CommonsPub repository attract contributions from the Open Source community, and it’s being used in other projects as well as MoodleNet.

Designing tech in 3D


By October, MoodleNet was really coming into focus. Alex quickly realised he’d joined a team building something going beyond merely another tech project, and an interview with Mary Cooch helped explain to the Moodle community why we’re building something completely different to the existing

Version 0.8 of our overview slide deck told a much better story than previously, thanks to some feedback from the wider MoodleNet community. At the end of the month, Mayel and I attended the Mozilla Festival in London. There was a whole decentralisation floor where we ran a workshop, and proceeded to successfully pitch for a small grant – details of which we’ll reveal in early 2019!

Hot on the heels of the Mozilla Festival was MoodleMoot US, where I ran a workshop. People from a diverse range of backgrounds participated in the session, from K12 and Higher Education to the corporate world. They could all see how MoodleNet would be useful in their context, and we again received positive feedback both in person and on Twitter.

Principles-ConnectedMoodle HQ has hired many new colleagues in 2018. In late October, Gry Stene joined us as Chief Product Officer. As her job title would suggest, Gry now oversees all of Moodle’s products, ensuring we are using resources effectively, building interoperable products, and preventing too much overlap.   

In November, with around two months until the MVP, we spent time thinking about the user sign-up experience. Outlandish built a prototype (with live code) and tested it with volunteers from the community. As is to be expected, although it was fine with no major flaws, the feedback pointed to how it could be better. We returned to the drawing board, reimagining the process to be even easier and more GDPR-compliant.   

Outlandish joined us for two days of a MoodleNet team in-person workweek, where Mayel and Alex met one another in person for the first time! The main purpose of the week was to ensure that the work on the front-end and back-end was hooked up together, using a data query language called GraphQL. Although we didn’t get through everything we wanted to get done that week, it was a very productive time, and meant we were in better shape than we would have been had we continued to work remotely.

Over the previous few weeks, Mayel had worked on contribution guidelines for the community, based on his own experience and other Open Source projects. We opened this for comments and, after a two-week feedback window, made modifications based on what we heard. We’ve adopted the Contributor Covenant and added specific guidance around how community members can get involved in making their first contribution.

contributeGiven he was in Athens, Mayel took the opportunity of running a workshop at MoodleMoot Greece, with a specific focus on localisation. After talking since at least July about the potential use of emoji triplets for identity and identification in decentralised systems, I finally got around to writing this up in a post describing what we’re calling Emoji ID.

As I write this towards the end of December, we’re in good shape for the MVP in early 2019. Mayel recommended Ivan Minutillo, a UX designer and front-end developer for our team and Gry did a fantastic job at getting him onboard very quickly. Not only that, but Ivan really hit the ground running, already having contributed to CommonsPub and experience with the core technologies we’re using on the front-end.

We had planned for Outlandish to overlap until next month with Ivan. However, given how quickly he came up-to-speed, and how efficiently the project has been documented, this was kept to a minimum. The six months we spent working with Outlandish were invaluable; there is no way we would be in the same position without them. I hope that we’ll be able to lean on their expertise again in 2019 for future stages of the project!

Since handing over from Outlandish, we’ve re-scoped the project milestones, drafted a testing plan for January 2019, and published v0.9 of our overview slide deck.

Adventure Time

Final words

It’s been an exciting but tiring year and I think the whole team is ready for a well-deserved two week break over Christmas! All of the above would have been enough for a team working full-time to achieve. As it happens, the only person working five days per week has been Alex, and only since early October. The rest of us work between two and four days on the MoodleNet project!

The proof of the pudding, as the English saying goes, is in the eating. So I’m looking forward to testing our first value proposition in January 2019: do people want to join communities to curate collections of resources?

Time will tell. Lots of people have given us their thoughts and opinions about MoodleNet this year and this project is better because of them. Any problems or issues with the project are, of course, my responsibility as MoodleNet Lead. However, anything that’s useful is due to the fantastic team I’ve had the privilege to assemble, input from my talented colleagues at Moodle HQ, and the following people who so have so generously lent their time:

  • Outlandish
    • Rob Cornish
    • Matt Crow
    • Sam Gluck
    • Kayleigh Walsh
  • Consultants
    • Phil Barker
    • Mike Larsson
    • Bryan Mathers
  • Testers
    • Miles Berry
    • Luca Bösch
    • Mary Cooch
    • Martin Deinhofer
    • Andy Field
    • Jessica Gramp
    • Oliver Quinlan
    • Emma Richardson
    • Christian Turton
  • Open Source & ActivityPub community
    • César Awad
    • Ruben Cancho
    • Hubert Chathi
    • Thomas Citharel
    • cj
    • Elizabeth Dalton
    • Nolan Damon
    • Debashish Datta
    • Julie Day
    • Noel De Martin
    • Vijay Anand Deenadayalan
    • Vicke Denniston
      Lynn Foster
    • Rogério Furtado
    • Wayne Gibbons
    • Ralf Hagemeister
    • Bob Haugen
    • Ralf Hilgenstock
    • Laura Hilliger
    • Don Hinkelman
    • Mandy Honeyman
    • John Hunter
    • Chris Kenniburg
    • John Kuti
    • KS Læring
    • François Lizotte
    • Lilian Low
    • Dan McGuire
    • Greg McVerry
    • Richard Oelmann
    • Adam Procter
    • Felipe Raimo
    • Ben Reynolds
    • Julian Ridden
    • Luiggi Sansonetti
    • John Saylor
    • Séverin Terrier
    • Cyril Z.
    • The creators and contributors of ActivityPub, ActivityStreams, Pleroma, Elixir, React and the countless open source projects we on which we rely.
  • Experts 
    • Martin Hawksey
    • Alan Levine
    • Stephen Downes
    • James Easton
    • Meg Goodine
    • Jim Groom
    • Grainne Hamilton
    • Kristina Ishmael
    • Khari Khambon
    • Tim Klapdor
    • Rick Jerz
    • John Kuti
    • Clint Lalonde
    • Kin Lane
    • Scott McLeod
    • Greg McVerry
    • Ian O’Byrne
    • Alan O’Donohoe
    • Richard Oelmann
    • Nitin Parmar
    • Mark Pegrum
    • Emma Richardson
    • R. John Robertson
    • Tom Salmon
    • Amber Thomas
    • Martin Weller
    • Tom Woodward

My deepest apologies if I have missed anyone from this list. Please do let me know if I have neglected to credit your input!


Say hello to Ivan Minutillo, MoodleNet’s new UX Designer/Front End Developer!

Ivan Minutillo

Those following the development of the MoodleNet project will be aware that we’ve been working closely with Outlandish over the last six months. The team there have been invaluable in getting us off the ground with design and front-end development.

As the project matures, it’s time for that work to be taken in-house. That’s why we were delighted to have the opportunity to quickly snap-up Ivan Minutillo, a talented UX designer and front-end developer, who lives and works in Gaeta, Italy. He’s already started to build on the work that Outlandish have started, and will continue to refine our vision for MoodleNet on a two day per week basis over the next six months.

Let’s find out a little more about Ivan…

We would love to hear a bit about your work history?

I worked in different agencies and startups during my twenties. In a more or less spontaneous way I was often been involved into the development of dashboards and social networks – which over the years have become my main interest from a UX, code and social point of view.

My first experience with the creation of a social network was in an italian startup, building a social e-commerce app. In the last few years I’ve worked on a dashboard with aimed to provide Identity Access Management for secure machine-to-machine connections, based on blockchain technology. In December I quit to focus on development “for the open”, building economic networks to facilitate the creation of economies within communities.

What do you love about what you do?

Code is politic, since every choice that a developer makes, creates constraints that are reflected in social and economic interactions between users. This aspect, which over the years has created a new class of power, can be seen as a lever to evolve a dialogue between the writer and the user of software, to transform authority into responsibility and to lighten the gap between the two parties.

Furthermore, since code is politic, by writing software based on assumptions different from those of the current dominant culture, we can create new possibilities and spread new ideas. Basically, code is my medium of expression.

What are your interests outside of work?

During the recent period I got interested in agriculture, and together with a group of friends we’re planning to start a mushroom cultivation on the next year.

I have a long time passion about beat generation literature, especially anything wrote by Ginsberg and Burroughs, and rock music (Little Wing by Jimy Hendrix is one of the best thing I’ve ever heard) But more than all, my main interest is create, enhance and be part of local and global communities, to move outside capitalism together.

Where is your favourite place in the world, and why?

I dont have any favourite place, but I am especially bound to the mountain range where I live: Monti Aurunci with all the flora and fauna that lives there.

What is ActivityPub?

This was my first question when I joined to MoodleNet team. Now, after studying it deeply for a few weeks, I feel able to give a proper answer. So I thought of writing a blog post, with my goal being to offer a nice introduction to ActivityPub for technical people. If you’re interested in my more general impressions on the fediverse and our approach to building a federated app, I recommend you to read my previous blog post about our goals.

ActivityPub is a protocol for decentralized social networks, which can also be extended to create all kinds of federated apps. So if you are thinking of building one it is very interesting to know how this standard works. It is important to notice it has two different parts:

  • Client to Server API
  • Server to Server API

A service can decide if it wants to implement only one or both of them. This decision just depends on the needs of the project. If you’re a frontend developer, you might use the Client to Server API. You will be focused on the Server to Server API when you only care about the federation part though.

ActivityStreams 2.0

The ActivityPub message format is JSON-LD, which can be used just like regular JSON and we’ll do this for this blog post. The vocabulary used in this protocol is defined by ActivityStreams 2.0 and ActivityPub just adds a couple of requirements more on top of it. In this vocabulary only exists two kind of entities: Link and Object. Here we will focus on Object and its subtypes. An Object has several fields and only two of them are required by ActivityPub: id and type. The most important properties are:

  • type: which defines the type of object. It can be a string or an array if the object implements more than a type. This is mandatory in ActivityPub.
  • id: a unique identifier for the object. For ActivityPub this field should be a URL. The interesting part is that you can retrieve the full object information making a GET request to this URL with the ActivityStreams accept header. This allows us to send just the id instead the full object information in many cases.
  • content: The content or textual representation of the Object, usually an HTML string.
  • name: A simple, human-readable, plain-text name for the object.
  • summary: A natural language summary of the object encoded as HTML.
  • image: A link to an image that represents an object.
  • @context: This is the only necessary property to accomplish with JSON-LD specification. In our examples we just set to "".

Natural Language Values

So any object can have those fields. It is interesting that any field likely to be translated, like content, name or summary, can be renamed to a “map variant” to include different languages, ie:

"@context": "",
"type": "Note",
"id": "",
"content": "This is a translated note"

"@context": "",
"type": "Note",
"id": "",
"contentMap": {
"es": "Esto es una nota traducida",
"en": "This is a translated note"

“Data Container” Objects

You may have noticed that the type of the previous object is "Note" instead of "Object". A Note is a subtype of object defined by ActivityStreams too, and it is used to represent any short written work. A subtype means that share the same fields, but it may define more if needed.

There are some more defined types like Article, Image, Page, Document, Video, and more. While it may feel strange to not see something like comment or similar, ActivityStreams is very generic and we have to keep this in mind. The recommendation is to use Note because it “Represents a short written work”.
Those objects may be considerated “data container” objects. They don’t define more fields and they are used to transmit information.


In addition to those “data container” objects, ActivityStream defines Activity objects. The type of those objects may be more intuitive:

  • Create
  • Delete
  • Update
  • Add
  • Remove
  • Join
  • Follow
  • etc

They are the type of actions that you can expect from a social network. Special attention should be paid to the Announce activity, as it used to call attention to particular objects or notifications. It can be understood like a “retweet” on Twitter, or a simple way to share an already created object in your social network.

Activities may have 6 additional properties compared to a simple object:

  • object
  • actor
  • target
  • origin
  • result
  • instrument

Of course, not all of them make sense in every type of activities, so they are optional. So imagine you want to represent that Luke created the previous note, you can write:

"@context": "",
"type": "Create",
"id": "",
"actor": "",
"object": ""

Here, you only used actor and object. The more common ones. You don’t need to use the rest of them if they do not make sense in your activity.

One important thing to keep in mind is that the ids of the objects will not always appear, and the complete specification of them may appear instead. The previous example could be written in the following way, both being completely valid:

"@context": "",
"type": "Create",
"id": "",
"actor": {
"type": "Person",
"id": "",
"name": "Luke"
"object": {
"type": "Note",
"id": "",
"contentMap": {
"es": "Esto es una nota traducida",
"en": "This is a translated note"


If you take a close look at the previous example you will see that Luke is a Person, this is a type of Object we haven’t yet mentioned. Person is one of the 5 types of actors that ActivityStreams defines:

  • Person
  • Group
  • Organization
  • Application
  • Service

Actors are objects that may execute the different activities, this means they can be used as the actor field on an Activity. An actor has two mandatory properties as well:

  • inbox
  • outbox

The previous two properties are mandatory for any actor. The following properties are not but they are recommended to be implemented:

  • following
  • follower
  • liked


All these five properties are from a core type we haven’t talked about yet: Collections. As you’d expect, a Collection is simply a group of objects. They also have additional properties, ie: totalItems with the number of elements in the Collection or items where you’ll find the objects in the collection.

So this means that the inbox of an actor is just a Collection containing all the activities received by the actor. The outbox contains all the activities sent by the actor. Any time an actor likes an object, this is added to their liked collection.

Obviously, after a while, those collections cannot be managed with just an array. It will be impractical to manage all the followers of a popular person in a simple array. For this reason, we have the last core type of ActivityStreams: the CollectionPage which should be used to paginate a full Collection.

Core types

So those are the 5 core object types that ActivityStreams defines:

  • Object
  • Actor
  • Activity
  • Collection
  • CollectionPage

All of them are also an Object, so they share most of the fields. Once you understand this vocabulary it becomes easier to work with the ActivityPub protocol.


A big difference from working with other private social networks is the “Audience Targeting”. All objects can use 5 optional fields for this:

  • to
  • bto
  • cc
  • bcc
  • audience

Not only that, but it is the client application that fills in these fields. It can be just an actor, but maybe is your followers collection or it is just “public”. This can be better understood with the following examples.


Sending a private message

First of all, messages are always activities in ActivityPub. So if you want to send a private message to Ben, you have to build a Create activity with a Note. It is equally important to set the field to to only Ben’s id, because is a private message between Alyssa and Ben. You don’t want to make it public or to share with your followers. The JSON could be something like the following:

"@context": "",
"type": "Create",
"id": "https://social.example/alyssa/posts/a29a6843-9feb-4c74-a7f7-081b9c9201d3",
"to": [
"actor": "https://social.example/alyssa/",
"object": {
"type": "Note",
"id": "https://social.example/alyssa/posts/49e2d03d-b53a-4c4c-a95c-94a6abf45a19",
"attributedTo": "https://social.example/alyssa/",
"to": [
"content": "Say, did you finish reading that book I lent you?"

This is a Create activity because, of course, the message didn’t already exist. As you can see, the actor property is just a Link with Alyssa’s ID. Not need to send the full object. Similarly with the property to with Ben’s ID, but in this case in an array.

ActivityPub defines that a client should always create new activities talking to the server where the user’s account resides. In this example, Alyssa account resides at “https://social.example/”. Once the message is received by the server it is persisted so it can be requested at any time, but also, it detects that the recipient of the message does not belong to this server. This means that it’s now the server which should communicate this message to Ben’s server, in this case: “https://chatty.example/ben/”. It will send a post request to Ben’s inbox. It should then be Ben’s server that notifies Ben that he has a new message.

Add an image to an album

In this example we are working with images. The user Alyssa just move an image from her “Camera Roll” album to “My Cat Pictures”. The client application generates the following activity to represent the action that just happened:

"@context": "",
"id": "https://social.example/alyssa/activities/10239"
"summary": "Alyssa added a picture of her cat to her cat picture collection",
"type": "Add",
"actor": "https://social.example/alyssa",
"to": "https://social.example/alyssa/followers",
"object": {
"type": "Image",
"name": "A picture of my cat",
"id": ""
"origin": {
"type": "Collection",
"name": "Camera Roll"
"id": "https://social.example/alyssa/collection/1"
"target": {
"type": "Collection",
"name": "My Cat Pictures",
"id": "https://social.example/alyssa/collection/278"

This activity is public only for the Alyssa’s followers. The client application send this activity to the Alyssa’s server. Now it is the server which has to locate all her followers and make sure that they receive this activity in their inbox. Maybe they are all locals, they resides on the same server, or maybe it has to send this activity to many external servers.

Follow request

In this scenario, Sally asks John to be friends in our application:

"@context": "",
"id": "",
"summary": "Sally requested to be a friend of John",
"type": "Offer",
"actor": "",
"object": {
"summary": "Sally and John's friendship",
"id": "",
"type": "Relationship",
"subject": "",
"relationship": "",
"object": ""
"target": "",
"to": "",
"cc": ""

We make this request using the Offer activity type with a Relationship object and with the target John. Now John can accept the offering with:

"@context": "",
"summary": "John accepted Sally's friend request",
"id": "",
"type": "Accept",
"actor": "",
"object": "",
"inReplyTo": "",
"context": "",
"to": "",
"cc": ""

It is interesting to see that in this application, the creator decided to make public this kind of interactions. To make public an object we have to add to any “targeting property” the value "", in this case in the cc property.


It is important to remember that ActivityPub is a protocol. It defines the expected behaviour but never the implementation details behind it. The client sends activities to the server. The server federates the same activities to other servers. The client can fetch for activities and the server should provide them. The way you do it is completely up to you.

There are a lot more things around ActivityPub, here we only scratched the surface. There are more types in the vocabulary, the possibility of extending it with your own types and properties, security recommendations, side effects, client and server responsibilities, etc. The goal of this article was to give a small introduction without getting lost in technical formalities. I hope you enjoyed.

This post was also published in Alex Castaño’s blog.

Photo by Marius Christensen

What is Emoji ID?

One thing you may have seen in the prototypes and mockups for MoodleNet is something called ‘Emoji ID’. You might be wondering what that is, even if you’ve heard us refer to it in a presentation or at a workshop. In this post, it’s my aim to explain it in the simplest way possible.


The problem

MoodleNet is a decentralised social network. This means that, unlike Twitter, Facebook, Instagram, or other centralised social networks, you can join one of a number of ‘instances’. As it’s possible to join more than one instance, your username isn’t just, for example, @dajbelshaw but or

Think of it like email, which is also a decentralised system. You can’t just type someone’s username to send them a message, you also have to include the relevant domain name. So, for example, you can’t just enter ‘ibrahima’ but have to use ‘’.

Back to social networks and let’s imagine that I’m looking for Mayel de Borniol, MoodleNet’s Technical Architect. Here’s what happens on Mastodon, which is kind of a decentralised version of Twitter:

Mastodon searching for 'Mayel'

Mayel’s got at least three accounts of which I’m aware. So which account should I use to start a conversation with him? If I get the wrong one he might not reply because it’s no longer in use, he uses it for other activities, or I’ve got the wrong Mayel.

Going further, what happens if someone deliberately sets up a parody, spoof, or catfishing account on a different instance but with the same username and profile picture? How do I know which one is the ‘real’ Mayel? Sure, I could perhaps try and memorise the longer username (e.g. but that seems unwieldy.

Surely we can do better?


The idea

Earlier this year, on my personal blog, I proposed an idea for using ‘emoji triplets’ as identifiers in decentralised social networks. I’d already started using them to add a bit of personality to my username on both Twitter and Mastodon:

Mastodon: emoji triplets

Other people use them too:

Eylan Ezekiel Twitter profile Maddie Mastodon profile

This can aid with identifying someone, especially if they’ve got many accounts or a particularly common name. Humans are good at recognising patterns, especially with items numbering fewer than seven, so combinations of three emojis work well.

Of course, these examples simply involve people adding emoji to a text field such as their display name. There’s nothing to stop people adding the same emoji to their profile as someone else. However, what if there was a separate field for the three emoji that are unique to that user? What if, once that user chose a particular combination of emoji, no-one else could?


The implementation

Every platform, whether it’s an email service, social network, or something else, has to have a way of identifying individual users.

Simplifying things a bit, anything you do on a platform involves linking a particular user with a particular action. In the code this is usually done through numbers, so for example user ‘783’ followed user ‘392’. Meanwhile, in the user interface you see something like ‘’ followed ‘’.

Mastodon profile - labelled

In other words, ‘’ is a fixed alias of user ‘783’. While I can change my Avatar and Display name as often as I like, I can’t usually change my Username. If I decide that I instead want to be, then I have to register a new account.

So, instead of email-like usernames that are long and difficult to remember, what if there was a separate field for emoji triplets? All of a sudden this become not just a decorative feature but something like an ‘Emoji ID’. There are several advantages to this:

  • Quick and obvious way to recognise a user even if they change their display name and/or avatar
  • Provides a standard, searchable way for users to customise their profile
  • A first step towards ‘nomadic identity’ (i.e. a way to move from one instance of the network to another without losing your followers)?

Here’s how it works:

  • User goes to sign up at a MoodleNet instance which is connected to Moodle HQ’s API
  • MoodleNet instance offers up a random, unique, and currently unused emoji ID to the user as part of the sign-up process. They can accept this, or choose their own so long as it hasn’t already been taken by another user.
  • Once the user has chosen their emoji ID it is registered both at the MoodleNet instance level and by the Moodle HQ API service, which makes it unique across all instances.


Additional information

Whether it’s to follow them, find the collections they’ve curated, or get in touch, users can be found by searching either for their display name or Emoji ID.

Using Emoji IDs opens up a whole world of possibilities. For example, one of the advantages for organisations using Moodle’s Branded Moodle Mobile App (BMMA) is that, when logging in, users no longer have to remember and type in the the exact domain name of their Moodle instance. Emoji ID could provide a similar solution for MoodleNet users, who then only have to enter three emoji, not (for example)

We could also help indicate which instance a user is on by reserving the first emoji for that purpose. So, for example, 💥👻💪 and 💥🎄🐻 would both be users on the same instance. Perhaps, similar to Sony’s plan for PlayStation users to be able to change their usernames for a fee, you might be able to associate a new Emoji ID to your account at a future time.



Before publishing this post, I shared several drafts with the team and various networks. Here’s some questions I received. Some of these are technical.

What’s the theoretical limit of unique emoji IDs?

Unicode 11.0 has 1644 unique emoji. So according to my calculations, there are 739,198,844 permutations. However, we may not use all the emoji as some are flags, Japanese symbols, etc. Either way, it’ll be a while before we have to worry about running out of unique Emoji IDs!

Doesn’t Emoji ID (and in particular a Moodle HQ API) break federation?

It doesn’t ‘break’ federation, it’s just a layer on top. Let’s say there’s a MoodleNet instance that isn’t connected to the HQ API. If a user on that instance wants to find a user or community on a different instance, they’d need the Emoji ID and domain name, or simply the URL.

Could I ever change my Emoji ID?

Theoretically, there’s nothing stopping us adding multiple Emoji IDs to a single backend identifier. So user ‘783’ might have several different Emoji IDs associated with it. We’d only ever show one, but the others would be reserved to prevent anyone else using them.

Many thanks to Mayel de Borniol, Emma Cragg, Noel De Martin, Brent Flanders, and Oliver Quinlan for their comments on earlier drafts of this post. Anything that leaves you confused or befuddled remains my fault. (Sorry!)

Reflecting on feedback from testers about the user sign-up process

User testing

Last week, the MoodleNet team were in Barcelona at Moodle Spain HQ. Much of the work week involved the kind of discussion and implementation that can be difficult to write about, as it mainly involved hooking up the backend and front-end code.

Kayleigh and Sam from Outlandish joined us in the office on Thursday and Friday, which meant that we had an opportunity to reflect on the results of some testing they did with users about the sign-up process for MoodleNet. Their findings are below (or click here).

Based on user feedback, which is always different from what you expect, we’ve decided to take a different approach to the sign-up process. It became clear that there are users who want to get straight in and start using platforms straight away. These are the kind of users who will complete their profile later.

On the other hand, there are users that want to complete their profiles straight away, so that they have a full ‘presence’ on the platform and others can find out more about them.

Our proposed workflow, which will have a knock-on effect on other elements of the user interface, is below (or click here).

What are your thoughts on this? Note that we’re planning to implement a (skippable) user tour for first-time users of MoodleNet. We’ll also be writing a post soon that explains ‘Emoji ID’ and why it’s more than just a cute thing to have on your profile!

Image by José Alejandro Cuffia used under the terms of an open license

Provide feedback on our draft Contributor Covenant!

Update: the consultation period is now closed — thanks for your comments!


A ‘Contributor Covenant‘ is a code of conduct for contributors to Open Source projects such as MoodleNet. The original version, adopted by over 40,000 projects, is based on the work of Coraline Ada Ehmke.

We have been inspired by this and other approaches to create a draft Contributor Covenant for MoodleNet. It will be used for:

  • Code contributions and interactions between community members
  • Beta testing (after which there will be a user agreement)
  • Security reviewers

Before we call this ‘version 1.0’ we would like feedback on our draft Contributor Covenant from the Moodle community. Here’s how to do it:

  1. Read the entire document
  2. Think about a traffic light system for giving feedback:
    • What’s good? (green)
    • Do you have any questions? (amber)
    • Does anything concern you? (red)
  3. Select the relevant text and ‘add comment’

This document is open for feedback over a two-week period from Wednesday 21st November to Wednesday 5th December 2018.

Link to draft Contributor Covenant:

Image by rawpixel used under the terms of an open license

Testing MoodleNet sign-ups

Update: sign-ups for this are now closed, and Outlandish will be in touch with those who registered their interest!

Usability testing

Over the next couple of weeks we’re going to be doing some online user testing of MoodleNet’s sign-up process. It will be run by Outlandish, with whome we’ve been working on front-end development and UX.

We’re aiming is to remove any barriers to adoption for the beta testing in January. So we need feedback on everything from “that button should be on the left” to “what on earth is that emoji ID thing?!”

It’s not remunerated, but you’d be front of the queue for a MoodleNet beta account (of which there’ll only be 100, initially) next year!

If that sounds like the kind of thing in which you’d be interested, here’s what to do:

  1. Introduce yourself here
  2. Check your availability for the following dates (GMT): Weds 14th (PM), Mon 19th (PM), Tues 20th November
  3. Fill in this form

Thanks in advance! We’re looking forward to making MoodleNet as awesome as possible!

Privacy notice: if you volunteer for testing, your details will be added to a spreadsheet, stored on Moodle HQ’s Google Drive. We’ll keep your information until the end of the testing process and share your details with Outlandish, who are overseeing the testing process. Before testing, you’ll be required to give your consent to ensure GDPR compliance.

Feedback from #MozFest and #MootUS18

Last week, members of the MoodleNet team ran well-attended sessions at the Mozilla Festival (London, UK) and the US MoodleMoot (Denver, CO, USA). The former was set within a wider framework of the decentralisation strand at MozFest, and the latter was an opportunity to gather ideas and feedback from a subsection of the Moodle community.

MozFest session post-its


Notes from the session

As anyone who has been will know, the Mozilla Festival is a mind-blowing weekend of sessions, talks, and collaboration, all focused on the open web. Our accepted session proposal was based on MoodleNet, but also on the wider concept of decentralisation — particularly in relation to the ActivityPub protocol.

Participants in the session ranged from educators who were dipping a toe in the water of decentralised technologies, through to those who worked with, or for, the W3C.

As well as feedback on what we’re trying to build with MoodleNet, a key aim for the workshop was for participants to be able to explain the importance of decentralisation using stories, metaphors, and allegories.

Some of our favourites included:

  • “FREEDOM to do weird stuff”
  • “In nature there is no boss and it’s evolved, is sustainable and resilient”
  • “Distributed power, be it online, in person, or how we live”
  • “Put your OER to the fediverse and gain more attraction”
  • “You can have nice things without being the product”

MoodleMoot US post-its


Notes from the session

MoodleMoots are events for the Moodle community which encourage collaboration and sharing of best practices. We ran very interactive session, with the aim to get as much feedback from workshop attendees as possible.

There were a range of participants, from Higher Ed CIOs, to K12 educators, to representatives from the corporate world. We learned a lot from the feedback we received, with some of the highlights being:

  • Insight into some of the tools that people are using that we haven’t come across before.
  • What participants liked about MoodleNet, what they have questions about, and what concerns them.
  • What we should add to MoodleNet after the core resource-sharing component.
  • Anything we’ve missed or haven’t discussed.

Interestingly, after the session, where participants had a lot of chance to ask questions and give feedback, two people came up to us separately and asked variations of the same question. Would organisations, they asked, be able to completely lock down MoodleNet so that it can only be used within that organisation?

We explained that this was not what we are aiming for with MoodleNet but that, of course, as open source software, there would be nothing stopping people from creating a version that would do this. We believe in the free and open sharing of educational resources, while recognising that there are some occasions (e.g. copyright, local laws) where resources would have to be restricted in some way.

We’re still working on working out the nuance here. One simple model is that which GitHub, the code-collaboration platform, uses. Creating a public repository on GitHub is available with a free account but, if you want to create a private repository, you have to pay. There’s an obvious parallel here with MoodleNet and collections, the key difference being the decentralised aspect.

Remember that anyone can suggest features for MoodleNet via our easy-to-use Changemap site!