Alpha Release · Open Source · AdonisJS v7

Reactive components
for AdonisJS

Build modern interactive applications with TypeScript classes and Edge templates. No client-side JavaScript required. No REST APIs. No GraphQL. Just your server code.

Get Started
$ npm install adowire
counter.ts
import { WireComponent } from 'adowire'

export default class Counter extends WireComponent {
  count = 0

  increment() {
    this.count++
  }

  decrement() {
    this.count--
  }
}
counter.edge
<div>
  <h1>{{ count }}</h1>

  <button adowire:click="increment">
    +
  </button>

  <button adowire:click="decrement">
    
  </button>
</div>

That's it. No fetch calls. No REST APIs. No state management libraries. It just works.

Features

Everything you need, nothing you don't

Write TypeScript on the server, HTML in your templates. Adowire handles the rest.

Zero Client-Side JS

Build fully interactive apps without writing a single line of JavaScript. Your TypeScript class is the component.

Real-time DOM Morphing

Server renders HTML, the client diffs and patches only what changed. Powered by morphdom for surgical updates.

HMAC-Signed Snapshots

Every component snapshot is signed with HMAC-SHA256. Tampered state is rejected. No client can forge server data.

TypeScript-First

Decorators, full type safety, IDE autocompletion. @Title, @Layout, @Validate — it's all typed.

SSE Streaming

Stream content word-by-word from the server via Server-Sent Events. Perfect for AI/LLM output, progress updates, and real-time feeds.

VineJS Validation

Uses AdonisJS's native VineJS validator — 5–10× faster than Zod. Zero extra dependencies. Errors flow to your template automatically.

How it works

Server renders. Client morphs.

Every interaction follows the same simple cycle — no client state to manage.

1

User Interacts

Click, type, submit — any adowire:* directive fires

2

AJAX to Server

Snapshot + action sent via POST. No boilerplate fetch calls

3

Server Executes

Your TypeScript method runs, state updates, Edge re-renders the HTML

4

DOM Morphs

Only changed nodes are patched. No full re-render. Feels instant

start/routes.ts
import router from '@adonisjs/core/services/router'

// One line. Component IS the page.
router.adowire('/counter', 'counter')
router.adowire('/dashboard', 'dashboard')
router.adowire('/settings', 'settings')

// No controller. No view file. No middleware wiring.
// The component handles everything.

Directives

One attribute. Full behavior.

HTML attributes that wire your template to server-side logic. No JavaScript glue code.

adowire:click

Call server methods on click. Pass arguments inline.

adowire:model

Two-way binding with .live, .blur, .debounce, .throttle modifiers.

adowire:submit

Handle form submissions server-side with validation.

adowire:loading

Show/hide elements, add classes, set attributes during requests.

adowire:poll

Auto-refresh on an interval. Supports .visible modifier.

adowire:dirty

Show unsaved changes. Add classes when local state differs from server.

adowire:show

Toggle visibility with a JS expression. No server roundtrip needed.

adowire:cloak

Hide elements until initialized. Prevents flash of unstyled content.

adowire:stream

SSE streaming with append or .replace modes. Perfect for AI output.

adowire:key

Stable identity for list items. Efficient DOM diffing.

adowire:ignore

Protect client-only DOM from server re-renders.

Lifecycle

Hooks for every stage

Full control over your component's lifecycle — from first mount to every subsequent round-trip. Plus property-specific hooks like updatingSearch().

mount() — First request only
boot() — Every request, before hydration
hydrate() — Subsequent AJAX requests
updating() / updated() — Property changes
rendering() / rendered() — Template output
dehydrate() — End of every request
exception() — Handle errors gracefully

Decorators

5 powerful decorators

TypeScript decorators that declare behavior at the class level — no configuration files needed.

@Computed() — Memoized getter, accessible in templates
@Locked() — Prevent client-side mutation
@Validate(rule) — VineJS validation on properties
@Title(text) — Set browser title for page components
@Layout(name) — Wrap in a layout template

Magic Actions

Built-in superpowers

Every component ships with 10 magic methods for common interactions — no boilerplate needed.

$refresh()

Re-render without calling any action

$set(prop, value)

Set a public property from the server

$toggle(prop)

Toggle a boolean property

$redirect(url)

Redirect the browser after the response

$dispatch(event)

Dispatch a browser event with params

$stream(name, content)

Stream content to a target element via SSE

$download(name, url)

Trigger a file download from the server

js(expression)

Execute a JavaScript expression on the client

skipRender()

Skip re-rendering for the current request

Plus state helpers: fill(), reset(), pull(), only(), all()

CLI

7 Ace commands included

Scaffold, list, move, delete, and configure components from the command line.

make:adowire

Scaffold class + view. Supports --page, --class, --view flags.

adowire:list

List all registered components. Supports JSON output.

adowire:layout

Generate a default Adowire layout template.

adowire:move

Rename/move component files and update class names.

adowire:delete

Delete component class and view files with confirmation.

adowire:stubs

Publish stub templates for customization.

configure

One-time setup: config, provider, directories.

+ more coming

Why Adowire

The traditional way vs. the Adowire way

Without Adowire
  • Write a REST API endpoint
  • Write fetch() calls in the frontend
  • Manage loading states in JavaScript
  • Parse JSON and update the DOM manually
  • Sync validation errors between server and client
  • Maintain two sources of truth for state
With Adowire
  • Write a TypeScript class with public properties
  • Add adowire:click to a button. Done.
  • Loading states are one attribute away
  • DOM updates automatically via morphdom
  • Errors flow to @error blocks in your template
  • Server is the single source of truth. Always.

Built on

Best-in-class foundations

AdonisJS v7
Edge.js v6
TypeScript
Alpine.js
VineJS
🔀 morphdom

Roadmap

What's shipped & what's next

Shipped in Alpha
  • Core reactive engine — snapshot, hydration, dehydration, DOM morphing
  • Public properties & two-way model binding
  • Server-side actions callable from templates
  • Full lifecycle hook system with property-specific hooks
  • Real-time SSE streaming ($stream)
  • 5 decorators — @Computed, @Locked, @Validate, @Title, @Layout
  • 11 client-side directives
  • HTML-style component tags (<adowire:counter />)
  • Page components with router.adowire()
  • Alpine.js $wire bridge
  • 7 Ace CLI commands
  • VineJS validation & HMAC snapshot security
🚧
Coming Soon
  • WireForm — dedicated form component with file uploads
  • Events & Nesting$dispatch, @On decorator, parent/child communication
  • Islands & Lazy Loading — partial hydration, @Lazy decorator
  • SPA Navigationadowire:navigate for seamless page transitions
  • File Uploads — direct upload support with progress tracking
  • Pagination — automatic cursor/offset pagination helpers
  • URL State@Url decorator for query string binding
  • Teleport — render output into a different DOM location
  • Testing UtilitiesWireTest harness for Japa

Ready to build?

Stop writing boilerplate. Start shipping features. Adowire makes AdonisJS apps feel like magic.

Star on GitHub
npm install adowire