developmentseed / developmentseed/cng-sandbox

Improve story performance, transitions, onboarding, and observability

Open
#600 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
3
Forks
0
Avg merge
2h 21m
Merged PRs (30d)
3

Description

## Context

PR #599 reduces the workspace and editor entry costs by lazy-loading top-level routes and optional editor workflows. During the accompanying product and architecture review, several follow-up opportunities emerged that are better handled as a deliberate second phase.

The most important remaining concern is that the published story reader still loads substantial MapLibre/deck.gl infrastructure up front, even when the first content is prose. The review also surfaced an ambiguous cross-dataset transition, inconsistent creation vocabulary, limited performance telemetry, and a slow/noisy frontend test environment.

## Goals

- make prose-first stories readable before map infrastructure finishes loading
- prevent stale or overlapping map layers during chapter transitions
- detect bundle and runtime performance regressions automatically
- make first-time creation paths easier to understand
- make frontend tests faster and more deterministic

## Recommended work

### 1. Progressively hydrate story maps

Render story prose and lightweight media immediately. Delay map initialization until a map-bound chapter is within a reasonable viewport threshold.

Implementation considerations:

- use an IntersectionObserver-based boundary around map, scrollytelling, and flyover blocks
- show a dimensionally stable loading state so hydration does not shift the document
- prewarm the next map block before it becomes visible
- respect reduced-motion preferences
- avoid initializing multiple off-screen MapLibre instances unnecessarily
- verify embeds and portable stories behave the same way

Acceptance criteria:

- prose-first stories render without downloading or executing the full map stack immediately
- the first approaching map is ready before or shortly after it enters the viewport
- chapter layout does not jump during hydration
- reader and embed behavior have focused automated coverage
- before/after reader entry and map-ready measurements are recorded

### 2. Formalize map transition ownership

The reviewed example briefly appeared to combine ocean-temperature and forest-emissions imagery during a chapter transition. Treat layer replacement as an explicit lifecycle instead of relying on incidental component timing.

Implementation considerations:

- define entering, active, and exiting layer states
- give each chapter transition a stable identity or generation token
- cancel stale asynchronous layer construction when the active chapter changes
- remove exiting datasets deterministically after the intended transition
- distinguish deliberate crossfades from accidental overlap

Acceptance criteria:

- rapidly scrolling across chapters cannot restore an obsolete layer
- switching datasets does not leave both visible unless the chapter explicitly requests a crossfade or overlay
- visual regression coverage includes raster-to-raster and raster-to-vector transitions
- transition behavior is documented near the rendering architecture

### 3. Add bundle budgets to CI

Track meaningful application entry points instead of relying only on Vite's generic chunk warning.

Suggested budgets:

- application bootstrap
- workspace route
- story reader route
- story editor entry
- map route
- largest synchronous dependency group

Acceptance criteria:

- CI produces a readable size report with raw and gzip values
- budgets compare against committed thresholds or an approved baseline
- a meaningful regression fails CI with the affected entry point named
- intentionally lazy optional chunks are reported separately
- PR #599's output becomes the initial baseline

### 4. Add real-user performance instrumentation

Record user-visible milestones rather than only asset transfer sizes.

Suggested events and measures:

- workspace content ready
- story editor interactive
- story prose visible
- first map frame
- first successful data layer frame
- chapter transition duration
- tile or layer initialization failure
- route and connection type, without recording private dataset names or URLs

Acceptance criteria:

- measurements use the existing analytics approach and follow its privacy constraints
- dashboards or documented queries expose p50, p75, and p95
- slow starts can be separated into application, API, map engine, and tile/data phases
- instrumentation failures never block the user experience

### 5. Clarify creation vocabulary and first-use paths

Standardize the workspace around two clear starting intents:

1. create a map from data
2. create a story

Review and align the labels currently represented by “Add data,” “Quick map,” “New story,” and similar calls to action across workspace, navigation, and empty states.

Acceptance criteria:

- the same action uses the same label throughout the application
- each primary workspace action appears once per relevant surface
- empty states explain the next concrete action without adding tutorial copy
- focused tests protect the chosen labels and destinations

### 6. Stabilize frontend tests

The local suite currently exhibits slow module imports, repeated CSS parser noise, localStorage environment sensitivity, and tests that pass individually but exceed timeouts in larger batches.

Implementation considerations:

- establish localStorage explicitly in shared test setup
- identify heavy modules that should be mocked in routing and editor unit tests
- suppress or fix known non-actionable stylesheet parsing noise
- separate lightweight unit suites from WebGL/integration suites
- collect per-file transform, import, and test timings in CI

Acceptance criteria:

- the focused route, workspace, and editor suites run reliably without custom `NODE_OPTIONS`
- tests do not require broadly increasing global timeouts
- CSS warnings no longer obscure failures
- heavy map integration tests remain representative and run in an appropriate environment

## Suggested sequence

1. Bundle budgets and runtime instrumentation
2. Progressive story-map hydration
3. Explicit map transition lifecycle
4. Creation vocabulary cleanup
5. Test environment stabilization in parallel with the implementation work

Instrumentation and budgets should land first so later changes can be evaluated against real baselines rather than intuition.

## Related work

- PR #599
- Frontend architecture notes in `docs/frontend-gotchas.md`
- Story renderer and map composition code in `frontend/src/components/StoryRenderer.tsx` and `frontend/src/components/UnifiedMap.tsx`

Contributor guide

Open the contributing guide

Research direction

Start by reading docs/frontend-gotchas.md, frontend/src/components/StoryRenderer.tsx, and frontend/src/components/UnifiedMap.tsx, then review PR #599's output as the proposed baseline. Begin with bundle budgets and runtime instrumentation before investigating hydration, transitions, vocabulary, and test-suite work. Done requires the stated performance, transition, CI, analytics, UX, and frontend test acceptance criteria to be covered without blocking users.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript, vite
Domain
frontend, observability, performance, testing
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.