@livestore/livestore 0.4.0-dev.22 → 0.4.0-dev.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/QueryCache.js +1 -1
- package/dist/QueryCache.js.map +1 -1
- package/dist/SqliteDbWrapper.d.ts +5 -5
- package/dist/SqliteDbWrapper.d.ts.map +1 -1
- package/dist/SqliteDbWrapper.js +8 -8
- package/dist/SqliteDbWrapper.js.map +1 -1
- package/dist/SqliteDbWrapper.test.js +2 -2
- package/dist/SqliteDbWrapper.test.js.map +1 -1
- package/dist/effect/LiveStore.d.ts +14 -7
- package/dist/effect/LiveStore.d.ts.map +1 -1
- package/dist/effect/LiveStore.js +0 -15
- package/dist/effect/LiveStore.js.map +1 -1
- package/dist/effect/LiveStore.test.d.ts +2 -0
- package/dist/effect/LiveStore.test.d.ts.map +1 -0
- package/dist/effect/LiveStore.test.js +42 -0
- package/dist/effect/LiveStore.test.js.map +1 -0
- package/dist/live-queries/base-class.d.ts +3 -3
- package/dist/live-queries/base-class.d.ts.map +1 -1
- package/dist/live-queries/base-class.js +2 -2
- package/dist/live-queries/base-class.js.map +1 -1
- package/dist/live-queries/client-document-get-query.d.ts +1 -1
- package/dist/live-queries/client-document-get-query.d.ts.map +1 -1
- package/dist/live-queries/client-document-get-query.js +1 -1
- package/dist/live-queries/client-document-get-query.js.map +1 -1
- package/dist/live-queries/computed.d.ts.map +1 -1
- package/dist/live-queries/computed.js +2 -2
- package/dist/live-queries/computed.js.map +1 -1
- package/dist/live-queries/db-query.js +14 -14
- package/dist/live-queries/db-query.js.map +1 -1
- package/dist/live-queries/db-query.test.js +2 -2
- package/dist/live-queries/db-query.test.js.map +1 -1
- package/dist/live-queries/signal.test.js +2 -2
- package/dist/live-queries/signal.test.js.map +1 -1
- package/dist/mod.d.ts +1 -1
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js.map +1 -1
- package/dist/reactive.d.ts +9 -9
- package/dist/reactive.d.ts.map +1 -1
- package/dist/reactive.js +9 -26
- package/dist/reactive.js.map +1 -1
- package/dist/reactive.test.js +2 -2
- package/dist/reactive.test.js.map +1 -1
- package/dist/store/StoreRegistry.d.ts +30 -5
- package/dist/store/StoreRegistry.d.ts.map +1 -1
- package/dist/store/StoreRegistry.js +54 -31
- package/dist/store/StoreRegistry.js.map +1 -1
- package/dist/store/StoreRegistry.test.js +251 -250
- package/dist/store/StoreRegistry.test.js.map +1 -1
- package/dist/store/create-store.d.ts +6 -2
- package/dist/store/create-store.d.ts.map +1 -1
- package/dist/store/create-store.js +13 -7
- package/dist/store/create-store.js.map +1 -1
- package/dist/store/devtools.d.ts +1 -1
- package/dist/store/devtools.d.ts.map +1 -1
- package/dist/store/devtools.js +3 -3
- package/dist/store/devtools.js.map +1 -1
- package/dist/store/store-eventstream.test.js +2 -2
- package/dist/store/store-eventstream.test.js.map +1 -1
- package/dist/store/store-types.d.ts +70 -5
- package/dist/store/store-types.d.ts.map +1 -1
- package/dist/store/store-types.js.map +1 -1
- package/dist/store/store-types.test.js +1 -1
- package/dist/store/store-types.test.js.map +1 -1
- package/dist/store/store.d.ts +81 -2
- package/dist/store/store.d.ts.map +1 -1
- package/dist/store/store.js +128 -45
- package/dist/store/store.js.map +1 -1
- package/dist/utils/dev.js.map +1 -1
- package/dist/utils/stack-info.js +2 -2
- package/dist/utils/stack-info.js.map +1 -1
- package/dist/utils/tests/fixture.d.ts +1 -1
- package/dist/utils/tests/fixture.d.ts.map +1 -1
- package/dist/utils/tests/fixture.js.map +1 -1
- package/dist/utils/tests/otel.d.ts.map +1 -1
- package/dist/utils/tests/otel.js +5 -5
- package/dist/utils/tests/otel.js.map +1 -1
- package/package.json +58 -17
- package/src/QueryCache.ts +1 -1
- package/src/SqliteDbWrapper.test.ts +4 -2
- package/src/SqliteDbWrapper.ts +12 -11
- package/src/ambient.d.ts +0 -7
- package/src/effect/LiveStore.test.ts +61 -0
- package/src/effect/LiveStore.ts +17 -26
- package/src/live-queries/__snapshots__/db-query.test.ts.snap +336 -231
- package/src/live-queries/base-class.ts +7 -6
- package/src/live-queries/client-document-get-query.ts +4 -2
- package/src/live-queries/computed.ts +3 -2
- package/src/live-queries/db-query.test.ts +3 -2
- package/src/live-queries/db-query.ts +15 -15
- package/src/live-queries/signal.test.ts +3 -2
- package/src/mod.ts +1 -0
- package/src/reactive.test.ts +3 -2
- package/src/reactive.ts +22 -23
- package/src/store/StoreRegistry.test.ts +317 -293
- package/src/store/StoreRegistry.ts +63 -38
- package/src/store/create-store.ts +26 -11
- package/src/store/devtools.ts +5 -6
- package/src/store/store-eventstream.test.ts +4 -2
- package/src/store/store-types.test.ts +3 -1
- package/src/store/store-types.ts +47 -8
- package/src/store/store.ts +172 -55
- package/src/utils/dev.ts +2 -2
- package/src/utils/stack-info.ts +2 -2
- package/src/utils/tests/fixture.ts +2 -1
- package/src/utils/tests/otel.ts +8 -7
- package/docs/api/index.md +0 -3
- package/docs/building-with-livestore/complex-ui-state/index.md +0 -3
- package/docs/building-with-livestore/crud/index.md +0 -3
- package/docs/building-with-livestore/data-modeling/index.md +0 -30
- package/docs/building-with-livestore/debugging/index.md +0 -17
- package/docs/building-with-livestore/devtools/index.md +0 -79
- package/docs/building-with-livestore/events/index.md +0 -355
- package/docs/building-with-livestore/examples/ai-agent/index.md +0 -5
- package/docs/building-with-livestore/examples/todo-workspaces/index.md +0 -885
- package/docs/building-with-livestore/examples/turnbased-game/index.md +0 -7
- package/docs/building-with-livestore/opentelemetry/index.md +0 -227
- package/docs/building-with-livestore/production-checklist/index.md +0 -5
- package/docs/building-with-livestore/reactivity-system/index.md +0 -202
- package/docs/building-with-livestore/rules-for-ai-agents/index.md +0 -9
- package/docs/building-with-livestore/state/materializers/index.md +0 -300
- package/docs/building-with-livestore/state/sql-queries/index.md +0 -94
- package/docs/building-with-livestore/state/sqlite/index.md +0 -45
- package/docs/building-with-livestore/state/sqlite-schema/index.md +0 -306
- package/docs/building-with-livestore/state/sqlite-schema-effect/index.md +0 -300
- package/docs/building-with-livestore/store/index.md +0 -625
- package/docs/building-with-livestore/syncing/index.md +0 -136
- package/docs/building-with-livestore/tools/cli/index.md +0 -177
- package/docs/building-with-livestore/tools/mcp/index.md +0 -187
- package/docs/examples/cloudflare-adapter/index.md +0 -44
- package/docs/examples/expo-adapter/index.md +0 -44
- package/docs/examples/index.md +0 -55
- package/docs/examples/node-adapter/index.md +0 -44
- package/docs/examples/web-adapter/index.md +0 -52
- package/docs/framework-integrations/custom-elements/index.md +0 -142
- package/docs/framework-integrations/react-integration/index.md +0 -937
- package/docs/framework-integrations/solid-integration/index.md +0 -293
- package/docs/framework-integrations/svelte-integration/index.md +0 -42
- package/docs/framework-integrations/vue-integration/index.md +0 -294
- package/docs/getting-started/expo/index.md +0 -882
- package/docs/getting-started/node/index.md +0 -115
- package/docs/getting-started/react-web/index.md +0 -626
- package/docs/getting-started/solid/index.md +0 -3
- package/docs/getting-started/vue/index.md +0 -471
- package/docs/index.md +0 -208
- package/docs/llms.txt +0 -146
- package/docs/misc/CODE_OF_CONDUCT/index.md +0 -133
- package/docs/misc/FAQ/index.md +0 -37
- package/docs/misc/community/index.md +0 -88
- package/docs/misc/credits/index.md +0 -14
- package/docs/misc/design-partners/index.md +0 -13
- package/docs/misc/package-management/index.md +0 -21
- package/docs/misc/performance/index.md +0 -25
- package/docs/misc/resources/index.md +0 -46
- package/docs/misc/state-of-the-project/index.md +0 -37
- package/docs/misc/troubleshooting/index.md +0 -82
- package/docs/overview/concepts/index.md +0 -78
- package/docs/overview/how-livestore-works/index.md +0 -56
- package/docs/overview/introduction/index.md +0 -413
- package/docs/overview/technology-comparison/index.md +0 -40
- package/docs/overview/when-livestore/index.md +0 -81
- package/docs/overview/why-livestore/index.md +0 -111
- package/docs/patterns/ai/index.md +0 -15
- package/docs/patterns/anonymous-user-transition/index.md +0 -10
- package/docs/patterns/app-evolution/index.md +0 -72
- package/docs/patterns/auth/index.md +0 -377
- package/docs/patterns/effect/index.md +0 -1505
- package/docs/patterns/encryption/index.md +0 -6
- package/docs/patterns/external-data/index.md +0 -5
- package/docs/patterns/file-management/index.md +0 -11
- package/docs/patterns/file-structure/index.md +0 -14
- package/docs/patterns/list-ordering/index.md +0 -369
- package/docs/patterns/offline/index.md +0 -32
- package/docs/patterns/orm/index.md +0 -18
- package/docs/patterns/presence/index.md +0 -11
- package/docs/patterns/rich-text-editing/index.md +0 -11
- package/docs/patterns/server-side-clients/index.md +0 -97
- package/docs/patterns/side-effects/index.md +0 -11
- package/docs/patterns/state-machines/index.md +0 -11
- package/docs/patterns/storybook/index.md +0 -209
- package/docs/patterns/undo-redo/index.md +0 -9
- package/docs/patterns/version-control/index.md +0 -8
- package/docs/platform-adapters/cloudflare-durable-object-adapter/index.md +0 -453
- package/docs/platform-adapters/electron-adapter/index.md +0 -15
- package/docs/platform-adapters/expo-adapter/index.md +0 -262
- package/docs/platform-adapters/node-adapter/index.md +0 -160
- package/docs/platform-adapters/tauri-adapter/index.md +0 -15
- package/docs/platform-adapters/web-adapter/index.md +0 -287
- package/docs/sustainable-open-source/contributing/docs/index.md +0 -94
- package/docs/sustainable-open-source/contributing/info/index.md +0 -63
- package/docs/sustainable-open-source/contributing/monorepo/index.md +0 -195
- package/docs/sustainable-open-source/sponsoring/index.md +0 -104
- package/docs/sync-providers/cloudflare/index.md +0 -773
- package/docs/sync-providers/custom/index.md +0 -65
- package/docs/sync-providers/electricsql/index.md +0 -159
- package/docs/sync-providers/s2/index.md +0 -230
- package/docs/tutorial/0-welcome/index.md +0 -48
- package/docs/tutorial/1-setup-starter-project/index.md +0 -105
- package/docs/tutorial/2-deploy-to-cloudflare/index.md +0 -195
- package/docs/tutorial/3-read-and-write-todos-via-livestore/index.md +0 -530
- package/docs/tutorial/4-sync-data-via-cloudflare/index.md +0 -210
- package/docs/tutorial/5-expand-business-logic/index.md +0 -174
- package/docs/tutorial/6-persist-ui-state/index.md +0 -453
- package/docs/tutorial/7-next-steps/index.md +0 -22
- package/docs/understanding-livestore/design-decisions/index.md +0 -33
- package/docs/understanding-livestore/event-sourcing/index.md +0 -40
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
# Syncing
|
|
2
|
-
|
|
3
|
-
## How it works
|
|
4
|
-
|
|
5
|
-
LiveStore is based on [the idea of event-sourcing](/understanding-livestore/event-sourcing) which means it syncs events across clients (via a central sync backend) and then materializes the events in the local SQLite database. This means LiveStore isn't syncing the SQLite database itself directly but only the events that are used to materialize the database making sure it's kept in sync across clients.
|
|
6
|
-
|
|
7
|
-
The syncing mechanism is similar to how Git works in that regard that it's based on a "push/pull" model. Upstream events always need to be pulled before a client can push its own events to preserve a [global total order of events](https://medium.com/baseds/ordering-distributed-events-29c1dd9d1eff). Local pending events which haven't been pushed yet need to be rebased on top of the latest upstream events before they can be pushed.
|
|
8
|
-
|
|
9
|
-
<SyncingDiagram />
|
|
10
|
-
|
|
11
|
-
## Events
|
|
12
|
-
|
|
13
|
-
A LiveStore event consists of the following data:
|
|
14
|
-
- `seqNum`: event sequence number
|
|
15
|
-
- `parentSeqNum`: parent event sequence number
|
|
16
|
-
- `name`: event name (refers to a event definition in the schema)
|
|
17
|
-
- `args`: event arguments (encoded using the event's schema definition, usually JSON)
|
|
18
|
-
|
|
19
|
-
### Event sequence numbers
|
|
20
|
-
|
|
21
|
-
- Event sequence numbers: monotonically increasing integers
|
|
22
|
-
- client event sequence number to sync across client sessions (never exposed to the sync backend)
|
|
23
|
-
|
|
24
|
-
### Sync heads
|
|
25
|
-
|
|
26
|
-
- The latest event in a eventlog is referred to as the "head" (similar to how Git refers to the latest commit as the "head").
|
|
27
|
-
- Given that LiveStore does hierarchical syncing between the client session, the client leader and the sync backend, there are three heads (i.e. the client session head, the client leader head, and the sync backend head).
|
|
28
|
-
|
|
29
|
-
## Sync backend
|
|
30
|
-
|
|
31
|
-
The sync backend acts as the global authority and determines the total order of events ("causality"). It's responsible for storing and querying events and for notifying clients when new events are available.
|
|
32
|
-
|
|
33
|
-
### Requirements for sync backend
|
|
34
|
-
|
|
35
|
-
- Needs to provide an efficient way to query an ordered list of events given a starting event ID (often referred to as cursor).
|
|
36
|
-
- Ideally provides a "reactivity" mechanism to notify clients when new events are available (e.g. via WebSocket, HTTP long-polling, etc).
|
|
37
|
-
- Alternatively, the client can periodically query for new events which is less efficient.
|
|
38
|
-
|
|
39
|
-
## Clients
|
|
40
|
-
|
|
41
|
-
- Each client initially chooses a random `clientId` as its globally unique ID
|
|
42
|
-
- LiveStore uses a 6-char nanoid
|
|
43
|
-
- In the unlikely event of a collision which is detected by the sync backend the first time a client tries to push, the client chooses a new random `clientId`, patches the local events with the new `clientId`, and tries again.
|
|
44
|
-
|
|
45
|
-
### Client sessions
|
|
46
|
-
|
|
47
|
-
- Each client has at least one client session
|
|
48
|
-
- Client sessions within the same client share local data
|
|
49
|
-
- In web adapters: multiple tabs/windows can be different sessions within the same client
|
|
50
|
-
- Sessions are identified by a `sessionId` which can persist (e.g., across tab reloads in web)
|
|
51
|
-
- For adapters which support multiple client sessions (e.g. web), LiveStore also supports local syncing across client sessions (e.g. across browser tabs or worker threads)
|
|
52
|
-
- Client session events are not synced to the sync backend
|
|
53
|
-
|
|
54
|
-
## Auth (authentication & authorization)
|
|
55
|
-
|
|
56
|
-
- TODO
|
|
57
|
-
- Provide basic example
|
|
58
|
-
- Encryption
|
|
59
|
-
|
|
60
|
-
## Advanced
|
|
61
|
-
|
|
62
|
-
### Sequence diagrams
|
|
63
|
-
|
|
64
|
-
#### Pulling events (without unpushed events)
|
|
65
|
-
|
|
66
|
-
```d2
|
|
67
|
-
...@../../../../src/content/base.d2
|
|
68
|
-
|
|
69
|
-
shape: sequence_diagram
|
|
70
|
-
|
|
71
|
-
Client: {
|
|
72
|
-
label: "Client"
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
SyncBackend: {
|
|
76
|
-
label: "Sync Backend"
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
Client -> SyncBackend: "`pull` request\n(head_cursor)"
|
|
80
|
-
SyncBackend -> SyncBackend: "Get new events\n(since head_cursor)"
|
|
81
|
-
SyncBackend -> Client: "New events"
|
|
82
|
-
Client -> Client: "Client is in sync"
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
#### Pushing events
|
|
86
|
-
|
|
87
|
-
```d2
|
|
88
|
-
...@../../../../src/content/base.d2
|
|
89
|
-
|
|
90
|
-
shape: sequence_diagram
|
|
91
|
-
|
|
92
|
-
Client: {
|
|
93
|
-
label: "Client"
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
SyncBackend: {
|
|
97
|
-
label: "Sync Backend"
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
Client -> Client: "Commit events"
|
|
101
|
-
Client -> SyncBackend: "`push` request\n(new_local_events)"
|
|
102
|
-
SyncBackend -> SyncBackend: "Validate & persist"
|
|
103
|
-
SyncBackend -> Client: "Push success"
|
|
104
|
-
Client -> Client: "Client is in sync"
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Rebasing
|
|
108
|
-
|
|
109
|
-
### Merge conflicts
|
|
110
|
-
|
|
111
|
-
- Merge conflict handling isn't implemented yet (see [this issue](https://github.com/livestorejs/livestore/issues/253)).
|
|
112
|
-
- Merge conflict detection and resolution will be based on the upcoming [facts system functionality](https://github.com/livestorejs/livestore/issues/254).
|
|
113
|
-
|
|
114
|
-
### Compaction
|
|
115
|
-
|
|
116
|
-
- Compaction isn't implemented yet (see [this issue](https://github.com/livestorejs/livestore/issues/136))
|
|
117
|
-
- Compaction will be based on the upcoming [facts system functionality](https://github.com/livestorejs/livestore/issues/254).
|
|
118
|
-
|
|
119
|
-
### Partitioning
|
|
120
|
-
|
|
121
|
-
- Currently LiveStore assumes a 1:1 mapping between an eventlog and a SQLite database.
|
|
122
|
-
- In the future, LiveStore aims to support multiple eventlogs (see [this issue](https://github.com/livestorejs/livestore/issues/255)).
|
|
123
|
-
|
|
124
|
-
## Design decisions / trade-offs
|
|
125
|
-
|
|
126
|
-
- Require a central sync backend to enforce a global total order of events.
|
|
127
|
-
- This means LiveStore can't be used in a fully decentralized/P2P manner.
|
|
128
|
-
- Do rebasing on the client side (instead of on the sync backend). This allows the user to have more control over the rebase process.
|
|
129
|
-
|
|
130
|
-
## Notes
|
|
131
|
-
|
|
132
|
-
- Rich text data is best handled via CRDTs (see [#263](https://github.com/livestorejs/livestore/issues/263))
|
|
133
|
-
|
|
134
|
-
## Further reading
|
|
135
|
-
|
|
136
|
-
- Distributed Systems lecture series by Martin Kleppmann: [YouTube playlist](https://www.youtube.com/playlist?list=PLeKd45zvjcDFUEv_ohr_HdUFe97RItdiB) / [lecture notes](https://www.cl.cam.ac.uk/teaching/2122/ConcDisSys/dist-sys-notes.pdf)
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
# LiveStore CLI
|
|
2
|
-
|
|
3
|
-
The LiveStore CLI provides tools for creating new projects and integrating with AI assistants through MCP (Model Context Protocol).
|
|
4
|
-
|
|
5
|
-
:::caution[Experimental - Not Production Ready]
|
|
6
|
-
The LiveStore CLI is an experimental preview and not ready for production use. APIs, commands, and functionality may change significantly. Use for development and evaluation purposes only.
|
|
7
|
-
:::
|
|
8
|
-
|
|
9
|
-
## Installation
|
|
10
|
-
|
|
11
|
-
You can use the LiveStore CLI in several ways:
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
# Recommended: Use bunx (no installation needed)
|
|
15
|
-
bunx @livestore/cli --help
|
|
16
|
-
|
|
17
|
-
# Alternative options:
|
|
18
|
-
npm install -g @livestore/cli # Global install
|
|
19
|
-
npm install -D @livestore/cli # Project install
|
|
20
|
-
npx @livestore/cli --help # Use with npx
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Commands
|
|
24
|
-
|
|
25
|
-
### `livestore new-project`
|
|
26
|
-
Create a new LiveStore project from available examples.
|
|
27
|
-
|
|
28
|
-
```bash
|
|
29
|
-
# Interactive selection
|
|
30
|
-
livestore new-project
|
|
31
|
-
|
|
32
|
-
# Specify example and path
|
|
33
|
-
livestore new-project --example web-todomvc my-project
|
|
34
|
-
|
|
35
|
-
# Use specific branch
|
|
36
|
-
livestore new-project --branch dev
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
### `livestore mcp`
|
|
40
|
-
MCP server tools for AI assistant integration. See [MCP Integration](/building-with-livestore/tools/mcp) for details.
|
|
41
|
-
|
|
42
|
-
```bash
|
|
43
|
-
# Start MCP server
|
|
44
|
-
livestore mcp
|
|
45
|
-
|
|
46
|
-
# Available subcommands
|
|
47
|
-
livestore mcp coach # AI coaching assistant (requires API key env var)
|
|
48
|
-
livestore mcp tools # Development tools server
|
|
49
|
-
|
|
50
|
-
# Coach command requires API key - check implementation for specific variable name
|
|
51
|
-
# Example: OPENAI_API_KEY=your_key livestore mcp coach
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### `livestore sync`
|
|
55
|
-
|
|
56
|
-
Import and export events from the sync backend. Useful for backup, migration, and debugging.
|
|
57
|
-
|
|
58
|
-
#### Export
|
|
59
|
-
|
|
60
|
-
Export all events from the sync backend to a JSON file:
|
|
61
|
-
|
|
62
|
-
```bash
|
|
63
|
-
livestore sync export \
|
|
64
|
-
--config livestore-cli.config.ts \
|
|
65
|
-
--store-id my-store \
|
|
66
|
-
events.json
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
**Example output:**
|
|
70
|
-
|
|
71
|
-
```
|
|
72
|
-
Exporting events from LiveStore...
|
|
73
|
-
Config: livestore-cli.config.ts
|
|
74
|
-
Store ID: my-store
|
|
75
|
-
Output: events.json
|
|
76
|
-
|
|
77
|
-
Connecting to sync backend...
|
|
78
|
-
✓ Connected to sync backend: @livestore/cf-sync
|
|
79
|
-
Pulling events from sync backend...
|
|
80
|
-
Pulled 127 events
|
|
81
|
-
Exported 127 events to /path/to/events.json
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
**Options:**
|
|
85
|
-
- `--config, -c` (required) - Path to a config module that exports `schema` and `syncBackend`
|
|
86
|
-
- `--store-id, -i` (required) - Store identifier
|
|
87
|
-
- `--client-id` - Client identifier for the sync connection (default: `cli-export`)
|
|
88
|
-
- Large exports load data in memory; for very large stores run this on a machine with sufficient RAM.
|
|
89
|
-
|
|
90
|
-
#### Import
|
|
91
|
-
|
|
92
|
-
Import events from a JSON file to the sync backend:
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
livestore sync import \
|
|
96
|
-
--config livestore-cli.config.ts \
|
|
97
|
-
--store-id my-store \
|
|
98
|
-
events.json
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
**Example output:**
|
|
102
|
-
|
|
103
|
-
```
|
|
104
|
-
Importing events to LiveStore...
|
|
105
|
-
Config: livestore-cli.config.ts
|
|
106
|
-
Store ID: my-store
|
|
107
|
-
Input: events.json
|
|
108
|
-
|
|
109
|
-
Reading import file...
|
|
110
|
-
Found 127 events in export file
|
|
111
|
-
Checking for existing events...
|
|
112
|
-
Connecting to sync backend...
|
|
113
|
-
✓ Connected to sync backend: @livestore/cf-sync
|
|
114
|
-
Pushing events to sync backend...
|
|
115
|
-
Pushed 100/127 events
|
|
116
|
-
Pushed 127/127 events
|
|
117
|
-
Successfully imported 127 events
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
**Options:**
|
|
121
|
-
- `--config, -c` (required) - Path to a config module that exports `schema` and `syncBackend`
|
|
122
|
-
- `--store-id, -i` (required) - Store identifier
|
|
123
|
-
- `--client-id` - Client identifier for the sync connection (default: `cli-import`)
|
|
124
|
-
- `--force, -f` - Force import even if store ID in the file doesn't match
|
|
125
|
-
- `--dry-run` - Validate the import file without actually importing
|
|
126
|
-
- Large imports are memory-intensive because the JSON is loaded fully before validation/push.
|
|
127
|
-
|
|
128
|
-
**Note:** The sync backend must be empty when importing. The import will fail if events already exist.
|
|
129
|
-
|
|
130
|
-
### Config file
|
|
131
|
-
|
|
132
|
-
Both MCP and sync commands require a config file (conventionally named `livestore-cli.config.ts`) that exports:
|
|
133
|
-
|
|
134
|
-
## `reference/cli/config.ts`
|
|
135
|
-
|
|
136
|
-
```ts filename="reference/cli/config.ts"
|
|
137
|
-
|
|
138
|
-
// Re-export your app's schema (adjust path to your project)
|
|
139
|
-
export { schema } from './schema.ts'
|
|
140
|
-
|
|
141
|
-
// Provide a sync backend constructor
|
|
142
|
-
export const syncBackend = makeWsSync({
|
|
143
|
-
url: process.env.LIVESTORE_SYNC_URL ?? 'ws://localhost:8787',
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
// Optionally, pass an auth payload (must be JSON-serializable)
|
|
147
|
-
export const syncPayload = {
|
|
148
|
-
authToken: process.env.LIVESTORE_SYNC_AUTH_TOKEN,
|
|
149
|
-
}
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
### `reference/cli/schema.ts`
|
|
153
|
-
|
|
154
|
-
```ts filename="reference/cli/schema.ts"
|
|
155
|
-
|
|
156
|
-
const events = {}
|
|
157
|
-
|
|
158
|
-
const tables = {
|
|
159
|
-
todos: State.SQLite.table({
|
|
160
|
-
name: 'todos',
|
|
161
|
-
columns: {
|
|
162
|
-
id: State.SQLite.text({ primaryKey: true }),
|
|
163
|
-
text: State.SQLite.text(),
|
|
164
|
-
completed: State.SQLite.boolean({ default: false }),
|
|
165
|
-
},
|
|
166
|
-
}),
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const state = State.SQLite.makeState({ tables, materializers: {} })
|
|
170
|
-
|
|
171
|
-
export const schema = makeSchema({ events, state })
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
## Global options
|
|
175
|
-
|
|
176
|
-
- `--verbose` - Enable verbose logging
|
|
177
|
-
- `--help` - Show command help
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
# MCP integration
|
|
2
|
-
|
|
3
|
-
LiveStore includes MCP (Model Context Protocol) integration that allows AI assistants like Claude to access LiveStore documentation, examples, and development tools.
|
|
4
|
-
|
|
5
|
-
:::caution[Experimental]
|
|
6
|
-
The MCP integration is experimental and under active development. Features may change.
|
|
7
|
-
:::
|
|
8
|
-
|
|
9
|
-
For installation and general CLI usage, see the [LiveStore CLI](/building-with-livestore/tools/cli) documentation.
|
|
10
|
-
|
|
11
|
-
## What is MCP?
|
|
12
|
-
|
|
13
|
-
MCP (Model Context Protocol) is a standard for providing AI assistants with access to external resources and tools. LiveStore's MCP server gives AI assistants access to:
|
|
14
|
-
|
|
15
|
-
- LiveStore documentation and guides
|
|
16
|
-
- Schema examples for common app types
|
|
17
|
-
- Development tools and utilities
|
|
18
|
-
|
|
19
|
-
## Usage
|
|
20
|
-
|
|
21
|
-
Start the MCP server:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
bunx @livestore/cli mcp
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Available commands
|
|
28
|
-
|
|
29
|
-
### `bunx @livestore/cli mcp coach`
|
|
30
|
-
Starts an AI coaching assistant with access to LiveStore documentation and best practices.
|
|
31
|
-
|
|
32
|
-
### `bunx @livestore/cli mcp tools`
|
|
33
|
-
Provides development tools and utilities for working with LiveStore projects.
|
|
34
|
-
|
|
35
|
-
### LiveStore Runtime Tools
|
|
36
|
-
|
|
37
|
-
- `livestore_instance_connect`
|
|
38
|
-
- Connects a single in-process LiveStore instance by dynamically importing a module that exports `schema` and a `syncBackend` factory (and optionally `syncPayload`).
|
|
39
|
-
- Notes:
|
|
40
|
-
- Only one instance can be active at a time; connecting again shuts down and replaces the previous instance.
|
|
41
|
-
- Reconnecting creates a fresh, in-memory client database. The visible state is populated by your backend's initial sync. Until sync completes, queries may return empty or partial results.
|
|
42
|
-
- Module contract (generic example):
|
|
43
|
-
|
|
44
|
-
## `reference/mcp/module-contract.ts`
|
|
45
|
-
|
|
46
|
-
```ts filename="reference/mcp/module-contract.ts"
|
|
47
|
-
|
|
48
|
-
export { schema } from './schema.ts'
|
|
49
|
-
|
|
50
|
-
export const syncBackend = makeWsSync({ url: process.env.LIVESTORE_SYNC_URL ?? 'ws://localhost:8787' })
|
|
51
|
-
|
|
52
|
-
export const syncPayload = { authToken: process.env.LIVESTORE_SYNC_AUTH_TOKEN ?? 'insecure-token-change-me' }
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### `reference/mcp/schema.ts`
|
|
56
|
-
|
|
57
|
-
```ts filename="reference/mcp/schema.ts"
|
|
58
|
-
|
|
59
|
-
const events = {
|
|
60
|
-
entityCreated: Events.synced({
|
|
61
|
-
name: 'v1.EntityCreated',
|
|
62
|
-
schema: Schema.Struct({
|
|
63
|
-
id: Schema.String,
|
|
64
|
-
title: Schema.String,
|
|
65
|
-
createdAt: Schema.DateFromString,
|
|
66
|
-
}),
|
|
67
|
-
}),
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const tables = {
|
|
71
|
-
entities: State.SQLite.table({
|
|
72
|
-
name: 'entities',
|
|
73
|
-
columns: {
|
|
74
|
-
id: State.SQLite.text({ primaryKey: true }),
|
|
75
|
-
title: State.SQLite.text({ default: '' }),
|
|
76
|
-
createdAt: State.SQLite.text({ default: '' }),
|
|
77
|
-
},
|
|
78
|
-
}),
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const materializers = State.SQLite.materializers(events, {
|
|
82
|
-
'v1.EntityCreated': ({ id, title, createdAt }) =>
|
|
83
|
-
tables.entities.insert({ id, title, createdAt: createdAt.toISOString() }),
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
const state = State.SQLite.makeState({ tables, materializers })
|
|
87
|
-
|
|
88
|
-
export const schema = makeSchema({ events, state })
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
- Params example: `{ "configPath": "livestore-cli.config.ts", "storeId": "<store-id>" }`
|
|
92
|
-
- Returns example:
|
|
93
|
-
`{ "storeId": "<store-id>", "clientId": "client-123", "sessionId": "session-abc", "schemaInfo": { "tableNames": ["..."], "eventNames": ["..."] } }`
|
|
94
|
-
|
|
95
|
-
- `livestore_instance_query`
|
|
96
|
-
- Executes raw SQL against the client database (read-only).
|
|
97
|
-
- Notes:
|
|
98
|
-
- SQLite dialect; use valid SQLite syntax.
|
|
99
|
-
- `bindValues` must be an array (positional `?`) or a record (named `$key`). Do not pass stringified JSON.
|
|
100
|
-
- Params example (positional): `{ "sql": "SELECT * FROM my_table WHERE userId = ?", "bindValues": ["u1"] }`
|
|
101
|
-
- Params example (named): `{ "sql": "SELECT * FROM my_table WHERE userId = $userId", "bindValues": { "userId": "u1" } }`
|
|
102
|
-
- Returns example: `{ "rows": [{ "col": "value" }], "rowCount": 1 }`
|
|
103
|
-
|
|
104
|
-
- `livestore_instance_commit_events`
|
|
105
|
-
- Commits one or more events defined by your connected schema.
|
|
106
|
-
- Notes:
|
|
107
|
-
- Use the canonical event name declared in your schema (e.g., `v1.EntityCreated`).
|
|
108
|
-
- `args` must be a non-stringified JSON object matching the event schema. Date fields typically accept ISO 8601 strings.
|
|
109
|
-
- Params example: `{ "events": [{ "name": "v1.EntityCreated", "args": { "id": "e1", "title": "Hello", "createdAt": "2024-01-01T00:00:00.000Z" } }] }`
|
|
110
|
-
- Returns example: `{ "committed": 1 }`
|
|
111
|
-
|
|
112
|
-
- `livestore_instance_status`
|
|
113
|
-
- Reports instance/runtime info.
|
|
114
|
-
- Returns example (connected): `{ "_tag": "connected", "storeId": "<store-id>", "clientId": "client-123", "sessionId": "session-abc", "tableCounts": { "my_table": 12 } }`
|
|
115
|
-
- Returns example (not connected): `{ "_tag": "disconnected" }`
|
|
116
|
-
|
|
117
|
-
- `livestore_instance_disconnect`
|
|
118
|
-
- Disconnects the current LiveStore instance and releases resources.
|
|
119
|
-
- Returns: `{ "_tag": "disconnected" }`
|
|
120
|
-
|
|
121
|
-
### Sync export/import tools
|
|
122
|
-
|
|
123
|
-
These tools connect directly to the sync backend (without creating a full LiveStore instance) to export or import events. Useful for backup, migration, and debugging.
|
|
124
|
-
|
|
125
|
-
- `livestore_sync_export`
|
|
126
|
-
- Exports all events from a sync backend to JSON data.
|
|
127
|
-
- Notes:
|
|
128
|
-
- Connects directly to the sync backend and pulls all events.
|
|
129
|
-
- Returns the export data as a JSON object that can be saved or passed to import.
|
|
130
|
-
- Params example: `{ "configPath": "livestore-cli.config.ts", "storeId": "my-store" }`
|
|
131
|
-
- Returns example: `{ "storeId": "my-store", "eventCount": 127, "exportedAt": "2024-01-15T10:30:00.000Z", "data": { "version": 1, "storeId": "my-store", "events": [...] } }`
|
|
132
|
-
|
|
133
|
-
- `livestore_sync_import`
|
|
134
|
-
- Imports events from export data to a sync backend.
|
|
135
|
-
- Notes:
|
|
136
|
-
- The sync backend must be empty before importing.
|
|
137
|
-
- Use `force: true` to import even if the store ID in the data doesn't match.
|
|
138
|
-
- Use `dryRun: true` to validate the import without actually importing.
|
|
139
|
-
- Params example: `{ "configPath": "livestore-cli.config.ts", "storeId": "my-store", "data": { "version": 1, "storeId": "my-store", "events": [...] } }`
|
|
140
|
-
- Params with options: `{ "configPath": "...", "storeId": "...", "data": {...}, "force": true, "dryRun": true }`
|
|
141
|
-
- Returns example: `{ "storeId": "my-store", "eventCount": 127, "dryRun": false }`
|
|
142
|
-
|
|
143
|
-
## Local Cloudflare sync (dev)
|
|
144
|
-
|
|
145
|
-
Run a local Cloudflare sync backend:
|
|
146
|
-
|
|
147
|
-
1. Start the sync worker (wrangler):
|
|
148
|
-
- `cd tests/integration/src/tests/adapter-cloudflare/fixtures`
|
|
149
|
-
- `wrangler dev`
|
|
150
|
-
- You should see an info page at `http://localhost:8787/`.
|
|
151
|
-
|
|
152
|
-
2. Start the MCP server in another terminal:
|
|
153
|
-
- `bunx @livestore/cli mcp server`
|
|
154
|
-
|
|
155
|
-
3. From your MCP client (e.g., Claude Desktop), call tools:
|
|
156
|
-
- Use your own config file path and storeId. The repo also provides an example: `examples/cf-chat/livestore-cli.config.ts`.
|
|
157
|
-
- Connect: `livestore_instance_connect` with `{ "configPath": "livestore-cli.config.ts", "storeId": "<store-id>" }`
|
|
158
|
-
- Commit: `livestore_instance_commit_events` with `[ { "name": "v1.EntityCreated", "args": { "id": "e1", "title": "Hello", "createdAt": "2024-01-01T00:00:00.000Z" } } ]`
|
|
159
|
-
- Query: `livestore_instance_query` with `{ "sql": "SELECT * FROM my_table ORDER BY createdAt DESC LIMIT 5" }`
|
|
160
|
-
- Status: `livestore_instance_status`
|
|
161
|
-
- Disconnect: `livestore_instance_disconnect`
|
|
162
|
-
|
|
163
|
-
## Adding to Claude
|
|
164
|
-
|
|
165
|
-
To use with Claude Desktop, add the MCP server to your Claude configuration:
|
|
166
|
-
|
|
167
|
-
```json
|
|
168
|
-
{
|
|
169
|
-
"mcpServers": {
|
|
170
|
-
"livestore": {
|
|
171
|
-
"command": "bunx",
|
|
172
|
-
"args": ["@livestore/cli", "mcp"]
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
## Available resources
|
|
179
|
-
|
|
180
|
-
The MCP server provides access to:
|
|
181
|
-
|
|
182
|
-
- **Documentation**: Overview, features, getting started guides
|
|
183
|
-
- **Architecture**: Technical design and principles
|
|
184
|
-
- **Schema Examples**: Pre-built schemas for todo, blog, e-commerce, and social apps
|
|
185
|
-
- **Development Tools**: Project scaffolding and utilities
|
|
186
|
-
|
|
187
|
-
This enables AI assistants to provide context-aware help with LiveStore development.
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# Cloudflare Durable Objects examples
|
|
2
|
-
|
|
3
|
-
# Cloudflare Durable Objects Examples
|
|
4
|
-
|
|
5
|
-
Examples using `@livestore/adapter-cloudflare` for Cloudflare Workers and Durable Objects.
|
|
6
|
-
|
|
7
|
-
<CardGrid>
|
|
8
|
-
{cloudflareExamples.map((example) => {
|
|
9
|
-
const { url, label } = getExampleDemoLinks(example);
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<Card title={example.title} key={example.title}>
|
|
13
|
-
{example.image ? (
|
|
14
|
-
<Image src={example.image.url} width={example.image.width} height={example.image.height} alt={`${example.title} application interface`} />
|
|
15
|
-
) : (
|
|
16
|
-
<div style="background: linear-gradient(135deg, #1f2937 0%, #374151 100%); height: 200px; display: flex; align-items: center; justify-content: center; color: #9ca3af; font-size: 14px; border-radius: 8px;">
|
|
17
|
-
Screenshot coming soon
|
|
18
|
-
</div>
|
|
19
|
-
)}
|
|
20
|
-
<p>{example.description}</p>
|
|
21
|
-
<p><strong>Technologies:</strong> {example.technologies.join(' • ')}</p>
|
|
22
|
-
{example.syncProvider && (
|
|
23
|
-
<p><strong>Sync Provider:</strong> {example.syncProvider}</p>
|
|
24
|
-
)}
|
|
25
|
-
<div style="margin-top: auto; padding-top: 1rem;">
|
|
26
|
-
{url && (
|
|
27
|
-
<p style="margin: 0 0 0.5rem 0;"><a href={url} target="_blank" rel="noopener noreferrer">{label}</a></p>
|
|
28
|
-
)}
|
|
29
|
-
<p style="margin: 0;"><a href={example.sourceUrl} target="_blank" rel="noopener noreferrer">View Source →</a></p>
|
|
30
|
-
</div>
|
|
31
|
-
</Card>
|
|
32
|
-
);
|
|
33
|
-
})}
|
|
34
|
-
</CardGrid>
|
|
35
|
-
|
|
36
|
-
## Cloudflare Adapter
|
|
37
|
-
|
|
38
|
-
- Runs LiveStore inside Cloudflare Durable Objects
|
|
39
|
-
- Uses Durable Object Storage API (not traditional databases)
|
|
40
|
-
- SQLite WASM with Cloudflare-specific VFS
|
|
41
|
-
- No WebSocket support - uses Durable Objects' distributed consistency
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
<a href={`https://github.com/livestorejs/livestore/tree/${getBranchName()}/examples`}>View all examples on GitHub →</a>
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
# Expo adapter examples
|
|
2
|
-
|
|
3
|
-
# Expo Adapter Examples
|
|
4
|
-
|
|
5
|
-
Examples using `@livestore/adapter-expo` for React Native mobile applications.
|
|
6
|
-
|
|
7
|
-
<CardGrid>
|
|
8
|
-
{expoExamples.map((example) => {
|
|
9
|
-
const { url, label } = getExampleDemoLinks(example);
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<Card title={example.title} key={example.title}>
|
|
13
|
-
{example.image ? (
|
|
14
|
-
<Image src={example.image.url} width={example.image.width} height={example.image.height} alt={`${example.title} application interface`} />
|
|
15
|
-
) : (
|
|
16
|
-
<div style="background: linear-gradient(135deg, #1f2937 0%, #374151 100%); height: 200px; display: flex; align-items: center; justify-content: center; color: #9ca3af; font-size: 14px; border-radius: 8px;">
|
|
17
|
-
Screenshot coming soon
|
|
18
|
-
</div>
|
|
19
|
-
)}
|
|
20
|
-
<p>{example.description}</p>
|
|
21
|
-
<p><strong>Technologies:</strong> {example.technologies.join(' • ')}</p>
|
|
22
|
-
{example.syncProvider && (
|
|
23
|
-
<p><strong>Sync Provider:</strong> {example.syncProvider}</p>
|
|
24
|
-
)}
|
|
25
|
-
<div style="margin-top: auto; padding-top: 1rem;">
|
|
26
|
-
{url && (
|
|
27
|
-
<p style="margin: 0 0 0.5rem 0;"><a href={url} target="_blank" rel="noopener noreferrer">{label}</a></p>
|
|
28
|
-
)}
|
|
29
|
-
<p style="margin: 0;"><a href={example.sourceUrl} target="_blank" rel="noopener noreferrer">View Source →</a></p>
|
|
30
|
-
</div>
|
|
31
|
-
</Card>
|
|
32
|
-
);
|
|
33
|
-
})}
|
|
34
|
-
</CardGrid>
|
|
35
|
-
|
|
36
|
-
## Expo Adapter
|
|
37
|
-
|
|
38
|
-
- Uses native Expo SQLite stored in device's SQLite directory
|
|
39
|
-
- Requires New Architecture (Fabric) - incompatible with old architecture
|
|
40
|
-
- Single-threaded operation in main thread
|
|
41
|
-
- WebSocket connections for sync via React Native dev server
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
<a href={`https://github.com/livestorejs/livestore/tree/${getBranchName()}/examples`}>View all examples on GitHub →</a>
|
package/docs/examples/index.md
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# Examples
|
|
2
|
-
|
|
3
|
-
# Example Applications
|
|
4
|
-
|
|
5
|
-
Discover how to build local-first applications with LiveStore through our comprehensive collection of example apps. Each example demonstrates different features, patterns, and platform integrations to help you get started quickly.
|
|
6
|
-
|
|
7
|
-
## Browse by platform adapter
|
|
8
|
-
|
|
9
|
-
LiveStore supports multiple platform adapters, each optimized for different environments. Choose the adapter that matches your target platform:
|
|
10
|
-
|
|
11
|
-
<CardGrid>
|
|
12
|
-
<LinkCard
|
|
13
|
-
title="Web Adapter"
|
|
14
|
-
href="/examples/web-adapter/"
|
|
15
|
-
description={`Browser-based applications with SQLite WASM, Web Workers, and framework integrations. ${webExamples.length} examples • React, SolidJS, Svelte, Web Components`}
|
|
16
|
-
/>
|
|
17
|
-
|
|
18
|
-
<LinkCard
|
|
19
|
-
title="Node Adapter"
|
|
20
|
-
href="/examples/node-adapter/"
|
|
21
|
-
description={`Server-side applications, CLI tools, and backend services with native SQLite performance. ${nodeExamples.length} examples • Effect, CLI applications`}
|
|
22
|
-
/>
|
|
23
|
-
|
|
24
|
-
<LinkCard
|
|
25
|
-
title="Expo Adapter"
|
|
26
|
-
href="/examples/expo-adapter/"
|
|
27
|
-
description={`React Native mobile applications with offline-first architecture and cross-platform sync. ${expoExamples.length} examples • iOS, Android, React Native`}
|
|
28
|
-
/>
|
|
29
|
-
|
|
30
|
-
<LinkCard
|
|
31
|
-
title="Cloudflare Durable Objects"
|
|
32
|
-
href="/examples/cloudflare-adapter/"
|
|
33
|
-
description={`Edge computing with Durable Objects, global distribution, and serverless scaling. ${cloudflareExamples.length} examples • Workers, Durable Objects, Edge`}
|
|
34
|
-
/>
|
|
35
|
-
</CardGrid>
|
|
36
|
-
|
|
37
|
-
## Getting started
|
|
38
|
-
|
|
39
|
-
1. **Choose your platform** from the adapter categories above
|
|
40
|
-
2. **Browse examples** that match your use case and framework preference
|
|
41
|
-
3. **Clone and run** the examples locally to see LiveStore in action
|
|
42
|
-
4. **Study the source code** to understand patterns and best practices
|
|
43
|
-
|
|
44
|
-
## Multi-adapter examples
|
|
45
|
-
|
|
46
|
-
Some examples demonstrate **cross-platform synchronization** by using multiple adapters:
|
|
47
|
-
- **CF Chat** uses both Web and Cloudflare adapters for hybrid client-server architecture
|
|
48
|
-
- **Sync-enabled examples** show how to connect different platforms seamlessly
|
|
49
|
-
|
|
50
|
-
## About LiveStore
|
|
51
|
-
|
|
52
|
-
LiveStore is a local-first data layer that runs everywhere - from browsers to mobile apps to edge computing. Each adapter provides platform-optimized features while maintaining a consistent API across all environments.
|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
<a href={`https://github.com/livestorejs/livestore/tree/${getBranchName()}/examples`}>View all examples on GitHub →</a>
|