Static sites

When a site needs no server of its own, as a landing page or docs usually don't, Sluurp can write it out as plain files. Pages arrive already drawn, and islands still wake in the browser. This site is published that way.

sluurp static --public website --public todos=examples/todos/app --out dist

It takes --public exactly as serve does, a folder or a repository’s address, then runs the app on your machine and reads it the way a visitor would. Starting from / and each mounted app, it follows every link, script, stylesheet, island, import-map entry, module import and font, and writes what it gets:

  • a page as path/index.html, so /docs/sync becomes docs/sync/index.html;
  • everything else at its own path, with modules compiled from TypeScript saved as .js, so any file host sends them as scripts.

What works, and what does not

Everything drawn on the server comes through as it is: pages, Markdown docs, highlighted code and the UI kit. Islands keep working when they only draw and react: charts, forms, a Page editor, the chart playground.

What needs a server stays behind: the API, sync, "use server" functions and live cursors. An island that talks to the server loads, but has nobody to answer it. The Todos Collab example on this site is one of those.

GitHub Pages

The output includes a .nojekyll file, so GitHub publishes /_/, the folder with the theme and styles, instead of dropping it the way Jekyll does with underscore folders. A workflow to publish on every push:

.github/workflows/pages.yml
name: Pages
on:
  push:
    branches: [master]
permissions:
  contents: read
  pages: write
  id-token: write
jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: github-pages
    steps:
      - uses: actions/checkout@v4
      - run: curl -fsSL https://raw.githubusercontent.com/SluurpHQ/sluurp/master/install.sh | sh
      - run: ~/.sluurp/bin/sluurp static --public website --out dist
      - uses: actions/upload-pages-artifact@v3
        with:
          path: dist
      - uses: actions/deploy-pages@v4

Served from a folder

A project’s GitHub Pages site is served from a folder named after the repository: username.github.io/repo/. Give that folder as --base:

sluurp static --public website --out dist --base repo

Everything a page or stylesheet names from the root (/docs, /_/theme.css) is moved under /repo/, and each page’s import map sends the root’s folders there too. What a module imports, and the islands loaded by name, arrive under the base with no module’s text changed. At a custom domain or in a username.github.io repository, the site is at the root, and no --base is needed.

Your own code that builds a root path from a string, such as link.href = "/theme.css", isn’t seen by the build. Resolve it from the module instead: new URL("../theme.css", import.meta.url).