Metano.Build
2.1.0
dotnet add package Metano.Build --version 2.1.0
NuGet\Install-Package Metano.Build -Version 2.1.0
<PackageReference Include="Metano.Build" Version="2.1.0" />
<PackageVersion Include="Metano.Build" Version="2.1.0" />
<PackageReference Include="Metano.Build" />
paket add Metano.Build --version 2.1.0
#r "nuget: Metano.Build, 2.1.0"
#:package Metano.Build@2.1.0
#addin nuget:?package=Metano.Build&version=2.1.0
#tool nuget:?package=Metano.Build&version=2.1.0
Metano
Write shared domain code once in C#. Ship clean TypeScript today, with an experimental Dart/Flutter backend on the same IR.
Metano is a Roslyn-powered transpiler for teams that keep their backend in .NET and want to share domain code with frontend or app targets. Its primary target emits idiomatic TypeScript that fits normal JS tooling; an experimental Dart/Flutter target is also available for validating the multi-backend architecture.
Why Metano?
Most full-stack .NET products end up describing the same concepts twice: entities, DTOs, enums, validation rules, small calculations, and JSON contracts. Metano keeps C# as the source of truth and generates real target code, not only declaration stubs. TypeScript is the mature target today; Dart is intentionally documented as experimental while its coverage grows.
Use it when you want:
- One domain model across backend and frontend without hand-maintained type mirrors.
- Behavior as well as shapes: records, methods, operators, guards, LINQ, async, exceptions, and JSON serializer contexts.
- Idiomatic generated code: modules, classes, interfaces, branded primitives, string unions, normal imports, and target-specific output where the backend supports it.
- Low runtime weight: no .NET runtime in the browser, no global shim, only small helper imports when the emitted code needs them.
- Native target workflow: generated TypeScript packages work with Bun,
Vite, Vitest, Biome, ESLint, bundlers, and source maps; the Dart backend
emits
.dartfiles consumed by the Flutter sample.
What It Generates Today
using Metano.Annotations;
[assembly: TranspileAssembly]
[assembly: EmitPackage("sample-todo")]
namespace SampleTodo;
[StringEnum]
public enum Priority { Low, Medium, High }
public record TodoItem(string Title, bool Completed = false, Priority Priority = Priority.Medium)
{
public TodoItem ToggleCompleted() => this with { Completed = !Completed };
public TodoItem SetPriority(Priority priority) => this with { Priority = priority };
public override string ToString() => $"[{(Completed ? "x" : " ")}] {Title} ({Priority})";
}
export const Priority = {
Low: "low",
Medium: "medium",
High: "high",
} as const;
export type Priority = (typeof Priority)[keyof typeof Priority];
export class TodoItem {
constructor(
readonly title: string,
readonly completed: boolean = false,
readonly priority: Priority = "medium",
) {}
toggleCompleted(): TodoItem {
return this.with({ completed: !this.completed });
}
setPriority(priority: Priority): TodoItem {
return this.with({ priority: priority });
}
toString(): string {
return `[${this.completed ? "x" : " "}] ${this.title} (${this.priority})`;
}
equals(other: any): boolean {
return (
other instanceof TodoItem &&
this.title === other.title &&
this.completed === other.completed &&
this.priority === other.priority
);
}
hashCode(): number {
const hc = new HashCode();
hc.add(this.title);
hc.add(this.completed);
hc.add(this.priority);
return hc.toHashCode();
}
with(overrides?: Partial<TodoItem>): TodoItem {
return new TodoItem(
overrides?.title ?? this.title,
overrides?.completed ?? this.completed,
overrides?.priority ?? this.priority,
);
}
}
Note: parts of the generated code were omitted for brevity and files got merged into this single example. The excluded part contains the imports, for example.
Feature Highlights
- C# records, classes, structs, interfaces, delegates, inheritance, generics, overloads, extension methods, nullable types, async, exceptions, pattern matching, and nested types.
- TypeScript-friendly output controls such as
[StringEnum],[PlainObject],[Branded],[Ignore],[NoContainer],[GenerateGuard],[ObjectArgs],[Optional], and[Import]. - BCL mappings for collections, LINQ,
decimal,Guid, temporal types,BigInteger, tasks, strings, math, and console output. - Cross-project package generation with
[EmitPackage], generated barrels, npm dependency updates, and package-aware imports. System.Text.Jsonsource-generation metadata emitted as a TypeScriptSerializerContext.- TypeScript and Dart/Flutter compiler targets built on a shared IR.
Getting Started
The default walkthrough targets TypeScript, because that is the production path
and the one wired into Metano.Build.
Prerequisites: .NET SDK 10.0 preview, C# preview features, and a JS runtime such as Bun.
dotnet add package Metano
dotnet add package Metano.Build
Point your C# project at a generated TypeScript package:
<PropertyGroup>
<MetanoOutputDir>../my-domain-ts/src</MetanoOutputDir>
<MetanoClean>true</MetanoClean>
</PropertyGroup>
Then build:
dotnet build
For manual runs:
dotnet tool install --global Metano.Compiler.TypeScript
dotnet metano-typescript -p path/to/YourProject.csproj -o path/to/output/src --clean
The full walkthrough is in Getting Started.
For the experimental Dart backend:
dotnet run --project src/Metano.Compiler.Dart/ -- \
-p samples/SampleCounterV1/SampleCounterV1.csproj \
-o targets/flutter/sample_counter/lib/sample_counter \
--clean
See the Dart/Flutter roadmap and the Flutter sample target.
Documentation
| Start here | Purpose |
|---|---|
| Documentation home | Map of the guides and references |
| Getting started | First TypeScript project, build integration, generated package flow |
| Attribute reference | Every public annotation and when to use it |
| BCL mappings | How standard C# types lower, with current tables focused on TypeScript |
| Cross-project references | Multi-project packages and generated imports |
| JSON serialization | JsonSerializerContext support |
| Architecture | Compiler pipeline, shared IR, TypeScript/Dart targets, and extension points |
| Comparison | How Metano differs from Blazor, Bridge.NET, NSwag, and Fable |
| ADRs | Design decisions behind the current architecture |
Samples
- HelloWorld — top-level statements and the smallest generated module.
- SampleTodo — records, string enums, LINQ overloads, and JSON serializer context output.
- SampleTodo.Service — Hono service, cross-package imports, DTOs, and module entry points.
- SampleIssueTracker — richer domain model with branded IDs, aggregates, LINQ, inheritance, and repositories.
- SampleOperatorOverloading — value
objects, operator overloads, exceptions, and
BigInteger. - SampleCounterV1 through SampleCounterV5 — UI-oriented counter variants covering MVP, MVU, component models, Inferno interop, SolidJS interop, and a related Dart/Flutter target.
Generated TypeScript lives under targets/js. Experimental Dart output is exercised by targets/flutter/sample_counter.
Contributing
Metano is young and moving quickly. Before changing compiler behavior, read the architecture guide and the relevant architecture decision records.
Useful local checks:
dotnet run --project tests/Metano.Tests/
dotnet csharpier format .
bunx biome check .
Versions are computed from git tags with MinVer. Releases publish the NuGet
packages plus the metano-runtime npm package.
Links
- Repository: github.com/danfma/metano
- NuGet: nuget.org/packages/Metano
- npm runtime: npmjs.com/package/metano-runtime
- Issues and roadmap: github.com/danfma/metano/issues
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.1.0 | 27 | 5/2/2026 |
| 2.0.0 | 26 | 5/1/2026 |
| 1.1.0 | 37 | 5/1/2026 |
| 1.0.3 | 64 | 4/30/2026 |
| 1.0.2 | 57 | 4/30/2026 |
| 0.9.0 | 80 | 4/29/2026 |
| 0.8.1 | 86 | 4/27/2026 |
| 0.8.0 | 84 | 4/25/2026 |
| 0.7.0 | 91 | 4/23/2026 |
| 0.6.1 | 101 | 4/22/2026 |
| 0.6.0 | 89 | 4/22/2026 |
| 0.5.0 | 90 | 4/17/2026 |
| 0.4.2 | 111 | 4/14/2026 |
| 0.4.1 | 99 | 4/13/2026 |
| 0.4.0 | 103 | 4/13/2026 |
| 0.3.0 | 106 | 4/12/2026 |
| 0.2.0 | 97 | 4/11/2026 |
| 0.1.0 | 107 | 4/11/2026 |