-
-
Notifications
You must be signed in to change notification settings - Fork 4
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 ?
All reactions
Replies: 22 comments 4 replies
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.)
All reactions
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.
All reactions
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?
All reactions
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
All reactions
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:
- https://mastrojs.github.io/guide/setup/ has a box now "Alternative option: command line", which links to:
- https://mastrojs.github.io/guide/setup-mastro-cli-or-server/#different-ways-to-run-mastro
Does that make sense and clarify things?
All reactions
-
🎉 1
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.
All reactions
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".
All reactions
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.
All reactions
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)
All reactions
Sure, will work on deploying to other platforms 💪
All reactions
-
🚀 1
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.
All reactions
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.
All reactions
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.
All reactions
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
All reactions
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 themainconfig field.
ah, okay. but does it still need the --assets, because that's already in the wranger.json:
deploy --config wrangler.json
All reactions
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
All reactions
-
👍 1
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.
All reactions
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 :-)
All reactions
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
All reactions
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.
All reactions
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)
All reactions
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 🤩
All reactions
-
🎉 1
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?
All reactions
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.
All reactions
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 🤷
All reactions
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.
All reactions
-
👍 1