Mastro 👨‍🍳 Docs

Search results

Blog GitHub   Bluesky

Installation and setup

There are various way to run Mastro. If you prefer the command-line over running Mastro in the browser as a VS Code extension, make sure one of the following JavaScript runtimes is installed. If you’re unsure which runtime to pick, we recommend Deno.

Running one of the following commands downloads the corresponding template repository into a newly created folder.

Deno

deno run -A npm:@mastrojs/create-mastro@0.0.8
Copied!

Or use the template repo.

Node.js

Mastro supports Node.js >= 24. pnpm is recommended, although npm and yarn also work.

pnpm create @mastrojs/mastro@0.0.8
Copied!

Or use the template repo.

Bun

bun create @mastrojs/mastro@0.0.8
Copied!

Or use the template repo.

SSG, SSR and deploying

Mastro supports both static site generation (SSG) and running a server with on-demand server-side rendering (SSR).

To start your local development server, run:

This actually runs the same server as you would probably run in production for on-demand rendering (with the exception of the --watch flag). Check out the deno.json/package.json, which is just running the server.ts file that was in the template repo. This server.ts is the entrypoint to your application, and where you call the mastro.fetch handler – yes, Mastro is basically just a library.

To generate a static site, run:

This will create a generated folder by passing synthetic Request objects to your route handlers.

To publish your website, see deploy to production in the guide.

TypeScript

While you can also just use JavaScript, Mastro supports TypeScript out of the box. Since Deno, Node.js and Bun support type-stripping TypeScript on the fly, server files are directly executed by the respective runtime.

However, browsers are not there yet. Therefore, files in the routes/ folder that end with *.client.ts are transpiled to *.client.js on the fly using ts-blank-space – both when they are served via the server, and when a static site is generated. This also rewrites imports from .ts to .js, e.g. import foo from "./foo.ts" is transformed to import foo from "./foo.js". (To see the gory details, look for the tsToJs function in Mastro’s server.ts implementation.).

By itself, neither starting the server nor loading a .client.ts file will perform any type-checking. To check your project for type errors, run:

You may want to make sure this is executed as part of your deployment pipeline, for example by prepending deno check && to your generate task in deno.json (or pnpm run check && to package.json respectively).

Testing

To add tests, refer to the documentation of your platform’s built-in test runner:

Middleware

While Mastro itself doesn’t have the concept of a middleware, you can easily run some code on each request that hits your on-demand rendering server by modifying the server.ts file. For example in Deno:

server.ts
import mastro from "@mastrojs/mastro/server";

Deno.serve(async (req) => {
  // modify request here before it hits your Mastro routes
  const res = await mastro.fetch(req);
  // modify response returned by your Mastro routes
  return res;
});
Copied!

If there is demand, we could introduce a @mastrojs/middleware package that formalizes this concept somewhat.

Bundling, build/pregenerate step and asset pipeline

To bundle client-side JavaScript, CSS or transform images, see Bundling, pregenerating assets and caching in the guide