A WebAssembly library for building MVU-style web applications with .NET.
Abies is a pure functional web framework for .NET that brings the Model-View-Update (MVU) pattern to WebAssembly. Inspired by Elm, it provides:
- Virtual DOM with efficient diffing and patching
- Type-safe routing with parser combinators
- Unidirectional data flow for predictable state management
- Pure functional architecture - no side effects in your domain logic
# Install the Abies templates (one-time)
dotnet new install Abies.Templates
# Create a new Abies application
dotnet new abies -n MyApp
cd MyApp
dotnet runusing Abies;
using static Abies.Html.Elements;
using static Abies.Html.Attributes;
using static Abies.Html.Events;
await Runtime.Run<Counter, Arguments, Model>(new Arguments());
public record Arguments;
public record Model(int Count);
public record Increment : Message;
public record Decrement : Message;
public class Counter : Program<Model, Arguments>
{
public static (Model, Command) Initialize(Url url, Arguments argument)
=> (new Model(0), Commands.None);
public static (Model, Command) Update(Message message, Model model)
=> message switch
{
Increment => (model with { Count = model.Count + 1 }, Commands.None),
Decrement => (model with { Count = model.Count - 1 }, Commands.None),
_ => (model, Commands.None)
};
public static Document View(Model model)
=> new("Counter",
div([], [
button([onclick(new Decrement())], [text("-")]),
text(model.Count.ToString()),
button([onclick(new Increment())], [text("+")])
]));
public static Message OnUrlChanged(Url url) => new Increment();
public static Message OnLinkClicked(UrlRequest urlRequest) => new Increment();
public static Subscription Subscriptions(Model model) => SubscriptionModule.None;
public static Task HandleCommand(Command command, Func<Message, System.ValueTuple> dispatch)
=> Task.CompletedTask;
}Subscriptions let you react to external event sources (timers, browser events)
without putting side effects in Update.
public record Tick : Message;
public record ViewportChanged(ViewportSize Size) : Message;
public record SocketEvent(WebSocketEvent Event) : Message;
public static Subscription Subscriptions(Model model) =>
SubscriptionModule.Batch([
SubscriptionModule.Every(TimeSpan.FromSeconds(1), _ => new Tick()),
SubscriptionModule.OnResize(size => new ViewportChanged(size)),
SubscriptionModule.WebSocket(
new WebSocketOptions("wss://example.com/socket"),
evt => new SocketEvent(evt))
]);The repository includes Conduit, a full implementation of the RealWorld specification - a Medium.com clone with:
- User authentication (login/register)
- Article CRUD operations
- Comments and favorites
- User profiles and following
- Tag filtering and pagination
| Project | Description |
|---|---|
Abies |
Core framework library |
Abies.Templates |
dotnet new project templates |
Abies.Conduit |
RealWorld example app (frontend) |
Abies.Conduit.Api |
RealWorld example app (backend) |
Abies.Counter |
Minimal counter example |
Abies.SubscriptionsDemo |
Subscriptions demo app |
Abies.Tests |
Unit tests |
See docs/subscriptions-demo.md for the demo walkthrough (including the mock WebSocket feed).
- .NET 10 SDK or later
- A modern browser with WebAssembly support
Abies includes comprehensive benchmarks for the Virtual DOM diffing algorithm. Performance is continuously monitored with automated quality gates.
π View Benchmark Results β Interactive charts with historical trends
| Scenario | Typical Performance |
|---|---|
| Small DOM diff (2-3 elements) | ~235 ns |
| Medium DOM diff (15-20 elements) | ~310 ns |
| Large DOM diff (150+ elements) | ~256 ns |
See docs/benchmarks.md for details on running benchmarks locally.
dotnet build# Start the API server
dotnet run --project Abies.Conduit.Api
# In another terminal, start the frontend
dotnet run --project Abies.ConduitSee the docs folder for:
- Documentation Index
- Installation
- Your First App
- Project Structure
- MVU Architecture
- Commands & Effects
- Components (Elements)
- Subscriptions
- Testing
- Runtime API
- Virtual DOM
Step-by-step guides to learn Abies:
- Counter App β Your first Abies app
- Todo List β Managing collections
- API Integration β HTTP commands
- Routing β Multi-page apps
- Forms β Input handling & validation
- Subscriptions β External events
- Real World App β Complete example
- Tracing β OpenTelemetry integration
We welcome contributions! Abies follows trunk-based development with protected main branch.
- Fork and clone the repository
- Create a feature branch from
main - Make your changes with tests
- Ensure all tests pass locally
- Submit a pull request following our PR template
For detailed guidelines, see CONTRIBUTING.md.
- Be respectful and constructive
- Follow code style guidelines
- Write tests for new features
- Keep PRs small and focused
- All changes require peer review
The main branch is protected and requires:
- β Pull request with 0+ approval (allows self-approval for solo dev)
- β GitHub Copilot automated code review (optional but recommended)
- β
All CI checks passing (CD, E2E, CodeQL, PR validation)
- Note: E2E timeouts are warnings only (see E2E Timeout Handling)
- β Up-to-date branch
- β All conversations resolved
See Branch Protection Guide for details.
For solo development: You can approve your own PRs, but all automated checks must still pass. GitHub Copilot provides automated code review feedback. See Copilot Review Guide.
Abies is a Latin name meaning "fir tree".
- A: as in "father" [a]
- bi: as in "machine" [bi]
- es: as in "they" but shorter [eΛs]
Stress: First syllable (A-bi-es)
Phonetic: AH-bee-ehs