intentx-svelte Svelte Themes

Intentx Svelte

Intent-first headless state management for Svelte powered by intentx-runtime.

πŸ”Άβš‘ intentx-svelte

LIVE EXAMPLE


intentx-svelte is an architectural layer for Svelte. It enforces a strict separation between:

  • Business Logic (deterministic runtime)
  • UI Rendering (Svelte reactivity)

It is not a store library.

It is a bridge between deterministic logic and Svelte’s reactive UI.


✨ Why intentx-svelte?

Use it when your UI starts to feel like business logic.

βœ… Complex async workflows
βœ… Intent-based architecture
βœ… Microfrontend communication
βœ… Testable business logic
βœ… Cross-runtime reuse (Node / SSR / workers)

Avoid it when:

❌ You only need $: reactive statements
❌ Your state is purely local UI
❌ You want reducer-style state


πŸ€” Why not just Svelte stores?

Svelte stores are excellent for reactivity.

But they do not provide:

  • Intent routing
  • Cross-logic orchestration
  • Deterministic runtime snapshotting
  • Cross-framework runtime reuse
  • Explicit business boundaries

Stores solve reactivity.

intentx solves orchestration.


🧠 Mental Model

UI / HTTP / Queue / Cron
        ↓
  intentx-runtime
        ↓
Fine-grained reactivity updates UI

Core principle:

Intent is the only mutation entry point. The runtime owns behavior. UI only triggers intent.


πŸ“¦ Installation

npm install intentx-svelte

🧩 Core Logic (Framework-Agnostic)

Define logic outside components:

import { createLogic } from "intentx-svelte"

export const counterLogic = createLogic({
  name: "counter",

  state: {
    count: 0
  },

  computed: {
    double: ({ state }) => state.count * 2
  },

  intents: (bus) => {
    bus.on("inc", ({ setState }) => {
      setState((s) => {
        s.count++;
      });
    });
  },

  actions: {
    inc({ emit }) {
      return () => emit("inc");
    },
  },
})

Logic is:

  • Serializable
  • Deterministic
  • Testable without UI
  • Reusable across runtimes

πŸš€ Usage

// counter.ts
import { useLogic } from "intentx-svelte"
import { counterLogic } from "./counter.logic"

export const counter = useLogic(counterLogic)
<script>
  import { counter } from "./counter"
</script>

<button on:click={counter.actions.inc}>
  {$counter.store.count}
</button>

<p>Double: {$counter.store.double}</p>

No wrapper components.
No magic subscriptions.

UI only consumes state.


πŸ“¦ What useLogic Returns

const counter = useLogic(counterLogic)
{
  runtime,   // βš™ LogicRuntime instance
  store,     // πŸ—‚ merged state + computed (Svelte store)
  state,     // πŸͺž alias of store
  actions,   // 🎯 logic actions
  emit       // πŸ“‘ emit intent
}

πŸ”₯ Important

  • store is readonly
  • Mutations must go through actions
  • Svelte reactivity remains untouched

πŸ“‘ Multiple Logic (Bus)

Each logic instance is isolated by default.

To enable communication between runtimes, you can share an Intent Bus.


import { useLogic } from "intentx-react"

// βœ… Same scope β†’ shared bus
useLogic(logic, {
  scope: "dashboard",
  sharedBus: true
})

// ❌ Different scope β†’ different bus
useLogic(logic, {
  scope: "settings",
  sharedBus: true
})

How it works

When sharedBus: true is enabled:

  • A singleton bus is created per scope

  • Same scope β†’ same bus instance

  • Different scope β†’ different bus

  • No global leakage

If no scope is provided:

useLogic(logic, {
  sharedBus: true
})

β†’ uses a default global scope bus.


2️⃣ Custom Bus (Advanced / Cross-Scope)

import { createIntentBus } from "intentx-svelte"

const bus = createIntentBus()

useLogic(logicA, { bus })
useLogic(logicB, { bus })

Behavior

  • Full cross-scope communication
  • Manual orchestration control
  • Suitable for:
    • Microfrontend
    • App-wide coordination
    • Complex workflow systems

πŸ” Behavior Comparison

Mode Isolation Scope-aware Cross-scope Recommended
Default (no options) βœ… Full ❌ ❌ Small/local logic
sharedBus: true ❌ Per scope βœ… ❌ Modular apps
Custom bus ❌ Manual ❌ βœ… Advanced architecture

🎯 Recommendation

βœ… Use sharedBus for modular communication.
βœ… Use custom bus for orchestration layer.
🚫 Avoid global single bus without scope in large apps.


🧩 Context API

Provide logic via Svelte context:

import { setLogicContext, useLogicContext } from "intentx-svelte"
import { counterLogic } from "./counter.logic"

Provider:

<script>
  setLogicContext("counter", counterLogic)
</script>

<slot />

Consume:

const counter = useLogicContext("counter")

🌍 SSR

  • Runtime created during SSR
  • Deterministic snapshot
  • Hydration-safe
  • No fake empty stores
  • Server snapshot serializable
  • Client rehydrates from deterministic state

Works with:

  • SvelteKit
  • Node SSR
  • Edge runtimes

πŸ§ͺ Testability Upgrade

No Svelte required:

const runtime = counterLogic.create()

runtime.actions.inc()
expect(runtime.state.count).toBe(1)

No DOM.
No component mounting.
Pure deterministic logic.

That is the real split.


πŸ” Comparison

This is not about β€œbetter”. It’s about solving different layers of the architecture.

Problem / Responsibility Svelte Only intentx-svelte
Local UI state βœ… Perfect ❌ Overkill
Simple derived values βœ… $: ❌ Unnecessary
Complex async workflows ⚠️ Manual βœ… Structured
Cross-component orchestration ⚠️ Implicit βœ… Explicit
Cross-runtime reuse (Node/SSR) ❌ βœ…
Deterministic snapshotting ❌ βœ…
Intent-based communication ❌ βœ…
Microfrontend signaling ❌ βœ…

Svelte handles reactivity.

intentx handles orchestration.


🎯 Philosophy

Rendering is reactive.

Business logic should be deterministic.

intentx-svelte ensures they never mix.


πŸ“œ License

MIT

Top categories

Loading Svelte Themes