Frequently Asked Questions
General
Does Anchor replace Svelte?
No. Anchor enhances Svelte by adding direct mutation support, schema validation, and powerful state management patterns while working seamlessly with Svelte's reactivity system.
Why use Anchor when Svelte 5 runes already support direct mutation?
Svelte 5 runes ($state(), $derived()) are great for reactive state! Anchor complements them by adding:
What Anchor Adds:
- Schema Validation: Runtime type checking with Zod - enforce data integrity beyond TypeScript
- Async State:
query(),fetchState(),streamState()with automatic status tracking - Form Handling:
form()with automatic validation and error tracking - Immutability Patterns:
immutable()+writable()for controlled shared state access - Persistence:
persistent(),session()for localStorage/sessionStorage sync - Portability: Business logic works across React, SolidJS, Svelte, vanilla JS (
@anchorlib/core)
When to Use What:
- Runes: Simple reactive state, UI-focused logic
- Anchor: Validation, async operations, forms, portable business logic, advanced patterns
Think of Anchor as a state management library that adds features on top of runes, not a replacement.
Performance
Does Anchor add overhead to Svelte?
Minimal. Anchor implements its own fine-grained reactivity system via @anchorlib/core, then integrates with Svelte components. The proxy layer adds negligible overhead while providing significant developer experience improvements.
How does Fine-Grained Reactivity work?
Anchor implements its own fine-grained reactivity system. When you mutate state.count++, only components reading state.count update—nothing else re-runs. This gives you the same fine-grained performance as Svelte stores.
When should I use Anchor vs runes vs stores?
- Runes (
$state()): Simple reactive state with direct mutation - Anchor
mutable(): When you need schema validation, immutability patterns, or portable business logic - Anchor
form(): Forms with validation - Anchor
query(): Async operations with status tracking - Svelte stores: Legacy pattern for Svelte 4 compatibility or when you need store contracts
Note: Both runes and Anchor support direct mutations. Choose Anchor when you need validation, async handling, or portability.
Business & Impact
Is it hard to learn?
No. If you know JavaScript objects and Svelte 5 runes, you already know Anchor. The API is similar to runes but with added features like schema validation and async state management.
Does Anchor reduce development costs?
Yes. By eliminating boilerplate for forms, async state, and providing direct mutations, teams ship features faster. Schema validation catches bugs at runtime before they reach production.
How does it affect AI coding?
Anchor is AI-friendly. Its declarative patterns with schema validation and automatic async state management reduce boilerplate, making it ideal for AI-assisted development.
Is maintenance cheaper?
Yes. Schema validation catches bugs at runtime, and immutability patterns enforce clear contracts for shared state. This reduces runtime bugs and makes code easier to maintain.
Comparison
How is this different from Svelte stores?
Svelte stores require immutable updates: $store = newValue or store.update(v => newValue). Anchor uses direct mutations on proxies: state.count++. Both provide fine-grained reactivity, but with different APIs.
Is this like MobX?
Similar concept (observable proxies with automatic tracking). Both use proxies to intercept mutations and trigger reactivity. Anchor's @anchorlib/core implements its own tracking mechanism, then @anchorlib/svelte integrates it with Svelte's component system.
Can I use Anchor with Svelte stores?
Yes! Anchor state (mutable(), immutable()) and Svelte stores work side-by-side. Use $: reactive statements for stores and effect() for Anchor state. They're complementary, not exclusive.
Component Architecture
Do I need special component wrappers?
No. Anchor works with standard Svelte components. No HOCs, no wrappers needed.
Can I use Svelte control flow?
Absolutely! Use {#if}, {#each}, {#await} as normal. Anchor state works seamlessly with all Svelte control flow directives.
Can I use Svelte lifecycle hooks?
Yes. onMount, onDestroy, and other Svelte lifecycle hooks work perfectly with Anchor state. Use them as you normally would.
State Management
Is mutable state safe?
Yes. Anchor uses immutable() + writable() for shared state, enforcing read-only public interfaces with controlled write access. This ensures unidirectional data flow.
Does it track nested properties?
Yes. mutable() tracks nested objects and arrays by default. Mutating state.user.name only updates components reading that specific property.
Can I validate my state?
Yes. Anchor supports Zod schemas for both mutable() and form(). Invalid data is rejected at runtime, ensuring type safety beyond TypeScript.
Reactivity System
How do effects work?
Anchor's effect() automatically tracks dependencies. Unlike Svelte's $: reactive statements, it only tracks Anchor state. For Svelte stores, use $: reactive statements instead.
Do I need dependency arrays?
No. Effects track dependencies automatically based on what you read during execution. No manual arrays, no stale closures.
How do I stop tracking?
Use untrack() to read data without subscribing to it. This is useful for reading configuration or performing side effects without creating dependencies.
What if I need a copy of the state?
Use snapshot() to create a non-reactive deep clone. This is useful for logging, serialization, or passing data to external APIs.
Forms & Validation
How do I handle forms?
Use form() with a Zod schema. It returns [state, errors] where state is mutable and errors updates automatically as you type. Use bind:value for two-way binding.
Can I validate on submit only?
Yes. Use schema.safeParse(state) in your submit handler. The form() helper validates on change by default, but you control when to check errors.
How do I show validation errors?
Use {#if errors.fieldName} to conditionally render error messages. Errors update automatically as the user types.
Async Operations
How do I handle async data?
Use query() for general async operations, fetchState() for HTTP requests, or streamState() for streaming responses. All include automatic status tracking.
Do I need to manage loading states manually?
No. query(), fetchState(), and streamState() all provide a status property ('idle' | 'pending' | 'success' | 'error') that updates automatically.
How do I cancel requests?
Async functions receive an AbortSignal parameter. Pass it to fetch() and Anchor handles cancellation automatically when a new request starts or the component unmounts.
Two-Way Binding
How do I do two-way binding?
Use Svelte's native bind:value directive with Anchor state. No special helpers needed—Svelte's binding works perfectly with Anchor's mutable state.
When should I use two-way binding?
For form inputs, use bind:value, bind:checked, etc. Svelte's binding directives work seamlessly with Anchor state, providing automatic two-way synchronization.
Can I bind to nested properties?
Yes. Use bind:value={state.user.name} to bind directly to nested properties. Anchor tracks the mutation and updates automatically.
Ecosystem
Does it work with SvelteKit?
Yes. Anchor state works in both client and server components. Just be careful with module-level state in SSR—use Svelte context for request-scoped state.
Can I use it with existing Svelte libraries?
Absolutely. Anchor is just state management—it works alongside any Svelte library. Use it with SvelteKit, Svelte Routing, or any other ecosystem tool.
Does it work with TypeScript?
Yes. Anchor is written in TypeScript with full type inference. Schemas provide runtime validation that complements TypeScript's compile-time checking.