---
title: Browser-SDK einbauen
description: Verbinde deine Oberfläche mit lokalem JSON-Speicher, Account-Panel und ausdrücklich aktiviertem Cloud-Sync.
order: 50
updated: 2026-10-18
keywords: sdk, javascript, adapter, mountaccount, createjsonadapter, indexeddb, localstorage, offline, konflikt
videos: []
---
## Mit der generierten Vorlage beginnen

Lade im [Entwicklerportal](https://account.julianverse.de/developer/apps) die Vorlage deiner registrierten App herunter. Sie enthält die öffentliche Konfiguration, die Module, den Account-Bereich und den passenden Callback. Die Module müssen lokal zusammen mit deiner App ausgeliefert werden.

Die Konfiguration enthält unter anderem `issuer`, `app`, `clientId`, `redirectUri`, `scope` und die aktiven `resources`. Nach einer Änderung der Registrierung aktualisierst du auch diese Konfiguration.

## Ein vollständiges kleines Beispiel

Lege in deiner App-Oberfläche die Elemente an und binde das Panel-Stylesheet ein:

```html
<link rel="stylesheet" href="./account/panel.css">
<label for="notes">Meine Notiz</label>
<textarea id="notes"></textarea>
<p id="save-status" role="status"></p>
<div id="account"></div>
<script type="module" src="./app.mjs"></script>
```

In `app.mjs` ersetzt du den Beispiel-Editor durch Folgendes. Die Datenart `notes` muss vorher registriert und in der Konfiguration enthalten sein:

```js
import { createJSONAdapter, mountAccount } from './account/sdk.mjs';
import { config } from './account/config.mjs';

const adapter = createJSONAdapter(config);
const notes = document.querySelector('#notes');
const status = document.querySelector('#save-status');

function render() {
  notes.value = adapter.get('notes')?.text ?? '';
}

notes.addEventListener('input', () => {
  try {
    adapter.set('notes', { text: notes.value });
    status.textContent = 'Auf diesem Gerät gespeichert.';
  } catch {
    status.textContent = 'Lokales Speichern fehlgeschlagen. Text bitte sichern.';
  }
});

try {
  render();
  await mountAccount({
    root: document.querySelector('#account'),
    config,
    adapter,
    onApply: resource => {
      if (resource === 'notes') render();
    },
  });
} catch {
  status.textContent = 'Gespeicherte Daten oder Account-Bereich konnten nicht geladen werden.';
}
```

`set()` speichert lokal und meldet eine Änderung an einen eventuell aktiven Sync. Es erzwingt keinen ersten Upload. `onApply` aktualisiert nach einem Cloud-Import die eigene Oberfläche. Das Beispiel zeigt lokalen Speicherstatus; den Cloud-Status zeigt das Account-Panel.

## Ein eigenes Datenformat anbinden

Statt `createJSONAdapter` kannst du einen eigenen Adapter an `mountAccount` übergeben:

| Bestandteil | Aufgabe |
| --- | --- |
| `resources` | Liste registrierter Ressourcenschlüssel |
| `keys` | Zuordnung zu beobachteten localStorage-Schlüsseln |
| `labels` | Sichtbare Namen unter `de` und `en` |
| `snapshot(resource)` | Aktuellen lokalen Inhalt als JSON-Objekt liefern |
| `validate(resource, document)` | Cloud-Dokument vor einer Übernahme prüfen |
| `backup(resource)` und `backupKey(resource)` | Vorhandenen lokalen Stand sichern |
| `apply(resource, document)` | Nur die ausgewählte Datenart übernehmen |

Melde lokale Änderungen nach dem Speichern über `window.dispatchEvent(new CustomEvent('julianverse:change', { detail: { key } }))`. `key` ist ein beobachteter Speicherschlüssel. Lege fest, welche Daten Teil eines Snapshots sind, und schließe Zugangsdaten aus.

## Den Sync-Kern direkt verwenden

Das SDK exportiert außerdem `JulianverseSync`, `IndexedDBStore`, `SyncError`, `beginLogin` und `finishLogin`. Der Sync-Kern trennt Konten nach Issuer, Konto-ID und App und hält lokale Arbeitskopien und ausstehende Änderungen in IndexedDB.

`attach()` meldet an, `enable()` verlangt die erste Datenquellenwahl, `save()` speichert lokal, `sync()` gleicht ab und `resolve()` behandelt einen Konflikt. Bei einer eigenen Oberfläche musst du Fehler, ausstehende Änderungen und Konflikte selbst sichtbar machen. Die generierte Vorlage enthält bereits ein passendes Panel.

## Hosting prüfen

Verwende die exakte registrierte App- und Callback-Origin. Das Popup darf nicht durch eine unpassende Opener-Policy getrennt werden. Cookies zur Wiederanmeldung können auf externen Domains blockiert sein; biete dann eine erneute Anmeldung an und erhalte lokale Inhalte.

Teste auch abgewiesenen Browserspeicher, widerrufene Zugänge und zwei gleichzeitig geöffnete Tabs. Vermeide einen pauschalen Reset bei Fehlern. Siehe [OAuth-Callback und Tokens](/docs/entwicklung/oauth/) sowie [API-Konfliktverhalten](/docs/entwicklung/api/).
