joshcirre/duo
Duo brings local-first IndexedDB syncing to Laravel and Livewire apps. Add one trait and your components become offline-capable Alpine.js, with automatic model caching, optimistic updates, schema extraction, and a sync queue that resumes when you're back online.
Duo is local-first Livewire: your component reads from IndexedDB, applies changes optimistically, and keeps working offline โ while your own Livewire methods remain the only thing that writes to your database.
This release is a rewrite of the sync architecture and drops Livewire 3. Upgrade both packages together:
joshcirre/duo ^0.2[@joshcirre](https://github.com/joshcirre)/vite-plugin-duo ^0.2/api/duo/{table} endpoints. Duo writes an optimistic record, then calls your real $wire method; the server reports the Eloquent operations that ran and the client reconciles. Validation, policies, and events work exactly as in plain Livewire.$wire when you're back online, including after a reload.[@duoMeta](https://github.com/duoMeta) in your layout, the service worker caches visited pages and the component boots from IndexedDB with no network.duo scope is added server-side, so there is no client-side DOM rewriting and no "duo is not defined" race.$this->prop โ column mappings, and literal defaults for accurate optimistic rendering.Against the workbench demo in headless Chromium: optimistic create/toggle/delete, validation rollback with Livewire-rendered errors, offline queue + replay, recovery from a killed server, replay of a previous session's queue on load, and a full page load with the server down.
composer require joshcirre/duo:^0.2 and npm install -D [@joshcirre](https://github.com/joshcirre)/vite-plugin-duo@^0.2livewire/livewire ^4.0.data-duo-* markers to the lists you want rendered from IndexedDB (see the README). Components with WithDuo alone still get page caching and offline action replay./api/duo/* or window.duo.getSyncQueue() (still present as an alias for the action queue).<x-duo::debug /> โ Delete Database) if you were running 0.1.x locally.See the CHANGELOG for the full list, and the README for the marker reference and known limitations.
Note: 0.x โ the marker vocabulary and JavaScript API may still change.
Full Changelog: https://github.com/joshcirre/duo/compare/v0.1.6...v0.1.7
Full Changelog: https://github.com/joshcirre/duo/compare/v0.1.5...v0.1.6
Full Changelog: https://github.com/joshcirre/duo/compare/v0.1.4...v0.1.5
Full Changelog: https://github.com/joshcirre/duo/compare/v0.1.3...v0.1.4
Full Changelog: https://github.com/joshcirre/duo/compare/v0.1.2...v0.1.3
Full Changelog: https://github.com/joshcirre/duo/compare/v0.1.1...v0.1.2
First public release of Duo - a local-first IndexedDB syncing package for Laravel and Livewire applications.
This release includes:
joshcirre/duo - Laravel service provider and traits[@joshcirre](https://github.com/joshcirre)/vite-plugin-duo - Vite plugin and client library[@duoMeta](https://github.com/duoMeta) directive includes CSRF token automaticallycomposer require joshcirre/duo
npm install -D [@joshcirre](https://github.com/joshcirre)/vite-plugin-duo
Syncable trait to your models:use JoshCirre\Duo\Syncable;
class Todo extends Model
{
use Syncable;
}
WithDuo trait to your Livewire/Volt components:use JoshCirre\Duo\WithDuo;
new class extends Component {
use WithDuo;
// ...
}
[@duoMeta](https://github.com/duoMeta) to your layout:<head>
[@vite](https://github.com/vite)(['resources/css/app.css', 'resources/js/app.js'])
[@duoMeta](https://github.com/duoMeta)
</head>
import duo from '[@joshcirre](https://github.com/joshcirre)/vite-plugin-duo';
export default defineConfig({
plugins: [duo()],
});
That's it! Your app now has local-first syncing with offline support.
Built with:
MIT License - see LICENSE for details.
Note: This is a 0.x release, meaning the API may change before 1.0. Please report any issues on GitHub.
How can I help you explore Laravel packages today?