Hosting a published site

A published site is a folder of plain files: HTML pages, a stylesheet, a search index, your images. Any web host that serves files can host it, and none of them needs a build step, because EtherPK has already built the site. This page walks through the hosts most people use. How the folder gets made in the first place is in Publishing Your Notes As A Website.

Whichever host you pick, the loop afterwards is the same: edit your notes, publish again into the same folder, push or upload. EtherPK rewrites the files it produced and leaves the rest of the folder alone, so the git history, a CNAME and a robots.txt all survive.

What is in the folder

File What it is for
index.html, <page>.html, 404.html The pages. Links between them are relative, so the site works from a subfolder as well as a domain's root.
theme/, assets/ The stylesheet, the search script and the images your pages use.
search.json, search-index.js The search index; the second copy is what search reads when the site is opened from disk.
sitemap.xml, feed.xml For search engines and feed readers. Both need the publication's Site address set.
.nojekyll Tells GitHub Pages to serve the files as they are.
.github/workflows/pages.yaml A GitHub Actions workflow that deploys the folder. Written once; yours to edit or delete.
wrangler.jsonc, .assetsignore Cloudflare's configuration for the same folder, and the list of files in it that are not part of the site (.git, the workflow, this table's other entries), which Cloudflare would otherwise serve. Both written once.
README.md, AGENTS.md, .gitignore Notes for people and coding agents about what the folder is. Your own text in AGENTS.md outside the marked section is kept.

Everything except CNAME, robots.txt, the once-written files above and your own text in AGENTS.md is regenerated on every publish, so make changes in EtherPK, not in the folder.

Before you start

  • Set the publication's Site address in Settings → Publish to the address the site will have (https://you.github.io/docs, https://docs.example.com). The sitemap and the feed are only written with one.
  • Open index.html from the folder in a browser first. The pages, the navigation and search all work from disk, so anything wrong is visible before the site is anywhere public.

GitHub Pages

Free, and the folder already carries the workflow that deploys it.

  1. Make the folder a git repository and push it. GitHub's New repository page shows the exact commands; they come to this:

    cd ~/Sites/docs          # the folder you publish into
    git init -b main
    git add -A
    git commit -m "Publish the docs"
    git remote add origin git@github.com:you/docs.git
    git push -u origin main
    
  2. In the repository on GitHub, open Settings → Pages and set Source to GitHub Actions. Nothing else to choose: the workflow in the folder is picked up on the next push.

  3. Push again, or run the workflow once from the Actions tab (Deploy to GitHub Pages → Run workflow). The run ends with the site's address, https://you.github.io/docs/.

After that, every publish is git add -A && git commit -m "Update" && git push, and the site updates within a minute.

Without Actions. If you'd rather not use a workflow, delete .github/ and set Source to Deploy from a branch, branch main, folder / (root). The .nojekyll file makes GitHub serve the folder as it is.

Your own domain. Add a file called CNAME to the folder containing just the domain (docs.example.com), commit it, and point the domain at GitHub in your DNS as GitHub's guide describes. EtherPK never touches CNAME.

Cloudflare

Cloudflare's home for a static site is a Worker with static assets (the successor to Cloudflare Pages for new projects). It is free for a site like this, and the folder's wrangler.jsonc describes it: the folder is the site, 404.html is the not-found page, and /guide and /guide.html both work.

From your computer, with Node installed:

cd ~/Sites/docs
npx wrangler login       # once; opens the browser
npx wrangler deploy

The Worker is named after the publication (docs), and the first deploy prints its address, https://docs.<your-account>.workers.dev. Repeat npx wrangler deploy after each publish.

From a repository, so a push deploys: push the folder to GitHub or GitLab as above, then in the Cloudflare dashboard choose Workers & Pages → Create → Import a repository, pick it, leave the build command empty and keep the deploy command npx wrangler deploy. Cloudflare runs that on every push.

Your own domain. In the Worker's Settings → Domains & Routes, add the domain; Cloudflare sets the DNS up when the domain is on Cloudflare already.

Netlify

The quickest route when the folder is not in git: open app.netlify.com/drop and drag the folder onto the page. The site is live at a *.netlify.app address a few seconds later, and 404.html is used for missing pages without any setup. To update it, open the site in Netlify and drop the folder on its Deploys tab.

From the command line instead:

cd ~/Sites/docs
npx netlify-cli deploy --prod --dir .

Or connect a repository (Add new site → Import an existing project), leave the build command empty and set the publish directory to /.

Other hosts

The folder is plain files, so the pattern is always "serve this folder, index.html first, 404.html for anything missing":

  • GitLab Pages wants the files under public/ and a .gitlab-ci.yml. This one copies the folder there on every push:

    pages:
      script:
        - mkdir .public && cp -r * .public && mv .public public
      artifacts:
        paths: [public]
      rules:
        - if: $CI_COMMIT_BRANCH == "main"
    
  • Vercel: npx vercel --prod in the folder, or import the repository with the framework set to Other and no build command.

  • Amazon S3: enable static website hosting on the bucket with index.html as the index document and 404.html as the error document, and put CloudFront in front of it for HTTPS and a domain.

  • Your own server: point the web root at the folder. For nginx, root /var/www/docs; and error_page 404 /404.html; is the whole configuration.

If something is off

  • A page is missing from the site: the publish report (Show report on the finished notification, or under the publication in Settings → Publish) says which documents were left out and why, usually because a page is not public or does not name the publication.
  • Search finds nothing: the folder holds an older publish without search-index.js, or the host is not serving search.json. Publish again and upload the whole folder.
  • Links to other pages break under a subfolder: they shouldn't - every link is relative - but a host that strips .html needs to serve /guide as guide.html, which GitHub Pages, Cloudflare and Netlify all do by default.
  • The old site is still showing: Cloudflare and Netlify update within seconds; GitHub Pages can take a minute, and a browser may cache the page - reload hard.