Skip to content

Native-first · Frontend-only

A frontend framework you can own.

The browser is the platform. Mado is the convention.

Build public sites and live applications from one Web Component and page model. Mado keeps the browser visible: no backend runtime, no hydration protocol, no framework compiler, and no third-party runtime dependencies in core.

Pre-1.0 · actively dogfooded

A smaller abstraction

Use the platform. Add only the missing coordination.

Mado connects the browser primitives an application repeatedly needs. It does not replace the DOM, the History API, custom elements or your backend.

Visible platform

Templates create DOM. Attributes remain attributes. Events remain events. Browser knowledge keeps its value.

Bounded framework

Components, reactivity, routing, pages, data and forms share a lifecycle without growing into a backend platform.

Owned output

The release is HTML, CSS and JavaScript. The UI library copies editable source instead of adding a browser dependency.

The application model

Three contracts orient the whole application.

01

One component model

Standards-based custom elements, open Shadow DOM and fine-grained signals. The component you inspect is the component the browser runs.

component("project-card", () => html`…`)
02

One page model

A page owns its data, metadata and view. The same route can become useful HTML at release time and a live SPA after boot.

page({ static: true, head, view })
03

One release artifact

Public pages, the SPA shell, sitemap, canonical metadata and deploy files leave one command as ordinary static assets.

npm run release

Universal without a server runtime

Static where public. Live where personal.

Choose the delivery mode per route without changing component or page semantics.

Public document

Useful before JavaScript

mado release opens the real application in a browser and captures declared public routes with their head metadata.

  • Searchable route HTML
  • Canonical and social metadata
  • Sitemap generated from the route contract

Live application

Interactive after one atomic takeover

The router resumes the same page tree, then signals, forms and browser navigation behave like a normal SPA.

  • No second component model
  • No server hydration protocol
  • No backend coupled to the frontend framework

Proof of concept

This site is the proof.

Every public route on madojs.dev is written as a Mado page, captured by the Mado release pipeline, styled with copied Mado UI source and packaged for Cloudflare as static assets.

See what is verified
Create the same foundation
npm exec --yes --package @madojs/mado@latest -- mado init my-app

One lifecycle

Batteries that share one application model.

Signals

Small reactive state without a virtual DOM runtime.

Routing

Explicit routes, lazy pages and browser-native navigation.

Data

Resources, mutations and invalidation with one lifecycle.

Forms

Typed state around native form semantics.

Static capture

Browser-rendered HTML from the real application.

UI source

Copy components into the project and own every line.

A readable codebase

Readable by people. Bounded enough for agents.

Explicit route manifests, ordinary TypeScript and local source reduce the invisible state an engineer—or an AI system—must reconstruct before making a safe change.

Mado ships a versioned llms.txt contract so tools can reason from the installed version rather than generic framework memory.

A deliberate boundary

Focused on the frontend.

Mado does not choose your database, authentication provider, job queue or server runtime. Connect any backend through the web platform and keep that boundary explicit.

Start from source, not a black box

Build the first route in minutes.

Begin with the verified starter, then keep only the conventions your product needs.