avvy-app is the primary web client for Avvyland: users create branes, import 3D objects through a wizard, place them on the grid, and switch between Build / Play / Mobile interaction modes. The app also bridges Shopify, importing 3D product models for virtual showrooms.
Repo: gitlab.avvyland.com/avvy/avvy-app.
Framework. React 19 + React Router DOM 7.
UI. Bootstrap 5.3 with React Bootstrap; SCSS with variables and mixins; dark theme by default.
3D. Three.js via the bundled avvy-engine.dev.js (see avvy-engine).
Animation. Tween.js.
Build. Vite for production; Create React App / Craco for dev. PWA-capable via service worker.
Transport. Axios for HTTP; CBOR-X for wire encoding; WebWorkers for heavy work.
Integration. Shopify App Bridge for the e-commerce path.
Entity hierarchy. BaseEntity → Block (placed object) and BaseEntity → Prototype (template). Entities support i18n, cell-based positioning, parent/child relations, properties, and handler bindings.
Dual coordinate system. Cell space for grid validation; world space for rendering. Snapping is implemented as a translation between the two.
Singleton service layer.
apiService — CBOR REST + WebSocket against state-server.braneService — brane lifecycle and config.manipulatorService — user interaction.storageService — entity persistence.loaderService — asset loading.cellsService — grid validation + raycasting.creatorService — 3D model processing for the Wizard.prototypeService — template management.Rendering pipeline. Custom Three.js wrapper (avvy-engine.dev.js); FPV and Orbit cameras; distance-based LOD; geometry/material deduplication; WebGL with fallback.
BUILD. Object placement and editing. Selection (single and multi), rotation guides on all axes, grid-snapped movement, take/remove, visual outlines.
PLAY. Walkthrough exploration and interaction.
MOBILE. Touch-optimized controls and UI.
Two-tier object creation flow:
Simple Mode. Guided steps for GLB/GLTF import, scale/position/pivot, cell-size configuration, metadata, preview generation (512×512 and 256×256).
Advanced Mode. Full parameter editor.
Outputs are published as Prototypes with interface assignments; previews are generated server-side via avvy-worker.
avvy-app/src/services/cellsService.*).Specific numeric limits (cell count per brane, inventory size, concurrent-editor cap) that appeared on an earlier version of this page came from a stale DESCRIPTION.md; they are removed here until reconfirmed against current avvy-app/src/ code.
Persistent. user/state, brane/{id}/state, object/{id}/state via API.
Session. Active placement object, interaction mode, camera, selection.
Local. Preferences, favorites, collapsed-panel state.
Prototype ─▶ Instantiation ─▶ Block ─▶ Placement ─▶ Storage
Entity data ─▶ schema gen ─▶ Three.js objects ─▶ WebGL render
API calls are CBOR-encoded; long-lived state syncs go over the WebSocket described in WebSocket protocol.
Shopify OAuth ─▶ product fetch ─▶ GLB/USDZ detection ─▶ import to Wizard ─▶ place in brane. Product-importer is a separate App Bridge surface that boots when the merchant authorizes the app.
npm install
npm run dev # Craco dev server
npm run build # Vite production build
Backend URL is overridden via env in src/hooks/useStateServer.jsx. HTTPS for local dev requires a cert pair (TLS is mandatory for the WebSocket).
gitlab.avvyland.com/avvy/avvy-app — README.md, src/ directly (note: the in-repo DESCRIPTION.md is treated as suspect; do not lift claims from it without cross-checking against current code). Deployment: gitlab.avvyland.com/avvy/argocd/avvyapp/{deployment,ingress,service}.yaml (image gitlab.avvyland.com:5050/avvy/avvy-app:latest, port 9898, ingress app.avvyland.com).