export const gettingStartedContent = `# Getting Started with LiveStore Build your first local-first application with LiveStore in minutes. This guide walks through creating a real-time collaborative todo app that works offline and syncs when online. ## Quick Start ### 1. Installation \`\`\`bash # Install LiveStore core npm install @livestore/livestore # Choose your platform adapter npm install @livestore/adapter-web # For web applications npm install @livestore/adapter-node # For Node.js applications npm install @livestore/adapter-expo # For React Native/Expo apps \`\`\` ### 2. Define Your Schema LiveStore uses an event-driven architecture where all changes are recorded as immutable events and applied to materialized SQLite tables. \`\`\`typescript // schema.ts import { Events, makeSchema, Schema, SessionIdSymbol, State } from '@livestore/livestore' // Define your state as SQLite tables export const tables = { todos: State.SQLite.table({ name: 'todos', columns: { id: State.SQLite.text({ primaryKey: true }), text: State.SQLite.text({ default: '' }), completed: State.SQLite.boolean({ default: false }), deletedAt: State.SQLite.integer({ nullable: true, schema: Schema.DateFromNumber }), createdAt: State.SQLite.integer({ schema: Schema.DateFromNumber }), }, }), // Client-only state (not synced) uiState: State.SQLite.clientDocument({ name: 'uiState', schema: Schema.Struct({ newTodoText: Schema.String, filter: Schema.Literal('all', 'active', 'completed') }), default: { id: SessionIdSymbol, value: { newTodoText: '', filter: 'all' } }, }), } // Define events that represent state changes export const events = { todoCreated: Events.synced({ name: 'v1.TodoCreated', schema: Schema.Struct({ id: Schema.String, text: Schema.String, createdAt: Schema.Date }), }), todoCompleted: Events.synced({ name: 'v1.TodoCompleted', schema: Schema.Struct({ id: Schema.String }), }), todoUncompleted: Events.synced({ name: 'v1.TodoUncompleted', schema: Schema.Struct({ id: Schema.String }), }), todoDeleted: Events.synced({ name: 'v1.TodoDeleted', schema: Schema.Struct({ id: Schema.String, deletedAt: Schema.Date }), }), // UI state events (local only) uiStateSet: tables.uiState.set, } // Materializers map events to state changes const materializers = State.SQLite.materializers(events, { 'v1.TodoCreated': ({ id, text, createdAt }) => tables.todos.insert({ id, text, completed: false, createdAt }), 'v1.TodoCompleted': ({ id }) => tables.todos.update({ completed: true }).where({ id }), 'v1.TodoUncompleted': ({ id }) => tables.todos.update({ completed: false }).where({ id }), 'v1.TodoDeleted': ({ id, deletedAt }) => tables.todos.update({ deletedAt }).where({ id }), }) const state = State.SQLite.makeState({ tables, materializers }) export const schema = makeSchema({ events, state }) \`\`\` ### 3. Create Reactive Queries LiveStore queries automatically update your UI when underlying data changes. \`\`\`typescript // queries.ts import { queryDb } from '@livestore/livestore' import { tables } from './schema.js' // Reactive query for all active todos export const activeTodos$ = queryDb( tables.todos .select() .where({ deletedAt: null, completed: false }) .orderBy('createdAt'), { label: 'activeTodos' } ) // Reactive query for completed todos export const completedTodos$ = queryDb( tables.todos .select() .where({ deletedAt: null, completed: true }) .orderBy('createdAt'), { label: 'completedTodos' } ) // UI state query export const uiState$ = queryDb( tables.uiState.get(), { label: 'uiState' } ) \`\`\` ### 4. Connect to Your UI Framework #### React Integration \`\`\`typescript // TodoApp.tsx import React from 'react' import { useLiveQuery, dispatchEvent } from '@livestore/react' import { activeTodos$, completedTodos$, uiState$ } from './queries.js' import { events } from './schema.js' const TodoApp: React.FC = () => { const activeTodos = useLiveQuery(activeTodos$) const completedTodos = useLiveQuery(completedTodos$) const uiState = useLiveQuery(uiState$) const createTodo = (text: string) => { const id = crypto.randomUUID() dispatchEvent(events.todoCreated({ id, text, createdAt: new Date() })) } const toggleTodo = (id: string, completed: boolean) => { dispatchEvent( completed ? events.todoCompleted({ id }) : events.todoUncompleted({ id }) ) } const deleteTodo = (id: string) => { dispatchEvent(events.todoDeleted({ id, deletedAt: new Date() })) } return (