pyreon

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.

Get started →$ npm create @pyreon/zero@latest my-app↗ docs

Synthetic row-list benchmark: ahead of Solid on most ops, behind it on deep-tree mount. Author-judged — no independent run yet.

LIVE · only the digit re-rendersfiring
$count42
// counter.tsx
const $count = signal(0)
setInterval(() => $count.set($count+1), 2600)
<Counter>{$count}</Counter>

The wrapping component, the layout, the page — never re-render. Only the digit node is updated.

01 · benchmark · krausest-style row list (chromium / playwright)

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.

frameworkcreate 1kreplace 1kupdateselectcreate 10k
●Pyreon8.838.640.6450.01588.31
Octane9.278.950.6750.02594.94
Solid9.479.301.300.02593.23
Vue 39.309.210.9900.30597.10
React 1911.2510.530.8550.185216.97

Source: BENCHMARKS.md §1 (2026-09-23 run). Select is below the clock resolution — no verdict. run yours · methodology in the repo.

METHOD

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.

SCOPE

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.

02 · mechanism · how it works

Signal reads in. Targeted re-runs out.

Four mechanisms, named the way the source names them — the words your profiler will print at 3am.

01~>
Value-level signal reads
Reading a signal inside an effect or template registers a dependency on that value. Writing notifies exactly those subscribers — never the component, never the tree.
02//
Compiled templates · _tpl / _bind
JSX compiles to static HTML templates plus per-signal bindings. Static parts hoist once at module load; only the bindings ever re-run.
03[]
Zero-alloc mount
No virtual nodes, no diff array, no per-render allocation. Mount walks the template once and wires bindings straight to the DOM.
04>>
Streaming SSR + islands
Server renders to a stream with Suspense + async components. Islands hydrate independently — interactive before the tree settles.
03 · compat · use the api you know

React, Preact, Vue 3, or SolidJS. 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.

React 18+↻ → signals
// useState → signal
const [c, setC] = useState(0)
useEffect(fn, [c])
Preact 10↻ → signals
// mirrors @preact/signals
const c = signal(0)
effect(() => log(c.value))
Vue 3.4↻ → signals
// composition · ref/computed
const c = ref(0)
const d = computed(() => c.value*2)
SolidJS 1.9↻ → signals
// createSignal / createEffect
const [c, setC] = createSignal(0)
createEffect(() => log(c()))
04 · zero · full-stack meta-framework

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.config.ts
export default defineConfig({
  routes: {
    '/':         { render: 'ssg' },
    '/blog/:id': { render: 'isr', revalidate: 60 },
    '/feed':     { render: 'ssr-stream' },
    '/app/*':    { render: 'islands' },
  },
  ai: { mcp: true, llmsTxt: true },
})
RENDER MODES
SSGPre-rendered at build. Static HTML + signal-hydration islands.
ISRCached, revalidated on demand. CDN-friendly.
SSR-STREAMServer-rendered with streaming Suspense + async components.
ISLANDSMostly static; interactive parts hydrate independently.
SPAClient-only. Same component model, no server.
05 · ai · for agents that read source, not guess it

First-class MCP + llms.txt.

Every Pyreon project ships a generated llms.txt manifest and an MCP server exposing typed tools. Agents read your actual source — no prompt scaffolding, no scraping.

llms.txt · auto-generated● in sync · CI-gated
# 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
MCP tool call · from your editor's agenttyped tools
→ get_api({ symbol: "createStore" })
← signature, example, mistakes[],
  seeAlso, addedIn — straight from the
  package manifest, not a guess.
06 · ecosystem · counted, not exclaimed

76 packages. Routing, forms, data, devtools — already there.

Routing, state, styling, tooling, and native targets share the same reactive foundation.

core10
@pyreon/compiler · @pyreon/core · @pyreon/head · @pyreon/primitives · @pyreon/reactivity · @pyreon/router · @pyreon/runtime-dom · @pyreon/runtime-server · 2 more
fundamentals27
@pyreon/a11y · @pyreon/charts · @pyreon/code · @pyreon/dnd · @pyreon/document · @pyreon/feature · @pyreon/flow · @pyreon/form · 19 more
native6
@pyreon/native-cli · @pyreon/native-compiler · @pyreon/native-router-kotlin · @pyreon/native-router-swift · @pyreon/native-runtime-kotlin · @pyreon/native-runtime-swift
tools16
@pyreon/atlas · @pyreon/cli · @pyreon/config · @pyreon/lathe · @pyreon/lint · @pyreon/loom · @pyreon/mcp · @pyreon/preact-compat · 8 more
ui-system11
@pyreon/attrs · @pyreon/connector-document · @pyreon/coolgrid · @pyreon/document-primitives · @pyreon/elements · @pyreon/kinetic · @pyreon/kinetic-presets · @pyreon/rocketstyle · 3 more
zero6
@pyreon/create-multiplatform · @pyreon/create-zero · @pyreon/meta · @pyreon/zero · @pyreon/zero-cli · @pyreon/zero-content
total · 76 packages · 6 categories