8.5 KiB
Plan: React + Vite Rewrite of Azure Image Chooser
Rewrite the current Streamlit application into a two-tier web app (React + Vite frontend and Node.js backend) while preserving core image-discovery behavior (location -> publisher -> offer -> SKU -> version) and generated usage outputs, and redesigning UX and template architecture, with strict non-destructive workspace constraints.
Hard constraints
- Existing workspace files must remain untouched, except .gitignore.
- All new application source must live under src/.
- Build artifacts must be emitted only to dist/.
- A new Dockerfile and entrypoint.sh must be added at the workspace root.
- The container runtime must use Node.js 24 LTS on Debian trixie-slim (node:24-trixie-slim).
- All new source code must be TypeScript and use the TypeScript 6 transpiler (latest revision).
- Frontend UI must use plain Material UI v9.x.x.
- All MUI-related questions and implementation decisions must be resolved using mui-mcp as the primary source/tool.
- Frontend must use the latest stable React line (React 19.2.x), with no legacy compatibility or migration work included.
- Docker is not available in the target environment; container lifecycle operations must use Apple-sponsored container CLI only.
Steps
-
Phase 0 - Planning artifact handoff
-
After plan mode is turned off, copy plan artifacts to workspace directory migration-plan/ for future reference:
- migration-plan/plan.md
- migration-plan/version-manifest.md
-
Keep session/repo memory files as source-of-truth backups.
-
Phase 1 - Baseline and migration contract
-
Capture current functional contract from existing app behavior in app/image-chooser.py: cascading selectors, semantic version sorting, empty-state behavior, and SKU export format.
-
Define backend API contract for frontend consumption: locations, publishers, offers, skus, versions, templates, rendered output, and SKU export endpoints, including error payloads.
-
Lock frontend framework prerequisites from current MUI status before scaffolding: Material UI v9.x.x, React 19.2.x (latest stable), Emotion styling engine defaults, and required companion packages.
-
Explicitly exclude legacy React compatibility paths and migration workarounds from scope (no legacy shims, no backward-compat migration tracks).
-
Define target repository layout under src/ for frontend and backend packages, with dist/ as the fixed artifact directory.
-
Define non-destructive execution guardrails: no edits to legacy files except .gitignore updates for node_modules and artifact outputs.
-
Phase 2 - Node backend in src
-
Scaffold backend under src/backend in TypeScript (mandatory) with modules for Azure compute discovery, template catalog, rendering, and validation, compiled with TypeScript 6.
-
Implement Azure integration equivalent to current data loaders, including region_type=Physical filtering and conditional semantic version sorting when all versions match X.Y.Z.
-
Implement endpoint caching (TTL by endpoint+params) and structured logging.
-
Implement redesigned template subsystem with metadata model and render endpoint.
-
Add backend tests under src/backend aligned to the API contract.
-
Phase 3 - React + Vite frontend in src
-
Scaffold frontend under src/frontend using Vite with TypeScript (mandatory), configure output directory to dist/, compile with TypeScript 6, use React 19.2.x (latest stable), and use plain Material UI v9.x.x as the UI component library.
-
Build cascading async selectors with deterministic reset behavior (location -> publisher -> offer -> sku -> version).
-
Implement API-driven state management (for example TanStack Query) with loading, empty, and error states.
-
Implement usage output UI with template selection, rendered snippet display, copy action, and SKU export display, using plain Material UI v9.x.x components and styling primitives (Emotion-based engine).
-
Add frontend tests under src/frontend for cascade behavior and output rendering.
-
Phase 4 - Root runtime wrapper and cutover
-
Add new root Dockerfile that builds/runs the new src-based application stack on Node.js 24 LTS with Debian trixie-slim (node:24-trixie-slim), and ensure runtime commands are documented/executed via Apple container CLI (not Docker).
-
Add new root entrypoint.sh that starts the new runtime components.
-
Update .gitignore for node_modules, dist artifacts, and any new temporary outputs.
-
Validate core behavior parity against Streamlit baseline using representative selections and generated outputs.
-
Keep legacy assets in place (untouched) during and after migration unless separately approved for cleanup.
Parallelism and dependencies
- Phase 0 runs first and gates execution handoff artifacts in workspace.
- Phase 1 blocks implementation.
- After API contract freeze, backend (Phase 2) and frontend scaffold (Phase 3) can run in parallel.
- Phase 4 depends on stable frontend/backend run commands and artifact paths.
Relevant files
- /Users/slawek/src/azure-image-chooser/app/image-chooser.py - source-of-truth behavior reference only; do not modify.
- /Users/slawek/src/azure-image-chooser/app/templates.json - current template catalog reference only; do not modify.
- /Users/slawek/src/azure-image-chooser/app/templates/arm_vm.jsonc - output reference only; do not modify.
- /Users/slawek/src/azure-image-chooser/app/templates/azurerm_hcl.tpl - output reference only; do not modify.
- /Users/slawek/src/azure-image-chooser/app/templates/shell.tpl - output reference only; do not modify.
- /Users/slawek/src/azure-image-chooser/.gitignore - only existing file allowed to be changed.
- /Users/slawek/src/azure-image-chooser/src/ - new source tree for rewritten application.
- /Users/slawek/src/azure-image-chooser/dist/ - artifact output directory.
- /Users/slawek/src/azure-image-chooser/Dockerfile - new root runtime image definition.
- /Users/slawek/src/azure-image-chooser/entrypoint.sh - new root runtime entrypoint.
Verification
- Workspace contains migration-plan/plan.md and migration-plan/version-manifest.md after plan mode is off.
- Git diff check confirms only new files plus .gitignore modifications; no edits in legacy files.
- Backend tests pass for API contract, validation, filtering, sorting, and rendering.
- Type-check/transpile verification passes with TypeScript 6 for both backend and frontend packages.
- Frontend tests pass for selector cascade and output rendering.
- Frontend dependency and implementation checks confirm plain Material UI v9.x.x is used (no alternate UI framework).
- Verification confirms MUI installation prerequisites are met for React 19.2.x and Emotion packages.
- Verification confirms there are no legacy compatibility layers or migration-specific workarounds in frontend dependencies/configuration.
- Local run verifies UI flow and generated outputs match baseline behavior for representative scenarios.
- Image build inspection via Apple container CLI confirms the runtime base image is Node.js 24 LTS on Debian trixie-slim (node:24-trixie-slim).
- Artifact generation confirms outputs land only in dist/ directory.
Decisions
- Use Node.js backend (confirmed).
- Keep only core functionality unchanged; UX and architecture can be redesigned (confirmed).
- Redesign template system now (confirmed).
- Enforce non-destructive migration: existing files untouched except .gitignore (confirmed).
- Place all new application code in src/ and add new root Dockerfile + entrypoint.sh (confirmed).
- Use Node.js 24 LTS on Debian trixie-slim as container runtime base image (confirmed).
- Use TypeScript-only source with TypeScript 6 transpiler across backend and frontend (confirmed).
- Use plain Material UI v9.x.x for frontend UI implementation (confirmed).
- Use mui-mcp as the primary tool/source for all MUI-related implementation questions (confirmed).
- Use latest stable React (19.2.x at planning time) and exclude legacy compatibility/migration paths (confirmed).
- Use Apple container CLI (macOS 26, Apple silicon) for container operations; no Docker dependency (confirmed).
Scope boundaries
- In scope: functional core parity for image lookup and output generation, new frontend/backend architecture in src/, root runtime wrappers, and .gitignore updates.
- Out of scope: modifying existing legacy app/ and terraform/ files, removing legacy code, or altering old deployment definitions.
Further Considerations
- Artifact output is fixed to dist/ for consistency with the chosen convention.
- If backend and frontend are separate runtime processes, define entrypoint process model early (single-process with static serve vs process manager).