Explorer
KNOW-PAT-150

Modèle données annotations — schema, versioning, autosave

Domaine
web-uiux
Type
pattern
Priorité
P0

Parent : [[INDEX-WEB-UIUX]]

Modèle données annotations

Problème

Sans schema versionné, les annotations cassent à la première évolution (nouveau type, migration) et l'autosave corrompt les données (race conditions).

Solution — Document racine versionné

interface AnnotationDocument {
  version: 1
  id: string
  targetUrl: string
  createdAt: string
  updatedAt: string
  viewport: { width: number; height: number }
  annotations: Annotation[]
}

type Annotation =
  | PinAnnotation
  | TextAnnotation
  | RectAnnotation
  | ThreadAnnotation

interface BaseAnnotation {
  id: string
  type: "pin" | "text" | "rect" | "thread"
  authorId: string
  createdAt: string
  /** Position normalisée [[KNOW-PAT-149|KNOW-PAT-149]] */
  anchor: { x: number; y: number; scrollX: number; scrollY: number }
  resolved?: boolean
}

interface PinAnnotation extends BaseAnnotation {
  type: "pin"
  color: string
  label?: string
}

interface TextAnnotation extends BaseAnnotation {
  type: "text"
  content: string
  fontSize: number
  width: number
}

interface ThreadAnnotation extends BaseAnnotation {
  type: "thread"
  messages: { id: string; body: string; createdAt: string }[]
}

Persistance

Couche Rôle
Optimistic local IndexedDB ou localStorage draft immédiat
Autosave serveur Debounce 2–5s, PAT-136 race guards
Snapshot export JSON + PNG optionnel pour partage
// Autosave : jamais écraser si version serveur > locale
async function save(doc: AnnotationDocument) {
  const remote = await api.get(doc.id)
  if (remote && remote.updatedAt > doc.updatedAt) {
    throw new ConflictError(remote)
  }
  await api.put(doc)
}

API minimale

GET    /sessions/:id
PUT    /sessions/:id          (If-Match: updatedAt ou version)
POST   /sessions/:id/annotations
PATCH  /annotations/:id
DELETE /annotations/:id

Exemple incorrect

// ❌ Tableau global non typé, coords px, pas de version
const comments = [{ x: 400, y: 200, text: "fix this" }]
localStorage.setItem("data", JSON.stringify(comments))

Source

  • Excellence design-tool — 2026-06-09

Liens connexes

  • [[KNOW-PAT-136-ProjectBeta-editor-ux-patterns|KNOW-PAT-136]]
  • [[KNOW-PAT-149|KNOW-PAT-149]]