signal-based · full-stack · ai-native
Reactivity that knows
exactly where to fire.
Fine-grained signal tracking — no virtual DOM, no diffing, no wasted work. When a signal changes, only the nodes that read it run again. Measured, not marketed — honest about the trade-offs.
Synthetic row-list benchmark: ahead of Solid on most ops, behind it on deep-tree mount. Author-judged — no independent run yet.
// counter.tsx const count = signal(0) setInterval(() => count.update(n => n + 1), 2600) <span>{count()}</span>
The wrapping component, the layout, the page — never re-render. Only the digit node is updated.
The measured numbers. Read them as data.
Wall-clock milliseconds on a krausest-style row-list suite (Chromium via Playwright, lower = faster). These are synthetic workloads — every framework here optimizes for different real-world shapes. It's a data point, not a verdict.
| framework | create 1k | replace 1k | update | select | create 10k |
|---|---|---|---|---|---|
| ●Pyreon | 8.83 | 8.64 | 0.645 | 0.015 | 88.31 |
| Octane | 9.27 | 8.95 | 0.675 | 0.025 | 94.94 |
| Solid | 9.47 | 9.30 | 1.30 | 0.025 | 93.23 |
| Vue 3 | 9.30 | 9.21 | 0.990 | 0.305 | 97.10 |
| React 19 | 11.25 | 10.53 | 0.855 | 0.185 | 216.97 |
Source: BENCHMARKS.md §1 (2026-09-23 run). Select is below the clock resolution — no verdict. run yours · methodology in the repo.
krausest-style row-list suite, Chromium via Playwright, wall-clock ms — same machine, same run, 100 pooled samples. Re-run it yourself; the config is in the repo.
We report our own measured numbers, losses included: Solid mounts a deep component tree 1.29× faster, and Octane ties us on partial update and swap. No independent run exists yet. Every framework here is good work by good people.
Signal reads in. Targeted re-runs out.
Four mechanisms, named the way the source names them — the words your profiler will print at 3am.
React, Preact, Vue 3, SolidJS, or Svelte. Pick your dialect.
Compatibility layers compile each API down to Pyreon signals. Migrate one component at a time, or just write what your team already speaks.
// useState → signal const [c, setC] = useState(0) useEffect(fn, [c])
// mirrors @preact/signals const c = signal(0) effect(() => log(c.value))
// composition · ref/computed const c = ref(0) const d = computed(() => c.value*2)
// createSignal / createEffect const [c, setC] = createSignal(0) createEffect(() => log(c()))
SSR · SSG · ISR · islands · SPA. One config.
Zero is the meta-framework atop Pyreon: file-system routing, API routes, server actions, every render strategy in one config.
zero({ mode: 'ssr', ssr: { mode: 'stream' }, routeRules: { '/': { renderMode: 'ssg' }, '/blog/**': { renderMode: 'isr' }, '/app/**': { renderMode: 'spa' }, }, isr: { revalidate: 60 }, ai: { name, description, origin }, })
First-class MCP + llms.txt.
Zero can generate an llms.txt for your app (zero({ ai })), and the scaffold can wire the @pyreon/mcp server, so agents query Pyreon's real API surface instead of guessing it.
# Pyreon > Signal-based UI framework. Fine-grained, no VDOM. ## Core API - signal: create a tracked reactive value - computed: pure function of other signals - effect: side effect, auto-tracked - untrack: read without subscribing
→ get_api({ package: "reactivity", symbol: "createStore" }) ← signature, example, notes, mistakes — generated from the package manifest, not a guess.
77 packages. Routing, forms, data, devtools — already there.
Routing, state, styling, tooling, and native targets share the same reactive foundation.