# Vue Client Scaffold Specification

## Recommended Stack

- Vue 3
- Vite
- Vue Router
- Pinia
- JavaScript
- `gnexus-ui-kit` for UI primitives and design system

Project decision: do not use TypeScript. Reliability should come from a small
API normalization layer, explicit mappers, and runtime response validation where
backend shapes are uncertain.

## Directory Layout

```text
webclient/
  docs/
  public/
  src/
    app/
      App.vue
      main.js
      providers.js
    api/
      client.js
      errors.js
      http.js
      mappers.js
      modules/
        areas.js
        devices.js
        scripts.js
      schemas/
        areas.js
        common.js
        devices.js
        scripts.js
    assets/
    components/
      app/
      data/
      feedback/
      forms/
      layout/
      overlays/
    features/
      areas/
      devices/
      scripts/
    router/
      index.js
      routes.js
    stores/
      areas.js
      devices.js
      favorites.js
      scripts.js
      ui.js
    styles/
      main.scss
      tokens.scss
    utils/
      concurrency.js
      dates.js
      format.js
      storage.js
  index.html
  package.json
  vite.config.js
```

## Route Mode

Use hash mode first.

Reason:

- Current client uses `#!/...`.
- Hash mode does not require web server rewrite configuration.
- It reduces deployment risk while the old and new clients coexist.

Target route mapping:

| Route | Component |
| --- | --- |
| `/` | Redirect to `/areas/favorites`. |
| `/devices` | `features/devices/pages/DevicesListPage.vue` |
| `/devices/scanning` | `features/devices/pages/DevicesScanningPage.vue` |
| `/scripts/actions` | `features/scripts/pages/ScriptActionsPage.vue` |
| `/scripts/regular` | `features/scripts/pages/ScriptRegularPage.vue` |
| `/scripts/scopes` | `features/scripts/pages/ScriptScopesPage.vue` |
| `/areas/favorites` | `features/areas/pages/AreaFavoritesPage.vue` |
| `/areas/tree` | `features/areas/pages/AreaTreePage.vue` |
| fallback | `features/system/NotFoundPage.vue` |

Future option:

- Switch to history mode after nginx/apache routing is explicitly configured.

## Environment Variables

Use Vite environment variables:

```text
VITE_API_BASE_URL=http://smart-home-serv.local
VITE_API_PROXY_PATH=/proxy.php
VITE_API_TIMEOUT_MS=10000
```

For local development with Vite dev server:

```text
VITE_API_BASE_URL=http://localhost:5173
VITE_API_PROXY_PATH=/proxy.php
```

If `proxy.php` remains in the old `webclient/` directory during development,
either:

- copy/adapt it into `webclient/public/proxy.php` for PHP-served deployment;
- or configure Vite dev proxy and call backend directly in dev.

## API Client Requirements

The API client should be promise-based:

```ts
const result = await devicesApi.list();

if (!result.ok) {
  // normalized error
  return;
}

const devices = result.data.devices;
```

No UI component should parse raw backend envelopes directly.

Layering:

- `http.js` - low-level fetch, timeout, abort, proxy path wrapping.
- `client.js` - common request helpers and response normalization.
- `modules/*.js` - domain-specific methods.
- `mappers.js` - response field unification currently done by `Helper`.
- `schemas/*.js` - lightweight runtime validators for uncertain response shapes.

## UI Kit Integration Contract

The `gnexus-ui-kit` repository was not available from this environment, so exact
package exports are intentionally not assumed in this spec.

Acceptable integration options, in preferred order:

1. Install as package/git dependency if it exposes Vue components or CSS assets.
2. Use a git dependency pinned by commit/tag in the lockfile.
3. Add as git submodule only if package/git dependency is not viable.
4. Avoid copying a versioned release into the project because the UI-kit updates
   often and should remain a live design dependency.

Whichever option is chosen, create one local compatibility layer:

```text
src/components/ui/
  UiButton.vue
  UiBadge.vue
  UiCard.vue
  UiDialog.vue
  UiInput.vue
  UiSelect.vue
  UiTable.vue
  UiToast.vue
```

Application code should prefer local compatibility components for app-specific
behavior, but these components must remain thin and track UI-kit public APIs.
The goal is full UI-kit update compatibility, not a forked component library.

## Initial Dependencies

Expected package dependencies:

```json
{
  "dependencies": {
    "@vitejs/plugin-vue": "latest",
    "vite": "latest",
    "vue": "latest",
    "vue-router": "latest",
    "pinia": "latest"
  },
  "devDependencies": {
  }
}
```

Add exact `gnexus-ui-kit` dependency only after its packaging format is known.

## Build Scripts

Recommended scripts:

```json
{
  "scripts": {
    "dev": "vite --host 0.0.0.0",
    "build": "vite build",
    "preview": "vite preview --host 0.0.0.0"
  }
}
```

## First Milestone Scaffold

Minimum files for the first working milestone:

- `src/app/main.js`
- `src/app/App.vue`
- `src/router/index.js`
- `src/router/routes.js`
- `src/api/client.js`
- `src/api/modules/areas.js`
- `src/stores/areas.js`
- `src/features/areas/pages/AreaFavoritesPage.vue`
- `src/components/layout/AppShell.vue`
- `src/components/feedback/AppErrorState.vue`
- `src/components/feedback/AppLoadingState.vue`

The first milestone is complete when `/areas/favorites` can call
`GET /api/v1/areas/list`, render favorite areas from localStorage, and show an
empty state without using any code from the old client.
