Skip to content

Navigation Menu

Sign in
Sign up

Deno Deploy and other deployment options #19

adwinmbd started this conversation in General
Discussion options

Hi,
I was deploying a project to deno deploy that contain that contains markdown. I am using the native markdown package mastro/markdown.
When I navigate to either /posts/ or /posts/uno I receive the following error:

500: TypeError
TypeError: Failed loading https://registry.npmjs.org/micromark-extension-gfm for package "micromark-extension-gfm"
 0: npm package not found in cache: "micromark-extension-gfm", --cached-only is specified.

This error occurs only in production but not in the local environment. It works fine locally.
This is the source code:

// deno.json
{
 "tasks": {
 "dev": "deno run --watch=. --allow-read --allow-net --allow-env server.ts",
 "make": "deno eval \"import 'mastro/generate';\""
 },
 "imports": {
 "mastro": "jsr:@mastrojs/mastro@0.2.2"
 },
 "lock": false
}
// data/posts/uno.md
---
title: Uno Post
date: 2025年09月12日
---
This is our first blog post.
// routes/posts/index.server.js
import { html, htmlToResponse } from "mastro";
import { readMarkdownFiles } from "mastro/markdown";
export const GET = async () => {
 const posts = await readMarkdownFiles("data/posts/*.md");
 return htmlToResponse(
 html`
 <!DOCTYPE html>
 <html>
 <head>
 <title>Posts</title>
 <link rel="stylesheet" href="/site.css">
 </head>
 <body>
 <h1>Posts</h1>
 ${posts.map((post) =>
 html`
 <p>
 <a href="${"/posts" + post.path.slice(11, -3)}">${post.meta.title}</a>
 </p>
 `
 )}
 </body>
 </html>
 `,
 );
};
// routes/posts/[slug].server.js
import { getParams, html, htmlToResponse, readDir } from "mastro";
import { readMarkdownFile } from "mastro/markdown";
export const GET = async (req) => {
 const { slug } = getParams(req.url);
 console.log('the slug variable holds the value', slug)
 const post = await readMarkdownFile(`data/posts/${slug}.md`);
 // posts.map((post) =>
 return htmlToResponse(
 html`
 <!DOCTYPE html>
 <html>
 <head>
 <title>${post.meta.title}</title>
 <link rel="stylesheet" href="/site.css">
 </head>
 <body>
 <h1>${post.meta.title}</h1>
 <main>
 ${post.content}
 </main>
 </body>
 </html>
 `,
 );
};
export const getStaticPaths = async () => {
 const posts = await readDir("../../data/posts/");
 return posts.map(p => "/posts/" + p.slice(0, -3) + "/");
}

I used the Deno deploy instruction from Mastro GH page.
Is there a specific way to deploy sites with markdown ?

You must be logged in to vote

Replies: 22 comments 4 replies

Comment options

Did you use deno install as the "Install command"?

btw. I'm curious: do you find the guide/documentation does a good job explaining deno vs. the VSCode in-browser extension vs. deno deploy vs. static site generation etc? Was this all new to you before you started reading the Mastro Guide, or..? (Because for example at first, I assumed newcomers would start with the VSCode extension instead of the command-line, but perhaps that assumption was wrong.)

You must be logged in to vote
0 replies
Comment options

Yes, for the install command I used deno install. Used the same instructions as the mastro github page.

Framework preset: no preset
Install command: deno install
Build command: blank
Runtime configuration: Dynamic app with entrypoint server.ts

It does a great job for probably new generation of beginners. Those probably who are acquainted with modern tools and ai. But for those whose introduction to web development was the basics and traditional cms like wordpress. They may dive straight for the command line. This is because they develop local first instead of cloud first.
What I found intriguing about Mastro is that it offers more than static site generation than Eleventy.js but is simpler than Astro.js.

You must be logged in to vote
0 replies
Comment options

And you're using Deno Deploy EA (not Classic)? Because I just tried and mastro/markdown loads fine for me in https://github.com/mb21/mastro-template-basic/ -> https://mastro-template-basic.mastrojs.deno.net/about 🤔

Thanks for the feedback, that makes sense! And now you just want to try out Deno Deploy, or have a specific use-case in mind where static site generation doesn't work? Or did the guide make it seem like you had to use Deno Deploy?

You must be logged in to vote
0 replies
Comment options

Yes, am using EA deploy not classic. The reason why am using Deno Deploy is because I would like to use the ci/cd pipeline. I would like to create a markdown file locally push it to github. Then let Deno redeploy the site with a new post. The guide did not make it seem I needed Deno deploy it just provided the option to what I was looking for. I think I started by looking at the github page before following the guide. When I saw the about section on GH I tried the guide.
Looking at the code. I noticed it did not have a .md file ? Probably generated on the fly ? Or maybe the issue is something to do with readMarkdownFile or readMarkdownFiles ?
I tried a fresh project with markdown files and still hit the same error.
https://github.com/adwinmbd/mastro-eval -> https://mastro-eval.adwinmbd.deno.net/posts/ -> https://mastro-eval.adwinmbd.deno.net/posts/uno

You must be logged in to vote
0 replies
Comment options

Thanks, I see lock: false in your deno.json. You should remove that and commit the deno.lock file also to your repo. Does it work then?

Meanwhile, I've finally improved the command-line and deployment docs:

Does that make sense and clarify things?

You must be logged in to vote
0 replies
Comment options

Waah. That was it. Sorry for leading you down a wild goose chase 😅.
The doc changes are great it does the difference between using the extension and command line. I even see the inclusion of the deno.lock in case someone was to miss it.
A suggestion, Windows has many different ways of installing Deno. Using WSL is overkill. Its downloading a whole linux environment to use a program. Maybe nudging the user to pick what fits likes this:

On Windows, you can try Powershell, or use other means to install Deno.

You must be logged in to vote
0 replies
Comment options

Great, thanks! So probably you don't even need Deno Deploy for now and can use GitHub Pages instead?

WSL is overkill.

Right, doesn't jibe well with the minimal spirit of Mastro. I now changed it to "On Windows, you can try PowerShell, or for additional compatibility use WSL". But perhaps everything actually works without WSL as well, and I'm just paranoid from more complex projects, where in the end the advice to users was always to "just use WSL".

You must be logged in to vote
0 replies
Comment options

I understand. Windows at times doesn't play nice with other systems.
I still need Deno deploy. GH pages is good for static sites. But Deno deploy allows both static and dynamic sites. When I need more than a static site like throw in a sqlite database GH pages only allow reads but with Deno I can both read and write.

You must be logged in to vote
0 replies
Comment options

Yes, exactly. Let me know if you've tried other hosts. If so, I can add instructions to the guide. (there is an open issue about CloudFlare for example #4)

You must be logged in to vote
0 replies
Comment options

Sure, will work on deploying to other platforms 💪

You must be logged in to vote
0 replies
Comment options

I managed to deploy Mastro as a static site on cloudflare using github actions. The source code is here:
https://github.com/adwinmbd/cfmastro. I came across a small bug of which I opened issue17 for it. The bug is not for cloudflare but rather from building static server pages.
Since Mastro build output for now, is only static sites I provided a demo of cloudflare deployment of static sites.

I think as long as hosting providers support github actions there's a high chance Mastro will be able to be deployed on them at least for static sites.

You must be logged in to vote
0 replies
Comment options

Thanks a lot! I pushed a new Mastro version with the fix.

Yes, for static pages, it should work on any host. It's just the build step that currently needs a deno environment, so building on Cloudflare probably wouldn't work (although I don't see anywhere whether this is running Node.js or a Cloudflare Worker). But yes, I suppose there are no real downsides to using GitHub Actions for the build? 🤷

Edit: I copied your config and streamlined it a bit here: https://mastrojs.github.io/guide/cli-deploy-production/#cloudflare-workers Didn't test it yet, but according to cloudflare docs e.g. wrangler.json is the canonical config nowadays.

You must be logged in to vote
0 replies
Comment options

Awesome.
I replaced the wrangler.toml with wrangler.json file and updated the deploy.yml file. I confirm that deploying with wrangler.json edit works. The deploy.yml needs to reflect the change to wrangler.json
I also upgraded Mastro to 0.3.2. The server page issue is fixed.

You must be logged in to vote
0 replies
Comment options

I noticed the Cloudflare deploy.yml in the documentation pages has some errors. On this page:
https://mastrojs.github.io/guide/cli-deploy-production/#cloudflare-workers

When running the initialization command deno run -A jsr:@mastrojs/mastro@0.3.2/init. Looking at the deno.json file the build command is generate. In the example https://github.com/adwinmbd/cfmastro I changed the build command to make. I find make or build to be less of a mouthful.

In order, to avoid confusion for a new user. I suggest the build command in the deploy.yml to reflect the build command that is the initialization script. Like this :

 - name: Build package
 run: deno task generate

Also in the deploy to cloudflare step. The current build configuration command fails.

 - name: Deploy to Cloudflare Workers
 uses: cloudflare/wrangler-action@v3
 with:
 accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
 apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
 command: deploy

Command deploy results in Github actions failing with the error:

[ERROR] Missing entry-point: The entry-point should be specified via the command line (e.g. `wrangler deploy path/to/script`) or the `main` config field.

On the cfmastro example there is an entry point in the Deploy to Cloudflare workers command. This is what was added:

command: deploy --assets ./generated --config wrangler.json

This is what I suggest as the update Cloudflare deploy.yml file:

name: Deploy Site
on:
 push:
 branches: [ main ]
permissions:
 contents: read
jobs:
 deploy:
 runs-on: ubuntu-latest
 steps:
 - uses: actions/checkout@v4
 - name: Install Deno
 uses: denoland/setup-deno@v2
 with:
 deno-version: v2.x
 - name: Build package
 run: deno task generate
 - name: Deploy to Cloudflare Workers
 uses: cloudflare/wrangler-action@v3
 with:
 accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
 apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
 command: deploy --assets ./generated --config wrangler.json
You must be logged in to vote
0 replies
Comment options

Yeah, people familiar with static site generators or other build system like C make, will be more familiar with the terms "build" or "make". But I wanted to make it somewhat newbie friendly, hence "generate". But t's just a default and easy to change.

[ERROR] Missing entry-point: The entry-point should be specified via the command line (e.g. wrangler deploy path/to/script) or the main config field.

ah, okay. but does it still need the --assets, because that's already in the wranger.json:

deploy --config wrangler.json
You must be logged in to vote
0 replies
Comment options

Alright. I understand.
I redeployed the site again with command: deploy --config wrangler.json.
I confirm that it works well. There's no need for --assets ./generated. So in the end this is how it looks for the deploy step.

 - name: Deploy to Cloudflare Workers
 uses: cloudflare/wrangler-action@v3
 with:
 accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
 apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
 command: deploy --config wrangler.json
You must be logged in to vote
0 replies
Comment options

I stumbled upon this trove. It contains multiple examples on how to deploy static sites on different platforms without using Github actions.
I went down the rabbit hole testing it for Mastro. These are the deployment settings of Mastro I used on the different platforms.

Cloudflare Workers

build_command: curl -fsSL https://deno.land/install.sh | sh && /opt/buildhome/.deno/bin/deno task build

deploy_command: npx wrangler deploy --assets ./generated --name mastro-temp --compatibility-date 2025年10月20日

Netlify

build_command: curl -fsSL https://deno.land/install.sh | sh && /opt/buildhome/.deno/bin/deno task build
publish_directory: generated

Render

build: curl -fsSL https://deno.land/install.sh | sh && /opt/render/.deno/bin/deno task build

publish_directory: generated

Vercel

build: curl -fsSL https://deno.land/install.sh | sh && /vercel/.deno/bin/deno task build

output_directory: generated

With this, I think that users have plenty of examples on how to deploy Mastro on different platforms.
These settings only apply for deploying static sites. For server side rendering Deno deploy seems to be the best option at the moment.

You must be logged in to vote
0 replies
Comment options

Thanks a lot! I'll add those to https://mastrojs.github.io/guide/cli-deploy-production/ somewhere.

I also released Mastro v0.4.0, with Node.js compatibility, so Mastro should run in lots more places now (probably even Bun, but I haven't tested). Deno is still the recommended option though, as it makes quite a few things less painful compared to Node.js.

And I've started GitHub Discussions. Moving this thread over there now :-)

You must be logged in to vote
0 replies
Comment options

Wow that's great. Node.js opens a lot of options. I tried deploying a small project using the Node.js version in Deno deploy. I confirm it works. These are the settings I used:

// package.json
{
 "name": "my-website",
 "type": "module",
 "scripts": {
 "dev": "node --watch server.ts",
 "make": "node node_modules/@mastrojs/mastro/src/generator.js",
 "check": "tsc"
 },
 "dependencies": {
 "@remix-run/node-fetch-server": "^0.10.0"
 },
 "devDependencies": {
 "@types/node": "^24.7.2",
 "typescript": "^5.9.3"
 },
 "volta": {
 "node": "24.9.0"
 }
}
// deno.json
{
 "imports": {
 "@mastrojs/mastro": "jsr:@mastrojs/mastro@^0.4.0"
 }
}

I removed the mastro import from the package.json file because Deno deploy was complaining. However, build settings remain the same.
install command: deno install
runtime configuration: dynamic app > entrypoint > server.ts

You must be logged in to vote
0 replies
Comment options

I tried using a basic app with node.js version of mastro but in Bun but it failed.
This is the package.json file:

{
 "name": "mastro",
 "type": "module",
 "scripts": {
 "dev": "node --watch server.ts",
 "make": "node node_modules/@mastrojs/mastro/src/generator.js",
 "check": "tsc"
 },
 "dependencies": {
 "@mastrojs/mastro": "jsr:^0.4.0",
 "@remix-run/node-fetch-server": "^0.10.0"
 },
 "devDependencies": {
 "@types/node": "^24.7.2",
 "typescript": "^5.9.3"
 },
 "volta": {
 "node": "24.9.0"
 }
}

Bun install gave the following error:

InstallFailed cloning repository for @mastrojs/mastro
error: @mastrojs/mastro@jsr:^0.4.0 failed to resolve

I also tried using .npmrc file to handle the jsr package part as shown here

@jsr:registry=https://npm.jsr.io
{
 "dependencies": {
 "@mastrojs/mastro": "npm:@jsr/mastrojs__mastro@^0.4.0"
 
 }
}

But starting the proect fails because it can't download mastro. It seems that because npm or bun has limited support of jsr packages at the moment. It brings problems to run Mastro.

You must be logged in to vote
1 reply
Comment options

mb21 Oct 27, 2025
Maintainer

Awesome, thanks for the feedback!
Hm.. regarding bun. How did you install it? with bun create @mastrojs/mastro@latest? (I still need to add that to the homepage)

Comment options

I installed it using pnpm create @mastrojs/mastro@latest then run bun install.
However, when using bun create @mastrojs/mastro@latest. It works great 🙂
I even deployed a SSR app on Render using Bun.
This means that you can run Mastro SSR natively in Deno Deploy. Mastro Node.js SSR also works in Deno Deploy. With this addition Mastro SSR can run in Render using Bun.
These are the settings I used to run Mastro SSR using Bun in Render:
build command: bun install
start command: bun run dev
Awesome 🤩

You must be logged in to vote
1 reply
Comment options

mb21 Oct 27, 2025
Maintainer

very cool! btw. you'll want to use bun server.ts instead of bun run dev, because the dev command is an alias to bun --watch server.ts, as you can see in the package.json, or the equivalent in deno.json. I've updated the docs a bit here: https://mastrojs.github.io/guide/deploy/#deploy-server-to-production

interesting! but why would one want to deploy Mastro with Node.js to Deno Deploy instead of using Deno? Just because they're more familiar with Node.js you think?

Comment options

Thanks, will switch to bun server.ts 👌
Yes, there are people who find the Deno ecosystem limited compared to the Node one. They prefer leveraging the power of NPM and do things the Node.js way while using Deno Deploy for hosting their projects. Deno even noticed this that's why they are actively working on compatibility with Node.js.

You must be logged in to vote
2 replies
Comment options

mb21 Oct 28, 2025
Maintainer

Interesting, then perhaps I should add some docs for that case as well. I always assumed the added Node.js compatibility just so you can add npm packages to your deno projects. And I assumed people who like Node.js more just wouldn't use Deno Deploy, but use something like Render instead 🤷

Comment options

Yeah, it's true. The docs will expand with the new features being added. Hobby developers are open to trying new platforms. They like keeping their options open to tackle unforeseen issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants
Converted from issue

This discussion was converted from issue #16 on October 23, 2025 11:42.

AltStyle によって変換されたページ (->オリジナル) /