Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 110 additions & 24 deletions source/developers/concepts/about_xblock_asides.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ data, and UI elements to many XBlock instances at once, across XBlock types you
do not own, while preserving the host XBlock's code, fields, and Open Learning
XML (OLX) representation.

.. warning::

Asides have many limitations, including issues around course import and
export. See :ref:`Aside Limitations` for more detail.

.. contents:: Contents
:local:
:depth: 1
Expand Down Expand Up @@ -135,21 +140,44 @@ XML child element under its host block, named after the Aside's entry point
name. On import, the runtime reconstitutes the asides automatically. This
means an Aside-enhanced course is portable, with limitations described below.

Reaching Outside the Iframe
============================

An Aside's fragment renders inside the same iframe as its host block, so
its JavaScript is confined to that iframe unless it does something about
it. The browser's ``postMessage`` API is the way out. The Learning
micro-frontend already recognizes a handful of built-in message types
(for things like opening a modal or resizing the frame) that any Aside
can send for free, with no setup. Beyond those, an Aside can post a
message with any custom ``type`` it defines, but nothing reacts to a
made-up type by default — something has to be listening for it. That
listener is a deployment-time addition, registered through the Learning
MFE's own runtime configuration, not a fork of the MFE itself. MIT Open
Learning's "AskTIM" chat button (the `ol-openedx-chat`_ Aside, described
next under "Real-World Examples") works exactly this way: its
JavaScript posts a message, and a small companion script MIT deploys
alongside the MFE listens for it and opens a chat drawer. See
:ref:`XBlock Asides Reference` for the full mechanics and
:ref:`Add an XBlock Aside` for a worked example of both halves.

Real-World Examples
*******************

Two implementations in the wild illustrate the range of what asides can
do.
Three implementations in the wild illustrate the range of what asides can
do, from a bare waffle-flag toggle to a fully wired author-facing UI.

Rapid Response XBlock
=====================

The `rapid-response-xblock`_ from MIT Open Learning is a single Aside that
applies to Problem blocks. It overlays an instructor-only control on the
problem in the LMS that lets a live instructor open and close response
windows during a lecture, and it renders a real-time chart of student
responses. Course authors enable it per problem in Studio. The repository
name calls it an "xblock" but the implementation is purely an Aside.
applies to Problem blocks restricted to a single multiple-choice response
type. It overlays an instructor-only control on the problem in the LMS
that lets a live instructor open and close response windows during a
lecture, and it renders a real-time chart of student responses. A Boolean
field enables or disables it per problem, exposed through a checkbox in
its ``studio_view``; a companion, Django-settings-gated ``author_view``
shows the same checkbox in Studio's author preview. The repository name
calls it an "xblock" but the implementation is purely an Aside.

Open Learning Chat Aside
========================
Expand All @@ -160,7 +188,30 @@ context-aware chat drawer that streams messages to a backend large language
model, passing block-specific context such as a video transcript identifier
or a problem's siblings. A single Aside class, registered as one entry
point, handles both block types and uses ``should_apply_to_block`` to gate
on a course-level waffle flag and per-course settings.
on a course-level waffle flag, the block-type check, and a course-level
enabled setting together. A course-author checkbox in its ``author_view``
toggles the button per block, backed by a scoped field and an AJAX handler.
See :ref:`Add an XBlock Aside` for a full walkthrough of this pattern.

Structured Tags Aside
=====================

The `StructuredTagsAside`_ ships with the Open edX platform code by default, in
``cms/lib/xblock/tagging/tagging.py``. It attaches a tag picker to
Problem blocks so course authors can apply structured tags for content
search and organization. Unlike the other examples, its entire
author-facing configuration UI *is* its ``AUTHOR_VIEW`` fragment — there
is no separate toggle checkbox, just the tag picker itself, and the
picker only appears at all when Studio's aside-rendering gate (see
:ref:`XBlock Asides Reference`) is enabled. It has no
``should_apply_to_block``
override; it instead checks ``isinstance(block, ProblemBlock)`` inline
inside its view method. Its own author view method is, confusingly,
still named ``student_view_aside`` even though it is decorated for
``AUTHOR_VIEW`` — a reminder that an Aside's view method names are
conventions, not requirements enforced by the framework.

.. _Aside Limitations:

Limitations
Comment thread
asadali145 marked this conversation as resolved.
***********
Expand All @@ -171,15 +222,35 @@ state of the codebase as of the Sumac release and from a 2025 Open edX
Conference talk by Peter Pinch of MIT Open Learning. Read it before
committing to an Aside-based design.

No Authoring Story in the Course Authoring MFE
==============================================

The Studio author view for an Aside is rendered by the legacy course
authoring frontend. The current Authoring micro-frontend has no
defined location to display Aside author UI. If your project depends on the
new MFE for authoring, plan to render the Aside's author UI through a
different mechanism, or accept that authors will use the legacy Studio for
this part of the workflow.
No Native Authoring Story in the Course Authoring MFE
======================================================

The Authoring micro-frontend has no native code for rendering or
toggling Asides — it does not know Asides exist. What it does have is
a unit editor that embeds the legacy Studio unit page in an iframe, so

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, I think I'm not following here though. What do you need to do, as a course author), to look at the legacy Studio unit page to see the Asides render?

Expanding on this, will the deprecation of legacy Studio break this flow entirely? And if you can only see Asides in legacy Studio, how do things render in the learning MFE?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First of all, we should understand that AUTHOR_VIEW and STUDIO_VIEW are 2 different things that can serve an identical UI/View, but it is rendered in different places in legacy Studio. So, I used AUTHOR_VIEW or STUDIO_VIEW in the usage.

What do you need to do, as a course author, to look at the legacy Studio unit page to see the Asides render?

If you are using legacy Studio, and an aside supports both AUTHOR_VIEW and STUDIO_VIEW, you should see it render in 2 places:

If you are using the new authoring MFE:

  • Open a course
  • Open a unit page with a block that the aside supports
  • You should see AUTHOR_VIEW rendered with the block contents at the end of the block. This is the same as above for the legacy unit page.

will the deprecation of legacy Studio break this flow entirely?

No, it will not break because the new authoring MFE uses an iframe to render the unit page, and it still supports the AUTHOR_VIEW, and we use it in the MITODL-maintained asides.

And if you can only see Asides in legacy Studio, how do things render in the learning MFE?

learning MFE displays STUDENT_VIEW of an aside so it will display whatever the Xblock Aside's STUDENT_VIEW returns. Regardless of its support in authoring MFE.

MORE DETAILS

Let me simplify all this for you. We have 2 studio views/UIs: legacy and new authoring MFE.

  • We have 2 aside views, AUTHOR_VIEW and STUDIO_VIEW, in an aside's code. The main purpose of these 2 is to configure the Aside data if needed, like enable/disable.
  • Legacy studio UI:
    • Legacy studio supports both AUTHOR_VIEW and STUDIO_VIEW of asides. Author and Studio views render in 2 different places.
    • AUTHOR_VIEW renders on the unit page; this is supported in both legacy and new authoring MFE. The unit page is basically an IFrame served by the studio backend. It has no connection to Authoring MFE, apart from the fact that it just renders the Iframe served by the studio backend.
    • STUDIO_VIEW renders at:
      • Click the edit button on a block, like a problem block.
      • In the editing dialog UI, there should be Editor, Settings, and Plugins in the title bar. Click "Plugins".
      • You should see the STUDIO_VIEW rendered here. MITODL's legacy repo for rapid response aside, has some details https://github.com/mitodl/rapid-response-xblock/tree/master. NOTE: This is a deprecated repo referenced here for clarity in Studio View.
  • Authoring MFE / new Studio UI:
  • Learning MFE
    • Learning MFE displays the STUDENT_VIEW of an aside, so it does not depend on AUTHOR_VIEW or STUDIO_VIEW.

Let me know if you need more help understanding this. We can even have a meeting to clarify the understanding.

an Aside's ``author_view`` UI (a checkbox, a tag picker, whatever the
Aside renders) shows up inside that embedded page when authors use the
new MFE, exactly as it would in legacy Studio, gated by the same
``StudioConfig`` setting. There is no separate MFE-specific toggle to
configure. The embedded page and the MFE aren't otherwise isolated
from each other, either — they already exchange at least one real
``postMessage`` today. See :ref:`XBlock Asides Reference` for the full
mechanics of both the Studio-side gate and this iframe relationship.

A Host Block Vanishes Silently If Its Aside Is Uninstalled
=============================================================

If a course was authored with an Aside attached to one of its blocks,
and that Aside is later uninstalled or its entry point renamed,
re-importing the course does not raise any error — the import reports
success. What actually happens is worse than losing the Aside's data:
the **host block that carried the Aside is dropped from the course
entirely**. It does not appear as an error block or a placeholder; it
simply isn't there. There is no warning that anything was lost. If you
depend on a course's blocks surviving its lifecycle, treat uninstalling
or renaming an Aside that's in use as a breaking, silent change to
every course that has it attached to a block, and audit affected
courses before doing so.

Not All XBlocks Round-Trip Through OLX
======================================
Expand All @@ -188,17 +259,31 @@ OLX export and import for asides depends on the host XBlock cooperating
with the export process. Some XBlocks, including ORA2, do not preserve
Aside data through their export and import paths. If your Aside must
survive a course export and re-import on a course that uses one of these
blocks, test the round trip end to end before depending on it.
blocks, test the round trip end to end before depending on it. (This is
a different failure mode from the previous limitation: here the host
XBlock is present but doesn't cooperate with serialization; there, the
Aside itself is simply gone.)

Multiple Asides on a Single Block Are Not Reliable
==================================================

The runtime supports multiple Aside types decorating the same block in
principle, but interactions between asides on the same block are not
well-tested. Two asides that both decorate ``student_view`` on the same
block may render correctly in isolation and break when combined. If you
need this, build a single Aside that composes both behaviors rather than
relying on two independent asides to coexist.
well-tested, and this goes deeper than rendering. Two Asides attached
to the same block type that happen to declare an identically-named
``Scope.content`` or ``Scope.settings`` field share the *same stored
value* on the platform's Split modulestore, confirmed by directly
installing `ol-openedx-chat`_ and `rapid-response-xblock`_ together
with both fields renamed to ``enabled``: toggling one Aside's checkbox
in Studio's author view visibly checks the other Aside's checkbox too,
even though the two render entirely different markup and JavaScript.
See :ref:`XBlock Asides Reference` for the mechanism. Two Asides that
both decorate ``student_view`` can also render correctly in isolation
and break when combined, independent of field naming. If you need
multiple Asides on the same block type, give every field a name that's
unlikely to collide with another installed Aside, and build a single
Aside that composes the behaviors instead of relying on two independent
Asides to coexist wherever you can.

JavaScript Library Loading Is Limited
=====================================
Expand All @@ -216,11 +301,12 @@ If you are ready to build an Aside, start with :ref:`XBlock Aside Quickstart`.
If you already have a target XBlock in mind and want a step-by-step recipe, read
:ref:`Add an XBlock Aside`. For the complete list of classes, decorators,
methods, and entry points, consult :ref:`XBlock Asides Reference`. The
`StructuredTagsAside`_ may also be a helpful reference.
`rapid-response-xblock`_, `ol-openedx-chat`_, and `StructuredTagsAside`_
implementations described above are also worth reading directly as
reference material.

.. _rapid-response-xblock: https://github.com/mitodl/open-edx-plugins/tree/main/src/rapid_response_xblock
.. _ol-openedx-chat: https://github.com/mitodl/open-edx-plugins/tree/main/src/ol_openedx_chat
.. _xblock-sdk: https://github.com/openedx/xblock-sdk
.. _StructuredTagsAside: https://github.com/openedx/openedx-platform/blob/release/verawood/cms/lib/xblock/tagging/tagging.py#L17

.. seealso::
Expand Down
Loading