Pseudo-SPA routing with a plain static site
  • TypeScript 74.3%
  • JavaScript 20.8%
  • CSS 4.1%
  • Dockerfile 0.8%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-22 11:57:37 -04:00
.vscode it works 2026-10-22 10:39:25 -04:00
blog it works 2026-10-22 10:39:25 -04:00
src maybe including scripts as modules caches them 2026-10-22 11:57:37 -04:00
static fix double load for real 2026-10-22 11:41:39 -04:00
.dockerignore it works 2026-10-22 10:39:25 -04:00
.gitignore it works 2026-10-22 10:39:25 -04:00
config.ts it works 2026-10-22 10:39:25 -04:00
Dockerfile it works 2026-10-22 10:39:25 -04:00
index.ts it works 2026-10-22 10:39:25 -04:00
LICENSE it works 2026-10-22 10:39:25 -04:00
package-lock.json wunphile fix 2026-10-22 11:39:27 -04:00
package.json wunphile fix 2026-10-22 11:35:25 -04:00
prettier.config.ts it works 2026-10-22 10:39:25 -04:00
README.md add explanation 2026-10-22 11:46:06 -04:00
tsconfig.json it works 2026-10-22 10:39:25 -04:00
wrangler.jsonc it works 2026-10-22 10:39:25 -04:00

Static Site Content Swap Demo

The idea is that you can have SPA-like behavior on a fully static site by designating an element as the content container and only replacing its content on page loads. It does this by loading pages with fetch and writing their HTML to an off-DOM element. Once the HTML is in the element, the router finds the content element and swaps out the current page content with it. It also finds scripts in the new page and executes them.

Scripts loaded from other pages are given a hook, window.addCleanup to register cleanup functions. Those functions are run when the router navigates away from the page. This helps for things like setInterval and other things that otherwise wouldn't be cleaned up without a full page reload.

See main.js.

Prerequisites

  • Node.js 24+

Usage

To build the site, run node --run build.

To run the site in development mode, run node --run dev.

To format all code with Prettier, run node --run fmt.

To check TypeScript types, run node --run check.

TypeScript

This template uses TypeScript, but takes advantage of Node.js 22.6's built-in type stripping feature to run TypeScript code directly without a build step.

This allows hot reloading to work without resorting to a complicated build system like Vite.

Docker

You can also build the site using Docker:

mkdir -p dist
docker build -t wunphile-template .
docker run -v ./dist:/data/dist wunphile-template

The above also works with Podman if you replace docker with podman.

Cloudflare Workers

To configure your project for Cloudflare Workers, add Wrangler to your project:

npm install -D wrangler@latest

Edit the project name in wrangler.jsonc to what you want, then add the following script to your package.json:

{
	"scripts": {
		"deploy": "wrangler deploy"
	}
}

You can now deploy the site to Cloudflare Workers by running npm run deploy.

To set up automatic deployment, import your repository into Cloudflare Workers and set npm run build as your build command, and npm run deploy as your deploy command.

IDE Integration

Wunphile uses ES6 template literals for composing HTML. Different IDEs need different configuration to provide syntax highlighting and intellisense for HTML inside template literals.

VS Code

Install the es6-string-html extension.

JetBrains IDEs (WebStorm, IntelliJ IDEA, etc.)

Recent versions of JetBrains IDEs should support syntax highlighting and intellisense for HTML inside template literals out of the box.