MTL ExplorerReleased · 0.9.0Home

Frontend development

The Vue, TypeScript, MapLibre, and PrimeVue PWA lives in mtl-client/ and is served under /mtl/.

Generate the API package in the development container first, then run from mtl-client/:

npm install
npm run dev

Vite proxies /mtl/api to the local backend. Set VITE_DEV_PROXY_TARGET when using another backend address. The development service worker is disabled.

On this page

User flows

Design the complete user flow before editing UI code; avoid narrow visual patches. Follow the shared controls, panel behavior, and typography in the styling guide, and keep changes consistent across the flow.

Domain calculations belong to the server; follow backend ownership. Use generated API types and shared code rules.

Stable test identifiers

Give major actions, navigation, inputs, panels, and important result/error states stable data-test IDs. Add them during development and when filling regression gaps. Decorative elements need none.

Use purpose-based names, such as planner-save-plan, stable across layout, theme, and language changes. Put action IDs on interactive DOM elements in production builds. Scope repeated controls by stable item keys, not list positions.

Keep accessible names and labels; test IDs supplement them. Update affected tests when changing IDs. Follow the browser locator rules.

Profiling and checks

For browser profiling, use profile mode. It keeps the production runtime and chunk layout, disables JavaScript and CSS minification, includes source maps, and disables service worker generation and registration. Set MTL_PROFILE_DIR to a dedicated output directory on your data drive, then run:

export MTL_VITE_CACHE_DIR="$MTL_PROFILE_DIR/vite-cache"
npm run build:profile -- --outDir "$MTL_PROFILE_DIR/dist"
VITE_DEV_PROXY_TARGET=https://your-backend.example npm run preview:profile -- \
  --outDir "$MTL_PROFILE_DIR/dist" --host 127.0.0.1 --port 5196 --strictPort

Open /mtl/ on that port. Use a fresh origin or clear any existing service worker before recording. Unminified assets increase load size; compare final load timings with a normal production build.

Available checks:

npm run format:check
npm run type-check
npm run lint
npm test
npm run build

Run npm run format to format client source, tests, and configuration with the project Prettier settings.

build includes type checking; build-only only bundles assets. Edit source and public/, then rebuild. Do not edit copied server assets or dist/.

The manifest owns scripts and dependencies. Read styling, API generation, and documentation authoring.

Errors and diagnostics

Rethrow the original caught value with throw error. Do not replace it with new Error(String(error)): that loses its type, stack, HTTP response, and cancellation metadata. If a distinct user-facing message requires a wrapper, use new Error(message, { cause: error }) and retain the original failure. Report the original transport error before reading private response details for the UI. Keep credentials, response bodies, and private application values out of diagnostics.

Use startupLog and startup timer success for normal startup, progress, and sign-in transitions. Reserve warnings and errors for problems. Pass the actual failure as the third argument to startupWarn / startupError, or the second argument to timer warn / error; pass structured context separately after it. Use undefined for the error when a warning has only context. Context objects and timing metadata are not exceptions.

See diagnostic logging.