Output Types

A Transpose project compiles to one of two things: a runnable site or a library package. Which one you get is a property of the project, not of a tps.json setting.

A site build

This is the default. The compiler assembles a static site into the output folder configured by output:

bin/Debug/netstandard2.0/tps/
├── tps.js            # the runtime
├── tps.meta.js       # the runtime's reflection metadata
├── app.js            # your bundle
├── app.meta.js       # your bundle's reflection metadata
├── index.html        # generated page that loads the above, in order
└── assets/           # anything from the tps.json `resources` section

With outputFormatting: "Both" each JavaScript file also has a .min.js sibling, and a matching index.min.html is written — see Build Configurations for how the build configuration collapses the pair.

The folder is self-contained: serve it from any static file server.

A library build

A project that other Transpose projects reference is compiled with --emit-package. Instead of a site, the compiler emits a .NET assembly with the compiled JavaScript and the tps.json resources embedded as manifest resources, described by an embedded resource manifest.

The SDK selects this automatically for a project with <GeneratePackageOnBuild>true</GeneratePackageOnBuild>, which is how the Transpose.* packages and any component library of your own are built. Set "html": { "disabled": true } in tps.json so no page is generated.

A library ships its JavaScript in both a formatted and a pre-minified variant, so a consuming project extracts the variant its build configuration calls for and never has to minify library code itself.

Referenced projects are compiled once

When project B references project A, a site build for B consumes A's already-built assembly and extracts its embedded JavaScript, rather than recompiling A's sources into B's bundle. dotnet build builds A first, then B reuses it, so editing B re-transpiles only B.

This is the --separate-assemblies behaviour, and it is what the SDK uses for a ProjectReference.

Reading a package never loads it

The site build reads each reference's embedded JavaScript through assembly metadata rather than by loading the assembly. Loading it would lock the file for the process's lifetime — fine for a one-shot CLI, fatal for watch mode, where the next rebuild of a referenced project could no longer write its DLL.

Module systems are not implemented

h5 could emit its output under a JavaScript module system, selected by the module setting in h5.json or per type with [Module]. Transpose does not implement this yet. The module setting is ignored, and [Module] / [ModuleDependency] are not read.

What Transpose emits instead is a single global-scope bundle: namespaces and types become properties on the global object, registered through Transpose.define(...).

Transpose.define("MyNamespace.MyClass", {
    // …
});

Which means, in practice:

  • Load the runtime and your bundle with plain <script> tags, in that order. The generated index.html already does this.
  • There is no import / require of a Transpose bundle, and no export from one.
  • To use an npm package from C#, declare an [External] binding for the global the package exposes and load the package with its own <script> tag (or as a resources entry). See Calling JavaScript.
  • A bundler is not part of the pipeline. If your application needs one, treat the Transpose output as a pre-built vendor script rather than as a module to bundle.

File layout within a bundle

The outputBy setting selects how emitted code is distributed across files. ClassPath — one file per class, laid out by namespace path — is used to build the tps.js runtime itself. Every other mode currently emits one bundle, so this setting has no effect on an application project.

See also

© 2026 Curiosity. All rights reserved.