Skip to content

[3/3] Add Svelte docs#2367

Merged
nezaj merged 19 commits intomainfrom
svelte-sdk-docs
Mar 16, 2026
Merged

[3/3] Add Svelte docs#2367
nezaj merged 19 commits intomainfrom
svelte-sdk-docs

Conversation

@nezaj
Copy link
Contributor

@nezaj nezaj commented Mar 13, 2026

What it says on the tin! Specifically

  • Adds "Getting started with Svelte" docs page at /docs/start-svelte
  • Adds Svelte entry to the docs navigation sidebar
CleanShot 2026-03-13 at 13 50 17@2x

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 13, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 48d60d02-7ef4-497b-ad7a-e127314e02ae

📥 Commits

Reviewing files that changed from the base of the PR and between 0329096 and 51004fc.

📒 Files selected for processing (1)
  • client/packages/version/src/version.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • client/packages/version/src/version.ts

📝 Walkthrough

Walkthrough

Adds first-class Svelte/SvelteKit support: a new @instantdb/svelte SDK (reactive DB wrapper, room/presence APIs, UI components), CLI and create-instant-app template support, docs page, sandbox and example SvelteKit apps, tests, and tooling/config updates.

Changes

Cohort / File(s) Summary
Svelte SDK Core
client/packages/svelte/src/lib/InstantSvelteDatabase.svelte.ts, client/packages/svelte/src/lib/InstantSvelteRoom.svelte.ts, client/packages/svelte/src/lib/index.ts
Adds InstantSvelteDatabase wrapper, room/presence/topic hooks, room class, and a public barrel export exposing core types/APIs and Svelte integrations.
Svelte UI Components
client/packages/svelte/src/lib/SignedIn.svelte, client/packages/svelte/src/lib/SignedOut.svelte, client/packages/svelte/src/lib/Cursors.svelte
Adds SignedIn/SignedOut auth-aware components and a Cursors component for realtime cursor presence and rendering.
Tests
client/packages/svelte/src/tests/InstantSvelteDatabase.svelte.test.ts
Adds Vitest suite mocking core reactor covering non-reactive methods and reactive hooks (useQuery, useAuth, connection, localId, room behaviors).
CLI & Templates
client/packages/cli/src/index.js, client/packages/create-instant-app/src/cli.ts, client/packages/create-instant-app/scripts/copyExamples.ts, client/packages/create-instant-app/src/env.ts
Adds Svelte package alias and instant module detection, includes SvelteKit (sveltekit) template and --sv flag, updates package selection and env name mapping, and includes SvelteKit example copying.
Docs / Site
client/www/data/docsNavigation.js, client/www/pages/docs/start-svelte.md, client/www/components/docs/Fence.jsx
Adds "Getting started w/ Svelte" nav entry and a comprehensive getting-started doc; remaps svelte code fences to HTML for highlighting.
Sandbox SvelteKit App
client/sandbox/sveltekit/...
Adds a complete sandbox SvelteKit project (config, pages, routes, db wiring, ephemeral app provisioning, todo app, auth, cursors, ssr disables, styling).
Example SvelteKit Project
examples/sveltekit/...
Adds example project with schema, perms, db init, pages and layout, tooling configs, and README.
Tooling / Misc
client/.prettierignore, client/packages/version/src/version.ts, client/sandbox/sveltekit/.gitignore, examples/sveltekit/.gitignore
Adds .svelte-kit to prettier ignore and sandbox/example .gitignore entries; bumps package version to v0.22.159.

Sequence Diagram(s)

sequenceDiagram
    participant App as Svelte App
    participant SDK as InstantSvelteDatabase
    participant Reactor as Core Reactor
    participant Cache as Subscription Cache

    App->>SDK: call useQuery(query)
    activate SDK
    SDK->>Reactor: subscribeQuery(query)
    activate Reactor
    Reactor->>Cache: getPreviousResult(query)
    Cache-->>Reactor: cached result?
    Reactor-->>SDK: initial result (loading/data/cached)
    SDK-->>App: return reactive state
    deactivate Reactor
    deactivate SDK

    Note over Reactor,SDK: Later -> server pushes update
    Reactor->>SDK: emit new query result
    activate SDK
    SDK->>SDK: update Svelte $state
    SDK-->>App: reactive update
    deactivate SDK

    App->>SDK: component unmounts
    SDK->>Reactor: unsubscribeQuery
    Reactor->>Reactor: cleanup
Loading
sequenceDiagram
    participant User1 as User 1 (Browser)
    participant Cursors as Cursors Component
    participant Room as InstantSvelteRoom
    participant Reactor as Core Reactor
    participant User2 as User 2 (Browser)

    User1->>Cursors: onMouseMove(x,y)
    activate Cursors
    Cursors->>Room: publishPresence({x,y,xPercent,yPercent})
    activate Room
    Room->>Reactor: publishPresence to room/space
    Reactor->>User2: broadcast presence update
    deactivate Room
    deactivate Cursors

    User2->>Reactor: subscribe presence for room/space
    Reactor->>Room: deliver presence list
    Room->>Cursors: peers update
    Cursors->>Cursors: re-render remote cursors
    Cursors-->>User2: display cursors
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • drew-harris
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title '[3/3] Add Svelte docs' accurately describes the main change: adding documentation for Svelte, which is the primary purpose confirmed by both the PR description and file changes.
Description check ✅ Passed The pull request description is directly related to the changeset, specifically mentioning the addition of a 'Getting started with Svelte' docs page at /docs/start-svelte and the Svelte entry to the docs navigation sidebar, which are core changes in the PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch svelte-sdk-docs
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can disable the changed files summary in the walkthrough.

Disable the reviews.changed_files_summary setting to disable the changed files summary in the walkthrough.

Without this entry the svelte package version doesn't get set
before publish, causing CI to fail on first publish.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@nezaj nezaj force-pushed the svelte-sdk-example-app branch from 346fbb6 to c68e886 Compare March 13, 2026 20:59
@nezaj nezaj force-pushed the svelte-sdk-docs branch from 2dae3bd to bd0eb37 Compare March 13, 2026 20:59
@nezaj nezaj changed the title Add Svelte docs [3/3] Add Svelte docs Mar 13, 2026
@github-actions
Copy link
Contributor

View Vercel preview at instant-www-js-svelte-sdk-docs-jsv.vercel.app.

@nezaj nezaj force-pushed the svelte-sdk-example-app branch from c68e886 to 45d44a3 Compare March 13, 2026 21:47
@nezaj nezaj force-pushed the svelte-sdk-docs branch from bd0eb37 to 57b9a78 Compare March 13, 2026 21:47
@nezaj nezaj force-pushed the svelte-sdk-docs branch from 57b9a78 to bff1023 Compare March 13, 2026 22:16
@nezaj nezaj force-pushed the svelte-sdk-docs branch from bff1023 to 7ee420f Compare March 13, 2026 22:23
@nezaj nezaj force-pushed the svelte-sdk-docs branch from 7ee420f to 5559435 Compare March 13, 2026 22:24
@nezaj nezaj force-pushed the svelte-sdk-docs branch from 5559435 to 7bd0f66 Compare March 13, 2026 22:31
@nezaj nezaj force-pushed the svelte-sdk-docs branch from 7bd0f66 to 0fa8792 Compare March 13, 2026 22:35
@nezaj nezaj force-pushed the svelte-sdk-docs branch from 9ddf91c to 752c171 Compare March 14, 2026 01:04
@nezaj nezaj changed the base branch from svelte-sdk-example-app to main March 14, 2026 01:05
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
nezaj and others added 4 commits March 13, 2026 18:13
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Map svelte to html in Fence component for syntax highlighting.
This prevents Prettier from mangling Svelte template syntax in
code blocks while keeping the same highlighting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (5)
examples/sveltekit/src/instant.schema.ts (1)

16-20: Consider indexing createdAt if you plan to order todos by creation time.

The createdAt field is defined but not indexed. Per InstantDB guidelines, fields used for filtering or ordering should be indexed. If the todo list should display in chronological order, add .indexed():

♻️ Suggested change
     todos: i.entity({
-      createdAt: i.number(),
+      createdAt: i.number().indexed(),
       done: i.boolean(),
       text: i.string(),
     }),

Based on learnings: "CRITICAL: You MUST index any field you want to filter or order by in the schema".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/sveltekit/src/instant.schema.ts` around lines 16 - 20, The todos
entity defines createdAt via i.number() but doesn't mark it indexed; update the
schema for the todos entity (the i.entity with createdAt/done/text) to call
.indexed() on the createdAt field (i.number().indexed()) so InstantDB can
filter/order by creation time; ensure you modify the createdAt declaration
inside the todos i.entity block accordingly.
client/sandbox/sveltekit/src/routes/+page.svelte (2)

14-21: Consider moving useQuery outside the conditional block.

Calling db.useQuery() inside an {:else} block (via {@const}) means the reactive query is created and destroyed each time dbState changes. While this works for the sandbox demo, it differs from the pattern in examples/sveltekit/src/routes/+page.svelte where useQuery is called at the component's top level.

For consistency and to avoid potential subscription churn, consider restructuring to call useQuery unconditionally when db is available:

♻️ Suggested restructure
 <script lang="ts">
   import { id, type InstaQLEntity } from '@instantdb/svelte';
   import { dbState, type AppSchema } from '$lib/db.svelte';

   type Todo = InstaQLEntity<AppSchema, 'todos'>;

   let text = $state('');
+
+  // Derive query reactively when db is available
+  const query = $derived(dbState.db?.useQuery({ todos: {} }));
 </script>

 {`#if` dbState.isLoading}
   <div class="p-8 flex justify-center">Creating ephemeral app...</div>
 {:else if dbState.error}
   <div class="p-8 text-red-500">Error: {dbState.error}</div>
-{:else}
-  {`@const` db = dbState.db!}
-  {`@const` query = db.useQuery({ todos: {} })}
+{:else if query}
+  {`@const` db = dbState.db!}
   <div class="p-8 grid grid-cols-2 items-start gap-2">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/sandbox/sveltekit/src/routes/`+page.svelte around lines 14 - 21, The
reactive query is being created inside the {:else} block via {`@const` query =
db.useQuery(...)} which causes the subscription to be torn down and recreated
whenever dbState changes; move the db.useQuery call out of the conditional so
the query is created at the component scope whenever db is present (e.g., derive
a top-level {`@const` db = dbState.db} and then create {`@const` query = db &&
db.useQuery({ todos: {} })} or equivalent), keeping the conditional only for
rendering {`@render` welcome()} and {`@render` todoApp(db, query)}; update
references to query and db in todoApp() to use the top-level symbols so
subscriptions remain stable.

51-70: Consider adding type annotations to snippet parameters.

The snippets use db: any and query: any which loses type safety. Using proper types would improve developer experience:

♻️ Suggested improvement
-{`#snippet` todoApp(db: any, query: any)}
+{`#snippet` todoApp(db: typeof dbState.db, query: ReturnType<NonNullable<typeof dbState.db>['useQuery']>)}

However, this is acceptable for sandbox/example code where brevity is preferred.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/sandbox/sveltekit/src/routes/`+page.svelte around lines 51 - 70, The
snippet parameters in todoApp(db: any, query: any) should be annotated with
actual types instead of any: replace the any on db with your DB client/interface
type (e.g., DatabaseClient or whatever type represents the sandbox DB) and
replace query:any with a typed query/result shape (e.g., QueryResult<{ todos:
Todo[] }> or similar), add/import a Todo interface and the query result type,
and update any usages in todoForm, todoList, and actionBar if needed to match
those types so the snippet signature and its referenced helpers are type-safe.
client/packages/svelte/src/lib/InstantSvelteDatabase.svelte.ts (1)

43-51: Minor: Simplify boolean coercion.

!Boolean(result) can be simplified to !result since the truthiness check is equivalent.

♻️ Suggested simplification
 function stateForResult(result: any) {
   return {
-    isLoading: !Boolean(result),
+    isLoading: !result,
     data: undefined,
     pageInfo: undefined,
     error: undefined,
     ...(result ? result : {}),
   };
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/packages/svelte/src/lib/InstantSvelteDatabase.svelte.ts` around lines
43 - 51, In stateForResult, simplify the truthiness check by replacing the
explicit Boolean coercion; change the isLoading assignment from using
!Boolean(result) to using !result so the function reads isLoading: !result while
leaving the rest of stateForResult (data, pageInfo, error, and spread of result)
unchanged.
client/packages/svelte/src/lib/InstantSvelteRoom.svelte.ts (1)

185-196: Unconventional dependency tracking pattern.

The deps parameter and its handling (lines 186-193) is unusual. If deps contains functions, they're called for side effects; otherwise JSON.stringify(data) is used to track changes. This differs from React's dependency array pattern and may confuse users.

Consider documenting this behavior more explicitly, or using a more conventional reactive pattern where the caller passes reactive getters.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/packages/svelte/src/lib/InstantSvelteRoom.svelte.ts` around lines 185
- 196, The current $effect dependency tracking in InstantSvelteRoom.svelte.ts
uses an unconventional pattern: calling functions in deps or falling back to
JSON.stringify(data) before publishing via room.core._reactor.publishPresence;
update this to a clearer reactive-getter contract: require callers to pass deps
as an array of zero-arg getter functions (e.g., DepGetter[]) and inside $effect
iterate deps calling each getter to read reactive values (no silent
JSON.stringify fallback), and if the caller intends simple value tracking allow
an explicit helper like createValueGetter(data) or a documented whenEmpty
option; update the InstantSvelteRoom API docs and the $effect block to reference
deps, data, and room.core._reactor.publishPresence so callers know to pass
getters rather than raw values or rely on JSON.stringify.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@client/packages/svelte/src/lib/Cursors.svelte`:
- Around line 84-86: The fullPresence derivation uses
room.core._reactor.getPresence(...) which returns a synchronous snapshot and can
become stale; update the $derived for fullPresence to depend on the reactive
cursorsPresence.peers (or the existing peers derivation) so it recomputes when
presence changes. Concretely, change the derived call that creates fullPresence
(referencing fullPresence and room.core._reactor.getPresence) to use
cursorsPresence.peers (or peers) as an input dependency and call getPresence
inside the derived callback so fullPresence updates whenever
cursorsPresence.peers changes.

In `@client/www/pages/docs/start-svelte.md`:
- Around line 40-43: The import for the schema is using the wrong relative path;
update the import that assigns to the symbol "schema" (and the same import line
that brings in "init") so it points to the project-root schema by changing the
path from "../instant.schema" to "../../instant.schema" (this fixes resolution
from src/lib/db.ts to the root instant.schema).

In `@examples/sveltekit/src/app.css`:
- Around line 3-6: The Biome CSS parser needs tailwind directive parsing enabled
for the `@apply` usage in app.css; update the Biome config by adding
"tailwindDirectives": true under the css.parser section (so the parser will
accept `@apply` in :root/@layer base) or alternatively remove the `@apply` in the
:root block in app.css and replace it with an equivalent CSS
custom-property/fallback to avoid requiring the Biome change.

---

Nitpick comments:
In `@client/packages/svelte/src/lib/InstantSvelteDatabase.svelte.ts`:
- Around line 43-51: In stateForResult, simplify the truthiness check by
replacing the explicit Boolean coercion; change the isLoading assignment from
using !Boolean(result) to using !result so the function reads isLoading: !result
while leaving the rest of stateForResult (data, pageInfo, error, and spread of
result) unchanged.

In `@client/packages/svelte/src/lib/InstantSvelteRoom.svelte.ts`:
- Around line 185-196: The current $effect dependency tracking in
InstantSvelteRoom.svelte.ts uses an unconventional pattern: calling functions in
deps or falling back to JSON.stringify(data) before publishing via
room.core._reactor.publishPresence; update this to a clearer reactive-getter
contract: require callers to pass deps as an array of zero-arg getter functions
(e.g., DepGetter[]) and inside $effect iterate deps calling each getter to read
reactive values (no silent JSON.stringify fallback), and if the caller intends
simple value tracking allow an explicit helper like createValueGetter(data) or a
documented whenEmpty option; update the InstantSvelteRoom API docs and the
$effect block to reference deps, data, and room.core._reactor.publishPresence so
callers know to pass getters rather than raw values or rely on JSON.stringify.

In `@client/sandbox/sveltekit/src/routes/`+page.svelte:
- Around line 14-21: The reactive query is being created inside the {:else}
block via {`@const` query = db.useQuery(...)} which causes the subscription to be
torn down and recreated whenever dbState changes; move the db.useQuery call out
of the conditional so the query is created at the component scope whenever db is
present (e.g., derive a top-level {`@const` db = dbState.db} and then create
{`@const` query = db && db.useQuery({ todos: {} })} or equivalent), keeping the
conditional only for rendering {`@render` welcome()} and {`@render` todoApp(db,
query)}; update references to query and db in todoApp() to use the top-level
symbols so subscriptions remain stable.
- Around line 51-70: The snippet parameters in todoApp(db: any, query: any)
should be annotated with actual types instead of any: replace the any on db with
your DB client/interface type (e.g., DatabaseClient or whatever type represents
the sandbox DB) and replace query:any with a typed query/result shape (e.g.,
QueryResult<{ todos: Todo[] }> or similar), add/import a Todo interface and the
query result type, and update any usages in todoForm, todoList, and actionBar if
needed to match those types so the snippet signature and its referenced helpers
are type-safe.

In `@examples/sveltekit/src/instant.schema.ts`:
- Around line 16-20: The todos entity defines createdAt via i.number() but
doesn't mark it indexed; update the schema for the todos entity (the i.entity
with createdAt/done/text) to call .indexed() on the createdAt field
(i.number().indexed()) so InstantDB can filter/order by creation time; ensure
you modify the createdAt declaration inside the todos i.entity block
accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8c850e7e-9eae-4c9b-9d0b-33105fc8f43e

📥 Commits

Reviewing files that changed from the base of the PR and between 0fa8792 and 0409f0b.

⛔ Files ignored due to path filters (1)
  • client/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (49)
  • client/.prettierignore
  • client/packages/cli/src/index.js
  • client/packages/create-instant-app/scripts/copyExamples.ts
  • client/packages/create-instant-app/src/cli.ts
  • client/packages/create-instant-app/src/env.ts
  • client/packages/platform/__tests__/src/migrations.test.ts
  • client/packages/platform/src/migrations.ts
  • client/packages/svelte/src/lib/Cursors.svelte
  • client/packages/svelte/src/lib/InstantSvelteDatabase.svelte.ts
  • client/packages/svelte/src/lib/InstantSvelteRoom.svelte.ts
  • client/packages/svelte/src/lib/SignedIn.svelte
  • client/packages/svelte/src/lib/SignedOut.svelte
  • client/packages/svelte/src/lib/index.ts
  • client/packages/svelte/src/tests/InstantSvelteDatabase.svelte.test.ts
  • client/packages/version/src/version.ts
  • client/sandbox/sveltekit/.gitignore
  • client/sandbox/sveltekit/README.md
  • client/sandbox/sveltekit/package.json
  • client/sandbox/sveltekit/src/app.css
  • client/sandbox/sveltekit/src/app.html
  • client/sandbox/sveltekit/src/lib/config.ts
  • client/sandbox/sveltekit/src/lib/db.svelte.ts
  • client/sandbox/sveltekit/src/routes/+layout.svelte
  • client/sandbox/sveltekit/src/routes/+page.svelte
  • client/sandbox/sveltekit/src/routes/+page.ts
  • client/sandbox/sveltekit/src/routes/auth/+page.svelte
  • client/sandbox/sveltekit/src/routes/auth/+page.ts
  • client/sandbox/sveltekit/src/routes/cursors/+page.svelte
  • client/sandbox/sveltekit/src/routes/cursors/+page.ts
  • client/sandbox/sveltekit/svelte.config.js
  • client/sandbox/sveltekit/tsconfig.json
  • client/sandbox/sveltekit/vite.config.ts
  • client/www/components/docs/Fence.jsx
  • client/www/data/docsNavigation.js
  • client/www/pages/docs/start-svelte.md
  • examples/sveltekit/.gitignore
  • examples/sveltekit/README.md
  • examples/sveltekit/package.json
  • examples/sveltekit/src/app.css
  • examples/sveltekit/src/app.html
  • examples/sveltekit/src/instant.perms.ts
  • examples/sveltekit/src/instant.schema.ts
  • examples/sveltekit/src/lib/db.ts
  • examples/sveltekit/src/routes/+layout.svelte
  • examples/sveltekit/src/routes/+page.svelte
  • examples/sveltekit/src/routes/+page.ts
  • examples/sveltekit/svelte.config.js
  • examples/sveltekit/tsconfig.json
  • examples/sveltekit/vite.config.ts
✅ Files skipped from review due to trivial changes (4)
  • examples/sveltekit/tsconfig.json
  • examples/sveltekit/.gitignore
  • client/sandbox/sveltekit/README.md
  • examples/sveltekit/src/app.html
🚧 Files skipped from review as they are similar to previous changes (1)
  • client/www/data/docsNavigation.js

Comment on lines +84 to +86
const fullPresence = $derived(
room.core._reactor.getPresence(room.type, room.id),
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

fullPresence may contain stale data.

The $derived block calls room.core._reactor.getPresence() which is a synchronous snapshot, not a reactive subscription. This value won't update automatically when presence changes, potentially causing renderCursor to receive stale peer data. The peers derivation on line 83 works because cursorsPresence.peers is already reactive from the usePresence subscription.

Consider triggering the derivation when cursorsPresence.peers changes:

🔧 Proposed fix
  const peers = $derived(Object.entries(cursorsPresence.peers));
  const fullPresence = $derived(
+   // Re-derive when peers change
+   (cursorsPresence.peers,
    room.core._reactor.getPresence(room.type, room.id),
+   )
  );

Or more explicitly:

  const peers = $derived(Object.entries(cursorsPresence.peers));
- const fullPresence = $derived(
-   room.core._reactor.getPresence(room.type, room.id),
- );
+ const fullPresence = $derived.by(() => {
+   // Track peers to re-derive when presence updates
+   void cursorsPresence.peers;
+   return room.core._reactor.getPresence(room.type, room.id);
+ });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const fullPresence = $derived(
room.core._reactor.getPresence(room.type, room.id),
);
const peers = $derived(Object.entries(cursorsPresence.peers));
const fullPresence = $derived.by(() => {
// Track peers to re-derive when presence updates
void cursorsPresence.peers;
return room.core._reactor.getPresence(room.type, room.id);
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/packages/svelte/src/lib/Cursors.svelte` around lines 84 - 86, The
fullPresence derivation uses room.core._reactor.getPresence(...) which returns a
synchronous snapshot and can become stale; update the $derived for fullPresence
to depend on the reactive cursorsPresence.peers (or the existing peers
derivation) so it recomputes when presence changes. Concretely, change the
derived call that creates fullPresence (referencing fullPresence and
room.core._reactor.getPresence) to use cursorsPresence.peers (or peers) as an
input dependency and call getPresence inside the derived callback so
fullPresence updates whenever cursorsPresence.peers changes.

Comment on lines +40 to +43
```ts
import { init } from '@instantdb/svelte';
import schema from '../instant.schema';

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Incorrect schema import path.

The file is at src/lib/db.ts, but the import path ../instant.schema would resolve to src/instant.schema. The schema file is typically at the project root, so the path should be ../../instant.schema.

🔧 Proposed fix
 import { init } from '@instantdb/svelte';
-import schema from '../instant.schema';
+import schema from '../../instant.schema';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/www/pages/docs/start-svelte.md` around lines 40 - 43, The import for
the schema is using the wrong relative path; update the import that assigns to
the symbol "schema" (and the same import line that brings in "init") so it
points to the project-root schema by changing the path from "../instant.schema"
to "../../instant.schema" (this fixes resolution from src/lib/db.ts to the root
instant.schema).

Comment on lines +3 to +6
@layer base {
:root {
@apply font-sans;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Locate Biome config files
fd --hidden --glob 'biome*.json*' -t f

# 2) Inspect CSS/Tailwind parsing and include/exclude rules
fd --hidden --glob 'biome*.json*' -t f | xargs -I{} rg -n -C3 'tailwind|css|overrides|files|include|exclude|ignore' {}

# 3) Check existing repo convention for Tailwind directives in CSS
rg -n -C2 '@import "tailwindcss"|@layer|@apply' --type=css

Repository: instantdb/instant

Length of output: 5233


🏁 Script executed:

# Get complete biome.json file
cat -n biome.json | head -100

Repository: instantdb/instant

Length of output: 2346


🏁 Script executed:

# Check if there are any CSS-specific overrides or ignore patterns for examples/sveltekit
rg -n 'sveltekit|examples' biome.json -A2 -B2

Repository: instantdb/instant

Length of output: 43


🏁 Script executed:

# Check for biomeignore files
find . -name '.biomeignore' -o -name 'biomeignore*'

# Check biome.json for files/ignore patterns
rg -n 'files|ignore|exclude' biome.json

# Check if there's any VSCode settings or other config that might disable Tailwind
find . -name '.vscode' -type d -o -name 'tailwind.config.*' -type f | head -20

Repository: instantdb/instant

Length of output: 279


🏁 Script executed:

# Look for any CSS-related linting overrides in the examples/sveltekit directory
cat examples/sveltekit/biome.json 2>/dev/null || echo "No local biome.json in examples/sveltekit"

# Check if there's a package.json with Biome config override
grep -A5 -B5 'biome' examples/sveltekit/package.json 2>/dev/null || echo "No biome config in package.json"

Repository: instantdb/instant

Length of output: 134


🏁 Script executed:

# Check for biome-ignore comments in CSS files that use `@apply`
rg -n 'biome-ignore|@apply' --type=css -B1 -A1 | head -50

# Check if there are any known issues or comments about `@apply` in the sveltekit example
cat examples/sveltekit/src/app.css

Repository: instantdb/instant

Length of output: 1815


🌐 Web query:

Biome CSS Tailwind @apply support version 2.4.6

💡 Result:

Biome v2.4.6 supports parsing Tailwind CSS directives including @apply, but it’s opt-in.

Enable it either via config:

{
  "css": {
    "parser": {
      "tailwindDirectives": true
    }
  }
}

This option explicitly “enables parsing of Tailwind specific syntax, like @theme, @utility and @apply” and defaults to false. [1]

Or via CLI (available since Biome 2.3.x, and works in 2.4.6):

biome check  --css-parse-tailwind-directives=true file.css
biome format --css-parse-tailwind-directives=true file.css
biome lint   --css-parse-tailwind-directives=true file.css
biome ci     --css-parse-tailwind-directives=true file.css
``` [2]

**Sources:** [1] Biome configuration reference, [2] Biome 2.3.0 changelog (CLI flag).

---



</details>

**Enable Tailwind directive parsing in Biome configuration.**

The `@apply` directive at line 5 requires explicit opt-in in Biome 2.4.6. Add `"tailwindDirectives": true` to the CSS parser configuration in `biome.json`:

```json
{
  "css": {
    "parser": {
      "tailwindDirectives": true
    }
  }
}

Alternatively, use the CSS custom property fallback to avoid the dependency on Biome configuration:

Optional code-side fallback (avoid @apply)
 `@layer` base {
     :root {
-        `@apply` font-sans;
+        font-family: var(--font-sans);
     }
🧰 Tools
🪛 Biome (2.4.6)

[error] 5-5: Tailwind-specific syntax is disabled.

(parse)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/sveltekit/src/app.css` around lines 3 - 6, The Biome CSS parser
needs tailwind directive parsing enabled for the `@apply` usage in app.css; update
the Biome config by adding "tailwindDirectives": true under the css.parser
section (so the parser will accept `@apply` in :root/@layer base) or alternatively
remove the `@apply` in the :root block in app.css and replace it with an
equivalent CSS custom-property/fallback to avoid requiring the Biome change.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@client/www/pages/docs/start-svelte.md`:
- Around line 18-33: The docs omit changing into the newly created app and
starting the dev server: after the `npx sv create my-app` step add an
instruction to run `cd my-app` so subsequent `npm i `@instantdb/svelte`` and `npx
instant-cli init` run in the app folder, then add a step to start SvelteKit
(e.g., `npm run dev`) before directing users to the app; also update the URL to
include the scheme (`http://localhost:5173`). Reference the existing command
strings (`npx sv create my-app`, `npm i `@instantdb/svelte``, `npx instant-cli
init`, `npm run dev`) when making the edits.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 95712e1a-ee0d-4846-80ae-9eb33e58943c

📥 Commits

Reviewing files that changed from the base of the PR and between 0409f0b and 0329096.

📒 Files selected for processing (4)
  • client/packages/version/src/version.ts
  • client/www/components/docs/Fence.jsx
  • client/www/data/docsNavigation.js
  • client/www/pages/docs/start-svelte.md

Comment on lines +18 to +33
Create a blank SvelteKit app:

```shell
npx sv create my-app
```

Add the InstantDB Svelte Library:

```shell
npm i @instantdb/svelte
```

Use `instant-cli` to set up a new Instant project. This will prompt you to log in if you haven't already. It will then create a schema file, permissions file, and update your `.env` file.

```shell
npx instant-cli init
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Manual setup flow is missing two required steps.

After npx sv create my-app, the next commands still run in the caller's current directory, and the guide later sends readers to localhost:5173 without ever starting SvelteKit. Following the steps as written can install/init Instant in the wrong folder or leave no app listening on that port.

💡 Suggested doc patch
 ```shell
 npx sv create my-app
+cd my-app
 ```
@@
+Start the dev server:
+
+```shell
+npm run dev
+```
+
-Go to `localhost:5173`, and huzzah 🎉 You've got a fully functional todo list running!
+Go to `http://localhost:5173`, and huzzah 🎉 You've got a fully functional todo list running!

Also applies to: 194-194

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/www/pages/docs/start-svelte.md` around lines 18 - 33, The docs omit
changing into the newly created app and starting the dev server: after the `npx
sv create my-app` step add an instruction to run `cd my-app` so subsequent `npm
i `@instantdb/svelte`` and `npx instant-cli init` run in the app folder, then add
a step to start SvelteKit (e.g., `npm run dev`) before directing users to the
app; also update the URL to include the scheme (`http://localhost:5173`).
Reference the existing command strings (`npx sv create my-app`, `npm i
`@instantdb/svelte``, `npx instant-cli init`, `npm run dev`) when making the
edits.

@nezaj nezaj merged commit 7ff79f9 into main Mar 16, 2026
28 checks passed
@nezaj nezaj deleted the svelte-sdk-docs branch March 16, 2026 16:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants