Read-only global state
Cart badge
The smallest possible store consumer. Subscribes to a computed total and renders it.
Each panel header shows the source size of that component file (raw, gzipped, line count). Source-only — framework runtime (React ~45 KB, Vue ~35 KB, Svelte ~5 KB gzipped) is shared across every island and isn't included in these numbers.
React 291 B gzip · 13 lines
CartBadgeReact.tsx How this works
useStore on the computed total. The component re-renders only when cartCount changes, not on every cart mutation that doesn't affect the sum.
import { useStore } from '@nanostores/react';
import { cartCount } from '../stores/cart';
export default function CartBadgeReact() {
const count = useStore(cartCount);
return (
<span className="inline-flex items-center gap-1.5 rounded-full bg-sky-100 px-3 py-1 text-sm font-medium text-sky-900">
<span className="text-xs uppercase tracking-wider text-sky-700">React</span>
<span className="tabular-nums">{count}</span>
</span>
);
} Vue 280 B gzip · 14 lines
CartBadgeVue.vue How this works
useStore returns a ref. Templates auto-unwrap refs, so {{ count }} just works without .value.
<script setup lang="ts">
import { useStore } from '@nanostores/vue';
import { cartCount } from '../stores/cart';
const count = useStore(cartCount);
</script>
<template>
<span class="inline-flex items-center gap-1.5 rounded-full bg-emerald-100 px-3 py-1 text-sm font-medium text-emerald-900">
<span class="text-xs uppercase tracking-wider text-emerald-700">Vue</span>
<span class="tabular-nums">{{ count }}</span>
</span>
</template> Svelte 233 B gzip · 9 lines
CartBadgeSvelte.svelte How this works
$cartCount auto-subscription. Three lines of script, zero subscription boilerplate.
<script lang="ts">
import { cartCount } from '../stores/cart';
</script>
<span class="inline-flex items-center gap-1.5 rounded-full bg-orange-100 px-3 py-1 text-sm font-medium text-orange-900">
<span class="text-xs uppercase tracking-wider text-orange-700">Svelte</span>
<span class="tabular-nums">{$cartCount}</span>
</span>