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 →$ bunx create-pyreon-app↗ docs

Synthetic-benchmark parity with Solid. Real-app head-to-head: we haven't run it, and we won't claim it until we do.

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 · js framework benchmark (chromium / playwright)

The measured numbers. Read them as data.

Wall-clock milliseconds on the standard js-framework-benchmark 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
Pyreon9.19.10.8093.9
Solid9.910.04.60114.6
Vue 310.210.21.60.7109.3
React 1911.011.01.10.3220.1

Source: CLAUDE.md "Benchmark Results". run yours · methodology in the repo.

METHOD

Standard js-framework-benchmark suite, Chromium via Playwright, wall-clock ms — same machine, same run. Re-run it yourself; the config is in the repo.

SCOPE

We report our own measured numbers and synthetic-benchmark parity with Solid. Real-app head-to-head isn't run yet — we won't claim it until it is. 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

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

Everything you'd otherwise stitch together yourself. Every package is signal-aware, type-safe, and tree-shakeable.

core8
@pyreon/reactivity · @pyreon/core · @pyreon/compiler · @pyreon/runtime-dom · @pyreon/runtime-server · @pyreon/router · @pyreon/head · @pyreon/server
fundamentals22
@pyreon/store · @pyreon/form · @pyreon/query · @pyreon/i18n · @pyreon/storage · @pyreon/hooks · @pyreon/machine · @pyreon/flow · @pyreon/rx · @pyreon/+13 more
tools10
@pyreon/cli · @pyreon/lint · @pyreon/mcp · @pyreon/vite-plugin · @pyreon/typescript · @pyreon/storybook · @pyreon/react/preact/vue/solid-compat
ui-system11
@pyreon/ui-core · @pyreon/styler · @pyreon/unistyle · @pyreon/elements · @pyreon/attrs · @pyreon/rocketstyle · @pyreon/coolgrid · @pyreon/kinetic · @pyreon/+3 more
zero4
@pyreon/zero · @pyreon/zero-cli · @pyreon/create-zero · @pyreon/meta
total · 62 packages · 5 categories · all tree-shakeable