serve
Serves a locally built custom front-end over HTTP while proxying API calls to a remote workspace. The fastest way to iterate on a custom UI without re-uploading after every change.
The folder being served must look like a compiled Mosaik.FrontEnd bundle — the CLI checks for a mosaik.app marker file in the root. With --watch the CLI compiles that folder for you.
Syntax
Usage: curiosity-cli serve --server <url> [--path <dir>] [--watch <project>] [--name <name>] [--port <port>] [options]
curiosity-cli serve \
--server https://my-workspace.example.com/ \
--path ./MyApp/bin/Debug/netstandard2.0/tps/
If neither --path nor --watch is given, the current working directory is used. With --watch, the CLI compiles the project itself and serves what the compiler produced, so --path is optional.
If --server is omitted, the CLI tries to guess the workspace URL by scanning the *.js files in the bundle for a serverURL / apiURL variable — don't rely on this in real workflows, pass --server explicitly.
Options
| Option | Description |
|---|---|
--server |
Workspace URL to proxy API calls to. Strongly recommended to set explicitly. Alias -s. Default: guessed from the bundle. |
--path |
Local path to the compiled tps/ folder. Alias -p. Default pwd, or the folder produced by --watch. |
--watch |
Path to a Transpose front-end project (a .csproj, or the folder holding one) to compile and keep watching. See Watch mode. Alias -w. |
--configuration |
Build configuration used by --watch. Default Debug. |
--name |
App name shown in the dev UI's nav bar. Default Mosaik. |
--ignore-certificate-errors |
Disable TLS validation against the proxied workspace. Dev only. Default false. |
--port |
Local TCP port to bind. Default 5000. |
--cert-file |
Path to a certificate to enable HTTPS on the local listener. |
--cert-password |
Password for the cert file, if encrypted. |
--listen-to-any |
Bind to 0.0.0.0 instead of localhost. Useful for testing from another device on the same network. Default false. |
--enable-cors |
Enable CORS on the local server. Default false. |
--path-base |
Mount the dev server under a base path (e.g. /myapp). |
How it works
Under the hood, serve:
- Starts a local Kestrel server pointing at your
tps/folder. - Patches the served
index.htmlso the browser loads your JS bundle, with the proxied server address, the loading splash, and cache-busting asset hashes injected. The folder is watched, so the injection is re-applied when its files change on disk. - Proxies all
/api/...calls to the configured--server— includingtext/event-streamresponses, which are streamed through rather than buffered, and WebSocket connections, which are relayed as a real HTTP upgrade in both directions. - With
--watch, also compiles the front-end project and reloads the browser after each rebuild. Without it,serveonly hosts what is already on disk — rebuild and refresh yourself.
For this to work, the remote workspace must allow CORS from the dev server's origin. Add http://localhost:5000 (or whatever port you used) to the MSK_CORS environment variable and restart the workspace process.
Watch mode (--watch)
serve normally hosts an already-compiled output folder. Pass --watch with a front-end project and it also compiles that project, serves what it produced, and keeps rebuilding as you edit:
curiosity-cli serve \
--server https://my-workspace.example.com/ \
--watch ./MyApp/MyApp.csproj
What this changes:
--pathbecomes optional. The compiled site is what gets served, so there is nothing to point at on a fresh checkout. Pass--pathanyway if you serve a folder assembled from more than just this project's output.- Referenced projects are watched too. The project's own sources and those of every project it references are watched, so editing a shared front-end library rebuilds the app. One save triggers one rebuild.
- The browser reloads itself. The served
index.htmlcarries an injected script that opens a WebSocket back to the dev server; after each successful rebuild the page reloads. A client that reconnects while behind the current build is caught up immediately instead of waiting for the next edit. - A CSS-only change skips the compiler. When a change is confined to stylesheets, the CSS is re-copied and swapped into the page without a reload, so the running app keeps whatever state it was in.
- A compile error leaves the previous build in place. The errors are printed in MSBuild's format; fix and save again. If the first build fails, or the project produces no site (no
tps.json),servereports it and exits with code1. - No
tpstool needed. The compiler runs in process, through theTranspose.Compiler.Librarypackage, so the standalone Transpose compiler does not have to be installed for this path. Builds are incremental — an edit confined to method bodies reuses the cached JavaScript of every type it didn't touch, and an untouched referenced project isn't recompiled at all.
Everything else about serve still applies while watching: API proxying, CORS, --path-base, and the HTTPS options.
--configuration selects the build configuration (Debug by default). Use --configuration Release to reproduce a release build's output locally.
Typical workflow
See Custom Front-End development workflow for the full loop. The short version:
# Compile once, serve the output, rebuild and refresh by hand:
dotnet build
curiosity-cli serve -s http://localhost:8080 -p bin/Debug/netstandard2.0/tps
# Or let the CLI compile and rebuild for you:
curiosity-cli serve -s http://localhost:8080 -w .
# Iterate, then when ready:
curiosity-cli upload-front-end -s http://localhost:8080 -t $CURIOSITY_TOKEN -p bin/Debug/netstandard2.0/tps
Remarks
- Use
serveto iterate on a custom front-end locally while talking to a remote workspace, instead of re-uploading after each change. Add--watchto also compile the project and reload the page on every change. - Without
--watch, the target folder must already be a compiledMosaik.FrontEndbundle (it must contain amosaik.appmarker). Either way, the remote workspace must allow CORS from the dev server's origin. - Pass
--serverexplicitly; the URL-guessing fallback is for convenience only and shouldn't be relied on.--ignore-certificate-errorsis for local development only.
See also
upload-front-end— push the bundle to the workspace when iteration is done.- Transpose Getting Started — the compiler that produces the
tps/folder. - Tesserae UI — the component library most custom front-ends are built on.
- Custom Front-End development workflow.