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.
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`…`)
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 })
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 verifiednpm 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.