# Migrer une app sur un nouvel appareil

> Une app local-first sans comptes. Un code sur l’ancien téléphone, tapé sur le nouveau, et toute la base de données suit. Comment le construire avec s3nd, à quoi faire attention, et le guide complet.

Canonical: https://s3nd.sh/fr/use-cases/new-device · Markdown: https://s3nd.sh/fr/use-cases/new-device.md · English: https://s3nd.sh/use-cases/new-device

Une app local-first sans comptes. Un code sur l’ancien téléphone, tapé sur le nouveau, et toute la base de données suit.

```ts
import { store, SCHEMA_VERSION } from '@/lib/store'

export async function POST(request: Request) {
  const state = await request.json()
  const code = store.codes.create()

  await store.putSnapshot(code, state, {
    app: 'notes',
    version: SCHEMA_VERSION,
    device: request.headers.get('user-agent') ?? undefined,
    expiresIn: 60 * 60,
    ifAbsent: true,
  })

  return Response.json({ code })
}
```

## Ce qui se passe vraiment.
### Le problème
L’utilisateur a un nouveau téléphone. L’app sur l’ancien contient tout, dans IndexedDB, et il n’y a aucun compte où se connecter parce que l’app n’en a jamais eu besoin. IndexedDB ne quitte pas le navigateur dans lequel il a été écrit.

### Ce que s3nd y fait
L’ancien appareil exporte ses object stores, les poste à votre API, et reçoit un code de huit caractères. Le nouvel appareil tape le code, voit ce qu’il s’apprête à restaurer, et remplace sa base vide en une seule transaction. Le snapshot expire dans l’heure et le code est brûlé en cas de succès.

## Les choses faciles à rater.
- **Confirmer avant de remplacer** — Renvoyez createdAt et device depuis la lecture, et affichez-les. L’erreur la plus courante est de restaurer sur l’appareil qui avait déjà les données.
- **Versionner le snapshot** — Passez maxVersion à la lecture. Un snapshot issu d’une version plus récente de l’app échoue avec une erreur claire au lieu d’atterrir dans une version qui va le mal lire.
- **Brûler le code** — Un DELETE après un import réussi est le chemin propre ; l’expiration est le filet de sécurité. Les deux tiennent en une ligne.

Packages: s3nd, @s3nd/react. [Migrer sur un nouvel appareil, en détail](https://doc.s3nd.sh/docs/use-cases/new-device)
