RSSAmplifier

Blog

Mastro

Updates about the web framework and static site generator, as well as the Mastro Guide.

mastrojs.github.ioRSS feed ↗13 posts

Latest posts

TypeScript web framework with no build step – but how?

Mastro brands itself as a TypeScript web framework with no dependencies and no build step. But wait, how is that even possible? Don’t you have to compile TypeScript to JavaScript before you can run it? Yes, but developer experience all depends on how you do it. Most TypeScript web frameworks nowadays do the TypeScript compilation as part of a complex build pipeline, which also applies a bunch of…

How to easily add Standard.site support to your website

(Updated on June 15, 2026) Since Bluesky added support for Standard.site , everyone with a blog seems to be racing to roll out an implementation. That’s awesome, and yet another example of how ATproto feels like one of the more exciting things happening in tech right now. What ATmosphere? For a bit of background, see e.g. Steve Klabnik’s How Does BlueSky Work? and Declan Chidlow's Publishing on…

Four ways to do component-scoped CSS without a complex build step

People have been exploring different ways to organize their CSS for almost as long as CSS has been around. In the beginning with methodologies like BEM, later with tooling like CSS modules, CSS-in-JS, and now with Tailwind . But with browsers now natively supporting CSS nesting, variables and @scope rules, let's look at four approaches to do things without resorting to complex tooling. 1. One big…

Is AI causing a repeat of Frontend’s Lost Decade?

What AI is doing to the jobs of programmers feels very familiar to a lot of us frontend developers – because it has happened to us before. Let’s first look at the transformation of the frontend and agentic coding through the lens of deskilling , and then look at both changes through the lens of a higher level of abstraction . Finally, we’ll look at previous changes, like the advent of copy-pasta…

TypeScript full-stack web framework with no build step – for agents and humans

I would be lying if I said the Mastro web framework was designed from the ground up for AI agents. It was designed for humans, and to be as simple and minimal as possible, while still offering a great DX (developer experience). But it turns out, these properties make it exceptionally well-suited for AI agents as well. The whole source code of Mastro is just ~800 lines of TypeScript, which easily…

Whatever happened to JavaScript Service Workers?

What's the right way to think about Service Workers in 2026? Are they HTTP proxies, offline-capable web apps, or free frontend servers? Not to be confused with Web Workers, which are relatively simple background threads for a website, Service Workers are a special kind of Web Worker. They have been available in all major browsers since 2017, but after a couple of years of hype, they largely…

Everything is a route: how to use one interface for servers, static-site- and asset-generation

In Unix, everything is a file. In Mastro, everything is a route. You use the same standards-based Request/Response-API not only for writing your server, but also for static site and asset generation. Let me show you how. The Request/Response-API is the modern way to write JavaScript servers . For example to return text/plain : const myHandler = async (req: Request) => { return new Response("Hello…

Improve Time to First Byte by streaming your HTML

If you have a statically generated website hosted on a CDN, it’s probably very fast (unless you add too much client-side JavaScript). However, for dynamically generated pages that load content from a database, one of the most overlooked ways to speed up the perceived page load speed is HTTP streaming. Unless you do streaming on your server, when you load rows from your database, it’s usually…

Why not just use <del>inline styles</del> Tailwind?

Are WYSIWYG word processors, inline styles, and Tailwind conceptually the same? How to make the best use of modern CSS and HTML elements? And what do we actually gain by adding abstractions like style names and components, and what do we lose? There are many different ways to render text to pixels using a computer. Let’s go through some! We'll start with the lower level ones (closer to the…

How to generate og:images from text with Canvas

Use the web-standard Canvas API to render text to PNG – without spinning up a whole web browser. Here's how we implemented this approach in @mastrojs/og-image . A few weeks ago, Scott Jehl posted about the pain of generating Open Graph images : those images you link to with an og:image meta tag from your HTML, which are then displayed on social media or messenger apps when somebody shares a link…

How to incrementally migrate from Express to the standard Request/Response API

You want to migrate to the modern way to write JavaScript servers , which is supported across JavaScript runtimes . Deno.serve , Bun.serve , Cloudflare Workers etc. – they all use the same standards-based Request / Response API for route handlers: export const handler = (req: Request) => { return new Response(`Hello ${req.url}`); } But how do you incrementally migrate from your existing Express…

What I learned porting Mastro to Bun

In our last blog post, I talked about What I learned porting Mastro from Deno to Node.js . The next step was of course to get Mastro working on Bun as well. And again, there were some gotchas that took me some time to resolve. Let’s go through them. fs.glob The first thing I immediately ran into was easy to understand. Calling the Node.js fs.glob function with the withFileTypes option in Bun,…

What I learned porting Mastro from Deno to Node.js

The Mastro web framework and static site generator initially ran only in the browser and Deno – it was living in the future, so to speak. Here's the story of how I ported it to Node.js (which has a surprising amount of functionality built-in nowadays), and what I would do differently next time. The first part of Mastro that I coded was actually Reactive Mastro (a tiny reactive GUI library), which…