https://github.com/madojs/mado
A calm native-first web framework for sites and apps.
https://github.com/madojs/mado
admin-dashboard crud custom-elements esm forms frontend-framework html-templates madojs native-web no-build prerender router signals spa state-management static-site-generation typescript vanilla-js web-components zero-dependencies
Last synced: about 1 month ago
JSON representation
A calm native-first web framework for sites and apps.
- Host: GitHub
- URL: https://github.com/madojs/mado
- Owner: madojs
- License: mit
- Created: 2026-06-07T12:23:30.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2026-07-11T01:29:36.000Z (about 1 month ago)
- Last Synced: 2026-07-11T03:12:47.644Z (about 1 month ago)
- Topics: admin-dashboard, crud, custom-elements, esm, forms, frontend-framework, html-templates, madojs, native-web, no-build, prerender, router, signals, spa, state-management, static-site-generation, typescript, vanilla-js, web-components, zero-dependencies
- Language: JavaScript
- Homepage: https://madojs.dev
- Size: 3.11 MB
- Stars: 2
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
A calm native-first web framework for sites and apps.
Web Components · Signals · Browser-rendered static snapshots · Zero runtime dependencies
# Mado
> A calm native-first web framework for sites and apps.
[](https://www.npmjs.com/package/@madojs/mado)
[](https://github.com/madojs/mado/actions/workflows/ci.yml)
[](./LICENSE)
[](https://www.paypal.com/paypalme/tsekhmister)
Build with real Web Components, signals, routing, data and forms.
Ship live SPAs and browser-rendered static documents from one
component model.
**One component model. One page model. One release command.**
Mado (`窓`) means *window* in Japanese: a calm window into your app,
without dragging a whole frontend factory into the room.
## What you get
```txt
Mado component = Custom Element + open Shadow DOM
Mado page = route + load + head + view + optional static declaration
Mado release = Vite build
+ browser-rendered static documents
+ Declarative Shadow DOM
+ SPA fallback
+ deployment artifact
Client activation = atomic takeover
≠ hydration
≠ SSR reconciliation
```
Browser-native source, with Vite as the development and delivery
transport. No framework-specific compiler and zero runtime
dependencies.
## Use cases
- Public landing pages
- Documentation sites
- Product / catalog pages
- SaaS applications
- Business applications
- Admin panels and internal tools
- Dashboards
- Embedded widgets
## Quick start
```bash
npm exec --package @madojs/mado -- mado init my-app
cd my-app
npm install
npm run dev
```
The default starter is the universal starter: ~15 source files,
runnable without a backend, demonstrating one Shadow Component shared
between a static landing page and a live SPA route.
Need the modular reference architecture (auth shell, guarded zones,
billing module, HTTP client, module boundaries)?
```bash
mado init my-app --starter modular
```
## The Mado way
### Signals — reactive state
```ts
import { signal, computed, effect } from "@madojs/mado";
const count = signal(0);
const doubled = computed(() => count() * 2);
effect(() => console.log(count()));
count.set(1);
```
### Templates — tagged template html
```ts
html`${label}`;
```
- `${value}` — child content (text, nodes, arrays, nested `html`, `each`)
- `@event=${fn}` — event listener
- `attr=${v}` — attribute
- `.prop=${v}` — DOM property
- `?attr=${flag}` — boolean attribute
- Functions and signals are tracked reactively
### Components — real Web Components
```ts
import { component, css, html } from "@madojs/mado";
component(
"x-card",
() => () => html``,
{
styles: css`:host { display: block; padding: 1rem; }`,
},
);
```
Open shadow root, scoped styles, slots, attribute reactivity, a real
custom element under the hood. The same component renders inside the
static snapshot via Declarative Shadow DOM and inside the live SPA via
direct DOM attachment.
### Pages — `route + load + head + view`
```ts
import { html, page } from "@madojs/mado";
export default page({
static: true, // capture as HTML at release
title: "Mado Keyboard",
head: () => ({ description: "A canonical product page." }),
view: () => html`
Welcome
`,
});
```
### Routing — explicit, code-split
```ts
import { routes, routeUrl } from "@madojs/mado";
export default routes({
"/": () => import("./pages/home.page"),
"/users/:id": () => import("./pages/user.page"),
"*": () => import("./pages/not-found.page"),
});
// Internal links must be base-aware.
html`User`;
```
Lazy loading, layout groups, query params, guards, hover prefetch,
scroll restoration, error boundary, View Transitions, base-path
awareness (Vite `base` → runtime `import.meta.env.BASE_URL`).
### Data — resource + mutation
```ts
import { resource, mutation, jsonFetcher } from "@madojs/mado";
const user = resource(
() => `/api/users/${userId()}`,
jsonFetcher(),
{ staleTime: 60_000 },
);
const save = mutation(api.saveUser, {
invalidates: ["/api/users*"],
});
```
Cache, loading/error state, abort, refresh, optimistic `mutate()`,
glob-based invalidation. Lifecycle-aware inside components.
### Forms — browser constraint validation
```ts
import { useForm, html } from "@madojs/mado";
const form = useForm({
initial: { email: "", age: "" as number | "" },
});
html`
Save
`;
```
HTML owns constraints and keyboard/form semantics; Mado supplies typed values,
errors, touched/dirty state and abortable async validation.
### Static snapshots — SEO without SSR
```bash
mado release
```
`mado release` runs your app in a real Chromium and freezes the
rendered HTML — including the Shadow DOM via Declarative Shadow DOM —
into one file per route. On first paint Mado atomically replaces the
static tree with the live tree: no hydration protocol, no node
reconciliation, no per-attribute diffing.
- Real search engines see a fully rendered document.
- Social preview bots see the canonical / og tags inside the raw HTML.
- JS-disabled browsers see meaningful content.
- The live app boots from the same snapshot without re-fetching seeded
data.
## CLI
```bash
mado init my-app # scaffold universal starter
mado init my-app --starter modular # scaffold modular reference architecture
mado dev # Vite dev server
mado build # Vite production SPA build
mado typecheck # tsc --noEmit
mado static [--base-url …] # low-level snapshot only
mado release # vite build + snapshots + deployment files
mado preview # serve out/ like a real static host
mado new # scaffold canonical files
```
All CLI records share `level`, `scope`, `code`, `message`, `data` and a
timestamp. Use `--log-level`, `--log-format=pretty|plain|json`,
`MADO_LOG_LEVEL`, `MADO_LOG_FORMAT` or `NO_COLOR` for automation.
## Devtools
```ts
import { devtools } from "@madojs/mado/devtools.js";
devtools.open();
```
The development-only Shadow DOM overlay is toggled with `Alt+Shift+M` and
inspects reactivity, components, routing, data and structured diagnostics.
## Honest boundaries
- No server renderer.
- No hydration protocol.
- No framework compiler.
- No runtime dependencies.
- No built-in backend.
- No UI-kit marketplace.
- Modern evergreen browsers only.
- A compatible Chromium is required at release time for static routes.
- Static `paths()` and `initialData()` callbacks must be browser-safe
and secret-free (they run during discovery AND ship in the client
bundle).
## Why teams pick Mado
| What matters to you | Best choice |
|---|---|
| Largest ecosystem, most hires available | React or Vue |
| Reusable design-system components across host frameworks | Lit |
| Maximum rendering performance, JSX workflow | Solid or Svelte 5 |
| Progressive enhancement of server-rendered pages | htmx + your backend |
| One component model for sites and apps with calm maintenance | **Mado** |
## Production
```bash
mado release # typecheck + vite build + static snapshots + deployment files
mado preview # serve out/ like a real static host
```
One command, one artifact (`out/`). Upload anywhere: VPS, Cloudflare
Pages, GitHub Pages (with base), any static CDN.
## Documentation
Canonical docs (English) live in [`docs/en/`](./docs/en/README.md).
AI-agent entrypoints: [AGENTS.md](./AGENTS.md) · [llms.txt](./llms.txt)
## Tests
```bash
npm run typecheck
npm run build
npm test
npm run size
npm run package:smoke
```
The full snapshot + takeover round-trip and the base-path contract
are required CI gates (`.github/workflows/ci.yml → static-snapshot`),
run under a pinned Playwright-managed Chromium with
`MADO_REQUIRE_BROWSER=1` so they never silently skip on PRs.
## Contributing
Read [CONTRIBUTING.md](./CONTRIBUTING.md). Bug fixes with tests, docs
improvements, examples and carefully discussed core changes are
welcome. Runtime dependencies are not.
## License
MIT.