# Deployment guide

Mechanica is a static Vite application with client-side routing and WebGL assets. The production deployment target is Vercel, but the generated `dist/` folder can also be served from any static host that supports SPA rewrites and long-lived immutable asset caching.

## Build contract

- Install command: `npm install`
- Build command: `npm run build`
- Output directory: `dist`
- Preview command: `npm run preview`
- Node version: `>=20`

The build command runs TypeScript project validation before bundling with Vite. Production source maps are disabled by default and can be enabled with `VITE_ENABLE_SOURCE_MAPS=true`.

## Vercel setup

1. Import the repository into Vercel.
2. Select framework preset **Vite**.
3. Set:
   - Install command: `npm install`
   - Build command: `npm run build`
   - Output directory: `dist`
4. Add environment variables from `.env.example`.
5. Set `VITE_APP_ORIGIN` to the canonical production origin, for example `https://mechanica.example.com`.
6. Deploy a preview branch and run the QA checklist before promoting to production.

`vercel.json` contains the SPA rewrites, security headers, and immutable cache headers for hashed build assets plus decoder folders.

## Environment configuration

Only non-secret values belong in `VITE_` variables because Vite embeds them into client bundles.

Required public variables for production:

```bash
VITE_APP_NAME=Mechanica
VITE_APP_ORIGIN=https://your-production-domain.example
VITE_DEFAULT_MACHINE=four-stroke-petrol-engine
VITE_ASSET_BASE_URL=/assets/machines/
VITE_DRACO_DECODER_PATH=/draco/
VITE_KTX2_TRANSCODER_PATH=/basis/
VITE_ENABLE_PERF_OVERLAY=false
VITE_ENABLE_DEBUG_CAMERA=false
VITE_ENABLE_SOURCE_MAPS=false
VITE_SOCIAL_IMAGE=/social/mechanica-og.svg
```

## Routing

Mechanica is a single-page app. These routes rewrite to `index.html`:

- `/`
- `/catalogue`
- `/machine/:slug`
- `/viewer/:slug`
- all other client routes

Runtime route handling should display an in-app not-found state for unknown machine slugs rather than relying on the hosting platform’s 404 page.

## Headers

The Vercel configuration applies:

- `X-Content-Type-Options: nosniff`
- `X-Frame-Options: DENY`
- `Referrer-Policy: strict-origin-when-cross-origin`
- restrictive `Permissions-Policy`
- a CSP that allows:
  - same-origin scripts
  - WebAssembly execution needed by Basis/KTX2 transcoding
  - same-origin and blob workers used by asset decoders
  - inline styles for Vite/CSS-in-JS runtime compatibility

If third-party analytics or monitoring is added later, update `script-src`, `connect-src`, and `img-src` deliberately instead of weakening the policy globally.

## Cache policy

Hashed build assets under `/assets/` are cached for one year with `immutable`.

Decoder/transcoder folders are also cached for one year:

- `/draco/`
- `/basis/`

If decoder files are replaced, either keep their filenames versioned or purge the Vercel cache. Social preview and icon assets are cached for one week to allow brand updates without long stale periods.

## Asset decoder deployment

For Draco-compressed geometry, copy the decoder files from the resolved `three` package into `public/draco/` during asset pipeline setup. Typical files are:

- `draco_decoder.js`
- `draco_decoder.wasm`
- `draco_wasm_wrapper.js`

For KTX2/Basis textures, copy the transcoder files into `public/basis/`. Typical files are:

- `basis_transcoder.js`
- `basis_transcoder.wasm`

The exact file names and source locations should be confirmed against the installed Three.js version.

## Preview deployment QA

For every preview deployment:

1. Open the preview URL in a clean browser profile.
2. Load the catalogue.
3. Search and filter machines.
4. Open one machine from each category.
5. Confirm the 3D viewer renders without console errors.
6. Play/pause animation and change RPM.
7. Toggle exploded view, wireframe, annotations, and cross-section.
8. Select a part and confirm the detail drawer updates.
9. Copy a share link and open it in a private window.
10. Test a mobile viewport at 390px width.
11. Test with reduced motion enabled.
12. Run Lighthouse or WebPageTest for a production-like network profile.

## Rollback

Vercel retains immutable deployments. To rollback:

1. Open the Vercel project deployments list.
2. Select the last known-good production deployment.
3. Promote it to production.
4. Verify the app loads and share links still resolve.
5. If asset paths changed between deployments, purge caches for decoder folders and any public non-hashed assets.

## Domain and canonical URLs

Set `VITE_APP_ORIGIN` to the production origin. The runtime SEO/share layer should derive canonical machine URLs from that origin and the route slug.

For static social crawlers, `index.html` provides a robust default preview. Per-machine social cards require either:

- pre-rendered static HTML files generated for each machine route, or
- a Vercel Edge/SSR metadata endpoint that returns route-specific Open Graph tags before the SPA boots.

The current static deployment strategy uses default site-level tags plus client-side metadata updates for browser tabs and copy-link behavior.
