[{"data":1,"prerenderedAt":415},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Fv1\u002Fintroduction":121,"\u002Fdocs\u002Fv1\u002Fintroduction-surround":412},[4],{"title":5,"path":6,"stem":7,"children":8,"page":44},"Docs","\u002Fdocs","docs",[9],{"title":10,"path":11,"stem":12,"children":13,"page":44},"V1","\u002Fdocs\u002Fv1","docs\u002Fv1",[14,18,22,45,58,80,93,111],{"title":15,"path":16,"stem":17},"Introduction","\u002Fdocs\u002Fv1\u002Fintroduction","docs\u002Fv1\u002F0.introduction",{"title":19,"path":20,"stem":21},"How It Works","\u002Fdocs\u002Fv1\u002Fhow-it-works","docs\u002Fv1\u002F1.how-it-works",{"title":23,"icon":24,"path":25,"stem":26,"children":27,"page":44},"Client","i-lucide-laptop","\u002Fdocs\u002Fv1\u002Fclient","docs\u002Fv1\u002F2.client",[28,32,36,40],{"title":29,"path":30,"stem":31},"Client Setup","\u002Fdocs\u002Fv1\u002Fclient\u002Fsetup","docs\u002Fv1\u002F2.client\u002F1.setup",{"title":33,"path":34,"stem":35},"Syncing","\u002Fdocs\u002Fv1\u002Fclient\u002Fsyncing","docs\u002Fv1\u002F2.client\u002F2.syncing",{"title":37,"path":38,"stem":39},"Events","\u002Fdocs\u002Fv1\u002Fclient\u002Fevents","docs\u002Fv1\u002F2.client\u002F3.events",{"title":41,"path":42,"stem":43},"Configuration","\u002Fdocs\u002Fv1\u002Fclient\u002Fconfiguration","docs\u002Fv1\u002F2.client\u002F4.configuration",false,{"title":46,"icon":47,"path":48,"stem":49,"children":50,"page":44},"Server","i-lucide-server","\u002Fdocs\u002Fv1\u002Fserver","docs\u002Fv1\u002F3.server",[51,55],{"title":52,"path":53,"stem":54},"Server Setup","\u002Fdocs\u002Fv1\u002Fserver\u002Fsetup","docs\u002Fv1\u002F3.server\u002F1.setup",{"title":41,"path":56,"stem":57},"\u002Fdocs\u002Fv1\u002Fserver\u002Fconfiguration","docs\u002Fv1\u002F3.server\u002F2.configuration",{"title":59,"icon":60,"badge":61,"path":62,"stem":63,"children":64,"page":44},"NativePHP","i-lucide-smartphone","Commercial","\u002Fdocs\u002Fv1\u002Fnativephp","docs\u002Fv1\u002F4.nativephp",[65,69,73,76],{"title":66,"path":67,"stem":68},"Overview","\u002Fdocs\u002Fv1\u002Fnativephp\u002Foverview","docs\u002Fv1\u002F4.nativephp\u002F1.overview",{"title":70,"path":71,"stem":72},"Setup","\u002Fdocs\u002Fv1\u002Fnativephp\u002Fsetup","docs\u002Fv1\u002F4.nativephp\u002F2.setup",{"title":41,"path":74,"stem":75},"\u002Fdocs\u002Fv1\u002Fnativephp\u002Fconfiguration","docs\u002Fv1\u002F4.nativephp\u002F3.configuration",{"title":77,"path":78,"stem":79},"Lifecycle & Events","\u002Fdocs\u002Fv1\u002Fnativephp\u002Flifecycle","docs\u002Fv1\u002F4.nativephp\u002F4.lifecycle",{"title":81,"icon":82,"badge":61,"path":83,"stem":84,"children":85,"page":44},"Server Pro","i-lucide-bar-chart-2","\u002Fdocs\u002Fv1\u002Fserver-pro","docs\u002Fv1\u002F5.server-pro",[86,89],{"title":66,"path":87,"stem":88},"\u002Fdocs\u002Fv1\u002Fserver-pro\u002Foverview","docs\u002Fv1\u002F5.server-pro\u002F1.overview",{"title":90,"path":91,"stem":92},"Features","\u002Fdocs\u002Fv1\u002Fserver-pro\u002Ffeatures","docs\u002Fv1\u002F5.server-pro\u002F2.features",{"title":94,"icon":95,"path":96,"stem":97,"children":98,"page":44},"Advanced","i-lucide-settings-2","\u002Fdocs\u002Fv1\u002Fadvanced","docs\u002Fv1\u002F6.advanced",[99,103,107],{"title":100,"path":101,"stem":102},"Service Container","\u002Fdocs\u002Fv1\u002Fadvanced\u002Fservice-container","docs\u002Fv1\u002F6.advanced\u002F0.service-container",{"title":104,"path":105,"stem":106},"Conflict Resolution","\u002Fdocs\u002Fv1\u002Fadvanced\u002Fconflict-resolution","docs\u002Fv1\u002F6.advanced\u002F1.conflict-resolution",{"title":108,"path":109,"stem":110},"Payload Mapping","\u002Fdocs\u002Fv1\u002Fadvanced\u002Fpayload-mapping","docs\u002Fv1\u002F6.advanced\u002F2.payload-mapping",{"title":112,"icon":113,"path":114,"stem":115,"children":116,"page":44},"Examples","i-lucide-book-open","\u002Fdocs\u002Fv1\u002Fexamples","docs\u002Fv1\u002F7.examples",[117],{"title":118,"path":119,"stem":120},"Task Manager","\u002Fdocs\u002Fv1\u002Fexamples\u002Ftask-manager","docs\u002Fv1\u002F7.examples\u002F1.task-manager",{"id":122,"title":15,"body":123,"description":404,"extension":405,"links":406,"meta":407,"navigation":408,"path":16,"seo":409,"stem":17,"__hash__":411},"docs\u002Fdocs\u002Fv1\u002F0.introduction.md",{"type":124,"value":125,"toc":388},"minimark",[126,135,138,143,146,157,160,162,166,171,174,178,181,185,200,204,215,219,225,227,231,324,329,346,348,352,362,364,368],[127,128,129,130,134],"p",{},"Tether is an ",[131,132,133],"strong",{},"offline-first Laravel sync system"," for applications that need local database writes, reliable offline behaviour, and server reconciliation when connectivity returns. It lets you build apps that write locally first and synchronise with a central Laravel server without blocking the user or requiring a persistent connection.",[136,137],"hr",{},[139,140,142],"h2",{"id":141},"how-it-works","How it works",[127,144,145],{},"Tether records every create, update, and delete on the client as an immutable mutation log entry. When the client syncs, it sends those entries to the server (push), then fetches state snapshots changed since its last cursor (pull). The server reconciles conflicts and maintains the authoritative state.",[147,148,154],"pre",{"className":149,"code":151,"language":152,"meta":153},[150],"language-text","[Client local DB]\n      -> records every write\n[Client mutation log]\n      -> push sync (client-initiated)\n[Server sync endpoint]\n      -> applies mutations, stores authoritative state\n[Server model tables]\n      -> state snapshot pull response\n[Client reconciliation]\n","text","",[155,156,151],"code",{"__ignoreMap":153},[127,158,159],{},"There is no server-to-client push, no persistent socket, and no polling. All synchronisation is strictly client-initiated.",[136,161],{},[139,163,165],{"id":164},"core-concepts","Core concepts",[167,168,170],"h3",{"id":169},"offline-first-writes","Offline-first writes",[127,172,173],{},"All writes are persisted locally before any network activity. The client never blocks on network availability.",[167,175,177],{"id":176},"mutation-log","Mutation log",[127,179,180],{},"Every model change (create \u002F update \u002F delete) is captured as an immutable log entry with a unique ID, entity ID, operation type, payload, version number, and timestamp. These entries are the source of truth for push sync.",[167,182,184],{"id":183},"client-generated-identity-ulid","Client-generated identity (ULID)",[127,186,187,188,195,196,199],{},"Every syncable entity gets a client-generated ",[189,190,194],"a",{"href":191,"rel":192},"https:\u002F\u002Fgithub.com\u002Fulid\u002Fspec",[193],"nofollow","ULID"," stored in a ",[155,197,198],{},"tether_id"," column by default. The server never generates or reassigns IDs. This means records can be created offline and will safely sync later without identity remapping.",[167,201,203],{"id":202},"sync-cursor","Sync cursor",[127,205,206,207,210,211,214],{},"The server uses an integer microsecond cursor derived from syncable models' ",[155,208,209],{},"updated_at"," \u002F ",[155,212,213],{},"deleted_at"," values. Clients store the last seen cursor value and send it on each pull to receive only state snapshots changed since their last sync.",[167,216,218],{"id":217},"conflict-resolution","Conflict resolution",[127,220,221,222,224],{},"When two clients modify the same record before syncing, the server detects the conflict. By default, last-write-wins compares the mutation timestamp with the server record's ",[155,223,209],{},". Custom per-model resolvers can be registered for fine-grained control.",[136,226],{},[139,228,230],{"id":229},"packages","Packages",[232,233,234,250],"table",{},[235,236,237],"thead",{},[238,239,240,244,247],"tr",{},[241,242,243],"th",{},"Package",[241,245,246],{},"Install on",[241,248,249],{},"Purpose",[251,252,253,267,283,298,311],"tbody",{},[238,254,255,261,264],{},[256,257,258],"td",{},[155,259,260],{},"tether\u002Fcore",[256,262,263],{},"(transitive dep)",[256,265,266],{},"Shared primitives: contracts, enums, mutation value objects, applicator",[238,268,269,274,280],{},[256,270,271],{},[155,272,273],{},"tether\u002Fserver",[256,275,276,277],{},"Laravel ",[131,278,279],{},"server",[256,281,282],{},"Sync HTTP endpoint, server-side mutation application, pull snapshot generation",[238,284,285,290,295],{},[256,286,287],{},[155,288,289],{},"tether\u002Fclient",[256,291,276,292],{},[131,293,294],{},"client",[256,296,297],{},"Local mutation logging, push\u002Fpull sync engine, Syncable model trait",[238,299,300,305,308],{},[256,301,302],{},[155,303,304],{},"tether\u002Fnativephp-client",[256,306,307],{},"NativePHP app",[256,309,310],{},"Lifecycle and connectivity hooks for offline sync on iOS and Android",[238,312,313,318,321],{},[256,314,315],{},[155,316,317],{},"tether\u002Fpro-server",[256,319,320],{},"Laravel server",[256,322,323],{},"Observability dashboard, conflict management UI, replay tools",[127,325,326,328],{},[155,327,260],{}," is installed automatically as a dependency of the client and server packages. You do not install it directly.",[127,330,331,333,334,336,337,340,341,345],{},[155,332,304],{}," and ",[155,335,317],{}," are ",[131,338,339],{},"commercial packages"," - see ",[189,342,344],{"href":343},"\u002Fadd-ons","Add-ons"," for details.",[136,347],{},[139,349,351],{"id":350},"requirements","Requirements",[353,354,355,359],"ul",{},[356,357,358],"li",{},"PHP 8.3+",[356,360,361],{},"Laravel 12 or 13",[136,363],{},[139,365,367],{"id":366},"what-tether-is-not","What Tether is not",[353,369,370,376,382],{},[356,371,372,375],{},[131,373,374],{},"Not real-time."," Sync happens when the client initiates it. There is no push from the server.",[356,377,378,381],{},[131,379,380],{},"Not a replication system."," Tether reconciles state via mutation logs and state snapshots, not binary replication.",[356,383,384,387],{},[131,385,386],{},"Not opinionated about your UI stack."," The client and server packages are pure PHP - they work with any frontend.",{"title":153,"searchDepth":389,"depth":390,"links":391},1,2,[392,393,401,402,403],{"id":141,"depth":390,"text":142},{"id":164,"depth":390,"text":165,"children":394},[395,397,398,399,400],{"id":169,"depth":396,"text":170},3,{"id":176,"depth":396,"text":177},{"id":183,"depth":396,"text":184},{"id":202,"depth":396,"text":203},{"id":217,"depth":396,"text":218},{"id":229,"depth":390,"text":230},{"id":350,"depth":390,"text":351},{"id":366,"depth":390,"text":367},"Learn how Laravel Tether helps build offline-first apps with local writes, mutation logs, client-driven push\u002Fpull sync, and server reconciliation.","md",null,{},true,{"title":410,"description":404},"Offline-First Laravel Sync - Tether Introduction","3LDWc56NqrzNJhLScPEVpOoAO2WUsSPDu-HSj6wqpWk",[406,413],{"title":19,"path":20,"stem":21,"description":414,"children":-1},"Understand Tether's offline sync architecture for Laravel: mutation-log push, state-snapshot pull, ULID identity, idempotency, and conflict handling.",1780481011826]