Skip to content

Technical Review & Feature Comparison — February 2026 #33

@mmcky

Description

@mmcky

Technical Review & Feature Comparison

Date: February 2026
Repo: quantecon-theme-src (MyST/Jupyter Book 2.0 theme)
Compared against: quantecon-book-theme v0.18.0 (Sphinx/Jupyter Book ≤2 theme)


Part 1 — Technical Review of quantecon-theme-src

1.1 Architecture Overview

The new theme is a Remix v1.17 application built on the @myst-theme ecosystem. It serves as a MyST Markdown site template that is bundled and deployed to QuantEcon/quantecon-theme for use by downstream projects via myst start.

Layer Technology
Framework Remix 1.17 (CJS, Vercel-compatible)
UI React 18, TailwindCSS 3, Radix UI primitives
Content @myst-theme/* v0.14.0 suite
Compute Thebe (via @myst-theme/jupyter)
Search MiniSearch (via @myst-theme/search-minisearch)
Icons Lucide React

1.2 Code Quality Assessment

Strengths

  1. Clean component decomposition — Toolbar, Sidebar, Outline, Footer, etc. are well-separated single-responsibility components. The toolbar/ directory groups all toolbar-related buttons cleanly.

  2. Good use of myst-theme primitives — The theme correctly leverages @myst-theme/providers (e.g., useLinkProvider, useBaseurl, useNavOpen, useThemeSwitcher), @myst-theme/site (e.g., useHeaders, useSidebarHeight), and @myst-theme/jupyter (e.g., ComputeOptionsProvider, ThebeLoaderAndServer).

  3. TypeScript throughout — All source files are .tsx/.ts with proper type imports. The tsconfig.json enforces strict: true.

  4. Zero lint/compile errors — The codebase compiles cleanly with no TypeScript errors detected.

  5. Accessible tooltips and ARIA — Radix UI Tooltip, DropdownMenu, and Popover components provide sensible accessibility defaults. SkipTo navigation is included in root.tsx.

  6. Dark mode support — Uses Tailwind darkMode: 'class' with a custom color palette (qepage-dark, qetoolbar-dark, etc.) that is consistently applied across components.

  7. Custom grid system — A well-designed simple-center-grid using CSS Grid named lines (screen-start, body-start, body-end, margin-start, margin-end, screen-end) provides clean body + margin layout.

  8. Proper React patternsReact.memo on PageContent, useCallback for search factory, useMemo in PageProvider.

  9. Build pipeline — Clean separation between dev and prod Remix configs with a Makefile for automated deployment to the bundled theme repo.

Issues & Recommendations

High Priority
# Issue Location Recommendation
1 Missing JSDoc / code comments All files Almost no function, component, or module has documentation comments. The only comments are in remix.config.dev.js and a few CSS comments. Add JSDoc to all exported functions/components and purpose comments to modules.
2 No tests Project root There are zero test files. No unit tests, no integration tests, no visual regression tests. The old theme has tox, pytest, and Playwright tests. Add at minimum component unit tests (Vitest/Testing Library) and consider Playwright visual regression tests.
3 No CI/CD pipeline .github/ missing No GitHub Actions workflows. The old theme has extensive CI. Add workflows for: lint, typecheck, build, test, and deploy.
4 No .gitignore visible Project root Verify .gitignore exists and covers node_modules/, build/, .deploy/, public/build/, app/styles/app.css (generated).
5 No ESLint config Project root Despite @remix-run/eslint-config being a devDependency, there is no .eslintrc or equivalent configuration file, and no lint script in package.json.
6 Remix v1 is end-of-life package.json Remix 1.17 is very old (2023). The ecosystem has moved to Remix v2 / React Router v7. While this may be constrained by @myst-theme compatibility, plan for migration. V2 future flags are enabled which is good.
7 Deep import from @myst-theme/site Toolbar.tsx import { Search } from '@myst-theme/site/src/components/Navigation/Search' imports from src/ which is fragile and could break on upstream updates. Use a public export or contribute one upstream.
Medium Priority
# Issue Location Recommendation
8 node-fetch v2 used loaders.server.ts Using node-fetch@2 (CJS) instead of the native fetch available in Node 18+. If minimum Node version is raised (currently >=14, should be >=18), replace with native fetch.
9 node: ">=14" engine requirement package.json Node 14 is long EOL. Set to >=18 (current LTS baseline).
10 Hardcoded CDN URLs in root.tsx root.tsx lines 48-55 jupyter-matplotlib CSS v0.11.3 and font-awesome 4.7.0 are loaded via external CDN with no SRI. Consider: (a) adding integrity attributes, (b) bundling locally, or (c) removing if unused.
11 Font loaded via Google Fonts app.css line 1 Source Sans 3 is loaded via @import url(...) to Google Fonts which blocks rendering. Consider self-hosting the font or using <link rel="preload">.
12 Missing key prop in author list ProjectFrontmatter.tsx The <span> elements wrapping author names inside the .reduce() have no key prop. This triggers React warnings.
13 Typo: aira-label ProjectFrontmatter.tsx line 52 aira-label should be aria-label.
14 Swapped ARIA labels SidebarToggle.tsx The X icon has aria-label="Show table of contents" (should be "Hide") and the Menu icon has aria-label="Hide table of contents" (should be "Show"). These are reversed.
15 FontScaleListItems SSR safety FontScaleListItems.tsx document.documentElement.style.fontSize is accessed in useMemo without an SSR guard beyond the typeof document check. Consider using useEffect for the initial value. The default state index 1 doesn't guarantee alignment with the actual font size.
16 FullScreen API edge cases FullscreenButton.tsx No handling for fullscreen API unavailability (e.g., some mobile browsers, iframes). Add a document.fullscreenEnabled check to conditionally render.
17 No error handling on download trigger DownloadButton.tsx handleDownload calls triggerDirectDownload with await but has no try/catch. Failed downloads will silently error.
Low Priority
# Issue Location Recommendation
18 hide_toc / hideSearch props unused NavigationAndArticleWrapper.tsx The hide_toc and hideSearch props are accepted but never passed through or used to conditionally render the sidebar or search.
19 GridGuide is dead code GridGuide.tsx Not imported anywhere. Either remove or document as a development debugging utility.
20 Patches directory patches/ Three patch files exist for @jupyter-widgets/controls, @types/react-syntax-highlighter, and jupyterlab-plotly. Document why each patch exists and track upstream fix status in a comment or table.
21 Duplicated "Development" section README.md The README has two "## Development" sections (lines 67 and 86). Consolidate.
22 template.yml authorship template.yml Lists only Curvenote contributors as authors. Consider adding QuantEcon as an organizational author.
23 Missing CONTRIBUTING.md Project root The old theme has a detailed contributing guide. Add one for the new theme.
24 Missing LICENSE file completeness template/LICENSE Verify the template LICENSE is appropriate and consistent with the root LICENSE.

Part 2 — Feature Comparison: Old Theme vs. New Theme

2.1 Feature Parity Matrix

Feature Old Theme (quantecon-book-theme) New Theme (quantecon-theme-src) Status
Left Sidebar (Table of Contents) ✅ Collapsible sidebar with hierarchical ToC, auto-expand option, persistent option ✅ Slide-in sidebar with grouped headings, toggle button ✅ Parity (different UX, functional equivalent)
Right Sidebar (On This Page) ✅ Within-page ToC with toc-hN classes, sticky option with scroll highlighting ✅ Outline component in margin column with useHeaders hook ✅ Parity
Toolbar ✅ Fixed top toolbar with all action buttons ✅ Fixed top toolbar (50px) with all action buttons ✅ Parity
Home Button ✅ Feather icon link to master_doc ✅ Lucide House icon link to baseurl ✅ Parity
QuantEcon Logo/Link ✅ Logo linking to organisation URL ✅ Logo linking to quantecon.org ✅ Parity
Search ✅ In-toolbar search form (Sphinx search) ✅ MiniSearch-based search component ✅ Parity (better: client-side fuzzy search)
Fullscreen Toggle ✅ Feather maximize icon ✅ Lucide Maximize/Minimize icons with state ✅ Parity
Font Size +/− ✅ Plus/minus circle icons CirclePlus/CircleMinus with 3-step scale ✅ Parity
Dark/Light Mode sunset icon, localStorage toggle, dark-theme class Sunset icon, useThemeSwitcher from providers, Tailwind dark: ✅ Parity (improved: system-aware via myst-theme)
Download (Notebook) ✅ Download cloud icon, links to /_notebooks/{page}.ipynb CloudDownload dropdown with project + page downloads via MyST config ✅ Parity (improved: configurable via myst.yml)
Download (PDF) ✅ PDF icon with modal for Lecture PDF / Book PDF, with window.print() fallback ✅ Combined into Downloads dropdown (PDF downloads configured via myst.yml exports) ⚠️ Partial — No separate PDF icon or window.print() fallback
Launch Notebook ✅ Play icon with modal: Public (BinderHub/Colab/JupyterHub select) + Private input ✅ Play icon with Popover: Google Colab + Private JupyterHub input ⚠️ Partial — BinderHub deferred (see issue)
GitHub Link ✅ GitHub icon linking to repository URL ✅ GitHub icon linking to edit_url from frontmatter ✅ Parity (improved: edit-specific URL)
Mobile Responsive ✅ Basic responsive layout ✅ Full responsive with mobile action menu (ellipsis dropdown) ✅ Parity (improved)
Footer ✅ Hardcoded Creative Commons + "A theme by QuantEcon" ✅ Dynamic MyST content via config.parts.footer ✅ Parity (improved: configurable)
Prev/Next Navigation ✅ In sidebar footer with "Previous topic"/"Next topic" links ✅ Via getFooterLinks in loader (page data), but no visible UI component renders them Missing
Page Header (Title/Authors) ✅ Project title, author names with links ProjectFrontmatter with title, authors, affiliations ✅ Parity
Git Last Modified Date ✅ "Last changed: {date}" button with changelog dropdown ❌ Not implemented Missing
Git Changelog ✅ Expandable commit history list per page ❌ Not implemented Missing
Collapsible Stderr Warnings ✅ Auto-wraps verbose warnings in notebook cells with expandable interface ❌ Not implemented (may be handled by @myst-theme/jupyter) ⚠️ Needs verification
Code Syntax Highlighting Config qetheme_code_style toggle, Pygments style override support ❌ Not configurable (relies on myst-theme defaults) ⚠️ Missing (may not be needed if myst defaults are acceptable)
Color Scheme Options color_scheme option (seoul256, gruvbox, none), custom CSS auto-detection ❌ Not implemented Missing
RTL Support enable_rtl option with dir="rtl" on body ❌ Not implemented Missing
Edit Page Button use_edit_page_button configuration ✅ GitHub button links to edit_url when available ✅ Parity
Repository/Issues Buttons use_repository_button, use_issues_button ❌ Only edit URL supported, no separate repo/issues links ⚠️ Missing
Persistent Sidebar persistent_sidebar option keeps sidebar always visible ❌ Sidebar slides in/out only ⚠️ Missing
Sticky ToC sticky_contents with back-to-top and scroll spy ✅ Outline is absolute positioned, BackToTop appears on scroll ✅ Parity
Contents Auto-Expand contents_autoexpand for sidebar sections ❌ All sections are expanded by default ⚠️ Missing
MathJax Macros ✅ Custom LaTeX macros (EE, PP, RR, etc.) built into theme ❌ Not configured at theme level ⚠️ Needs verification — may be handled by MyST build
Thebe / Live Code ✅ Via launch_buttons.thebe flag ✅ Via ComputeOptionsProvider with notebookCompute / figureCompute ✅ Parity (improved)
SEO Meta Tags ✅ Twitter Cards, OpenGraph ✅ Via getMetaTagsForSite / getMetaTagsForArticle ✅ Parity
Sitemap ❌ Not included [sitemap.xml].tsx route with XSL stylesheet ✅ Improved
robots.txt ❌ Not included [robots.txt].tsx route ✅ Improved
objects.inv ❌ Handled by Sphinx [objects.inv].tsx proxy route ✅ Equivalent
Cross-references ❌ Sphinx native myst.xref.json support ✅ Equivalent
Plugins System plugins_list for adding custom JS ❌ Not implemented ⚠️ Missing
Visual Regression Tests ✅ Playwright-based ❌ None Missing
Unit Tests ✅ pytest + tox ❌ None Missing
CI/CD ✅ GitHub Actions ❌ None Missing
Documentation ✅ ReadTheDocs site, contributing guide ❌ README only Missing

2.2 Summary of Missing Features (Prioritized)

Must-Have for Parity

These features exist in the old theme and are actively used by QuantEcon lecture sites:

  1. Prev/Next Page Navigation — Footer links data is loaded (getFooterLinks) but never rendered in the UI. Need to add a PageFooterNav component.

  2. Git Last Modified Date + Changelog — The old theme shows "Last changed: {date}" with an expandable commit history. This is a significant UX feature for academic content. Implementation approach: either integrate with git via MyST build metadata or create a separate API route.

  3. PDF Download with Print Fallback — The old theme has a dedicated PDF icon with a modal offering "Lecture PDF" and "Book PDF" options, plus a window.print() fallback. The new theme's Downloads dropdown may not make this as discoverable.

Should-Have

  1. Color Scheme Options — Seoul256, Gruvbox, and custom CSS support. Evaluate if this is still needed or if the Tailwind-based dark mode is sufficient.

  2. Persistent Sidebar Option — Allow the sidebar to remain visible by configuration rather than always being a slide-in overlay.

  3. Repository/Issues Buttons — Separate toolbar buttons for viewing the repository and opening issues, distinct from the edit URL.

  4. Collapsible Stderr Warnings — Check if @myst-theme/jupyter already provides this. If not, implement collapsible output for stderr cells.

Nice-to-Have

  1. RTL Support — Needed if QuantEcon plans multilingual content.

  2. Contents Auto-Expand — Sidebar section expand/collapse behavior configuration.

  3. Plugins System — The old theme's plugins_list allows custom JS injection. Evaluate if this is needed in the MyST ecosystem.

  4. Configurable Code Highlighting — The old theme allows switching between custom QuantEcon and Pygments styles. Check if MyST defaults are adequate.

  5. BinderHub Launch Option — Deferred to a future release (tracked in GitHub issue). The new theme currently supports Colab and private JupyterHub only.


Part 3 — Specific Code Fixes Recommended

3.1 Bug Fixes — ✅ Fixed in PR #31

// ProjectFrontmatter.tsx — Fix typo: "aira-label" → "aria-label"
<div aria-label="Author names and links">

// ProjectFrontmatter.tsx — Add key prop to span elements
// Inside the reduce, add key={a.id ?? a.name ?? i} to each <span>

// SidebarToggle.tsx — Fix swapped ARIA labels
<X ... aria-label="Hide table of contents" />
<Menu ... aria-label="Show table of contents" />

3.2 Suggested File Organization

app/
├── backend/
│   └── loaders.server.ts       ✅ Good
├── components/
│   ├── layout/                  ← Group layout components
│   │   ├── ContentsSidebar.tsx
│   │   ├── NavigationAndArticleWrapper.tsx
│   │   └── GridGuide.tsx
│   ├── content/                 ← Group content components
│   │   ├── PageContent.tsx
│   │   ├── ProjectFrontmatter.tsx
│   │   ├── Outline.tsx
│   │   └── SiteFooter.tsx
│   ├── toolbar/                 ✅ Good
│   ├── ErrorPage.tsx
│   ├── Page.tsx
│   └── PageProvider.tsx
├── hooks/                       ✅ Good
├── routes/                      ✅ Good
├── styles/                      (move to app/ or keep at root)
└── types.ts                     ✅ Good

3.3 Missing Infrastructure

Item Recommendation Status
.github/workflows/ci.yml TypeScript check, build test, lint ✅ Added in PR #31
.eslintrc.js Use @remix-run/eslint-config Open
vitest.config.ts Unit tests with React Testing Library Open
playwright.config.ts Visual regression tests Open
.gitignore Ensure complete Open
CONTRIBUTING.md Development setup, PR guidelines ✅ Added in PR #31
.prettierrc Codify formatting rules (Prettier is in devDeps) Open
.nvmrc Pin Node version (e.g., 18) ✅ Added in PR #31

Part 4 — Overall Assessment

What the New Theme Does Well

  • Modern stack: React 18 + Tailwind + Radix UI is a much cleaner foundation than the jQuery + Bootstrap 4 + Jinja2 templates of the old theme.
  • MyST integration: Deeply integrated with the @myst-theme ecosystem, leveraging its providers, search, and Jupyter compute capabilities.
  • Dark mode: More robust implementation using Tailwind's class-based dark mode rather than manual CSS class toggling.
  • Mobile: The responsive mobile menu with Radix DropdownMenu is a significant improvement.
  • SEO/Web standards: Sitemap, robots.txt, and proper meta tags are built in at the route level.
  • Configurable footer: Content-driven rather than hardcoded.
  • Downloads: Flexible configuration through MyST's download/export system.

What Still Needs Work

  1. Testing — Zero tests remain the biggest gap. CI pipeline now runs typecheck + build (PR fix: quick wins from technical review (bugs, CI, Node, docs) #31), but no unit or integration tests yet.
  2. Documentation — CONTRIBUTING.md added (PR fix: quick wins from technical review (bugs, CI, Node, docs) #31), but inline code comments and JSDoc are still missing.
  3. Feature gaps — Prev/Next navigation, git metadata, BinderHub support are significant omissions.
  4. Minor bugs — Fixed in PR #31.
  5. Dependency modernization — Remix v1 EOL and node-fetch v2 remain. Node engine updated to >=18 (PR fix: quick wins from technical review (bugs, CI, Node, docs) #31).

Recommended Action Items (Ordered)

  1. Fix the bugs identified in Section 3.1 — ✅ PR #31
  2. Add prev/next page navigation UI
  3. Set up CI pipeline (typecheck + build) — ✅ PR #31
  4. Add at least smoke-level tests
  5. Add code comments/JSDoc to all components
  6. Evaluate git metadata feature need
  7. Update Node engine requirement — ✅ PR #31 (>=18, .nvmrc)
  8. Add CONTRIBUTING.md — ✅ PR #31
  9. Remix v2 migration — tracked in #28

Completed During Review


Part 5 — Download & Export: Theme Gaps

The upstream myst build --ipynb work (PR jupyter-book/mystmd#1882) is tracked separately in QuantEcon/meta#292. This section covers only theme-level gaps related to downloads and exports.

5.1 Notebook Download Button

The theme's DownloadButton component already supports configurable downloads via MyST's exports + downloads frontmatter. Once myst build --ipynb is available (see meta#292), notebooks will be built at CI time and served as static assets. The download button will work with no theme changes — just the appropriate myst.yml configuration:

# page frontmatter
downloads:
  - id: lecture-notebook
    title: Notebook (.ipynb)

Status: ✅ Ready (blocked on upstream myst build --ipynb merging)

5.2 PDF Download Parity

mystmd supports per-page and whole-book PDF export via both LaTeX and Typst. The theme's Downloads dropdown will surface these when configured in frontmatter:

downloads:
  - id: lecture-pdf
    title: Lecture (PDF)
  - id: book-pdf
    title: Book (PDF)
Aspect Old Theme (Sphinx/LaTeX) New Theme (mystmd)
Per-page PDF ✅ via LaTeX build + pdf_book_path ✅ via exports + downloads frontmatter
Whole-book PDF ✅ via latex_documents config ✅ via multi-article exports config
Print fallback window.print() on toolbar icon Not implemented
PDF engine options LaTeX only LaTeX or Typst

5.3 Missing: window.print() Fallback

The old theme provided a window.print() fallback when no pre-built PDF was available. The new theme's DownloadButton does not offer this.

Recommendation: Add a "Print this page" option to the Downloads dropdown that calls window.print(). This is a small theme-level change in DownloadButton.tsx.


Part 6 — PR Triage & Issues Opened

As part of this review (February 2026), all open PRs were triaged and resolved:

PRs Merged

PR Title Type
#8 v1.1.1 — Colab .myst suffix fix, version bump, patch cleanup Release
#23 Bump vm2 3.9.19 → 3.10.3 Security (critical — sandbox escape)
#14 Bump vite 5.4.14 → 5.4.21 Security (XSS/SSRF)
#25 Bump qs + express Security (prototype pollution)
#22 Bump lodash 4.17.21 → 4.17.23 Security (prototype pollution)
#21 Bump lodash-es 4.17.21 → 4.17.23 Security
#13 Bump tar-fs 2.1.2 → 2.1.4 Security (path traversal)
#24 Bump webpack 5.98.0 → 5.105.0 Security
#27 Bump minimatch 3.1.2 → 3.1.3 Security (ReDoS)
#5 Bump @babel/runtime 7.26.9 → 7.27.6 Dependency
#6 Bump @babel/helpers 7.26.9 → 7.27.6 Dependency
#9 Bump brace-expansion 1.1.11 → 1.1.12 Dependency
#10 Bump on-headers, compression, morgan Dependency
#11 Bump form-data Dependency
#15 Bump js-yaml Dependency
#20 Bump diff Dependency

PRs Closed (Not Merged)

PR Title Reason
#18 Bump @remix-run/node 1.17.1 → 2.17.2 Remix v1→v2 requires coordinated migration, not individual bumps
#19 Bump @remix-run/react 1.17.1 → 2.17.3 Same — tracked in #28

PRs Created & Merged (During Review)

PR Title Impact
#29 Fix CI: bump @remix-run/* 1.17→1.19, security fixes Fixed ERESOLVE CI failure, reduced vulns 60→37, added npm overrides
#30 Upgrade @myst-theme/* 0.14.x→1.1.2 Major dep upgrade, aligned with upstream, reduced vulns 37→34
#31 Quick wins: bug fixes, CI, Node engine, CONTRIBUTING.md Fix 3 bugs, add CI pipeline, .nvmrc, contributor guide
#32 Fix CI type-check errors (lodash types, Buffer→Uint8Array) Resolve 3 pre-existing type errors caught by new CI pipeline

Issues Opened

Issue Repo Title
#26 quantecon-theme-src BinderHub launch button support
#28 quantecon-theme-src Migrate from Remix v1 to v2
meta#292 meta Notebook export: contribute to mystmd PR #1882 (myst build --ipynb)

Part 7 — Security & Dependency Upgrade Summary

Work Completed

  1. Remix peer dependency fix (PR Fix CI: bump @remix-run/* from 1.17 to 1.19 (peer dependency conflict) #29): Bumped @remix-run/* from ~1.17.0 to ~1.19.0 to satisfy @myst-theme/site@0.14.0 peer dependency. Fixed CI ERESOLVE failure.

  2. Non-breaking audit fixes (PR Fix CI: bump @remix-run/* from 1.17 to 1.19 (peer dependency conflict) #29): Ran npm audit fix, added npm overrides for prismjs (^1.30.0) and katex (^0.16.21). Reduced vulnerabilities from 60 → 37.

  3. @myst-theme v1 upgrade (PR Upgrade @myst-theme/* from 0.14.x to 1.1.2 #30): Bumped all 7 @myst-theme/* packages + myst-to-react + myst-common + myst-config from 0.14.x to 1.1.2. Removed cytoscape override (mermaid 9→11 resolved the incompatibility). Reduced vulnerabilities from 37 → 34.

  4. @vercel/node upgrade investigated: Tested @vercel/node v2→v5. Result: v5 introduced more vulnerabilities (38 vs 34). Reverted — staying on v2.

Remaining 34 Vulnerabilities (Ecosystem-Wide)

Surveyed all projects in the myst-theme ecosystem (upstream myst-theme/book, curvenote/overlay, curvenote/landing). No project has migrated to Remix v2. The remaining 34 vulnerabilities affect every myst-theme consumer equally.

Blocker Vulns Status
Remix v2 migration ~13 Tracked in #28. @remix-run/vercel deprecated in v2, needs @vercel/remix.
@myst-theme upstream (nanoid, markdown-it) ~9 Awaiting upstream fixes in myst-to-react, myst-transforms
Remix dev toolchain (tar, cacache, esbuild, vite, cookie) ~7 Dev-only deps, not in production bundles
@vercel/node v2 transitive (ajv, path-to-regexp, esbuild) ~5 v5 upgrade makes it worse; blocked on ecosystem

Ecosystem Alignment (as of Feb 2026)

Aspect quantecon-theme-src myst-theme/book (upstream) curvenote/overlay
@remix-run/* ~1.19.0 ~1.17.0 ^1.19.3
@myst-theme/* ^1.1.2 ^1.1.2 ^0.13.3
@vercel/node ^2.15.1 ^2.15.1 ^2.15.9
packageManager npm@8.10.0 npm@8.10.0 npm@8.10.0
Remix version v1 + v2 future flags v1 + v2 future flags v1 + v2 future flags

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions