Local-first synchronization

로컬 우선 동기화

Edit on each device first and exchange changes when connectivity returns.

···
html
<div class="scene"><div class="title">EDIT OFFLINE → SYNC</div><div class="devices"><div class="tile">DEVICE A<div id="docA" class="doc">title</div></div><div class="connection" id="connection">OFFLINE</div><div class="tile">DEVICE B<div id="docB" class="doc">title</div></div></div><div id="syncState" class="muted">Both devices can edit locally</div></div>
css
.scene{width:min(94vw,760px);height:min(86vh,320px);padding:clamp(10px,2.5vmin,18px);border:1px solid var(--line);border-radius:14px;background:var(--surface);color:var(--fg);font:500 clamp(11px,1.3vw,16px)/1.25 "Pretendard Variable",Pretendard,-apple-system,sans-serif;display:flex;flex-direction:column;gap:clamp(7px,1.6vmin,12px);overflow:hidden}.scene *{box-sizing:border-box}.title{font-weight:750;color:var(--accent)}.muted{color:var(--muted)}.mono{font-family:ui-monospace,monospace}.row{display:flex;align-items:center;justify-content:center;gap:clamp(5px,1.4vmin,12px);flex:1;min-height:0}.tile{border:1px solid var(--line);border-radius:8px;background:var(--bg);padding:clamp(6px,1.6vmin,12px);text-align:center;min-width:0}.on{border-color:var(--accent)!important;background:color-mix(in srgb,var(--accent) 12%,var(--surface))!important}.pulse{animation:pulse 1.6s infinite alternate}@keyframes pulse{to{border-color:var(--accent);transform:translateY(-3px)}}.devices{display:flex;align-items:center;gap:6px;flex:1}.devices>.tile{flex:1;text-align:left;height:78%}.doc{margin-top:6px;padding:5px;border-left:3px solid var(--accent);color:var(--accent)}.connection{border:1px dashed var(--accent-3);padding:7px 3px;border-radius:6px;color:var(--accent-3);text-align:center;min-width:25%}.connection.on{color:var(--accent)}
js
let phase=0;function tick(){const p=phase%3;document.getElementById('docA').innerHTML=['title','title<br>A: sketch','title<br>A: sketch<br>B: note'][p];document.getElementById('docB').innerHTML=['title','title<br>B: note','title<br>A: sketch<br>B: note'][p];document.getElementById('connection').textContent=p===2?'CONNECTED':'OFFLINE';document.getElementById('connection').classList.toggle('on',p===2);document.getElementById('syncState').textContent=['Local copies begin equal','Each device edits without network','Changes exchanged; copies converge'][p];phase++}tick();setInterval(tick,1150)

A local-first app keeps working data on the device so reading and editing continue offline. When connectivity returns, devices exchange changes.

The demo lets two devices edit different lines offline, then synchronizes both. Concurrent edit policy and local data protection still need design.

When to use

Use it for collaborative or field apps that must remain editable on unreliable networks.

Open as page ↗