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.

$ 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 between inputs and server state.

adowire:submit

Handle form submissions server-side with validation.

adowire:loading

Show spinners and disable buttons during requests.

adowire:poll

Auto-refresh on an interval. Real-time without WebSockets.

adowire:stream

Server-Sent Events streaming. Word-by-word 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.

mount() — First request only
boot() — Every request
hydrate() — Subsequent requests
updating() / updated() — Property changes
rendering() / rendered() — Template output
dehydrate() — End of every request

Decorators

Configure with metadata

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

import { WireComponent,
  Title, Layout } from 'adowire'

@Title('Contact Form')
@Layout('layouts/app')
export default class Contact
  extends WireComponent {

  name = ''
  email = ''
  message = ''

  submit() {
    // Validate, save, redirect
  }
}

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

Ready to build?

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

npm install coming-soon