Building mobile-ready web applications often involves a heavy stack. You have React, Angular, or Vue combined with a UI framework, and suddenly your bundle size is massive before you've even written a line of code.
Enter Mithril.js. It's a modern client-side JavaScript framework for building Single Page Applications. It's small (< 10kb gzip), fast, and provides routing and XHR utilities out of the box.
Combine that with Ionic Framework for native-like UI components and Vite for instant dev server start times, and you have a powerhouse stack for rapid development.
But setting this up manually? Configuring Vite to handle Mithril's JSX (or Hyperscript), setting up Ionic's loader, configuring the router... it's a pain.
That's why I built create-vitriol.
What is Vitriol?
create-vitriol is a scaffolding tool that sets up a production-ready Mithril.js project powered by Vite. It supports:
- ⚡️ Vite: Instant server start and HMR.
- 📱 Ionic: Optional integration for mobile UI components.
- 📘 TypeScript: First-class support.
- 🔧 Flexible Syntax: Choose between JSX or Standard (Hyperscript).
- 🧪 Testing: Pre-configured with Vitest.
Getting Started
You don't need to install anything globally. Just run:
npm create vitriol@latest
(Or yarn create vitriol, pnpm create vitriol, bun create vitriol)
The Interactive Setup
The CLI will guide you through a few simple questions:
- Project Name: What do you want to call your app?
- Project Type: Standard (Hyperscript) or JSX?
- Language: Javascript/TypeScript?
- Ionic: Yes/No? (Select Yes for this tutorial!)
- DevContainer: Do you want a Docker dev environment?
And that's it! In less than a second, your project is scaffolded.
A Look Inside
Let's say you chose Standard (Hyperscript) + Ionic + TypeScript. Here is what the generated code looks like.
File-System Routing
Vitriol comes with a lightweight file-system router. You don't need to manually define route maps. Just create a file in src/pages/.
src/pages/home.ts:
import m from "mithril";
export default function Home() {
return {
view: () => {
return m("ion-page", [
m("ion-header", [
m("ion-toolbar", [
m("ion-title", "Home")
])
]),
m("ion-content", { class: "ion-padding" }, [
m("h1", "Welcome to Vitriol"),
m("p", "This is a Mithril + Ionic + Vite app."),
m("ion-button", { onclick: () => alert("Hello!") }, "Click Me")
])
])
}
}
}
Notice how we are using standard Ionic Web Components (ion-page, ion-header, ion-button) directly within Mithril's m() function. It works seamlessly.
Running the App
cd my-app
npm install
npm run dev
Your app will be running at http://localhost:5173.
Why this stack?
- Performance: Mithril is incredibly fast. Combined with Vite, the development experience is instantaneous.
- Simplicity: No complex build steps or "magic" imports. It's just JavaScript/TypeScript.
- Mobile Ready: Ionic provides the look and feel of a native mobile app, making it easy to wrap with Capacitor later.
Give it a try!
If you are looking for a lightweight alternative to the big frameworks without sacrificing modern tooling, give Vitriol a spin.
If you find it useful, please leave a ⭐️ on GitHub! Happy coding!
Top comments (0)