About XBlock Asides#
An XBlock Aside is a class that injects content into the rendered views of existing XBlocks without modifying those XBlocks. Asides let you add behavior, 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 Limitations for more detail.
What an Aside Is#
An Aside is a Python class that subclasses XBlockAside,
declares one or more view-injection methods using the
aside_for() decorator, and is registered with
the platform through a Python entry point in the xblock_asides.v1 group.
When the platform renders an XBlock view, the runtime collects every
applicable Aside, invokes its matching Aside view, and appends the resulting
fragments to the host XBlock’s rendered fragment.
An Aside is not a child XBlock. It does not appear in the course outline, it does not have its own URL, and it cannot be added to a course like a regular block. It exists only in relation to a host block, and its lifecycle is bound to that host block’s lifecycle.
For the precise API surface, see XBlock Asides Reference.
The Problem Asides Solve#
When you want to enhance the behavior of an XBlock that you did not write, you have three options:
Fork the XBlock and modify it directly.
Replace the XBlock with a new XBlock that wraps the original.
Attach an Aside to the existing XBlock.
The first two options carry significant costs. Forking creates a parallel codebase that must be maintained against upstream changes. Replacing the XBlock requires every existing course that uses the original to migrate, and it does not scale when you want to enhance many different XBlock types in the same way.
Asides solve this by externalizing the enhancement. The host XBlock is not modified. The same Aside can apply to a Video block, a Problem block, or any other block type, by overriding a single classmethod. Asides can serialize their own scoped fields during course import and export.
Reach for an Aside when all of the following are true:
You want to enhance one or more existing XBlock types without forking them.
The enhancement is conceptually layered on top of the block, not a replacement for any of its behavior.
The enhancement should apply to many block instances, possibly across block types, without per-instance configuration in the course outline.
The enhancement may need its own settings or stored data, scoped to the block instance.
Reach for something else when:
You are creating a brand new piece of course content. Write an XBlock.
You only need to react to platform events. Consider an Open edX event receiver.
How an Aside Relates to Its Host Block#
The runtime maintains a many-to-many relationship between asides and host blocks at runtime, but each Aside instance is bound to exactly one host block during a single render. The relationship is established in three stages.
Per-Block Filtering#
For each candidate Aside type, the runtime instantiates the Aside and asks
it whether it should apply to this specific block by calling its
should_apply_to_block() classmethod. The
default implementation returns True. Real-world asides almost always
override this method to restrict themselves to specific block types, course
contexts, or feature flags.
Rendering and Layout#
For each Aside that survives filtering, the runtime invokes the Aside method
that was decorated with @XBlockAside.aside_for(view_name) for the view
being rendered. The Aside method returns a Fragment, the runtime wraps
that fragment with identifying markup, and the runtime appends the wrapped
fragment to the host block’s rendered output. A runtime can override
layout_asides() to control where and how the
Aside fragments are placed.
Why Asides Are Worth the Trouble#
The framing above describes the trade-offs from the perspective of someone choosing among extension mechanisms. The deeper reasons asides exist, and remain useful, come from the production deployments that depend on them.
Multiple Block Types, One Implementation#
A single Aside class can decorate Video blocks, Problem blocks, and any
other block type the author chooses, by checking block.category or
block.scope_ids.block_type inside should_apply_to_block. The MIT
Open Learning chat Aside, for example, attaches an “AskTIM” chat button to
both Video and Problem blocks from a single class, with one entry point.
Without asides, the same outcome would require either two parallel forks
or replacement blocks for both types.
OLX Export and Import#
When a course is exported to OLX, the platform serializes each Aside as an 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
XBlock Asides Reference for the full mechanics and
Add an XBlock Aside for a worked example of both halves.
Real-World Examples#
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 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#
The ol-openedx-chat Aside, also from MIT Open Learning, attaches an
“AskTIM” chat button to Video and Problem blocks. The button opens a
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, 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 Add an XBlock Aside for a full walkthrough of this pattern.
Limitations#
Asides are a real, working feature in production deployments, but the ecosystem around them is incomplete. The list below is drawn from the 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.
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#
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. (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, 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 silently share the same
stored value on the platform’s Split modulestore — confirmed by
directly reproducing the collision. See XBlock Asides Reference
for the mechanism and the reproduction. 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#
Asides use the same fragment-based JavaScript loading mechanism as XBlocks, which assumes a single set of static assets. If your Aside needs a JS library that is not already loaded by the host page, you must add it through the fragment, and you must handle ordering and conflicts yourself. There is no shared Aside-level mechanism for declaring library dependencies.
Where to Go Next#
If you are ready to build an Aside, start with Quickstart: Build Your First XBlock Aside. If you already have a target XBlock in mind and want a step-by-step recipe, read Add an XBlock Aside. For the complete list of classes, decorators, methods, and entry points, consult XBlock Asides Reference. The rapid-response-xblock, ol-openedx-chat, and StructuredTagsAside implementations described above are also worth reading directly as reference material.
See also
- XBlock Asides Reference (reference)
The complete API surface for
XBlockAsideand its runtime hooks.- Add an XBlock Aside (how-to)
A step-by-step recipe for adding an Aside to existing XBlocks.
- Quickstart: Build Your First XBlock Aside (quickstart)
A beginner-friendly walkthrough from zero to a running Aside.
- Hooks Extension Framework (concept)
An alternative extension mechanism for non-view-based behaviors.
Maintenance chart
Review Date |
Working Group Reviewer |
Release |
Test situation |