MFE Rewrite — what's left to do
This issue tracks the remaining work to finish migrating Open edX off server-rendered
legacy pages and onto MFEs. It is organized by what needs to happen next, not by page
area, so the open work is scannable. Completed work is collapsed at the bottom.
Detailed history and per-row notes live on the (now unmaintained) Confluence page —
MFE Rewrite Tracker.
That page is being archived and banner-linked here for reference; this issue is the live home.
Goal: no default legacy pages by release "X"
How to read the tables
Each row shows what a user is actually served today, split into two columns because
vanilla Open edX and Tutor defaults diverge — and vanilla is the column that matters for
planning (anything that's MFE only because Tutor turns it on still needs to be made default-on
in the platform, and ideally the legacy view dropped). Next action is the concrete next step;
Notes holds the supporting context/caveats.
| Value |
Meaning |
MFE |
MFE served by default |
LEGACY |
Legacy view served by default |
REMOVED |
Legacy gone; MFE is the only option, no toggle |
REDIRECT |
Legacy URL survives only as a redirect |
N/A |
The MFE-vs-legacy split doesn't apply |
UNKNOWN |
Not established |
Bold (**LEGACY**) = verified against a merged PR or checked live in the 2026-07-29 review.
Trailing ? (MFE?) = inherited from the old doc's "default in Open edX" tag and not
verified — every MFE? is itself a work item (the default-sweep, task A2). Do not cite one
as fact.
DEPR context: umbrella #36108
("Various legacy Studio pages") is Closed with 52 tasks — strong signal most Studio rows
below are already done and just need confirming. The old doc is known to lag the code, so
where this issue and the Confluence page disagree, this issue is the more current.
🔴 Remove legacy — removal unblocked; just needs doing
Removal is decided and unblocked for every row here — the MFE is the valid version (or the feature is dead), and the legacy pages just need deleting.
| Page |
Vanilla |
Tutor |
Next action |
Notes |
Ref |
| Courseware: Search |
UNKNOWN |
UNKNOWN |
Remove the entire legacy openedx/features/course_search/ frontend bundle — the dead in-course Backbone UI and the dashboard search widget/factory — per DEPR #39089. Unblocked. |
Nothing loads the in-course UI; the learning MFE is the confirmed replacement. The /search/ endpoint and content index stay (shared with MFE in-course search), so no infra is freed. |
#39089 (fast-track DEPR) |
| Discussions (legacy forum tab) |
LEGACY |
MFE |
Unblocked — Breaking Changes Unblocked as of 2026-08-14. Clear to remove per the DEPR scope (#38940): the non-MFE forum tab, its waffle flags, and legacy config. |
Verified 2026-07-31: legacy is the vanilla default; Tutor forces the MFE on. Divided/cohorted-discussions config is separate → #38945. |
#38940 (fast-track DEPR) |
| Course Dashboard (Learner Home) |
LEGACY |
MFE |
Remove the legacy dashboard (dashboard.html + the student_dashboard render path) and the learner_home_mfe.enabled flag, per #35326. Removal deletes the flag, so vanilla switches to the MFE. Coordinate with #39089 on dashboard.html (that PR removes the search widget; #35326 removes the whole template). |
Cleared: the cross-course search decision is resolved (→ #39089), and the programs dashboard is confirmed independent (verified 2026-09-10 — renders its own learner_dashboard/programs.html inheriting main.html, no dependency on dashboard.html or the course-dash JS). |
#35326 |
| Discover New Courses (Catalog) + LMS Home |
LEGACY |
MFE |
Remove the legacy templates (index.html / courses.html / course.html) + redirect logic + the ENABLE_CATALOG_MICROFRONTEND flag, per DEPR #36785. Removal deletes the flag, so vanilla switches to the MFE. Transition unblocked (Verawood cut). |
Verified 2026-09-10 (master fef9dd5e6a): ENABLE_CATALOG_MICROFRONTEND defaults False, so the MFE is on only because Tutor sets it. MFE is frontend-app-catalog — the only new MFE needed for the remaining conversions (per sarina). Handled with Course About. |
#36785 |
| Course About |
LEGACY |
MFE |
Remove course_about.html / course_about_sidebar_header.html + redirect logic per DEPR #36785 (the ENABLE_CATALOG_MICROFRONTEND flag removal is shared with Discover New Courses). Transition unblocked (Verawood cut). |
⚠️ 2U uses Course About in its Edge environment (robrap 2026-09-04) — coordinate before breaking changes land. Same DEPR/flag as Discover New Courses. |
#36785 |
🟠 Flip the vanilla default, then remove — MFE exists but is off by default in vanilla
⭐ Confirmed divergence. The MFE exists but the platform toggle defaults False (Tutor turns it
on). Near-term step is to make it default-on in the platform — but unlike the removals above, this
one still has an open dependency before the legacy views can be dropped (see the row).
| Page |
Vanilla |
Tutor |
Next action |
Notes |
Ref |
| Login / Registration |
LEGACY |
MFE |
Build enterprise-branded logistration in the MFE, then flip ENABLE_AUTHN_MICROFRONTEND on (default-flip PR #39092) and remove the legacy views + flag. Blocked by: frontend-app-authn#1691. |
MFE at parity except the enterprise/SSO experience (audit 2026-09-10); details in the linked tickets. |
|
🟡 Build a replacement — legacy page with no MFE yet
These cannot just be removed; they need a replacement view built first.
| Page |
Vanilla |
Tutor |
Next action |
Notes |
Ref |
| Course Home: Custom Pages |
LEGACY |
LEGACY |
Build a course tab in frontend-app-learning that iframes the StaticTabBlock (via chromeless render_xblock). |
Legacy learner view is StaticCourseTabView at /courses/{id}/{tab_slug}/; the tab shows in the MFE nav (src/course-tabs/) but its link points back to the legacy page. Scoped ~2h with two people; help wanted. Not the same as the (removed) Studio custom-pages authoring UI. |
frontend-app-learning#2056 |
| Course Bookmarks |
LEGACY |
LEGACY |
Build the bookmarks list view in frontend-app-learning. |
Bookmarks are created in the MFE, but the "show my bookmarks" list is still the legacy Backbone page at /courses/{id}/bookmarks/; the MFE links out to it. The REST API already exists, so this is frontend-only. |
frontend-app-learning#2057 |
| Course Teams |
LEGACY |
LEGACY |
Build a replacement, likely a courseware tab in frontend-app-learning. |
Same pattern as the instructor dashboard tab. Cannot be ripped out. |
— |
| Instructor Dashboard (all pages) |
LEGACY |
LEGACY |
Continue building frontend-app-instructor-dashboard. Removing the legacy divided-discussions section + its course_discussions_settings_handler / discussion_topics endpoints is blocked by the DEPR RFC (#38945). |
Feature gap resolved 2026-07-31: cohort management is migrated (MFE uses /api/cohorts/v1|v2/), but divided/cohorted-discussions management is absent from the redesign. Discovery frontend-app-instructor-dashboard#225 decided to DEPR the legacy feature (assume it can go, let operators object) → DEPR #38945; those endpoints and their dashboard section stay until the RFC clears. |
#38945 |
🔵 Needs discovery — open questions (A5)
Not enough is known to act. This table is the tracker — open a sub-issue for a row only when
work on it actually begins; we are not pre-creating them.
| Page |
Vanilla |
Tutor |
Next action |
Notes |
Ref |
| ID Verification |
UNKNOWN |
UNKNOWN |
Discovery: which legacy IDV pages still exist, and can they be cleaned up? |
MFE lives in frontend-app-account. |
— |
| Course Home: Progress |
LEGACY |
MFE? |
Follow up with MIT (Peter); then reopen the DEPR. |
Legacy is still default in vanilla (Kyle). MIT keeps specific courses on legacy via a per-course flag because the MFE shows grades where the old page didn't. |
course_home_mfe.course_home_mfe_progress_tab |
| Courseware: Proctored Exam |
UNKNOWN |
UNKNOWN |
Outline the feature set on both sides, decide what to keep, involve product. |
Nobody could define parity. Contact Michael Roylance/Wrightman. |
edx-proctoring#1226 |
| Program Dashboard |
LEGACY |
LEGACY |
Research whether to convert it at all, given the sequences/pathways work. |
Row is internally inconsistent (in-development + "needs DEPR"). How does it relate to the learner dashboard (shared with the Course Dashboard discovery)? |
— |
| Course Certificates |
LEGACY |
LEGACY |
Research the current state; consider extracting as a plugin. |
Should've moved to Credentials years ago, never did, still used. ⚠️ Old URLs must keep working. |
— |
| Program Certificates |
LEGACY |
LEGACY |
Research the current state (together with Course Certificates). |
Credentials /credentials/{cert_id}. ⚠️ Old URLs must keep working. |
— |
| Track Selection |
LEGACY |
LEGACY |
Decide keep-and-rewrite vs DEPR. |
No MFE today; if kept it needs a rewrite, likely a small component in the new frontend site. |
course_modes.use_new_track_selection (?) |
| Course Messaging |
UNKNOWN |
UNKNOWN |
Establish what this page even is. |
Zero information about this row. |
— |
| Preview Language / dark_lang (LMS) |
LEGACY |
LEGACY |
Verify which pages the cookie affects; leaning toward removing the feature. |
MFEs ignore it (they follow the browser). CMS twin already redirected. |
#36271 |
| Basket / Payment |
N/A |
N/A |
Discovery: sort what stays as a checkout seam vs. what's dead. |
Not a simple removal. The purchase/upgrade integration (EcommerceService + ~11 upsell call-sites) is inert by default but exposes pluggable checkout hooks external tools may use. |
#38942 |
| Order History |
N/A |
N/A |
Confirm removability in the discovery. |
Ecommerce order history: an external MFE link (ORDER_HISTORY_MICROFRONTEND_URL) + the OrderView endpoint. Likely removable. |
#38942 |
| Studio: Pages & Resources |
LEGACY |
MFE? |
Discovery: establish what "off" serves and whether a legacy page exists at all. |
discussions.pages_and_resources_mfe defaults False in vanilla, so the MFE is off by default; Tutor likely on. (A4 finding.) |
discussions.pages_and_resources_mfe |
⚙️ In active development — MFE being built; not yet at the removal question
| Page |
Vanilla |
Tutor |
Next action |
Notes |
Ref |
| Studio: Unit Editor |
UNKNOWN |
UNKNOWN |
Land the last blocker, then remove the legacy unit editor. Blocked by: frontend-app-authoring#2620. |
The MFE unit editor is otherwise ready. |
#35261 |
| Studio: Text (HTML) Editor |
MFE? |
MFE? |
Finish the new editor, then remove the legacy one. Legacy removal blocked by the new editor still being in development. |
Flag new_core_editors.use_new_text_editor. |
#34692 |
| Studio: Problem (CAPA) Editor |
MFE? |
MFE? |
Finish the new editor, then remove the legacy one. Legacy removal blocked by the new editor still being in development. |
Flag new_core_editors.use_new_problem_editor. |
#35256 |
| Studio: Video Editor |
MFE? |
MFE? |
Finish the new editor, then remove the legacy one. Legacy removal blocked by the new editor still being in development. |
Flag new_core_editors.use_new_video_editor. |
#35257 |
| Studio: Library Authoring (all pages) |
UNKNOWN |
UNKNOWN |
Continue the relaunch, then resolve the dual-mode. Legacy removal blocked by the relaunch still being in progress. |
LIBRARY_MODE = 'mixed' means both are reachable at once — may need a third state. In development by Schema/OpenCraft/Axim. |
#32457 |
🏗️ Cross-cutting infrastructure — not pages, but blocks "headless"
Target end state: remove the JavaScript/SASS build chain from edx-platform entirely
(still run collectstatic, still serve some assets from Django views); XBlocks own their own JS
build. "We are nearly there."
| Item |
Next action |
Notes |
Ref |
Courseware: render_xblock |
Reduce to a thin wrapper over built-in views (keep the endpoint). |
Chromeless XBlock render endpoint iframed into learning/authoring; never fully removed. |
— |
| Courseware: Built-in XBlock Views |
Extract problem block + one other out of the platform build into xblocks-core. |
From xblocks-contrib; per-block flag xmodule.use_extracted_block.{tag}. |
#34827 · xblocks-core |
XBlock JS window globals |
Define an explicit interface + shim, then prune over time. |
Legacy XBlocks expect platform-provided objects on window (declare-your-deps → get only those; declare nothing → get everything). Brian + Kyle to discuss. |
— |
✅ Completed
Removed, migrated, or resolved — kept for reference
| Page |
Removed / migrated by |
| Studio: Logged-out Landing ("Howitworks") |
#36269 — removed, no replacement |
| Studio: Preview |
#36460 — legacy preview removed; native in learning MFE (merged 2025-05-14) |
| Studio: Course Custom Pages (legacy Tabs UI) |
#37557 — legacy Tabs UI dropped (merged 2025-11-20) |
| Studio: Maintenance (dashboard) |
#37432 — whole Maintenance dashboard removed (merged 2025-10-10); DEPR #36263 closed |
| Studio: Maintenance → Announcements |
#37432 — Announcements tool removed with the dashboard; DEPR #36263 closed |
| Studio: Maintenance → Force Publish Course |
Removed — "broken since it was first introduced" |
| Studio: Preview Language (dark_lang) — CMS |
#36271 — CMS page → redirect to LMS |
| Profile |
public-engineering#71 — frontend-app-profile |
| Account Settings |
public-engineering#71 — frontend-app-account |
| Course Home: Dates |
public-engineering#50 — frontend-app-learning |
| Course Home: Outline |
public-engineering#50 — frontend-app-learning |
| Courseware: Sequence (index) |
#35803 — legacy courseware.html sequence page removed; CoursewareIndex now redirects to the learning MFE. The LTI provider renders via render_xblock, not legacy code. |
Studio pages — A4, verified 2026-07-30 against openedx-platform master 1746666137. Legacy
Django handler now redirects to the authoring MFE; the use_new_* flags are deleted and the API
serializer hardcodes them true as a compat shim under
#37497. Old URLs persist only as a
redirect + JSON data API (full removal tracked by #37497).
| Page |
Removed / migrated by |
| Studio: Logged-in Home |
A4 — course_listing redirects to MFE (views/course.py:707) |
| Studio: Advanced Settings |
A4 — redirect to MFE (views/course.py:1607) |
| Studio: Schedule & Details |
A4 — redirect to MFE (views/course.py:1473) |
| Studio: Grading |
A4 — redirect to MFE (views/course.py:1513) |
| Studio: Updates |
A4 — redirect to MFE (views/course.py:1392) |
| Studio: Import |
A4 — redirect to MFE (import_export.py:96) |
| Studio: Export |
A4 — redirect to MFE (import_export.py:343) |
| Studio: Files & Uploads |
A4 — redirect to MFE (asset_storage_handlers.py:226) |
| Studio: Content Outline Editor |
A4 — redirect to MFE (views/course.py:802); vestigial legacy_studio.course_outline flag safe to delete |
| Studio: Course Team |
A4 — redirect to MFE (views/user.py:59) |
| Studio: Textbooks |
A4 — redirect to MFE (views/course.py:1752) |
| Studio: Group Configurations |
A4 — redirect to MFE (views/course.py:1941) |
| Studio: Certificates |
A4 — redirect to MFE (certificates.py:144) |
| Studio: Checklists |
A4 — redirect to MFE (views/checklists.py:26) |
| Studio: Video Uploads |
A4 — legacy page redirect-only (video_storage_handlers.py:770); use_new_video_uploads_page default False now gates the MFE feature (edX video pipeline), not legacy code |
| Learner Record |
Resolved 2026-07-31 — no legacy learner-record page in edx-platform (no route/template); program records are served by the Credentials service + frontend-app-learner-record. Platform holds only the MFE registration, ENABLE_LEARNER_RECORDS (default True), and a link to Credentials public_records_url. |
Meta / cross-cutting tasks
- A1 — Inventory audit (Feanil + Brian, sub-issue already open): audit the HTML templates
still living in edx-platform, which URLs render them, and whether they have replacements —
anything with no row here gets added. This is the inverted audit direction the team agreed on.
- A2 — Default sweep (Brian): resolve every
MFE? above to MFE / LEGACY / REMOVED in
each column independently. Every MFE? in this issue is one item on that list.
- A4 — Studio confirmation ✅ done 2026-07-30: 14 Studio pages + Video Uploads verified
REMOVED (redirect-to-MFE, use_new_* flags deleted under #37497)
and moved to Completed; Pages & Resources reclassified to 🔵 discovery. See the A4 comment.
- A5 — Needs-discovery section is the tracker; open a per-row sub-issue only when work on that row begins (we are not pre-creating them).
For contributors
- Paste research/verification output as issue comments (there's a template in the comments)
so it can be folded back into these tables. Keep the tables terse; put evidence in comments.
help wanted is a good fit for Course Home: Custom Pages — small and well-scoped (~2h).
MFE Rewrite — what's left to do
This issue tracks the remaining work to finish migrating Open edX off server-rendered
legacy pages and onto MFEs. It is organized by what needs to happen next, not by page
area, so the open work is scannable. Completed work is collapsed at the bottom.
Detailed history and per-row notes live on the (now unmaintained) Confluence page —
MFE Rewrite Tracker.
That page is being archived and banner-linked here for reference; this issue is the live home.
Goal: no default legacy pages by release "X"
How to read the tables
Each row shows what a user is actually served today, split into two columns because
vanilla Open edX and Tutor defaults diverge — and vanilla is the column that matters for
planning (anything that's MFE only because Tutor turns it on still needs to be made default-on
in the platform, and ideally the legacy view dropped). Next action is the concrete next step;
Notes holds the supporting context/caveats.
MFELEGACYREMOVEDREDIRECTN/AUNKNOWNBold (
**LEGACY**) = verified against a merged PR or checked live in the 2026-07-29 review.Trailing
?(MFE?) = inherited from the old doc's "default in Open edX" tag and notverified — every
MFE?is itself a work item (the default-sweep, task A2). Do not cite oneas fact.
DEPR context: umbrella #36108
("Various legacy Studio pages") is Closed with 52 tasks — strong signal most Studio rows
below are already done and just need confirming. The old doc is known to lag the code, so
where this issue and the Confluence page disagree, this issue is the more current.
🔴 Remove legacy — removal unblocked; just needs doing
Removal is decided and unblocked for every row here — the MFE is the valid version (or the feature is dead), and the legacy pages just need deleting.
UNKNOWNUNKNOWNopenedx/features/course_search/frontend bundle — the dead in-course Backbone UI and the dashboard search widget/factory — per DEPR #39089. Unblocked./search/endpoint and content index stay (shared with MFE in-course search), so no infra is freed.dashboard.html+ thestudent_dashboardrender path) and thelearner_home_mfe.enabledflag, per #35326. Removal deletes the flag, so vanilla switches to the MFE. Coordinate with #39089 ondashboard.html(that PR removes the search widget; #35326 removes the whole template).learner_dashboard/programs.htmlinheritingmain.html, no dependency ondashboard.htmlor the course-dash JS).index.html/courses.html/course.html) + redirect logic + theENABLE_CATALOG_MICROFRONTENDflag, per DEPR #36785. Removal deletes the flag, so vanilla switches to the MFE. Transition unblocked (Verawood cut).fef9dd5e6a):ENABLE_CATALOG_MICROFRONTENDdefaultsFalse, so the MFE is on only because Tutor sets it. MFE isfrontend-app-catalog— the only new MFE needed for the remaining conversions (per sarina). Handled with Course About.course_about.html/course_about_sidebar_header.html+ redirect logic per DEPR #36785 (theENABLE_CATALOG_MICROFRONTENDflag removal is shared with Discover New Courses). Transition unblocked (Verawood cut).🟠 Flip the vanilla default, then remove — MFE exists but is off by default in vanilla
⭐ Confirmed divergence. The MFE exists but the platform toggle defaults
False(Tutor turns iton). Near-term step is to make it default-on in the platform — but unlike the removals above, this
one still has an open dependency before the legacy views can be dropped (see the row).
ENABLE_AUTHN_MICROFRONTENDon (default-flip PR #39092) and remove the legacy views + flag. Blocked by: frontend-app-authn#1691.🟡 Build a replacement — legacy page with no MFE yet
These cannot just be removed; they need a replacement view built first.
frontend-app-learningthat iframes theStaticTabBlock(via chromelessrender_xblock).StaticCourseTabViewat/courses/{id}/{tab_slug}/; the tab shows in the MFE nav (src/course-tabs/) but its link points back to the legacy page. Scoped ~2h with two people;help wanted. Not the same as the (removed) Studio custom-pages authoring UI.frontend-app-learning./courses/{id}/bookmarks/; the MFE links out to it. The REST API already exists, so this is frontend-only.frontend-app-learning.frontend-app-instructor-dashboard. Removing the legacy divided-discussions section + itscourse_discussions_settings_handler/discussion_topicsendpoints is blocked by the DEPR RFC (#38945)./api/cohorts/v1|v2/), but divided/cohorted-discussions management is absent from the redesign. Discovery frontend-app-instructor-dashboard#225 decided to DEPR the legacy feature (assume it can go, let operators object) → DEPR #38945; those endpoints and their dashboard section stay until the RFC clears.🔵 Needs discovery — open questions (A5)
Not enough is known to act. This table is the tracker — open a sub-issue for a row only when
work on it actually begins; we are not pre-creating them.
UNKNOWNUNKNOWNfrontend-app-account.MFE?course_home_mfe.course_home_mfe_progress_tabUNKNOWNUNKNOWN/credentials/{cert_id}.course_modes.use_new_track_selection(?)UNKNOWNUNKNOWNN/AN/AEcommerceService+ ~11 upsell call-sites) is inert by default but exposes pluggable checkout hooks external tools may use.N/AN/AORDER_HISTORY_MICROFRONTEND_URL) + theOrderViewendpoint. Likely removable.MFE?discussions.pages_and_resources_mfedefaultsFalsein vanilla, so the MFE is off by default; Tutor likely on. (A4 finding.)discussions.pages_and_resources_mfe⚙️ In active development — MFE being built; not yet at the removal question
UNKNOWNUNKNOWNMFE?MFE?new_core_editors.use_new_text_editor.MFE?MFE?new_core_editors.use_new_problem_editor.MFE?MFE?new_core_editors.use_new_video_editor.UNKNOWNUNKNOWNLIBRARY_MODE = 'mixed'means both are reachable at once — may need a third state. In development by Schema/OpenCraft/Axim.🏗️ Cross-cutting infrastructure — not pages, but blocks "headless"
Target end state: remove the JavaScript/SASS build chain from
edx-platformentirely(still run
collectstatic, still serve some assets from Django views); XBlocks own their own JSbuild. "We are nearly there."
render_xblockxblocks-core.xblocks-contrib; per-block flagxmodule.use_extracted_block.{tag}.windowglobalswindow(declare-your-deps → get only those; declare nothing → get everything). Brian + Kyle to discuss.✅ Completed
Removed, migrated, or resolved — kept for reference
frontend-app-profilefrontend-app-accountfrontend-app-learningfrontend-app-learningcourseware.htmlsequence page removed;CoursewareIndexnow redirects to the learning MFE. The LTI provider renders viarender_xblock, not legacy code.Studio pages — A4, verified 2026-07-30 against
openedx-platformmaster1746666137. LegacyDjango handler now redirects to the authoring MFE; the
use_new_*flags are deleted and the APIserializer hardcodes them
trueas a compat shim under#37497. Old URLs persist only as a
redirect + JSON data API (full removal tracked by #37497).
course_listingredirects to MFE (views/course.py:707)legacy_studio.course_outlineflag safe to deleteuse_new_video_uploads_pagedefaultFalsenow gates the MFE feature (edX video pipeline), not legacy codeedx-platform(no route/template); program records are served by the Credentials service +frontend-app-learner-record. Platform holds only the MFE registration,ENABLE_LEARNER_RECORDS(defaultTrue), and a link to Credentialspublic_records_url.Meta / cross-cutting tasks
still living in
edx-platform, which URLs render them, and whether they have replacements —anything with no row here gets added. This is the inverted audit direction the team agreed on.
MFE?above toMFE/LEGACY/REMOVEDineach column independently. Every
MFE?in this issue is one item on that list.REMOVED (redirect-to-MFE,
use_new_*flags deleted under #37497)and moved to Completed; Pages & Resources reclassified to 🔵 discovery. See the A4 comment.
For contributors
so it can be folded back into these tables. Keep the tables terse; put evidence in comments.
help wantedis a good fit for Course Home: Custom Pages — small and well-scoped (~2h).