Static sites
If a site doesn't need a server (landing pages and docs usually don't), Sluurp can export it as static files. Pages are pre-rendered and islands still hydrate in the browser. This site is published that way.
sluurp static --public website --public todos=examples/todos/app --out distIt takes --public just like serve (a folder or a repository URL), runs the app locally and crawls it. Starting from / and each mounted app, it follows every link, script, stylesheet, island, import-map entry, module import and font, and writes out:
- pages as
path/index.html, so/docs/syncbecomesdocs/sync/index.html; - everything else at its own path, with TypeScript modules compiled and saved as
.jsso any host serves them with the right type.
What works
Everything rendered on the server comes through unchanged: pages, Markdown docs, highlighted code, the UI kit. Client-only islands keep working: charts, forms, a Page editor, the chart playground.
Anything that needs a server doesn’t: the API, sync, "use server" functions and live cursors. Islands that call the server still load, but get no response. The Todos Collab and Sheet examples on this site are like that.
GitHub Pages
The output includes a .nojekyll file so GitHub publishes /_/ (theme and styles) instead of Jekyll dropping it for starting with an underscore. A workflow to publish on every push:
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/releases/main/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@v4Served from a folder
A project’s GitHub Pages site lives under the repository name: username.github.io/repo/. Pass it as --base:
sluurp static --public website --out dist --base repoRoot-relative URLs in pages and stylesheets (/docs, /_/theme.css) are rewritten under /repo/, and each page’s import map is adjusted too, so module imports and named islands resolve under the base without rewriting any module. On a custom domain or a username.github.io repository the site is at the root and needs no --base.
Root paths built from strings in your own code, like link.href = "/theme.css", aren’t rewritten. Resolve them relative to the module instead: new URL("../theme.css", import.meta.url).