Future of Learner Dashboard architecture

On edX.org, we need to support a learner dashboard that includes some learning experiences (e.g. courses) that are available from other products, not hosted in the Open edX LMS learning experience. I’ll refer to these as “external learning experiences”, meaning “external to the Open edX LMS learning experience.”

Additionally, our team structure provides some additional context for our preferred architecture, because we’d want it to work with, and not against this team structure.

Learning Platform:

  • LMS learning experience
  • Studio (authoring of learning experience)

Marketplace:

  • Course discovery
  • Ecommerce
  • Enterprise features
  • Learner identity

Borders on both teams:

  • Learner dashboard (currently serviced by monolith)
  • Credentials (monolith + credentials service)

Finally, note that the concept of “external learning experiences” only affects Marketplace functionality and the border functionality (e.g. learner dashboard, credentials).

Regarding the need to support external learning experiences in strictly Marketplace functionality, there will need to be separate posts to address this. It is less clear who in the community uses the various parts, and although this needs to be addressed, it is out of scope for the rest of this post.

This post will focus solely on the learner dashboard, because even within our own organization, it brings up interesting design questions. Adding in the rest of the community adds an additional twist.

Here are some architectural options for a future learner dashboard that can support external learning experiences:

  1. Retain use of the existing Learner Dashboard MFE, only adding optional support for external learning experiences.

    a. Option A: Have the MFE call a variety of services, directly requesting data from the external sources in addition to the monolith, and combining data on the frontend. Note: I’m making an assumption that a simple UX would require combined data, and would rule out frontend plugins for certain functionality.
    b. Option B: Update the monolith’s backend apis that support the MFE to also support external learning experiences, or
    c. Option C: Use a new backend service that supports external learning experiences.

  2. Create a second unique Learner Dashboard MFE (External Edition).

    a. For simplicity’s sake, I’ll assume that if we are separating out support for external learning services in a new MFE, we’d probably want to do the same with a new supporting backend service.

  3. Are there better options?

One missing data point: would anyone in the community want similar support of external learning experiences from within the Open edX platform, and specifically for the Learner Dashboard experience?

As a maintainer of edx-platform, our beloved monolith, I have a preference for any solution that does not add support for external learning experiences to the monolith as part of supporting this dashboard. I’d prefer that the parts of the monolith supporting the learning experience remain purely focussed on LMS hosted learning experiences.

That said, the point of this post is to discuss and see what ultimately makes the most sense. Feel free to amend, or agree or disagree with anything I’ve posted, including any assumptions I’ve made.

I wonder if you could do this using filters on those APIs, so that the monolith itself doesn’t need to be modified? I think that option would require the fewest changes to the existing codebase(s).

Generally this sounds to me like the role of an LXP, not an LMS. So I lean toward thinking that it does not make sense to build LXP functionality into our LMS, but rather to improve its integration with LXPs or build a reference LXP. This sounds like a Core Product question though so perhaps there isn’t yet an answer. CC @jmakowski

Alternatively, “build/find an LXP, and add functionality to Open edX to configure the use of an LXP in lieu of the LMS dashboard” ?

In any case, I think a lot of the MFE vs. backend question here depends on your exact use case. Are the external courses treated, displayed, and interacted with in exactly the same way as the “internal” courses? If so, probably makes sense to push this into the backend, preferably using filters or something like that. If they need different display formats, or show different progress status, or have different types of navigation, or are interacted with differently, then it probably makes more sense to do a frontend solution.

1 Like

Thanks Braden. I’ve seen a lot of different definitions of LXP out there, but I agree that using a different term like LXP is helpful to talk about this split. I imagine that the edx.org version of this might be highly customized to 2U, and it remains to be seen how reusable our version will be, and who else would even have interest in it. That said, agreeing that this functionality doesn’t belong in the LMS (if anyone were interested) is part of what I was going after.

It is possible. However, as I noted in my post, I do not want to add more to our deployment of the monolith, so even if this could theoretically be plugged in, I agree with your earlier stance and would like to keep this functionality out of the LMS, even for us.

I guess my main questions were:

  1. Would the community want anything like this? And, I think your note about an LXP roadmap item is a great step for getting clarity for this, and
  2. If the LXP functionality were added to the platform, did the community think that architecturally this belonged directly in the LMS? And, your answer confirms that you too would think of LXP functionality separately.

This is actually exactly what we ended up doing to support external content in our b2b experience.

The challenge is what should be core and what is a plugin is a bit opaque right now.

Your post back in March around pulling Enterprise out of the platform is a similar conversation that doesn’t happen. Should the platform support external content and who makes that decision? Is the relationship between a learner and their organization/company valuable feature of the platform? As you said: “This sounds like a Core Product question though so perhaps there isn’t yet an answer.”

I just posted this in a Slack thread, but realized I should put it here. :wink:

Caveat: I’m just being reminded that LXP is a thing today. But from trying to dig into that, I feel like an LXP carries with it the expectation that content is personalized/curated in some way, which (while really interesting) I don’t think is the spirit of where Robert was going in opening up the topic for discussion.

For 2U, its more that we can see a future where we need a unified dashboard where users can see both content from the Open edX LMS and other LMSes that our clients already use. To put that in Open edX terms, we want to show external content on the learner dashboard alongside stuff from LMS. We likely want detailed progress/completion/etc. data in there as well regardless of where the content comes from.

It’s unclear to me if there’s a good/sane way to enable that through extensibility/plugins/etc. alone, or whether anyone else has these sorts of use cases. :thinking_face: I want to make sure that if/when we get closer to this future, we’re doing the right thing for our business, sure, but in a way that’s palatable and healthy for the Open edX platform and doesn’t involve awkward, bolted on “extensions” after the fact.

Thanks @djoy.

Yes. This description is more helpful than the term LXP, which probably means something different to every person who reads it. If LXP means the same thing to you, then feel free to think about this as an LXP.

My main point is that thus far we are converging on the fact that this functionality could be added to the LMS because it is extensible, but that architecturally it feels like something that is bigger than the LMS. If someone strongly disagrees with this take, and feels that this should be LMS functionality, then feel free to argue for that.

If we agree this does not belong in the LMS, I don’t see us having awkward, bolted on extensions. I imagine a separate service, which itself may or may not be made to be extensible, depending on the needs of others.

1 Like

I could see an equally strong case for supporting external content…

Back in 2018, before LXPs were widely talked about and long before the 2U acquisition of edX, we had a few customers that wanted to host their own content. Not being our business model we referred them to Open edX providers that could help them stand up the platform on their own. However they also wanted to offer edX courses in the same experience. It was unfortunate we had to tell them while we can integrate edx.org with six other LMS/LXPs (Degreed, Cornerstone, SuccessFactors, Canvas, Moodle, Blackboard via Integrated Channels) we don’t support integrations with Open edX due to the fact it doesn’t support external content.

While the external content use case is top of mind for 2U right now as we integrate across product lines, I do believe there is value outside of 2U. I would be curious to hear from community if they’ve also experienced this need before we pass it off.

It’s also clear to me as we continue to leverage plugins to keep the core small - plugins that may or may not live within the Open edX github org - the extensions directory is critical to discoverability and configuration of those plugins. Many of us love Django for its “batteries included” toolbox. If we don’t include batteries with the platform we need to make those easy to discover, install and configure.

I should clarify that when I wrote: “architecturally it feels like something that is bigger than the LMS”, I was not saying it is bigger than the Open edX platform. I am just trying to find its rightful home within the platform. It feels to me that specifically keeping this out of the LMS service will provide cleaner boundaries, but it still could be functionality of the larger platform.

So my reflex reaction is similar to @robrap’s here, but I would like understand just how deep the rabbit hole would go.

How far would that integration have to go, and where would the obvious seams be for the users?

There seem to be at least a few broad categories when it comes to course-specific interactions:

  • Before Learning: enrollment/access control, display on the dashboard at all.
  • During Learning: progress, administration (e.g. bulk emails, resetting scores), analytics…
  • After Learning: grades, credentials, analytics, etc.

Right now, we can sort of hack in the Before Learning pieces by making a fake stub course with the most basic metadata needed by other parts of the LMS (e.g. course key, start date), having users enrolled in that, and then using a filter to send them somewhere else when they try to access the course.

Some of the course administration work in During Learning is possible to do in the Instructor Dashboard, though we’d probably want to split out the parts of it that are not content-dependent into something else. We could at least enroll students and do email communications with them here.

The After Learning pieces are dicier. There are many content-dependencies in grades and analytics. Maybe credentials could work without too much pain.

Another place where I could see a lot of user confusion arising is in cross-course features like the notifications work. If we went down the path of supporting external courses, would there be an expectation that those other courses could send notifications through the Open edX platform as well?


If you folks went the separate service way, I suspect that it would make sense just to make it 2U-specific from the outset. You’re going to want models to map between All the 2U Things, a lot of marketing/upsell stuff, etc. I think community-focus time would be best spent on crafting clean, generalized APIs where that new service has to extract data from Open edX–enrollments, grades, etc.

That being said, the bolted-on-extensions path might be a lot easier for the short-to-medium term, since it requires moving less data around. What do you see as your next big challenges if you continue down the path of keeping things in a plugin?

Thanks @dave.

Brief list of pros and cons of hacked stub courses in the LMS for external content. The list of cons more directly answers your question.

Pros:

  • We have the beginnings of this hack (stub courses) in places, and we wouldn’t need to undo it, but we’d probably still need to clean it up.
    • This is due to Open edX LMS and Studio being more tightly coupled to Discovery and Publisher than non-Open edX content.
  • As you noted, there might be less data to copy, because LMS/monolith already contains so much data.
    • However, the event bus hopefully opens doors that weren’t available to us before.
    • Also, if we want cleaner boundaries, might we want separate models (e.g. for enrollments, like Enterprise currently does), rather than mucking with the LMS enrollment data?
  • Probably quicker to get something going.

Cons:

  • LMS/monolith grows even larger, which has the following issues:
    • Increased friction with additional splits in ownership.
    • Increased collaboration on extensibility that otherwise would not be required.
    • Increased risk, surface area, and potentially MTTR for any LMS issues.
  • The stub-course design makes the design more complex.
    • Most functionality needs exceptional handling for locally hosted content vs foreign content.
    • It makes boundaries between the LMS learning experience and other functionality blurrier, and easy to overstep.
  • Plugins still have lots of hidden costs in the short-to-medium-term.
    • Dependency management and testing are the two biggest issues that come to mind.

A separate service, especially a 2U-specific service, reverses the pros/cons, but still has its own pros and cons. There are no perfect solutions.

I don’t have a final solution, but this won’t be the only place where we will need to dip in and out of the Open edX platform. Hopefully the event bus can help in certain areas, but there will be other design questions. Consider ecommerce, or credentials, etc. Will the Open edX platform be considered a closed system that can’t handle courses taught through the Open edX LMS? For 2U, we already know that can’t be the case, but what Open edX platform services expand their functionality to handle external courses remains to be seen.

I might go a bit off topic here, it’s just I can’t think of this without thinking of a big picture.

If we take a step back and think how LMS has evolved, from server side rendered content to a Restful like service where frontend transformed into a web app.

This probably came at a cost of which earlier one when extending the platform one can easily alter both backend and UX/UI (by overriding or creating a new template. However this is no longer as easy as it used to be with the MFEs, like should I create a standalone MFE just to add a little thing?

my 0.02 cent is that we develop a standard scheme data, where the MFE doesn’t need to know of the implementation details of the service that it’s communicating with. It’s just both MFE and the service respect the data scheme.

Now going back to our use case here, supporting external content would an implementation details, in short to support external service x; create an interface between it and the data scheme standard. And then the question where does that interface/transform code would live wouldn’t be hard, it can be a plugin or IDP, in the end all the MFE needs to know about is the URL of that unknown content but respects a specific data scheme.

Thanks @ghassan. Yours is a very reasonable suggestion if the UX between the two experiences are similar enough that it makes sense to keep a single MFE implementing both. At this point, the UX is not well defined enough to make that call.

I brought up the MFEs in the first place, so your post is definitely on topic. That said, my personal motivation was more about proposing/discussing a separate service for the backend, regardless of whether it is a 2U-specific service in the short or long term.

@robrap I don’t think it should be simliar, but of course the more simliar is the less complicated it would be.
Thinking of the MFEs patterns, we usually have tabs, container, cards, and we could abstract it in a away that the extneral content could be of any type, if it’s of tab type, then the content is expected to be rendered in spesfic page, while API would return the virtual-dom like object of which the MFE would rendere by mapping it to paragon componenet.

An example object would be that returned from a call

{
  "type": "paragon/container",
  "content": [
    {
      "type": "paragon/card",
      "props": {
        "text": "I am text"
      }
    },
    {
      "type": "paragon/image",
      "props": {
        "href": "example.com/img.png"
      }
    },
    {
      "type": "paragon/button",
      "props": {
        "name": "Enroll",
        "onClick": {
          "type": "event",
          "method": "POST",
          "url": "https/myseve.",
          "body": {
            "ids": [
              "1",
              "2"
            ]
          },
          "onSuccess": {
            "type": "event",
            "method": "rerender",
            "content": {
              "reqeust.body.id": "DOM.id"
            }
          }
        }
      }
    }
  ]
}

This is just a random example, my point is that we can apply this in any MFEs, this probably the bit that might be off-topic.

Thanks again @ghassan. Agreed that this is interesting, but we’ll probably need to hold off on the MFE design until we have more details around the experience we are trying to accomplish. At that time, we can take up this topic again. Or, if you want to push it further and start a frontend conversation now, maybe we could start a new topic.

1 Like

@robrap Could you (or someone on the product team) share more about the use cases for this need? Are these external learning experiences limited to other 2U products, or does the need extend beyond 2U? Which profiles of learners need this functionality? What’s the relationship between these external products and edx courses/programs? What’s the expected user journey, ie for learners to jump between in-progress products, or to complete one and then move onto the next?

@jmakowski: Apologies, but I did not create this post from clarity on the product-side, but from my own wish to ease ownership pain through some Conway-informed architecture.

For the sake of this engineering discussion, I think it is enough to imagine the part of a learner dashboard (or learner home) experience where the learner sees a list of their current enrollments and can navigate to any of these courses. For 2U, this would entail 2U products (at this time), some of which are edX courses, and some of which are not.

For the sake of this post, I am going to assume that any additional user journeys, or functionality like programs, etc., would be simpler to incorporate into a new supporting backend service as well, or at least would not fundamentally change community interest in turning this into core LMS functionality.

Does this answer your question enough for the sake of this post?

@jmakowski,

So I’m not on the product team at 2U, obviously, but I think I can take a stab at the spirit of what we see coming down the pipe.

To borrow some language from Anant, we want to support learners in their lifelong learning, and to offer a suite of “free to degree” products. Many of our learning experiences aren’t currently in the Open edX ecosystem and are completely different technology stacks, joined together on our marketing site (www.edx.org). That may be the case for some time.

So the relationship between these external products and edX courses/programs is that, while different technology/LMS, we ultimately want to provide a seamless UX as learners move between our learning experiences/products. I think the expected user journey is probably both of what you described - jumping between in-progress products and helping learners find the next thing that’s right for them. Today, I think Learner Dashboard is kind of the central hub where both of those activities happen, or at least start (for logged in users).

So ultimately we’re trying to figure out the right way to accomplish this, which may take a combination of new data sources/APIs from 2U-specific systems (that are potentially unrelated to Open edX!) to give us enrollment/progress data, and a UI where that data is displayed to the user. If we can abstract our needs a bit into a notion of supporting “external learning experiences”, and if that’s attractive to Open edX as a feature (or at least something we can plug in in a healthy way), we can investigate how we might do that. If, on the other hand, we don’t think this sort of thing is attractive to the platform, that may help us think about how we do it just for our own needs. … Which is also healthy for everybody. :smile: