The best CMS for static hosting is EmDash
A friendly editor for your posts and pages, plus plain, fast HTML for your visitors. Write in EmDash on your own computer, then put the finished site online for free with Harvis.
Why EmDash
Built on Astro
EmDash is made for Astro, the framework that turns your pages into lean HTML. That is exactly what a static host serves best.
A real editor
Posts, pages, media, menus, drafts, revisions and scheduling — the editing screen WordPress users already know, without the PHP server.
Ready for AI agents
EmDash ships with an MCP server, so Claude, Cursor and other agents can draft, edit and search your content for you.
Free and open source
No licence fee and no lock-in. Start with one command, and bring your old posts along with the built-in WordPress importer.
How EmDash fits a static host
EmDash normally runs on a server so editors can change content live. On a static host like Harvis there is no server, so you use EmDash differently: the editor stays on your own computer, and only the finished pages go online.
You write and publish content in EmDash's editor, build the site so every public page is saved as plain HTML, and upload that folder. Visitors get fast files with no database behind them — nothing to hack, patch or pay for.
Publish an EmDash site on Harvis
You need Node.js 22.16 or later. No Harvis account is needed to publish — you get a live link and a private claim link.
- 01
Create your site
Start the EmDash setup and choose Node.js as the place you'll run it and the Starter template. Then start the local server.
npm create emdash@latest cd my-emdash-site npm run dev
- 02
Write your content
Open the editor in your browser, finish the setup wizard, and write or edit your posts and pages. Remember to press Publish changes — drafts stay private.
http://localhost:4321/_emdash/admin
- 03
Turn on prerendering
Add export const prerender = true to every public page so Astro saves it as HTML during the build. Pages with a [slug] in their name also need getStaticPaths, which lists every post to save.
--- // src/pages/posts/[slug].astro import { getEmDashCollection, getEmDashEntry } from "emdash" export const prerender = true export async function getStaticPaths() { const { entries } = await getEmDashCollection("posts") return entries.map((post) => ({ params: { slug: post.id } })) } const { entry: post } = await getEmDashEntry("posts", Astro.params.slug) --- - 04
Build and publish
Build the site, then upload the dist/client folder. That folder holds your finished HTML, CSS and images. Harvis prints your live link and a claim link.
npm run build npx hosting deploy dist/client
Updating your site
Edit in EmDash as usual, then build and publish again. Your changes appear on the live site after the upload finishes.
npm run build npx hosting deploy dist/client
What doesn't come along
- The editor (/_emdash/admin) and EmDash's API stay on your computer. Keep your SQLite database and the .env file backed up.
- Images from EmDash's media library are served by its API, so they won't be in the static folder. Put site images in the public/ folder instead.
- Live search, comments, forms and logins need a server. Leave them out, or use an outside service for them.
- Harvis limits still apply: 50 MB per project and 500 files per site. Unclaimed sites expire 24 hours after the last deploy.
Want the full picture? Read the EmDash docs for templates, collections and plugins.