# Social metadata and sharing strategy

Mechanica supports shareable links to specific machines and viewer states. Browser-visible metadata can be updated client-side, while social crawler previews need static or server-generated HTML.

## Share URL goals

A copied link should reconstruct:

- active machine
- camera preset or camera position/target
- exploded view amount
- display mode
- cross-section axis and offset
- annotation label state
- selected part
- hidden parts
- part opacity overrides
- animation RPM and time scale

The link should not include:

- hover state
- FPS
- temporary drag state
- open tooltip coordinates
- raw Three.js object UUIDs
- local favourites
- user preferences unrelated to the shared view

## Canonical route format

Preferred route:

```text
/machine/<machine-slug>
```

Example:

```text
/machine/planetary-gearbox?preset=iso&explode=0.55&mode=solid&labels=1&part=sun-gear
```

If a router variation cannot encode the slug in the path, use:

```text
/viewer?machine=planetary-gearbox&preset=iso
```

## Query schema

| Param | Type | Clamp/validation |
| --- | --- | --- |
| `preset` | enum | `front`, `back`, `left`, `right`, `top`, `iso` |
| `cam` | six comma-separated numbers | camera xyz + target xyz, finite values only |
| `explode` | number | clamp `0` to `1` |
| `mode` | enum | `solid`, `wireframe`, `xray` |
| `clip` | axis + offset | axis `x/y/z`, offset clamp `-1` to `1` |
| `labels` | boolean | `1` or `0` |
| `part` | string | valid part ID for active machine |
| `hidden` | CSV | valid part IDs only |
| `opacity` | CSV pairs | `partId:value`, opacity clamp `0` to `1` |
| `rpm` | number | clamp to active machine animation range |
| `speed` | number | clamp `0.1` to `3` |

Unknown params should be preserved only if the router owns them. Viewer-state parsing should ignore unknown fields.

## Copy-link behavior

The copy-link control should:

1. Build the current route with serialized state.
2. Resolve it against `VITE_APP_ORIGIN` or `window.location.origin`.
3. Prefer `navigator.clipboard.writeText`.
4. Use a text-area fallback if Clipboard API is unavailable.
5. Show a success message in a visible toast and an ARIA live region.
6. Show a recoverable error state if copying fails.

The generated URL should be deterministic so copying twice without state changes produces the same string.

## Client-side metadata

On route changes, update:

- `document.title`
- `<meta name="description">`
- Open Graph title/description/url/image tags
- Twitter title/description/image tags
- `<link rel="canonical">`

For machine pages:

```text
<title><Machine Title> — Mechanica</title>
description=<machine description>
og:title=<Machine Title> — Mechanica
og:description=<machine description>
og:url=<canonical machine URL>
og:image=<machine social image or default image>
```

## Social crawler limitation

Most social crawlers do not execute the client application fully. A static SPA can provide a strong default site preview in `index.html`, but route-specific social cards require one of these strategies:

### Strategy A: pre-render machine HTML

Generate one static HTML file per machine route at build time with machine-specific meta tags and the same SPA root. This is simple and CDN-friendly.

Pros:

- fast
- no server runtime
- deterministic
- works on static hosting

Cons:

- requires a small build-time metadata generation script
- deploy must include all machine route HTML files

### Strategy B: Vercel Edge metadata response

Use an edge function or serverless route to return route-specific HTML metadata for crawlers and the SPA shell for browsers.

Pros:

- supports dynamic social images
- can handle future user-generated collections

Cons:

- more moving pieces
- CSP and cache policy must be maintained carefully
- higher operational complexity

### Current milestone strategy

The delivered static app uses a robust default preview in `index.html` and documents the per-machine options above. Runtime metadata updates should still be implemented because they improve browser tabs, bookmarks, accessibility tooling, and copied-link clarity even when social crawlers use default tags.

## Social image policy

Default image:

```text
/social/mechanica-og.svg
```

Per-machine images should use:

```text
/social/machines/<machine-slug>.png
```

Recommended dimensions:

- `1200x630`
- PNG or JPG for maximum platform compatibility
- less than `500 KB`
- dark background with clear machine silhouette and title

SVG is included as the lightweight default asset in this repository. For a public marketing launch, export a PNG equivalent for broader social-platform compatibility.
