Overview

Understand Regor’s reactive state, expressive templates, and direct DOM updates.

Regor is a reactive UI library designed for engineers who want:

  1. Direct control over runtime behavior.
  2. A powerful template/directive model.
  3. TypeScript-friendly reactivity primitives.
  4. Freedom to optimize with plain JavaScript and DOM when needed.

Regor is intentionally practical. It does not force one rigid rendering architecture for every use case.

Reactive stateExpressive templatesDirect DOM updates

Choose your mount boundary, connect state to markup, and compose the interactions your interface needs.

Architecture Positioning

Regor is Vue-inspired in directive syntax, but different by architecture.

  1. Regor does not rely on a Virtual DOM layer.
  2. Regor can bind existing server-rendered/static markup in place.
  3. Regor supports runtime composition and reentrance across already-mounted regions.
  4. Regor keeps optimization escape hatches close to plain DOM and JavaScript.
01 / State

Refs and computed

Store writable values and derive the values that depend on them.

02 / Template

Expressions and directives

Declare how state appears in HTML and SVG, and how events update it.

03 / View

The actual DOM

Regor updates the bound nodes as their reactive dependencies change.

Why Teams Choose Regor

1. Runtime flexibility without lock-in

Regor can bind existing markup and progressively enhance real pages. You can adopt it incrementally instead of rewriting everything.

2. Reactivity that stays explicit

You get ref, sref, computed, watchEffect, observe, and batching primitives. State flows are explicit and composable.

Control APIs like pause, resume, and entangle help you shape update behavior intentionally in complex flows.

3. Directive model with real depth

Regor supports rich directive workflows:

  1. Conditional rendering (r-if, r-else-if, r-else, r-show).
  2. List rendering (r-for with keys, table use cases, nested structures).
  3. Attribute/property/class/style/event binding (r-bind, .prop, .camel, :class, :style, @event).
  4. Form binding (r-model) and dynamic components (:is, :context).

4. Excellent fit for mixed environments

Regor works well when part of your DOM is owned by other systems, or when performance-critical sections need custom handling.

5. TypeScript without framework-only indirection

Regor uses plain TypeScript code paths for app and component contexts (createApp<T>, ComponentHead<TProps>, interfaces/classes). You keep normal TS ergonomics without relying on custom file format compilers.

See the flow in action

One state model, a connected viewLive Regor
YOUR TEAM / MONTHLY $100.00
Subtotal
$100.00
Discount
$0.00

Two inputs. Three computed values. One connected view.

import { batch, computed, html, ref } from 'regor'

export function createQuote(interactive = false) {
  const quantity = ref(4)
  const unitPrice = ref(25)
  const discounted = ref(false)
  const subtotal = computed(() => quantity() * unitPrice())
  const savings = computed(() => (discounted() ? subtotal() * 0.1 : 0))
  const total = computed(() => subtotal() - savings())
  const money = (value: number) => `$${value.toFixed(2)}`
  const reset = () =>
    batch(() => {
      quantity(4)
      unitPrice(25)
      discounted(false)
    })
  return {
    interactive,
    quantity,
    unitPrice,
    discounted,
    subtotal,
    savings,
    total,
    money,
    reset,
  }
}

export const quoteTemplate = html` <div class="guide-demo guide-demo--split">
  <div class="guide-controls">
    <label for="quote-quantity">Seats <strong>{{ quantity }}</strong></label>
    <input
      id="quote-quantity"
      type="range"
      min="1"
      max="20"
      r-model.number="quantity"
      :value="quantity"
      :disabled="!interactive"
    />
    <label for="quote-price"
      >Price per seat <strong>{{ money(unitPrice) }}</strong></label
    >
    <input
      id="quote-price"
      type="range"
      min="10"
      max="100"
      step="5"
      r-model.number="unitPrice"
      :value="unitPrice"
      :disabled="!interactive"
    />
    <label class="guide-check"
      ><input type="checkbox" r-model="discounted" :disabled="!interactive" />
      Apply a 10% team discount</label
    >
    <button type="button" @click="reset" :disabled="!interactive">
      Reset quote
    </button>
  </div>
  <div class="guide-readout">
    <span class="guide-kicker">YOUR TEAM / MONTHLY</span>
    <output class="guide-total" aria-live="polite">{{ money(total) }}</output>
    <dl>
      <div>
        <dt>Subtotal</dt>
        <dd>{{ money(subtotal) }}</dd>
      </div>
      <div>
        <dt>Discount</dt>
        <dd>{{ money(savings) }}</dd>
      </div>
    </dl>
    <p>Two inputs. Three computed values. One connected view.</p>
  </div>
</div>`
import { createApp, useScope } from 'regor'
import { createQuote, quoteTemplate } from './quote'
import { createServices, servicesTemplate } from './services'
import { createProfile, profileTemplate } from './profile'
import { createLifecycle, lifecycleTemplate } from './lifecycle'

// Each guide mounts only its own island. Everything outside the root stays static.
function mount<T extends object>(
  id: string,
  create: (interactive: boolean) => T,
  template: string,
) {
  const element = document.getElementById(id)
  if (element)
    createApp(
      useScope(() => create(true)),
      { element, template },
    )
}

mount('guide-quote', createQuote, quoteTemplate)
mount('guide-services', createServices, servicesTemplate)
mount('guide-profile', createProfile, profileTemplate)
mount('guide-lifecycle', createLifecycle, lifecycleTemplate)

Inputs update refs. Computed values derive the quote. Template bindings update the displayed totals. Explore reactivity and templates to follow the same example in detail.

Core Philosophy

Regor’s philosophy is:

  1. Keep defaults productive.
  2. Keep escape hatches available.
  3. Keep internals understandable.
  4. Keep control in developers’ hands.

What Regor Is Not Trying To Be

Regor is not built around artificial constraints to optimize only one benchmark shape. It is built for real product constraints where integration flexibility matters.

If your app needs:

  1. Existing-markup binding.
  2. Runtime composition.
  3. Context flexibility.
  4. Controlled optimization paths.

Regor is a strong fit.

Regor vs Vue (Practical Lens)

  1. Vue is a strong default for framework-owned SPA architecture.
  2. Regor is a strong default for progressive enhancement and static-first plus dynamic-island architectures.
  3. Vue commonly centers build tooling for peak DX/perf in SPA workflows.
  4. Regor keeps build-less and CSP-constrained runtime options first-class.
  5. Both are capable; pick based on rendering ownership and deployment constraints.

Practical Tradeoffs

Start with the DOM boundary

Decide which region Regor owns, then measure the interactions that matter there. The mounting and performance guides explore these choices.

Regor favors flexibility and control. In very binding-dense paths, runtime cost can grow with total DOM + binding volume. This is normal for highly dynamic runtime systems.

The upside is that Regor keeps optimization options open:

  1. Reduce binding density where it matters.
  2. Use stable keying and list strategies.
  3. Drop to targeted custom logic in hot sections.
  4. Keep the rest of the app high-level and maintainable.

Getting Started

Install Regor and mount your first view.

Explore getting started

Guide

Explore state, templates, components, and cleanup.

Explore guide

Directives

Try every directive with a focused live preview.

Explore directives

API Reference

Look up signatures and practical usage examples.

Explore api reference

Performance Guide

Measure, profile, and verify changes to your interface.

Explore performance guide