Frontmatter
| id | 9005 |
| title | Feat: Refactor Portal Header to Framework (using Dynamic Worker Arch) |
| state | Closed |
| labels | enhancementairefactoring |
| assignees | tobiu |
| createdAt | Feb 5, 2026, 3:51 PM |
| updatedAt | Feb 7, 2026, 5:01 PM |
| githubUrl | https://github.com/neomjs/neo/issues/9005 |
| author | tobiu |
| commentsCount | 1 |
| parentIssue | 8930 |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [] |
| blocking | [] |
| closedAt | Feb 7, 2026, 5:01 PM |
Feat: Refactor Portal Header to Framework (using Dynamic Worker Arch)
tobiu added parent issue #8930 on Feb 5, 2026, 3:51 PM

tobiu
Feb 5, 2026, 5:01 PM
Input from Gemini 3 Pro:
✦ I have finalized the refactoring of the Portal Header into the framework.
Corrected Architecture:
Framework (
src/app):
src/app/SharedCanvas.mjs: Generic base for worker-backed canvases (Dynamic Worker Architecture).src/app/header/Toolbar.mjs: Generic base Toolbar (Structure + Canvas injection, no items).src/app/header/Canvas.mjs: Header background visualization bridge.Portal App (
apps/portal):
apps/portal/view/HeaderToolbar.mjs: ExtendsNeo.app.header.Toolbar. Adds Portal-specific navigation items.- Updated
Viewport.mjsto use localHeaderToolbar.- Fixed import paths in all
apps/portal/canvas/files (../../../src/canvas/Base.mjs).DevRank App (
apps/devrank):
apps/devrank/view/HeaderToolbar.mjs: ExtendsNeo.app.header.Toolbar. Adds DevRank branding.- Updated
Viewport.mjsto use localHeaderToolbar.Bug Fixes:
- Resolved "Renderer Remote Stub not found" race condition in
SharedCanvas.initAsyncby polling for the remote stub availability.- Corrected import path levels for
Neo.canvas.Base.The solution is now robust, generic, and correctly separated.
tobiu closed this issue on Feb 7, 2026, 5:01 PM
tobiu assigned to @tobiu on Feb 7, 2026, 5:01 PM
Refactor the Portal Header (Toolbar and Canvas) into a reusable framework module
src/app/headerand update DevRank to use it.Context: Leverage the new Dynamic Worker Architecture (Epic #8948) used by
Sparkline. We will also refactorPortal.view.shared.Canvasinto the framework as it contains valuable shared logic (DOM listeners, etc.).Tasks:
Canvas Infrastructure (Renderer):
apps/portal/canvas/Base.mjstosrc/canvas/Base.mjs(renaming toNeo.canvas.Base).apps/portal/canvas/HeaderCanvas.mjstosrc/canvas/Header.mjs(renaming toNeo.canvas.Header).Neo.canvas.Headerto extend the newNeo.canvas.Base.Shared Canvas Component:
apps/portal/view/shared/Canvas.mjstosrc/component/CanvasShared.mjs(naming TBD, maybeNeo.component.CanvasSharedor similar).Portal.canvas.Helper).App Worker Components (
src/app/header):src/app/header/Canvas.mjs:apps/portal/view/HeaderCanvas.mjs.Neo.component.CanvasShared(or whatever we name it).initAsyncto useNeo.worker.Manager.startWorkerandNeo.worker.Canvas.loadModule(Pattern:Neo.component.Sparkline).src/app/header/Toolbar.mjs:apps/portal/view/HeaderToolbar.mjs.src/app/header/Canvas.mjs.src/app/header/ToolbarController.mjs:apps/portal/view/HeaderToolbarController.mjs.DevRank Integration:
apps/devrank/view/Viewport.mjs:vbox(Main container).Neo.app.header.Toolbar(The new reusable header).Containerwithcardlayout (flex: 1).GridContainer(DevRank Grid).Portal App Update:
Neo.app.header.*components and the newNeo.component.CanvasShared.