Valyrian.js

One application. Run it in the browser and Node.js.

Build components, state, routing, data and forms in one application. The browser mounts it, and Node.js imports the same application to render HTML for SSR.

See Valyrian.js in action

Create a component, connect a Pulse, and watch Valyrian.js update the part of the interface that depends on its state.

tsx
import { mount } from "valyrian.js";
import { createPulse } from "valyrian.js/pulses";

const [count, setCount] = createPulse(0);

const Counter = () => (
  <button
    aria-label={`Increase count. Current count: ${count()}`}
    onclick={() => setCount((current) => current + 1)}
  >
    Count:{" "}
    <output aria-atomic="true" aria-live="polite">
      {count()}
    </output>
  </button>
);

mount("#counter-demo", Counter);
Reactive counter

Explore Valyrian.js by capability

Add only the capabilities the application needs. Its components, routes and state logic remain reusable in the browser and Node.js.

  • Views and lifecycle

    Build vnodes, mount an application and respond to lifecycle changes.

  • Routing

    Resolve routes, redirect navigation and run route hooks.

  • Data and async work

    Send requests, represent pending work and coordinate queries and mutations.

  • State and forms

    Store values, run effects and validate form data.

  • Network, offline and PWA

    Observe connectivity, retain queued operations and manage service worker registration.

  • Browser and Node.js

    Import the browser application into Node.js, render it per request, isolate its server state and transform the resulting HTML.

Explore all guides

Why Valyrian

See how the same Valyrian.js application runs in the browser and Node.js with shared components, routes, state and application modules. Start with the overview or follow the path for the framework you already use.

Discover why Valyrian.js

Build the next screen. Keep growing from there.

Follow the guided Taskboard or explore the runtime by capability.