### Epicenter Server Example Usage Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20251014T101252 epicenter-server.md Demonstrates how to set up and start an Epicenter server using `createEpicenterServer`. Includes defining workspaces, starting the server with Bun, and examples of REST and MCP API calls. ```typescript import { defineEpicenter, createEpicenterServer } from '@epicenter/core'; import { blogWorkspace, authWorkspace } from './workspaces'; const epicenter = defineEpicenter({ workspaces: [blogWorkspace, authWorkspace], }); const app = createEpicenterServer(epicenter); // Start the server with Bun Bun.serve({ fetch: app.fetch, port: 3000, }); console.log('Server running at http://localhost:3000'); // REST API calls: // GET http://localhost:3000/blog/getAllPosts // POST http://localhost:3000/blog/createPost // GET http://localhost:3000/auth/getCurrentUser // MCP endpoints (always available): // POST http://localhost:3000/mcp/tools/list // POST http://localhost:3000/mcp/tools/call ``` -------------------------------- ### Setup and Start Commands for Self-Hosting Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260514T220000-self-host-first-class.md These commands are used to set up and start the Epicenter API for self-hosting. `bun run --cwd apps/api setup` performs initialization tasks like migrations and seeding, while `bun run --cwd apps/api start` boots the Bun server. ```bash bun run --cwd apps/api setup ``` ```bash bun run --cwd apps/api start ``` -------------------------------- ### Workspace Server Example Usage Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20251014T101252 epicenter-server.md Demonstrates how to set up and start a Workspace server using `createWorkspaceServer`. Includes starting the server with Bun and examples of REST and MCP API calls. ```typescript import { createWorkspaceServer } from '@epicenter/core'; import { blogWorkspace } from './workspaces/blog'; const app = createWorkspaceServer(blogWorkspace); // Start the server with Bun Bun.serve({ fetch: app.fetch, port: 3001, }); // REST API calls: // GET http://localhost:3001/getAllPosts // POST http://localhost:3001/createPost // MCP endpoints: // POST http://localhost:3001/mcp/tools/list // POST http://localhost:3001/mcp/tools/call ``` -------------------------------- ### Exit Criteria for PR 3: Setup Script and Docs Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260515T000000-latest-spec-orchestration-guide.md Ensure dependencies are installed, environment is configured, and setup script completes successfully. Verify local API start and CLI authentication flow. ```bash bun install cp apps/api/.env.example apps/api/.env bun --cwd apps/api setup bun --cwd apps/api start EPICENTER_API_URL=http://localhost:8787 epicenter auth login ``` -------------------------------- ### Local Server Start Command Example Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260227T120000-cli-reorganization.md Illustrates the 'local start' command for managing the local server process. It supports specifying a workspace, remote URL, and port. ```bash epicenter local start [--workspace ] [--remote ] [--port 3913] ``` -------------------------------- ### Install and Run Benchmark Tool Source: https://github.com/epicenterhq/epicenter/blob/main/examples/yjs-size-benchmark/README.md Navigate to the benchmark directory, install dependencies using bun, and start the development server. Access the tool via the provided localhost URL or network URL on the same WiFi. ```bash cd examples/yjs-size-benchmark bun install bun dev ``` -------------------------------- ### Clone and Run Opensidian Locally Source: https://github.com/epicenterhq/epicenter/blob/main/apps/opensidian/README.md Follow these steps to clone the repository, install dependencies, and start the development server for the Opensidian app. Ensure you have Bun installed. The API server needs to be started separately. ```bash git clone https://github.com/EpicenterHQ/epicenter.git cd epicenter bun install cd apps/opensidian bun dev ``` -------------------------------- ### Local PostgreSQL Setup for Development Source: https://github.com/epicenterhq/epicenter/blob/main/apps/api/README.md Provides bash commands to install PostgreSQL via Homebrew, start the service, create a 'postgres' role and 'epicenter' database, and push the initial schema. ```bash brew install postgresql brew services start postgresql # Homebrew creates a role matching your macOS username. Create the postgres role and database: psql -d postgres -c "CREATE ROLE postgres WITH LOGIN SUPERUSER PASSWORD 'postgres';" psql -U postgres -c "CREATE DATABASE epicenter;" # Push the schema bun run db:push:local ``` -------------------------------- ### Example: Server Start as a Method Source: https://github.com/epicenterhq/epicenter/blob/main/docs/articles/factory-method-patterns.md This demonstrates refactoring a standalone server start function into a method on a server object, improving API clarity and encapsulation. ```typescript const client = createClient(); const server = createServer(client); server.start({ port: 3913 }); ``` -------------------------------- ### Install and Run Fuji Development Server Source: https://github.com/epicenterhq/epicenter/blob/main/apps/fuji/README.md Clones the Epicenter repository, installs dependencies using Bun, and starts the Fuji development server. Assumes Bun is installed and the local API is running separately. ```bash git clone https://github.com/EpicenterHQ/epicenter.git cd epicenter bun install cd apps/fuji bun dev ``` -------------------------------- ### Desired Browser App Setup Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260503T002441-auth-client-sync-clean-break.md Example of initializing the auth client and opening a Fuji instance with direct auth dependency. ```typescript export const auth = createAuth({ baseURL: APP_URLS.API, sessionStorage: createSessionStorageAdapter(session), }); export const fuji = openFuji({ auth, peer, }); ``` -------------------------------- ### Remote Server Start Command Example Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260227T120000-cli-reorganization.md Shows the 'remote start' command for managing or connecting to a remote server process. It allows specifying a port. ```bash epicenter remote start [--port 3914] ``` -------------------------------- ### Y-Sweet Server Local Development Setup Source: https://github.com/epicenterhq/epicenter/blob/main/specs/y-sweet-sync-extension.md Commands to start a local Y-Sweet server with in-memory or persistent storage. ```bash # In-memory storage (data lost on restart) npx y-sweet@latest serve # Persistent storage npx y-sweet@latest serve ./data ``` -------------------------------- ### Local Development Setup Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260203T100000-static-workspace-viewing.md Commands to set up a local development environment. This includes starting the Y-Sweet server, the static workspace server, and the Tauri application. ```bash # Terminal 1: Start y-sweet npx y-sweet@latest serve ./y-sweet-data # Terminal 2: Start Bun process with static workspace bun run packages/epicenter/examples/static-workspace-server.ts # Terminal 3: Start Tauri app bun run --filter @epicenter/app dev ``` -------------------------------- ### Complete Call-Site Example for Workspace and Document Extensions Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260219T195800-document-extension-api.md Demonstrates a realistic setup for workspace and document extensions, including tag-based targeting for persistence, sync, and ephemeral presence. This example shows how to define tables and configure workspace extensions. ```typescript // ── Table Definitions ── const notes = defineTable( type({ id: 'string', title: 'string', updatedAt: 'number', _v: '1' }), ).withDocument('content', { guid: 'id', updatedAt: 'updatedAt', tags: ['persistent', 'synced'], }); const images = defineTable( type({ id: 'string', thumbId: 'string', thumbUpdatedAt: 'number', _v: '1' }), ).withDocument('thumb', { guid: 'thumbId', updatedAt: 'thumbUpdatedAt', tags: ['persistent'], }); const chat = defineTable( type({ id: 'string', msgDocId: 'string', msgUpdatedAt: 'number', _v: '1' }), ).withDocument('messages', { guid: 'msgDocId', updatedAt: 'msgUpdatedAt', tags: ['ephemeral'], }); // ── Workspace ── const syncUrl = 'wss://sync.example.com/{id}'; const workspace = createWorkspace({ id: 'my-app', tables: { notes, images, chat }, }) // Workspace extensions (workspace Y.Doc only) .withExtension('persistence', ({ ydoc }) => { const idb = new IndexeddbPersistence(ydoc.guid, ydoc); return { exports: { clearData: () => idb.clearData() }, lifecycle: { whenReady: idb.whenSynced, destroy: () => idb.destroy() }, }; }) .withExtension('sync', ({ ydoc, awareness }) => { const provider = createSyncProvider({ doc: ydoc, url: syncUrl, awareness: awareness.raw }); return { exports: { provider }, lifecycle: { destroy: () => provider.destroy() }, }; }) // Document extensions (content Y.Docs) // Persistence for docs tagged 'persistent' .withDocumentExtension('persistence', ({ ydoc }) => { const idb = new IndexeddbPersistence(ydoc.guid, ydoc); return { whenReady: idb.whenSynced, destroy: () => idb.destroy() }; }, { tags: ['persistent'] }) // Sync only for docs tagged 'synced' .withDocumentExtension('sync', ({ ydoc }) => { const provider = createSyncProvider({ doc: ydoc, url: syncUrl }); return { destroy: () => provider.destroy() }; }, { tags: ['synced'] }) // Ephemeral presence sync for docs tagged 'ephemeral' .withDocumentExtension('ephemeral-sync', ({ ydoc }) => { return createEphemeralSync(ydoc); }, { tags: ['ephemeral'] }) // Actions (terminal, same as before) .withActions((client) => ({ createNote: defineMutation({ ... }), })); ``` -------------------------------- ### Clone and Run Epicenter Project Source: https://github.com/epicenterhq/epicenter/blob/main/apps/skills/README.md Instructions to clone the Epicenter repository, install dependencies using Bun, and start the Skills Editor development server. ```bash git clone https://github.com/EpicenterHQ/epicenter.git cd epicenter bun install cd apps/skills bun dev ``` -------------------------------- ### Minimal End-to-End Workspace Setup Source: https://github.com/epicenterhq/epicenter/blob/main/docs/guides/consuming-epicenter-api.md Demonstrates the minimal setup for a live, collaborative document using Epicenter. It includes defining tables, attaching encryption, IndexedDB, and BroadcastChannel, and opening a collaboration session. Use this as a starting point for your application's data management. ```typescript import { createInstallationId, defineTable, type LocalOwner, openCollaboration, roomWsUrl, } from '@epicenter/workspace'; import { createSession, type InferSignedIn } from '@epicenter/svelte'; import * as Y from 'yjs'; import { type } from 'arktype'; import { auth } from './auth'; const appTables = { notes: defineTable( type({ id: 'string', title: 'string', _v: '1', }), ), }; function openMyAppDoc({ owner }: { owner: LocalOwner }) { const ydoc = new Y.Doc({ guid: 'epicenter.my-app', gc: true }); const encryption = owner.attachEncryption(ydoc); const tables = encryption.attachTables(appTables); const kv = encryption.attachKv({}); return { ydoc, encryption, tables, kv }; } function openMyApp({ owner, installationId, openWebSocket, }: { owner: LocalOwner; installationId: string; openWebSocket?: ( url: string | URL, protocols?: string[], ) => WebSocket | Promise; }) { const doc = openMyAppDoc({ owner }); const idb = owner.attachIndexedDb(doc.ydoc); owner.attachBroadcastChannel(doc.ydoc); const collaboration = openCollaboration(doc.ydoc, { url: roomWsUrl('https://api.epicenter.so', doc.ydoc.guid), openWebSocket, waitFor: idb.whenLoaded, installationId, actions: {}, }); return { ...doc, idb, collaboration, whenLoaded: idb.whenLoaded, async wipe() { doc.ydoc.destroy(); await collaboration.whenDisposed; await idb.whenDisposed; await owner.wipeLocalYjsData([doc.ydoc.guid]); }, [Symbol.dispose]() { doc.ydoc.destroy(); }, }; } export const session = createSession({ auth, build: ({ owner }) => { const workspace = openMyApp({ owner, installationId: createInstallationId({ storage: localStorage }), openWebSocket: auth.openWebSocket, }); return { workspace, [Symbol.dispose]() { workspace[Symbol.dispose](); }, }; }, }); export type MyAppSignedIn = InferSignedIn; ``` -------------------------------- ### Daemon Start Function Example Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260501T120000-daemon-peer-runtime-contract.md Illustrates starting a daemon with an empty action tree but functional RPC. This setup is suitable for daemons that do not expose remote commands but still participate in the peer network. ```typescript start: ({ projectDir }) => { const doc = openZhongwenDoc({ clientID: hashClientId(projectDir) }); const sync = attachSync(doc, { url: websocketUrl(`${apiUrl}/workspaces/${doc.ydoc.guid}`), getToken, webSocketImpl, }); const presence = sync.attachPresence({ peer }); const actions = {}; const rpc = sync.attachRpc(actions); return { ...doc, yjsLog, sync, presence, rpc, actions, }; } ``` -------------------------------- ### Start Development Server Source: https://github.com/epicenterhq/epicenter/blob/main/apps/tab-manager/README.md Start the local API and WXT extension dev server from the repo root. ```bash bun dev ``` -------------------------------- ### Example of Previous Context Setup Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260507T080000-drop-context-module-helper.md Illustrates the prior implementation where `createContext` was used in `session.svelte.ts` to establish a context for signed-in session data. This setup involved two callers per app: the Provider setting the context and descendants getting it. ```typescript const [getSignedInSession, setSignedInSession] = createContext(); ``` -------------------------------- ### Example App URLs Source: https://github.com/epicenterhq/epicenter/blob/main/docs/articles/workspace-apps-share-one-origin-on-purpose.md Demonstrates how multiple apps can be accessed via different paths under the same origin. ```txt http://127.0.0.1:43821/apps/fuji/ http://127.0.0.1:43821/apps/opensidian/ http://127.0.0.1:43821/apps/honeycrisp/ ``` -------------------------------- ### Block Installation Example Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260224T141400-local-server-plugin-architecture.md An example demonstrating the programmatic installation of a workspace block using the JSRepo API. ```typescript import { selectProvider, fetchBlocks, fetchRaw } from 'jsrepo/api'; import { github } from 'jsrepo/api'; // registry provider import { join } from 'path'; import { mkdirSync, writeFileSync } from 'fs'; async function installWorkspace(name: string, epicenterDir: string) { const registryUrl = 'github/EpicenterHQ/epicenter'; // 1. Resolve registry provider and state const provider = selectProvider(registryUrl); if (!provider) throw new Error(`No provider found for ${registryUrl}`); const state = await github.state(registryUrl); // 2. Fetch all available blocks from the registry const blocksResult = await fetchBlocks(state); if (blocksResult.isErr()) throw new Error(blocksResult.unwrapErr().message); const blocks = blocksResult.unwrap(); // 3. Find the requested workspace block const blockKey = `workspaces/${name}`; const block = blocks.get(blockKey); if (!block) throw new Error(`Workspace "${name}" not found in registry`); // 4. Fetch and write each file const targetDir = join(epicenterDir, 'workspaces', name); mkdirSync(targetDir, { recursive: true }); for (const file of block.files) { const repoPath = join(block.directory, file); const contentResult = await fetchRaw(block.sourceRepo, repoPath); if (contentResult.isErr()) throw new Error(`Failed to fetch ${file}: ${contentResult.unwrapErr()}`); writeFileSync(join(targetDir, file), contentResult.unwrap(), 'utf-8'); } // 5. Install any new deps introduced by this workspace bunInstall(epicenterDir); } ``` -------------------------------- ### Recommended Development Setup Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260515T160000-folder-routed-daemon-workspaces-clean-break.md Provides the recommended terminal commands for setting up the development environment. ```bash # terminal 1 epicenter daemon up # terminal 2 cd workspaces/fuji bun run dev ``` -------------------------------- ### Example Launch Post Copy Source: https://github.com/epicenterhq/epicenter/blob/main/docs/launches/2025-07-07/planning/demo-strategy.md This example demonstrates how to incorporate a demo video or GIF into a social media post to showcase immediate value and a real use case. ```text "Transcription should be free. I built Whispering as a free alternative to paid apps. Here's me using it with Claude Code to code faster than typing: [video/gif] Bring your own API key, pay cents not dollars." ``` -------------------------------- ### Install Ollama on Linux Source: https://github.com/epicenterhq/epicenter/blob/main/docs/guides/custom-endpoint-transformations.md Install Ollama on Linux systems by running the provided installation script. This command downloads and executes the official setup script. ```bash curl -fsSL https://ollama.com/install.sh | sh ``` -------------------------------- ### Benchmark Setup with Bun and YJS Source: https://github.com/epicenterhq/epicenter/blob/main/docs/articles/yjs-storage-efficiency/README.md Provides commands to set up the benchmark environment, including initializing a Bun project and adding the yjs dependency. ```bash # Setup mkdir yjs-benchmark && cd yjs-benchmark bun init -y bun add yjs ``` ```bash # Download the benchmark curl -O https://raw.githubusercontent.com/EpicenterHQ/epicenter/main/docs/articles/yjs-storage-efficiency/benchmark.ts ``` ```bash # Run it bun run benchmark.ts # Default: 100k records bun run benchmark.ts 50000 # Custom count ``` -------------------------------- ### Whispering App CLI Commands Example Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260115T100800-contract.md Provides example CLI commands generated for the Whispering app, covering list, get, add, update, and delete operations for recordings, as well as get and set for KV pairs. ```bash epicenter recordings list epicenter recordings get epicenter recordings add --title "Meeting" --duration 120 epicenter recordings update --title "Updated Title" epicenter recordings delete epicenter kv get defaultModel epicenter kv set defaultModel whisper-1 ``` -------------------------------- ### Example: Table Operations (Get) Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260407T120000-launch-readiness.md Shows how to retrieve data from a table in an Epicenter workspace. This example is for the README documentation. ```typescript const user = await workspace.tables.users.get(usersTable, { // ... }); ``` -------------------------------- ### Daemon Lifecycle Example Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260430T120000-cli-naming-decision.md Illustrates the typical execution of the `epicenter up` command and its associated actions. This command loads configuration, establishes network connections, binds a local socket, and operates in the foreground. ```bash epicenter up --dir |- loads epicenter.config.ts |- connects every workspace to the relay (WebSocket out) |- binds a per-`--dir` Unix socket for sibling CLI calls |- stays in foreground; SIGINT/SIGTERM tears it down `- no public HTTP listener, no port, no detach flag ``` -------------------------------- ### Epicenter CLI Command Examples Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260225T210000-workspace-apps-orchestrator.md Illustrates how to use the Epicenter CLI with different configurations for the home directory. ```bash # All equivalent: epicenter ls # uses ~/.epicenter/ EPICENTER_HOME=/tmp/test epicenter ls # uses /tmp/test/ epicenter --home /tmp/test ls # uses /tmp/test/ ``` -------------------------------- ### Clone and Install Epicenter Monorepo Source: https://github.com/epicenterhq/epicenter/blob/main/apps/dashboard/README.md Instructions to clone the repository and install dependencies using Bun. Ensure the API is running before starting the dashboard. ```bash git clone https://github.com/EpicenterHQ/epicenter.git cd epicenter bun install ``` -------------------------------- ### Define Yjs document GUIDs Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260504T163252-sign-out-preserve-encrypted-local-data.md These are examples of fixed string GUIDs used for Yjs documents, representing different workspaces or application modules. ```typescript new Y.Doc({ guid: 'epicenter.fuji', gc: false }); new Y.Doc({ guid: 'epicenter.honeycrisp', gc: false }); new Y.Doc({ guid: 'epicenter.opensidian', gc: false }); new Y.Doc({ guid: 'epicenter.tab-manager', gc: false }); ``` -------------------------------- ### Discovery File Example Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260220T133004-unified-local-server-architecture.md Illustrates the structure of the discovery file used to manage multiple running instances of the server, keyed by workspace path and including port and PID information. ```json { "/Users/braden/workspace-a": { "port": 54321, "pid": 111 }, "/Users/braden/workspace-b": { "port": 54322, "pid": 222 } } ``` -------------------------------- ### Option D: Status-Based Approach Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20250107T230000-installation-section-redesign.md Illustrates a status-based quick start guide with a visual progress indicator, followed by a full guide and optional enhancements. ```text ## Quick Start (2 minutes) ✅ Download → ✅ API Key → ✅ Test = 🎉 Ready! [Visual progress indicator] 📋 Full Installation Guide: 1. Download... 2. Get API Key... 3. Connect & Test... 🚀 Level Up (optional): - Custom providers - AI transformations - Advanced shortcuts ``` -------------------------------- ### Client Boot Flow Steps Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260108T133200-collaborative-workspace-config-ydoc.md Outlines the sequence of operations for a client to boot up, including authentication, connecting to the Registry Y.Doc, and then connecting to the specific workspace's Head and Data Y.Docs based on the epoch. ```plaintext 1. Authenticate → get registryId + bootstrapSyncNodes from auth server 2. Connect to Registry Y.Doc ({registryId}) → Get set of workspaceIds 3. To open a workspace: a. Connect to Head Y.Doc ({workspaceId}) b. Read epoch from head.epoch c. Connect to Data Y.Doc ({workspaceId}-{epoch}) d. Subscribe to head changes (for epoch bumps) 4. Use typed client for tables/kv operations ``` -------------------------------- ### Local and Remote Action Listing Examples Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260426T190000-cli-actions-unification.md Demonstrates how to list actions from the local workspace and from remote peers using the `epicenter list` command with different flags. ```bash $ epicenter list my-workspace ├── tabs │ ├── close (mutation) Close one or more tabs │ └── list (query) List all open tabs └── entries └── create (mutation) Create an entry ``` ```bash $ epicenter list --peer mac tabs.close mac:tabs.close (mutation) Close one or more tabs Input fields (pass as JSON): tabIds: array (required) ``` ```bash $ epicenter list --all self (this device) ├── tabs.close (mutation) └── entries.create (mutation) mac (online) ├── tabs.close (mutation) └── tabs.list (query) ipad (online, offers: 0) ``` -------------------------------- ### App Integration Example Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260326T084710-opinionated-workspace-auth-api.md Illustrates how the application integrates with the authentication client for bootstrapping and session management. ```text app const appReady = auth.bootstrap() void auth.refreshSession() root layout gates subtree on appReady ``` -------------------------------- ### Get Stable Device ID Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20251213T231125-multi-device-tab-sync.md Retrieves the stable device ID for the current browser installation. This ID is generated once on first install and persisted in `storage.local`. ```typescript /** * Get the stable device ID for this browser installation. * Generated once on first install, persisted in storage.local. */ export async function getDeviceId(): Promise { return deviceIdItem.getValue(); } ``` -------------------------------- ### Implementation Approach Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260512T222257-cli-daemon-command-clean-break.md Illustrates the intended implementation strategy, focusing on creating a new namespace that integrates existing commands with updated documentation and runtime hints. ```txt new namespace -> existing lifecycle commands -> updated help, tests, README, and runtime hints ``` -------------------------------- ### App Composition Example Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260501T150015-peer-addressed-remote-client-api.md An example demonstrating how to compose application components, including awareness, sync, RPC, and the remote client, for a typical application setup. ```APIDOC ## App Composition ### Description Example of composing application components including awareness, sync, RPC, and the remote client. ### Code Example ```typescript const awareness = attachAwareness(doc.ydoc, { schema: { peer: PeerIdentity }, initial: { peer }, }); const sync = attachSync(doc, { url, getToken, waitFor: idb, awareness, }); const rpc = sync.attachRpc(doc.actions); const remote = createRemoteClient({ awareness, rpc }); return { ...doc, awareness, sync, rpc, remote, }; ``` ``` -------------------------------- ### Usage Example: Get Single Row Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20251206T201800-table-helper-status-api.md Demonstrates how to use the new `get()` method and handle the different `GetResult` statuses ('valid', 'invalid', 'not_found') using a switch statement. ```typescript // Get single row const result = db.posts.get({ id: '123' }); switch (result.status) { case 'valid': console.log(result.row.title); break; case 'invalid': console.log('Validation failed:', result.error.context.summary); break; case 'not_found': console.log('Not found:', result.id); break; } ``` -------------------------------- ### Environment Variables for Self-Hosting Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260514T220000-self-host-first-class.md This example `.env.example` file lists all required environment variables for self-hosting Epicenter. Ensure these are set correctly in your `.env` file, including database connection strings, secrets, ports, and asset storage paths. ```bash DATABASE_URL=postgres://... ENCRYPTION_SECRETS=1: # openssl rand -base64 32, then "1:" BETTER_AUTH_SECRET=... # openssl rand -base64 32 PORT=8787 PUBLIC_BASE_URL=http://localhost:8787 ASSETS_DIR=./assets-storage # local filesystem path # Optional. If unset, only email/password works. GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET= ``` -------------------------------- ### Example: Creating a workspace client with capabilities and options Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260108T001900-workspace-create-accepts-capabilities.md Instantiates a workspace client with capabilities that require specific configuration options. This example shows how to pass options to the `sqlite` capability, such as `debounceMs`. ```typescript const client = await workspace.create({ sqlite: sqlite({ debounceMs: 50 }), persistence, }); ``` -------------------------------- ### Get MIME Type and Extension with 'mime' Package Source: https://github.com/epicenterhq/epicenter/blob/main/docs/articles/mime-type-library-decision.md Use mime.getType() to get the MIME type from a file extension and mime.getExtension() for the reverse lookup. Ensure the 'mime' package is installed. ```typescript import mime from 'mime'; mime.getType('mp3'); // 'audio/mpeg' mime.getExtension('audio/wav'); // 'wav' ``` -------------------------------- ### Update GitHub Actions for Bun Installation Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20250725T153000-pnpm-to-bun-migration.md Replace the PNPM setup action with the Bun setup action in GitHub Actions workflows. Ensure the correct Bun version is specified. ```yaml # Remove pnpm installation step - name: install pnpm uses: pnpm/action-setup@v4 with: version: 10.11.0 # Replace with Bun installation - name: setup bun uses: oven-sh/setup-bun@v2 with: bun-version: latest ``` ```yaml # Before - uses: pnpm/action-setup@v4 # After - uses: oven-sh/setup-bun@v2 ``` -------------------------------- ### Example CLI commands Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260421T155436-cli-scripting-first-redesign.md These examples show the desired state for CLI commands, including authentication, listing runnable actions, and running specific actions with parameters. ```bash $ epicenter auth login --server https://api.epicenter.so ``` ```bash $ epicenter list # tree of runnable actions ``` ```bash $ epicenter run tabManager.savedTabs.list ``` ```bash $ epicenter run tabManager.savedTabs.create --title "Hi" --url "..." ``` ```bash $ bun run scripts/export-recordings.ts # anything non-trivial ``` -------------------------------- ### Inline Daemon Configuration Example Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260501T120000-daemon-peer-runtime-contract.md An example of an inline daemon configuration within a project, demonstrating the full contract including route, metadata, and the start function for initializing workspace resources. ```typescript export default defineConfig({ hosts: [ defineDaemon({ route: 'notes', title: 'Notes', workspaceId: 'epicenter.notes', start: ({ projectDir }) => { const notes = openNotes({ id: 'notes', name: 'Notes', platform: 'node', clientID: hashClientId(projectDir), }); const actions = createNotesActions(notes); const sync = attachSync(notes, { url: websocketUrl(`${EPICENTER_API_URL}/workspaces/${notes.ydoc.guid}`), getToken: createCredentialTokenGetter({ serverOrigin: EPICENTER_API_API_URL, }), }); const presence = sync.attachPresence({ peer: { id: 'notes-daemon', name: 'Notes Daemon', platform: 'node', }, }); const rpc = sync.attachRpc(actions); return { ...notes, sync, presence, rpc, actions, }; }, }), ], }); ``` -------------------------------- ### Awareness Attachment Initialization Example Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260501T180000-awareness-source-of-truth.md Example demonstrating how to initialize an awareness attachment with a specific schema and initial state. The schema defines the structure of awareness data, and initial provides the starting values. ```ts const awareness = attachAwareness(ydoc, { schema: { peer: PeerIdentity, cursor: Cursor.or('null'), }, initial: { peer, cursor: null, }, }); ``` -------------------------------- ### Start Epicenter Components Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260208T010000-example-implementation.md Commands to start the Y-Sweet server, the Bun filesystem sync script, and the Svelte development server. ```bash # Terminal 1: Y-Sweet server npx y-sweet serve ./y-sweet-data # Terminal 2: Bun filesystem sync bun scripts/fs-sync.ts # Terminal 3: Svelte app bun run dev ``` -------------------------------- ### Epicenter App Example: Whispering Workspace Setup Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260130T111500-unified-workspace-architecture.md Illustrates setting up a Grid workspace with a HeadDoc for epochs and snapshots, including persistence configuration and accessing tables, KV, SQLite, and revisions. ```typescript // apps/epicenter/src/lib/workspaces/whispering.ts import { createGridWorkspace } from '@epicenter/workspace/grid'; import { createHeadDoc } from '@epicenter/workspace/core/docs'; import { workspacePersistence } from '@epicenter/workspace/extensions/persistence'; // 1. Create HeadDoc (if you want epochs/snapshots) const headDoc = createHeadDoc({ workspaceId: 'epicenter.whispering', providers: { persistence: ({ ydoc }) => headDocPersistence(ydoc, { filePath: join( epicenterDir, 'workspaces', 'epicenter.whispering', 'head.yjs', ), }), }, }); await headDoc.whenSynced; // 2. Create workspace with HeadDoc const whisperingWorkspace = createGridWorkspace({ id: 'epicenter.whispering', definition: whisperingDefinition, headDoc, // Enables epochs + snapshots }).withExtensions({ persistence: (ctx) => workspacePersistence(ctx, { directory: join(epicenterDir, 'workspaces'), outputs: { binary: true, json: true, sqlite: true }, revisions: { maxVersions: 50 }, }), }); // 3. Access everything through the client await whisperingWorkspace.whenSynced; // Tables const recordings = whisperingWorkspace.table('recordings').getAllValid(); // KV const theme = whisperingWorkspace.kv.get('theme'); // SQLite queries const { db, recordings: recordingsTable } = whisperingWorkspace.extensions.persistence; const recent = await db .select() .from(recordingsTable) .orderBy(desc(recordingsTable.createdAt)) .limit(10); // Revision history const { revisions } = whisperingWorkspace.extensions.persistence; await revisions.save('Before bulk delete'); ``` -------------------------------- ### Historical Daemon Definition Example Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260501T120000-daemon-peer-runtime-contract.md This historical example shows how a daemon was defined using `defineDaemon` within `default defineConfig`. It includes route, title, workspaceId, and a start function returning daemon components. ```typescript export default defineConfig({ hosts: [ defineDaemon({ route: 'notes', title: 'Notes', workspaceId: 'epicenter.notes-repro', start: () => ({ ...notes, actions, sync, presence, rpc, }), }), ], }); ``` -------------------------------- ### Install and Get Signed-In Session Reader Source: https://github.com/epicenterhq/epicenter/blob/main/specs/20260507T080000-drop-context-module-helper.md This snippet demonstrates how to create a context for reading signed-in session data and how to install a reader function. Use this pattern when a lazy reader for session data is required. ```typescript const [readSignedInSession, setSignedInSessionReader] = createContext<() => FujiSignedIn>(); export function getSignedInSession(): FujiSignedIn { return readSignedInSession()(); // double-call: get reader, then invoke it } export function installSignedInSession(read: () => FujiSignedIn): void { setSignedInSessionReader(read); } // layout's