Skip to content

Architecture

Parallax Designer follows a single-page, zero-router, composable-first architecture built with Vue 3 and TypeScript.

Design Principles

  • Pure core layer — All engine logic, schema validation, constraints, defaults, and export generation live in src/core/ with zero Vue imports. This makes the core testable in isolation and reusable outside of Vue.
  • Composable state management — Reactive state is managed through Vue composables (src/composables/) instead of a store library like Pinia or Vuex.
  • Single orchestratorApp.vue is the top-level orchestrator connecting all composables and passing data to components. There is no router because the entire app is one view.
  • Component composition — Components are pure SFCs focused on rendering and user interaction, receiving data and callbacks from the composable layer.

Folder Structure

src/
├── core/                  # Pure logic — no Vue dependency
│   ├── parallaxEngine.ts  # requestAnimationFrame loop, transforms
│   ├── schema.ts          # V3 validation + normalization
│   ├── projectDefaults.ts # Starter templates + 5 named presets
│   ├── projectConstraints.ts # Numeric min/max/step for every field
│   ├── backgroundStyle.ts # CSS background property composition
│   ├── exportRuntimeHtml.ts # Runtime HTML export planner + builder
│   ├── exportSnippet.ts   # JSON helper utilities
│   ├── imageRefs.ts       # idb:// URI helpers
│   ├── assetDb.ts         # Dexie DB (assets + customPresets)
│   └── utils.ts           # deepClone, makeId

├── composables/           # Stateful Vue integration
│   ├── useProjectState.ts # Central project ref, layer CRUD, z-index norm
│   ├── useProjectIO.ts    # Export/import and custom presets
│   ├── useParallaxEngine.ts # Engine lifecycle, pointer tracking, FPS
│   ├── useLayerAssets.ts  # IndexedDB images → object URLs
│   ├── useI18n.ts         # Custom typed i18n
│   ├── useToast.ts        # Global toast notifications
│   ├── useHelp.ts         # Contextual help tooltip state
│   └── useHelpDock.ts     # Help tooltip positioning

├── components/            # Vue SFCs
│   ├── ParallaxScene.vue  # Fullscreen viewport + geometry guide
│   ├── OverlayPanel.vue   # Draggable floating panel
│   ├── LayerList.vue      # Sortable layer stack
│   ├── LayerEditor.vue    # Geometry + motion editors
│   ├── LayerBasicEditor.vue # Name, image, background
│   ├── LayerBackgroundEditor.vue # Full CSS background UI
│   ├── SceneControls.vue  # Scene parameters
│   ├── HarmonicsControls.vue # Float harmonics
│   ├── controls/          # Reusable form controls
│   ├── modals/            # Modal dialogs
│   └── project-settings/  # Settings panel groups

├── types/                 # TypeScript type definitions
│   ├── parallax.ts        # Core types (project, scene, layer, etc.)
│   └── geometryGuide.ts   # Geometry guide types

├── i18n/                  # Internationalization
│   ├── config.ts          # Locale metadata + defaults
│   └── locales/           # EN, FR catalogs + registry

└── content/               # Static content
    └── helpContent.ts     # Help tooltip key mappings

Data Flow

Component Hierarchy

Key Patterns

No External State Store

The app uses no Pinia, Vuex, or other state management library. All state lives in reactive ref and computed values inside composables. State is shared by calling the same composable (global singletons) or by passing refs between composables (factory pattern).

Result Pattern for Validation

Schema validation and import operations return Result<T, E> instead of throwing exceptions:

ts
type Result<T, E> = { ok: true; data: T } | { ok: false; error: E };

This ensures all error paths are handled explicitly at the call site.

Z-Index Auto-Normalization

Layer add/remove/duplicate flows normalize zIndex values into a contiguous 1..N range. This avoids duplicate or missing stack ranks after structural edits.

Parallax Designer Documentation

Scroll to zoom · Drag to pan