LearnNewsExamplesServices
Frontmatter
id12305
titleAdopt chunked lazy nav for portal pulls (store + controller + theme)
stateClosed
labels
enhancementaiperformancebuild
assigneesneo-opus-ada
createdAtJun 1, 2026, 3:21 PM
updatedAtJun 1, 2026, 6:14 PM
githubUrlhttps://github.com/neomjs/neo/issues/12305
authorneo-opus-ada
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[x] 12219 Make tickets controller deep-link + default-route lazy-aware
closedAtJun 1, 2026, 6:14 PM

Adopt chunked lazy nav for portal pulls (store + controller + theme)

Closed v13.0.0/archive-v13-0-0-chunk-15 enhancementaiperformancebuild
neo-opus-ada
neo-opus-ada commented on Jun 1, 2026, 3:21 PM

Context

Sibling to #12304 (GPT's tickets-store switch) on the shared #12219 lazy-aware-nav track. Operator direction 2026-06-01: "gpt on tickets and you on pulls". After #12301 merged (release-grouped PR tree + chunked surface emitted), the operator pulled dev + theme-built and found the pulls view does not yet run in lazy mode:

  • apps/portal/store/Pulls.mjs still loads the flat ../../apps/portal/resources/data/pulls.json (all leaves), so the Latest group shows PR leaves directly with no chunk-folder nodes in the tree nav.
  • apps/portal/resources/data/pulls/index.json, manifest.json, and per-chunk leaf files already exist (emitted by #12301's buildScripts/docs/index/pulls.mjs).
  • apps/portal/view/news/pulls/MainContainer.mjs sets lazyChildLoad: true, but that is inert while the store consumes the flat all-leaves tree.
  • Separately: the PR-view timeline renders with no content-box bordersborder: 1px solid var(--gh-timeline-border) resolves to an undefined variable because the pulls theme scss does not define the --gh-* set (tickets + discussions theme scss define them at :root .neo-theme-neo-light).

The Problem

The Portal news perf track expects pulls to load only the root/group skeleton first, then fetch chunk leaves on folder expansion. The chunked data exists, but the consumer still points at the legacy monolith — so first paint pays the full PR-tree payload, the chunk folders are absent from the nav, and store.get(itemId) succeeds only against eagerly-loaded leaves (deep-links cannot honestly test lazy-aware resolution). The theme-var gap is a per-component lazy-CSS-load issue on the theme side (the structural rules ship via the @use added in #12301, but the color variables do not).

The Architectural Reality

  • apps/portal/store/Pulls.mjsurl points at the flat tree, not the chunked pulls/index.json.
  • apps/portal/view/news/pulls/MainContainerController.mjsonRouteItem/getDefaultRouteId call store.get(itemId) directly (the flat shape). The lazy-aware shape (already implemented in discussions/MainContainerController.mjs and being adopted for tickets in #12304/#12219) pre-loads unloaded chunk folders via childrenUrl / isChildrenLoaded before store.get.
  • resources/scss/theme-neo-{light,dark}/apps/portal/news/pulls/Component.scss — define pulls-specific badge colors only; do not define / @use the shared --gh-* timeline variables.

The Fix

  1. StorePulls.mjs url../../apps/portal/resources/data/pulls/index.json.
  2. Controllerpulls/MainContainerController.mjs adopts the lazy-aware getDefaultRouteId (folder-aware) + onRouteItem (pre-load the relevant chunk folder before store.get(itemId)), the same mechanism discussions/MainContainerController.mjs uses and #12304 adopts for tickets.
  3. Themepulls/Component.scss (theme-neo-light + theme-neo-dark) @use "../tickets/Component" so the --gh-* variables resolve (symmetric with the structural @use shipped in #12301).

Acceptance Criteria

  • AC1 — Pulls store loads pulls/index.json; the Latest group + release-version groups show chunk-folder nodes; PR leaves lazy-load on folder expansion (first paint loads only the skeleton).
  • AC2 — A deep-link #/news/pulls/<number> resolves under lazy load (controller pre-loads the containing chunk before selecting/scrolling).
  • AC3 — The default #/news/pulls route resolves the first PR under lazy load.
  • AC4 — PR-view timeline content boxes render their borders (theme --gh-* vars defined in the pulls theme CSS); build-output verifiable + L3 visual.
  • AC5 — Behavior parity with the tickets adoption (#12304) — no pulls-specific divergence in the lazy-load mechanism.

Out of Scope

  • Range-based chunk-folder display names (e.g. "1 – 100" / "101 – 134" instead of chunk-2) and open/closed state display in the tree — these are the cross-view UX brainstorm topic the operator raised for discussions; they apply to all chunked views and are tracked separately, not here.
  • Tickets adoption (#12304) and the discussions view (separate brainstorm).
  • The generator itself (already emits the chunked surface, shipped in #12301).

Decision Record impact

none — aligned-with the chunked-index emitter work (#12204 epic); no ADR amended/superseded.

Related

  • Blocks #12219 (lazy-aware nav); sibling to #12304 (tickets store switch).
  • Parent epic #12204 (Portal news — chunked lazy-load tree).
  • Origin: #12300 / PR #12301 (release-grouped + chunked-surface emitter merged 2026-06-01).

Origin Session ID: da9a6007-1250-4363-8c15-dff69eccb3be Retrieval Hint: "portal pulls chunked lazy store controller theme border var" / mirror discussions MainContainerController lazy onRouteItem

tobiu referenced in commit 43cf654 - "fix(portal): pulls chunked lazy nav — store + controller + theme vars (#12305) (#12307) on Jun 1, 2026, 6:14 PM
tobiu closed this issue on Jun 1, 2026, 6:14 PM
tobiu referenced in commit efa0d51 - "fix(portal): correct news tab order + document inverted layout (#12319) (#12320) on Jun 1, 2026, 8:42 PM