Watch Mode

tps --watch rebuilds a site whenever a source file changes and serves it over a local development server, reloading the page after each rebuild. It replaces the "build, then restart a static file server, then refresh" loop.

Running it

The compiler ships as the Transpose.Compiler dotnet tool. A normal build does not need it — the Transpose.Build.Target SDK resolves the compiler itself — but watch mode is driven from the CLI, so install the tool once:

dotnet tool install --global Transpose.Compiler
export PATH="$PATH:$HOME/.dotnet/tools"

Then point it at your project:

tps --project MyWebProject.csproj --watch

The site is served on http://localhost:4300. Use --watch-port to pick another port:

tps --project MyWebProject.csproj --watch --watch-port 5050

What it watches

Watch mode watches the sources of the root project and of every project it transitively references, so editing a shared component library rebuilds the application too. Changes are debounced, so saving one file triggers one rebuild rather than several.

The output folder itself is excluded, so a build never re-triggers itself.

How the page reloads

The index.html that watch mode serves carries a small injected script. It opens a websocket back to the dev server and acts on what the server sends:

  • reload — the page reloads itself. This is what happens after any real rebuild.
  • css — the page re-fetches its stylesheets in place, without reloading.

The script also carries the build version it was served with, so a client that reconnects (for example one whose reload navigation overlapped a second rebuild) catches up immediately rather than waiting for the next broadcast.

A CSS-only change skips the compiler

When every file in a debounced batch is a source of a stylesheet the last successful build already produced — a tps.json resources group, in the root project or in any project it references — watch mode re-copies the CSS instead of compiling, and tells the page css rather than reload. The running application keeps its state: open panels stay open, the current route stays put.

Anything else is a real build. Adding a new stylesheet has to add a <link> to index.html, deleting one has to remove it, and a .cs, .csproj or tps.json edit obviously needs compiling.

Incremental builds

Rebuilds go through the same incremental cache the SDK uses. Nothing is compiled at all when every input hashes the same, and an edit confined to method or accessor bodies reuses the cached JavaScript of every untouched type, the reflection metadata, and (in Debug) the emitted assembly. An edit in a referenced library that only touches method bodies leaves its consumers' compilation cached too, because a package DLL carries a sidecar hashing the metadata a consumer actually binds against.

The output is byte-identical whether or not the cache was used.

Embedding watch mode in your own server

If you already run a web server for your application, you do not need the dev server that tps --watch starts. The Transpose.Compiler.Library package exposes the same watch engine through a TransposeWatcher type: your host serves the build's output folder as static files and forwards the /__tps-livereload websocket path to the watcher. The Curiosity CLI's curiosity-cli serve --watch is built this way.

See also

  • Build Configurations — the incremental cache and the tps.<Configuration>.json overlay.
  • Resources — which files count as CSS sources for the fast path above.
© 2026 Curiosity. All rights reserved.