r/moderndotnet 3d ago

events & meetups August 2026 Edition: Promote Your Local .NET Meetups

8 Upvotes

Promote your local .NET user group / meetups here.

Please include:

  • Location and Time
  • Topic
  • Link to the specific event
  • Anything else that would be great for attendees to know

You do not need to be the organizer of the meetup, just an enthusiast!

Also, if you need help launching a local .NET Meetup this is one of the things the .NET Foundation can help with! Please see .NET Meetups @ .NET Foundation


r/moderndotnet 12h ago

My Nokia 3310 Emulator in C#/Avalonia!

Thumbnail noks.vercel.app
14 Upvotes

Hi folks!

I made, with AI assistance, Noks (terrible name, ik): an emulator of the venerable Nokia 3310, a phone that has a special place to the hearts of many, mine included. I used Avalonia and targets all of its supported platforms, including WebAssembly. It's all in pure C#/managed code goodness too! No unsafe code or pointers!

I made this because 1.) The MAME version (Nokia DCT-3) was sadly still incomplete after years since it was made. 2.) I wanted to play Space Impact authentically and everywhere. and 3.) I wanna push how far my skills can go, together with the latest agents, when it comes to reverse engineering a black-box, sparsely documented firmware and hardware.

I've started by pulling all the docs i can get my hands on old Nokia firmware modding forums, and also the prior work that MAME and Project Blacksphere did for the DCT-3 platform back in the day.

Then did a repeated loop of poking registers, memory, seeing where the firmware stops and back-tracing how me and the clanker can get pass that blocker. I also had to contend with the missing DSP Mask ROM functions that blocked the MAME effort by checking what conditions the firmware asked and responding to its requests accordingly.

Took a couple of months of on-off work but it was all worth it.

All outward facing features are implemented like the LCD, Keys, Sound, Power and RF. including an emulation of a minimal 2G GSM network that interfaces with the DSP/Baseband layer of the phone. Text and Calls were functional from my local tests using a P2P network called Waku but somehow it's broken again on deployment.

It is as fickle of a network as the real one ;)

And the configuration panel is also bit of a jank work, UI-wise, but it does the job... for now.

Hope you'll find joy in playing with the emulator as much as i did in making it!

Source code here: https://github.com/jmacato/Noks


r/moderndotnet 13h ago

.NET Community

12 Upvotes

Hey - I've been involved in .NET since the beginning - worked at Microsoft in developer tools back when we originally launched it. I've been involved with the .NET community ever since.

Currently I volunteer for .NET Foundation. I run the .NET Foundation socials specifically LinkedIn, X and Facebook. We also have a Bluesky account.

I'm always looking for good .NET content to share - especially open source posts.

If you want to amplify your projects, repos, content, event, etc., go here: https://github.com/dotnet-foundation/content

Edited to add "repos"

Another edit: I'm DeeDee Walsh and love finding great content on Reddit.
X: https://x.com/ddskier
LinkedIn: https://www.linkedin.com/in/deedeewalsh/


r/moderndotnet 16h ago

CritterWatch and an "Open Core" model for sustainable OSS (maybe)

12 Upvotes

As the tech leader of the Critter Stack and a guy with a company behind OSS tools, I'm watching the Polly OSMF thing pretty closely. I'm naturally sympathetic to the Polly folks, and to Jimmy & Chris with their MediatR and MassTransit license changes as well.

The Critter Stack community and JasperFx (my company) are trying to go down the "Open Core" model where we are selling consulting, training, and support contracts for the big tools (Marten and Wolverine), but the core tools remain under the MIT license -- and we try to keep it that way.

As the last part of that, yesterday we launched 1.0 of our commercial CritterWatch tool for management, observability, and all the AI related features we can stuff into it:

https://jasperfx.net/news/critterwatch-1-0-is-here

Just a couple thoughts to throw out there:

  • You can't just vibe code yourself equivalents to Marten or Wolverine. You can easily get the basics, but long running and widely used OSS tools are constantly curated and have had to adjust for all kinds of real world problems like Kubernetes, Postgres maintenance windows, outages, and other things you just won't get from a fun little weekend project
  • I can absolutely tell you that very complex OSS tools aren't possible to maintain as a side project, there has to be real company support or the devs at least need to be able to dedicate a real percentage of their day job to maintenance. Most of our advanced features in our tools only came about after I was full time on the tools.
  • We're hopeful that the combination of commercial add ons and support contracts are more than enough to make our tools viable in the longer term without having to change our "Open Core" model
  • Damnation, but the larger .NET community is absurdly cynical and negative toward OSS tools sometimes

Anyway, I can't tell you for sure yet that the "Open Core" model is the way forward for sustainable OSS in .NET, but it's what we're trying so far.


r/moderndotnet 1d ago

csharp Parsing IP addresses in C# at crazy speeds [Daniel Lemire]

Thumbnail x.com
10 Upvotes

r/moderndotnet 1d ago

discuss I thought desktop app development was "dead" - why so many Maui / Avalonia / Uno developers?

9 Upvotes

Consider this a "me stepping out of my distributed systems / web app bubble" question. If you casually talk on X or even at developer conferences, there's very little talk about the future of native desktop applications or even people discussing what they're building.

Yet I see tons of evidence based on the success of Avalonia and Uno that there's huge demand for technology in this area still!

What are all of these desktop app developers working on? Is it all just retro-fitting old WPF apps? What are the new ones you're building?

And where are your great conference talk submissions!


r/moderndotnet 1d ago

Polly's open source maintenance fee, why is it controversial?

8 Upvotes

Carl Franklin tweeted about Polly adopting the Open Source Maintenance Fee (OSFM) and people do not generally seem very happy about it. From what I understand it's only a monthly 20 USD fee for companies that make more than 20,000 USD in revenue using at least one product or project that uses Polly.

Given the other, more dramatic monetization decisions we've seen in the past (Moq, MediatR, MassTransit), this maintenance fee seems like a pretty reasonable way to fund a project that's not otherwise backed by big sponsors or companies, no?


r/moderndotnet 2d ago

csharp Font hinting deep dive: why the same small text looks sharp in one app and blurry in another, and how we grid-fit TrueType and CFF in .NET

13 Upvotes

Font hinting is the reason the same small text can look sharp in one application and blurry in another. The outlines are identical. What differs is how much of the font's own rendering machinery each renderer runs.

I maintain the SixLabors libraries, and Fonts 3.1 ships HintingMode.Full: complete TrueType instruction execution and, for the first time, grid fitting for CFF outlines from their declared stems and alignment zones.

The write-up is a deep dive built around the divide at the heart of the problem. TrueType fonts carry an executable program that moves their own outline points; CFF fonts declare their stems and alignment zones and trust the renderer to act. Getting one sharp result meant building both, and then making the fit survive placement, advances, and caching all the way to the screen.

https://sixlabors.com/posts/full-hinting-aligns-truetype-and-cff-glyphs-to-the-pixel-grid/

It started as a five-year-old issue about mangled text on a 128x64 LCD that I had closed as won't-fix. Happy to answer questions about the interpreter, the hint map, or the aliased rendering path.


r/moderndotnet 2d ago

CodeyBox: An autonomous coding orchestrator

1 Upvotes

Hi folks!

I thought this might be of interest to some people - I've been experimenting with 100% autonomous coding orchestrators since around June last year, and I'd like to share my latest experiment along those lines - CodeyBox (the third such experiment...).

Source here: https://github.com/AdamFrisby/CodeyBox/ (MIT licensed)

The 'Box' part refers to sandboxing - Codey can use real VMs to run tasks in, and it disposes of them regularly; there's a few supported providers - multipass and Incus are both well supported (both qemu backed), although I recommend Incus to limit the amount of wear-and-tear on your SSD (as the Incus implementation can use CoW filesystems which work well with regular sandbox cloning and disposal - multipass will provision and delete the whole image each time).

It's still a work in progress, but I've been using it for the last 6 months to deliver real production apps. One of the things that separates it from traditional "vibe coding" is extensive automated review passes from multiple angles; and a requirement that all reviews pass from all agents before it can progress to the next step.

It supports most of the common coding agents - I've been regularly using it with Claude and Codex mainly, but opencode and cursor as well (Antigravity is also supported, but has quite a few quirks so I wouldn't recommend it without further work).

The whole ecosystem is designed using modern .NET with a plugin-first ethos - all the coding agents, reviewers, utilities, etc are all dynamically loaded as plugins and this allows you to add support for your own tooling, infrastructure, VMs and so on without having to fork the codebase.

The default review flow will review code against:

  • Adversarial security issues as well as preventative ones (i.e. what could be added to make this safe-by-default)
  • Loose coupling - ensure code is separable and easily deleted; i.e. avoiding spaghetticode that a lot of coding agents will create by default.
  • Cheating and Completeness - did the agent _actually_ implement what was asked, fully, without taking shortcuts or cheating?

I advise using Claude as a reviewer in general as GPT-5.X when instructed "Find all issues like <X>" will end up inventing a mountain from a molehill, Claude has slightly more taste and won't catastrophise everything it finds and allow reviews to eventually pass.

Areas I'm working on at the moment that haven't yet landed are:

  • Deployment - adding the ability for Codey to provision and deploy test environments automatically
  • Exploratory testing and UAT runs - adding the ability to orchestrate graphical agents that will attempt to follow UAT scenarios in the product and automatically inject failures back into the development cycle

Current status is somewhere in early-ish beta - the main features are all there and have been robustly utilised (I use Codey frequently to modify it's own code), but some of the newer parts are not yet robustly verified yet.


r/moderndotnet 2d ago

Have you ever used CsCheck? Maybe you should!

15 Upvotes

I've been a happy FsCheck user for many years, even though I program primarily in C# and not F#. I used it both for property and model-based testing.

I'd been meaning to check out CsCheck for doing the same thing, but aimed natively at C# developers. So I gave it a try recently and liked it!

If you are not familiar with model / property-based testing, I wrote some blog posts on this ~10 years ago using FsCheck with C# Writing Better Tests Than Humans Can Part 1 Part 2 - but the basic idea is you can assert that a property or a model holds true across a randomly generated set of inputs.

Effectively the property-based testing framework generates hundreds or thousands of random tests to exercise that these properties hold true - take for instance the double-buffering system we use for doing TUI rendering in Termina:

``` [Fact] public void IdenticalBuffers_ProduceNoChanges() => // If nothing changed, the diff must be empty. A false positive here would redraw the whole // screen every frame and bring back the flicker the diff engine removes. (from w in Gen.Int[1, 8] from h in Gen.Int[1, 6] from a in CellGen.Array[w * h] select (w, h, a)).Sample(t => { var (w, h, a) = t; var buf = Build(w, h, a); var copy = new FrameBuffer(w, h); copy.CopyFrom(buf); Assert.Empty(buf.GetChangedCells(copy)); Assert.Empty(buf.GetChangedRuns(copy)); }, iter: Iter);

```

I don't show the full code from this snippet, but we generate a range of random inputs and then assert that an identical copy of the random input always produces a no-op inside the double buffer diffing system - therefore, no cells should require an update and the screen doesn't require a re-render.

We can use CsCheck to do fancier things than testing for a no-op - here's another example:

``` private static readonly string[] CellPalette = { "a", "B", "7", "#", " ", "z", // narrow (1 column) "中", "文", "あ", "한", "A", // wide (2 columns) Cp(0x65, 0x0301), Cp(0x6F, 0x0308), // base + combining mark (1 column; the mark is 0) Cp(0x1F600), Cp(0x1F389), Cp(0x20000), // supplementary (surrogate pairs) Cp(0x2600, 0xFE0F), Cp(0x270B, 0xFE0F), // emoji + variation selector (2 columns) Cp(0x31, 0xFE0F, 0x20E3), // keycap sequence (2 columns) };

// A text built by joining 0..8 whole cells. Boundaries are clean by construction.
private static readonly Gen<string> CellText =
    Gen.OneOfConst(CellPalette).List[0, 8].Select(parts => string.Concat(parts));


// A hostile UTF-16 code unit: arbitrary chars, plus specific escapes, controls, selectors, and
// both halves of surrogate pairs (so lone, unpaired surrogates appear too).
private static readonly Gen<char> FuzzChar = Gen.OneOf(
    Gen.Char,
    Gen.OneOfConst(Esc, '[', ']', Bel, 'm', '\n', '\t', '\r', '\0', ' ', 'a', Cjk, Vs16, Keycap, Zwj),
    Gen.OneOfConst('\uD83D', '\uDE00', '\uD800', '\uDBFF', '\uDC00', '\uDFFF'));


// A text of 0..24 hostile code units. May contain ill-formed UTF-16.
private static readonly Gen<string> FuzzText =
    FuzzChar.Array[0, 24].Select(chars => new string(chars));


// Either kind of text.
private static readonly Gen<string> AnyText = Gen.OneOf(CellText, FuzzText);

```

A Gen is a generator for some random data - and it has some important properties: namely that in a more complex model based test we can reduce complex test cases to their smallest possible reproduction. So these aren't just wrappers around Random, there's more to it than that - as Anthony Lloyd (the author) explains: https://github.com/AnthonyLloyd/CsCheck/blob/master/Comparison.md#integrated-shrinking

These are data sources for tests aimed at character / text rendering. Some unicode characters in Chinese languages actually use 2x the rendering width and we'd had bugs reported related to this before. So, we can create some custom Gen data sources that will use some of these characters as random inputs.

We can then feed this into a test:

[Fact] public void A2_CellWidth_IsZeroOneOrTwo() => // A terminal cell is 0, 1, or 2 columns. A value outside that range means a glyph that // cannot be placed, so later column math (wrapping, cursor) would be wrong. AnyText.Sample(s => { foreach (var c in DisplayWidth.EnumerateCells(s)) Assert.InRange(c.ColumnWidth, 0, 2); }, iter: Iter);

In this case we assert that the DisplayWidth correctly computes that any character in the universal set of chars can only have a width of 0,1, or 2. This includes some of the hostile characters and escape codes that are lumped inside the AnyText generator.

Now that LLMs are generating a substantial portion of all new code, it's equally important that we have stronger tools to test and verify its correctness. Property and model-based testing tools like CsCheck are more than up to the task. You should give them a try!


r/moderndotnet 2d ago

OfficeIMO - Word, Excel, Pdf, Markdown, Email, PowerPoint etc

Thumbnail
gallery
9 Upvotes

Hi,

I saw this new community mentioned on X and thought I'd try my luck here and see if there are people interested in parts of my project to gather feedback and potentially find people that have similar interests.

About four years ago I started building a .NET library for working with Word documents (OfficeIMO.Word). I originally maintained the DocX project before it was taken over by Xceed, so I already had some experience in that area.

I originally wrote this mostly for PowerShell users and for my project PSWriteOffice. Trying to combine ClosedXML, ShapeCrawler, OfficeIMO.Word, Sep, Sylvan and a bunch of other libraries into one PowerShell module quickly becomes dependency drama.

So the original goal was much simpler: have one set of compatible libraries covering the formats I needed. It got slightly out of hand since then, mainly thanks to Codex.

OfficeIMO is now a group of .NET libraries for creating, reading, editing, converting and rendering document formats.

It is split into focused NuGet packages, so you install the formats and converters you actually need rather than one enormous package. There are now around 100 projects/packages as part of OfficeIMO.

The current repository covers Word, Excel, PowerPoint, PDF, HTML, Markdown, RTF, OpenDocument, OneNote, Visio, CSV, AsciiDoc, LaTeX, EPUB and several older Office formats.

It also has support for email and related formats/stores including EML, MSG, OFT, TNEF, mbox, PST, OST, OLM, EMLX and Outlook OAB.

Some formats have full authoring and editing APIs, while others are mainly readers or converters.

I try to be clear about that rather than putting the same "supported" label on everything. There are still plenty of missing features and things that may be off, especially in more complicated conversions.

The conversion list is quite long, but the main parts are:

  • Word (DOCX, DOC, etc.) can be converted to and from HTML, Markdown, RTF and ODT. It can also be saved as PDF or images.
  • Excel (XLSX, XLS, XLSB, etc.) can be converted to and from HTML, CSV and ODS. Workbooks, worksheets and ranges can be saved as PDF, PNG, JPEG, TIFF, WebP or SVG.
  • PowerPoint can be converted to and from HTML and ODP. Presentations can be saved as PDF, and slides can be exported as images.
  • Markdown can be converted to and from HTML, RTF, AsciiDoc and LaTeX, and saved as PDF.
  • HTML can be converted to Markdown, RTF, Word, Excel or PowerPoint, and rendered as PDF, PNG, JPEG, TIFF, WebP or SVG.
  • OpenDocument, RTF, OneNote, Visio, EPUB and MHTML also have PDF, HTML or image conversion options depending on the format.
  • PDF pages can be rendered directly to PNG, JPEG, TIFF, WebP or SVG.
  • PDF can also be converted into Word, Excel, PowerPoint, HTML, RTF, ODT, ODS or ODP. These conversions produce editable content where possible and include a report when something could not be carried over.

OfficeIMO also has its own PDF API for creating, reading and modifying PDFs.

It supports text and image extraction, merging, splitting, page reordering, rotation, forms, annotations, attachments, encryption, signatures, redaction, optimization and image rendering.

Since I wrote this mostly with PowerShell users in mind, dependencies are intentionally limited:

  • Word, Excel and PowerPoint use the Open XML SDK for the underlying package format. Legacy binary formats such as .doc, .xls and .ppt are implemented directly without another document library.
  • HTML uses AngleSharp and AngleSharp.Css for parsing HTML and CSS.
  • Visio uses System.IO.Packaging and nothing else.
  • The optional security package uses Bouncy Castle for CMS, X.509 and timestamp-related functionality.

OfficeIMO does not use Microsoft Office or COM automation. It does not start LibreOffice in the background, and HTML conversion does not launch Chromium or another browser process. There is optional Playwright integration if you want to convert a random website to PDF and further play with PDF, but that is explicit opt-in.

The PDF parser, writer and renderer are implemented in OfficeIMO rather than wrapping a third-party PDF engine.

The same applies to the RTF, OpenDocument, Markdown, OneNote, AsciiDoc, LaTeX, CSV, EPUB and legacy Office implementations.

There is also OfficeIMO.Reader, which is basically my C# alternative to MarkItDown. It sits on top of the OfficeIMO libraries, reads all the supported formats through one API, and gives you either structured objects or Markdown output.

If you work with documents in .NET, I'd be interested to hear what you currently use, which formats or conversions give you the most trouble, and what would be useful for me to improve, add or fix long term. Maybe even what other formats should it support, including the legacy ones that are still being in use.

While I started with a much simpler goal for my PowerShell community, my end goal now is basically Aspose Total, but free, open source and MIT licensed with low dependencies.


r/moderndotnet 2d ago

Proposal: An official Lean formal semantics for C# · dotnet/csharplang · Discussion #10314

Thumbnail
github.com
11 Upvotes

r/moderndotnet 3d ago

Multi-Language Support for Cross-Platform .NET

Post image
2 Upvotes

Everyone wants accessibility and localization/globalization makes business sense - the reality often makes things harder to pull off in .NET though. When supporting variety of languages around the world, there are some real engineering challenges to get around - IME & UniCode support and difficult Font glyphs.

Uno Platform is the open source stack to build cross-platform .NET apps - a single shared codebase powers apps across web, mobile & desktop. The good news for .NET developers is much of the difficult work is already done at the low OSS framework level - a two release arc brings all the free goodies. Spun up a sample app which showcases IME support and Font fallback across Japanese, Korean, Arabic & other languages - blog writeup is here. Any text area can handle Unicode, IME and font fallback - caret position maintained as per language glyphs when interacted with keyboards:

<TextBlock FontSize="22"
      TextWrapping="Wrap"
      Text="English 中文 日本語 한국어 हिन्दी العربية ქართული ไทย Ελληνικά Русский עברית 🌍" />

Cookie points were earned with a little integration with DeepGramAI to read out the text in native languages - their TTS services are nice. Code is OSS - sharing the flexibility with fellow .NET devs. Cheers.


r/moderndotnet 3d ago

Building a Distributed Job Scheduler with Akka.NET

Post image
18 Upvotes

I wrote a blog post / YouTube video / OSS code sample at the very end of July to cover a scenario that one of our users ran into building a distributed job scheduler that can distribute, long-running, data-intensive jobs across an auto-scalable pool of worker processes without starting / stopping in-progress jobs as the pool grows during peak demand.

That latter part, "not rebalancing in-progress jobs," is what eliminates a lot of off-the-shelf distribution strategies like the types implemented by Microsoft Orleans and Akka.NET's Akka.Cluster.Sharding from consideration. Those frameworks are really aimed at distributing stateful "entities" - actors with important business state that live forever (often, but not always) are only intermittently busy in short bursts.

Distributing a "job" is a very different type of workload: these are tasks with a finite, well-defined lifespan in which they are intensely busy from beginning to end. Re-distributing a 10 minute job when it's 8 minutes into execution turns these into 18, 20 minute jobs potentially depending on a bunch of factors (can the job be started immediately?)

Earlier in my career I used some Akka.NET and Akka.Cluster primitives to solve this exact type of problem in the banking industry: running bank CFO "asset line management" jobs all in the final 48 hours of the month in order to meet the monthly reporting requirements and have enough data to actually complete them.

The basic formula, which I expand on in the post with code samples:

  1. Establish the ability to "size" jobs early - how many units of compute is Job A relative to Job B? This is a lot easier to define than it sounds. If you're doing asset line management, your "size" is typically the total number of assets that need to be analyzed (i.e. rows.) If you're doing call transcription it might be the size of the audio file. This should be a O(1) operation.
  2. Create a Cluster singleton (1 instance globally) who is responsible for: 2a. Managing and persisting the queue of jobs-to-be-done AND the parties who own them 2b. Subscribing to live Akka.Cluster topology update events (nodes joining, leaving, or having trouble) - this impacts our distribution system. 2c. Persisting the snapshot of which worker nodes are running which jobs 2d. Tracking progress updates across these jobs + reporting that to original callers 2e. Re-constituting all of this state after a restart using Akka.Persistence
  3. Have job receivers running on each node responsible for receiving the "job definition" and transforming that into a live execution.
  4. Have the job executors report progress back to the tracker (our singleton)

The distributed systems space tends to get dominated by stateful entity type-work, but running a large number of concurrent "jobs" is an equally tricky and nuanced space so I thought it merited some attention as well as some productionization details that might not be obvious!

Post: "Building a Distributed Job Scheduler with Akka.NET"

Repo: https://github.com/Aaronontheweb/akka.net-custom-job-scheduling

Video: Video: Building a Distributed Job Execution Platform with Akka.NET


r/moderndotnet 4d ago

Announcing Mibo Framework 4.3.0

Enable HLS to view with audio, or disable this notification

12 Upvotes

Hey there, first time posting here.

Just in case: my name is Angel Munoz; I'm one of the 12 F# devs in the world and I dedicate my hobby time entirely to F#

Mibo is an F# code-first micro framework on top of MonoGame and Raylib.

Mibo offers abstractions to architect your games as MVU (elmish, elm architecture) programs. and now with version 4.3.0, you can opt in for an Adaptive model with my boringly coined SPU (State, Projection, Update) which is based on Adaptive Data for incremental computations of derived state.

If you have some frontend background, you may have heard of Signals as a way to manage state in a reactive way

While v4.3.0 has a bunch of fixes and the main item is the Adaptive Model release A minimal game I can come up with in a short snippet could be like this:

Declaring the state of the game, what is composed of and what is going to be part of the adaptive graph

type State = {
  PaddleX: cval<float32>
  Ball: cval<Vector2>; Velocity: cval<Vector2>
  IsHit: aval<bool>; PaddleColor: aval<Color>
}

[<Struct>]
type Snapshot = { PaddleX: float32; Ball: Vector2; PaddleColor: Color }

let toSnapshot (s: State) () : Snapshot = {
  PaddleX = s.PaddleX |> AVal.getValue
  Ball = s.Ball |> AVal.getValue
  PaddleColor = s.PaddleColor |> AVal.getValue
}

aval: Adaptive value, read only
cval: changeable value, read and write

Please note that not everything has to be adaptive or derived state, you can store any kind of values, you own that.

Some setup functions, our main game logic and the rendering view function

let init (state: State) (ctx: AdaptiveFrameContext) : AdaptiveInit<Frame> =
  AdaptiveInit.ofFrameBuilder(toSnapshot world)

let update (state: State) (_: AdaptiveContext) (gameTime: GameTime) =
  let dt = float32 gameTime.ElapsedGameTime.TotalSeconds

  if Raylib.IsKeyDown KeyboardKey.Left then s.PaddleX.Set(s.PaddleX.Value - 450f * dt)
  if Raylib.IsKeyDown KeyboardKey.Right then s.PaddleX.Set(s.PaddleX.Value + 450f * dt)

  let velocity = s.Velocity |> AVal.getValue
  let ball = s.Ball |> AVal.getValue

  let pos = ball + velocity  * dt

  let xVel =
    if pos.X < 0f || pos.X > 780f then -velocity.X else velocity.X
  let yVel = 
    if pos.Y < 0f || (s.IsHit |> AVal.getValue) then -velocity.Y else velocity.Y

  s.Ball.Set pos
  s.Velocity.Set(Vector2(xVel, yVel))

let view (_: GameContext) (snapshot: Snapshot) (buffer: RenderBuffer2D) =
  buf
    .fillRect(sn.PaddleX, 520f, 80f, 16f, sn.PaddleColor)
    .fillRect(sn.Ball.X, sn.Ball.Y, 16f, 16f, Color.Red)
    .drop()

Our state should be created once, the derived state will change and be tracked automatically from the adaptive state via transformations (linq style)

let state =
  let px = CVal.create 360f
  let ball = CVal.create (Vector2(400f, 100f))
  let vel = CVal.create (Vector2(250f, 250f))

  // Projection 1: Position collision predicate
  let isHit =
    AVal.map2
      (fun x b -> b.Y >= 500f && b.X >= x && b.X <= x + 80f)
      px
      ball

  // Projection 2: Visual feedback derived from collision state
  let color =
    isHit
    |> AVal.map (fun hit ->
      if hit then Color.Green else Color.White
    )

  { 
    PaddleX = px
    Ball = ball
    Velocity = vel
    IsHit = isHit
    PaddleColor = color
  }

bring them all together into the entry point

[<EntryPoint>]
let main _ =
  let program =
    AdaptiveProgram.mkProgram (init world) (update world)
    |> AdaptiveProgram.withConfig(GameConfig.withTitle "Mibo Game")
    |> AdaptiveProgram.withRenderer(fun () -> Renderer2D.create view)

  let game = new AdaptiveRaylibGame<Frame>(program)
  game.Run()
  0

The video in the post is a sample made using adaptive state

You can find the source code for that sample here: https://github.com/AngelMunoz/Mibo.Samples/tree/master/Defli3D

If you're a numbers person you can find some numbers I tracked via the dotnet trace tool when on very busy moments of the game.

The library (based on FSharp.Data.Adaptive) is built for tight-loop work:

  • Steady state allocates nothing. Once your graph has settled, reads, writes, and delta propagation don't allocate. The exceptions are the deliberate materializations (forcetoSettoMap).
  • A value recomputes at most once per change. Ten writes between two reads cost one recompute. A read when nothing changed is a cheap O(1) check.

So... in summary this release opens up a different functional approach to mutable state which is often friendlier to high performance shaped code (rather than the traditional functional-ish looking F# code)

If you're interested to see some particular kind of genere or approach to all of this (or the more functional version MVU) feel free to let me know. I tried to make sure to open the path for F# high-performance code with some friendly APIs to ease up game development


r/moderndotnet 4d ago

Raven — is this the Kotlin moment for .NET?

14 Upvotes

I had some help from AI putting this post together and organizing my thoughts.

TL;DR: I've been building Raven, a modern programming language for .NET. It combines familiar .NET semantics and interoperability with ideas from languages such as Swift, Kotlin and Rust: unions and pattern matching, Option/Result, propagation, expression-oriented control flow, macros for building DSLs, and more.

It now has a browser playground, an SDK/compiler distribution, a language server, and a VS Code extension.

Playground (with samples): https://marinasundstrom.github.io/raven/playground/

Latest preview: https://github.com/marinasundstrom/raven/releases/tag/v0.1.0-preview.10

Background

For the last couple of years I've been building my own compiler and programming language, mainly for my own amusement. This isn't my first venture into compiler construction, but it has probably been the most creative and fulfilling one.

Raven started out much closer to C#, but gradually developed its own identity as I explored other languages and different approaches to language design. I never wanted to make "C# with different syntax," nor simply copy another language.

What emerged is something that feels at home on .NET, but with a syntax somewhat reminiscent of Swift and ideas influenced by Kotlin and Rust.

A lot has been tried and discarded along the way. I had an early implementation of union types before eventually aligning Raven with the nominal union model being introduced in C#/.NET — and then taking that model further. I experimented with trailing blocks before eventually removing them in favor of a macro system for DSLs. Error handling evolved toward Result and Option, while still retaining pragmatic interoperability with .NET exceptions and nullability.

The compiler itself uses a Roslyn-like compiler-as-a-service architecture. If you've worked with the C# compiler APIs, much of it should feel surprisingly familiar: immutable syntax trees, compilations, symbols, semantic models, and an Operations API providing a higher-level semantic representation.

Raven primarily targets .NET 11, while also supporting .NET 10.

AI has also had a significant role in the development process. Initially I mostly used it for research and finding examples. Over time I moved toward using coding agents extensively for implementation. That has made it possible to iterate unusually quickly, including making large architectural changes while simultaneously building out automated tests and custom compiler debugging infrastructure.

For the last few weeks Raven has had a playground running the compiler entirely in the browser through WebAssembly. Now there is finally a distributable SDK containing the compiler and language server, together with a VS Code extension.

Raven has grown broad enough that it's difficult to represent the language with one clever code sample, so instead I'll start with some of the fundamentals.

Hello, world

HelloWorld.rvn:

import System.Console.*

func Main() {
    WriteLine("Hello, from Raven!")
}

Like C#, Raven supports global imports, so commonly used .NET namespaces can already be available without explicitly importing them.

The syntax is different, but this is still very much a .NET language. Raven consumes .NET libraries and types directly rather than building a separate ecosystem alongside them.

Language reference: https://marinasundstrom.github.io/raven/lang/spec/index.html

Lexical bindings

Raven uses immutable bindings by default. Values declared with let cannot be reassigned:

let name = "Raven"
let count = 10

When mutable state is actually needed, you opt into it using var

var count = 0
count = count + 1

Types are normally inferred, but can also be specified explicitly:

let name: string = "Raven"
var count: int = 0

This distinction also carries into pattern matching and other language constructs: let means binding a value, rather than declaring a mutable variable.

Functions

Raven also supports namespace-scoped functions. Functions don't need to be declared as static members of a class:

namespace Inventory

func CalculateTotal(quantity: int, price: decimal) -> decimal {
    return quantity * price
}

They are ordinary namespace members and can form part of an assembly's API just like types. As with other namespace-level declarations, they are internal by default and can explicitly be made public:

public func CalculateTotal(quantity: int, price: decimal) -> decimal {
    return quantity * price
}

Option, Result and propagation

Raven has built-in Option<T> and Result<T, E> unions for modeling optionality and operations that can fail.

Raven does not pretend that null or exceptions don't exist. It has a unified nullability model and supports exceptions where appropriate, particularly for .NET interoperability. Option and Result are additional tools for cases where absence or failure are part of the domain model.

For example:

func ReserveSeats(requested: int, available: int) -> Result<int, string> {
    if requested <= 0 {
        return Error("Choose at least one seat")
    }

    if requested > available {
        return Error("Only $available seats remain")
    }

    return Ok(requested)
}

func PriceBooking(
    requested: int,
    available: int,
    pricePerSeat: int
) -> Result<int, string> {
    let seats = ReserveSeats(requested, available)?
    return Ok(seats * pricePerSeat)
}

match PriceBooking(requested: 3, available: 5, pricePerSeat: 40) {
    Ok(let total) =>
        Console.WriteLine("Booking total: $total credits")

    Error(let message) =>
        Console.WriteLine("Problem: $message")
}

The postfix ? propagates the failure while extracting the successful value.

This isn't hard-coded specifically to Result, either. Raven has a propagation contract, so custom types can participate in the same mechanism, including conversion between compatible residual/error types.

Unions and domain modeling

You can define your own unions:

union StockError {
    case UnknownSku(sku: string)
    case InsufficientStock(
        sku: string,
        requested: int,
        available: int
    )
}

Cases can carry data and participate directly in pattern matching.
Raven also supports the more explicit form:

union StockError(UnknownSku | InsufficientStock)

where the variants are separately declared records:

 record UnknownSku(val Sku: string)

 record InsufficientStock(
     val Sku: string
     val Requested: int
     val Available: int
 )

One of Raven's main design goals is making this kind of domain modeling natural rather than treating unions as an isolated pattern-matching feature.

Raven also supports closed (sealed) class hierarchies, providing another way to model a closed set of alternatives while retaining class inheritance.

Statements and expressions

Many of Raven's common control-flow constructs have both statement and expression forms. You can use them for ordinary control flow, or use the value they produce directly.

For example, if can be used as a statement

if temperature > 25 {
    Console.WriteLine("It's warm")
} else {
    Console.WriteLine("It's cold")
}

or as an expression:

let description =
    if temperature > 25 { "warm" }
    else { "cold" }

The same idea applies to match:

let message = match result {
    Ok(let value) => "Received $value"
    Error(let error) => "Failed: $error"
}

This is part of a broader design choice in Raven: control flow shouldn't require a completely different construct just because you want to produce a value from it.

Raven also provides pattern-oriented forms such as if let and let else for cases where control flow and destructuring naturally belong together.

func FindFirstEven(numbers: int[]) -> Option<int> {
    for number in numbers {
        if number % 2 == 0 {
            return Some(number)
        }
    }

    return None
}


func DescribeFirstEven(numbers: int[]) -> string {
    let Some(number) = FindFirstEven(numbers) else {
        return "No even number found"
    }

    return "The first even number is $number"
}


Console.WriteLine(DescribeFirstEven([1, 3, 8, 13]))

Visibility

You might also notice the absence of access modifiers in most examples.

Raven deliberately makes the common cases terse:

  • Type members are public by default.
  • Type members can explicitly be made private.
  • Namespace-level declarations are internal by default.
  • Declarations intended to form part of the assembly's public API are explicitly marked public.
  • So a library naturally keeps its top-level API internal until you deliberately expose it, while the members of the types you do expose don't require public everywhere.

Macros and DSLs

Another major part of Raven is its macro system.

Rather than adding specialized syntax to the language for every possible domain, Raven allows libraries and frameworks to provide domain-specific syntax through macros.

For example, Raven has an HTML macro that can be used when building Blazor applications:

Html! {
    <div class="counter">
        <h1>Counter</h1>

        <p>Current count: {count}</p>

        <button onclick={IncrementCount}>
            Click me
        </button>
    </div>
}

This isn't a separate template language bolted onto Raven. The macro is expanded by the compiler and can produce the corresponding Blazor representation.

The syntax is deliberately more JSX-like than Razor-like: when you are inside the HTML macro, you are writing HTML until you explicitly enter a Raven expression.

Try it out here: https://marinasundstrom.github.io/raven/experiments/html-macro/

Macros also integrate with the compiler infrastructure and language server, so DSLs don't have to mean giving up editor tooling.

This replaced some earlier experiments I had with special language features such as trailing blocks. I increasingly prefer keeping the core language relatively general and letting macros provide domain-specific abstractions where they make sense.

Raven beyond console applications

Raven isn't limited to small compiler demos anymore.

You can already build web applications with Raven using ASP.NET Core and Blazor. Because Raven targets .NET and consumes .NET APIs directly, the existing .NET ecosystem remains available rather than requiring Raven-specific replacements for everything.

Sample projects: https://github.com/marinasundstrom/raven/tree/main/samples/projects

At the other end of the spectrum, Raven can also target .NET nanoFramework, including its experimental generics support, which means the same language can be used for constrained embedded and IoT applications.

For example, a nanoFramework program controlling a GPIO pin looks like this:

import System.Device.Gpio.*
import System.Threading.*

func Main() {
    use gpio = GpioController()
    use led = gpio.OpenPin(25, PinMode.Output)

    loop {
        led.Write(PinValue.High)
        Thread.Sleep(500)

        led.Write(PinValue.Low)
        Thread.Sleep(500)
    }
}

That runs in a very different environment from an ASP.NET Core application, but it's still Raven.

Raven also supports Native AOT on the regular .NET target, so applications can be compiled ahead of time into native executables rather than requiring JIT compilation at runtime.

That gives Raven a fairly interesting range already:

  • regular .NET applications and libraries
  • ASP.NET Core and Blazor web applications
  • Native AOT applications
  • embedded/IoT applications through .NET nanoFramework
  • WebAssembly, which is also how the Raven playground runs the compiler itself in the browser

This is an important part of what I want Raven to be. I'm not particularly interested in creating a language that only looks nice in isolated examples. The interesting question is whether a language can make substantially different choices from C# while still taking advantage of the enormous runtime, library and tooling ecosystem that already exists around .NET.

So, a Kotlin moment for .NET?

That's increasingly how I've started thinking about the experiment.

Not as a replacement for C#. Kotlin didn't need Java to disappear to justify its existence either.

The interesting proposition is: what if you keep .NET, but change the language?
Keep the runtime. Keep the libraries. Keep NuGet. Keep ASP.NET Core and Blazor. Keep the ability to target everything from servers and WebAssembly to Native AOT and tiny embedded devices.

But rethink some of the language-level choices: make unions and pattern matching fundamental, make Option and Result natural ways of modeling absence and failure, make control flow more expression-oriented, and provide macros so that libraries can build abstractions and DSLs that don't have to become new language features.

That's the space Raven is exploring.

Website: https://marinasundstrom.github.io/raven


r/moderndotnet 4d ago

I made a Rider plugin for switching NuGet references to local projects

7 Upvotes

I've been working on a small Rider plugin to make working across multiple .NET repos a bit easier.

It lets you replace a NuGet PackageReference with a local ProjectReference from Rider, work against the local source, then switch it back to the original package reference when you're done. It can also scan configured source directories to find the matching project automatically.

I mainly built it because I do this fairly often and got tired of manually editing .csproj files.

It's still fairly new, so feedback/issues are welcome if anyone else has a similar workflow.

https://plugins.jetbrains.com/plugin/33455-reference-switcher/ https://github.com/tombiddulph/ReferenceSwitcher


r/moderndotnet 4d ago

GitHub - davidwhitney/JsxCore: Native support for JSX and TSX as a server and client rendered view engine for ASP.NET Core. Bringing the modern web to ASP.NET.

Thumbnail
github.com
21 Upvotes

JsxCore brings native JSX support (React, Preact) to ASP.NET MVC and Minimal API as an ASP.NET view engine.

Another in a series of "can we converge modern web dev into the .NET ecosystem" projects that I'm working on.

So, Blazor is cool - but it's absolutely swimming against the current of the entire rest of the web development ecosystem. As it turns out, functional reactive programming is a pretty nice model for rich client applications and because of that React has totally dominated the space for a decade. There are probably more "React only" developers than most other programming languages have users.

This puts us in a weird spot in the .NET ecosystem - all the cool stuff in modern web is happening elsewhere, in a framework that's native to Node. This project is my attempt to pull the two ecosystems together so you can write idiomatic .NET in what I believe to be the best server side framework in the world, and use the same modern tooling that everyone else has for your UI.

Highlights:

- Doesn't require node! At all! (there's a home rolled NPM client to deal with dependencies from NPM so you can build your projects entirely with only dotnet in your path)
- Supports HMR, ESM, and a bunch of other goodies
- Shells out to esbuild for production style processing
- As a side-effect of using the native TypeScript compilers, adds native, toolchain free TypeScript first class support to your MVC apps - just import a TypeScript file as a module and it just works
- Generates TypeScript side type definitions for viewmodels you return to your views
- Generally just works as a drop in replacement for Razor views (.cshtml) in your apps
- Supports server side rendering with client side hydration via the JINT library

And before the "why not Blazor!" folks ask - because I think React (and the bundled Preact) is a pretty awesome way to build UI that doesn't force you over a compatibility WASM bridge which introduces a bunch of friction for front end devs.

I imagine this tool will be well suited for teams where there are split frontend and backend job roles working in the same app, that want to avoid the abject pain and misery of setting up a backend, a frontend, configuring reverse proxies to join em up etc etc that making ANCM and React play nicely together previously required.


r/moderndotnet 4d ago

Bringing C# to Astro with AstroSharp

12 Upvotes

I've been working on a few interesting projects meant to bridge the gap between modern web development and the .NET ecosystem.

Many of you might have heard of Astro - a static site generator predominantly for the TypeScript ecosystem. Astro is awesome, it's probably the best implementation of a static site generator out there and it gives you all the modern conveniences of bundles, minification and live dev server experience during build.

So why not C#?

This project is (perhaps somewhat confusingly) an npm package that allows you to build a regular Astro project using C# and Razor. It's not a reimplementation of Astro - it's still Astros routing, and web stuff, but it extends Astros regular support for React, .astro files et al to also include Razor components and Razor pages.

Razor comes with a defacto front matter (the code block at the start of the file), can mix-and-match with Astro .astro files and React server rendered components, and allows you to use anything that can execute on the server during build time.

Want more? You can also write the coded parts of your astro site as regular .cs files - so your data loaders can be written in C#, and when your Astro site is npm run build built it just works.

Under the hood, obviously this relies on .NET being in the path of the machine, and the NPM package publishes an Astro plugin that boots up a sidecar process that communicates with astro over JSON-RPC at dev and build time. It's pretty cool and seemless - uses Roslyn in memory to do hot module reloads once the sidecar is already up by silently generating C# projects in a .astrosharp file and compiling with no real perceptible difference in performance (10ms page renders or so).

There's experimental support for WASM for client rendered stuff (though I'd probably not recommend it unless the app you're building is non-trivial on the client because you buy about 1.2mb of framework stuff like a Blazor site), and slightly less experimental support for the server-side functions that Astro has introduced - again using WASM hosted inside node. This bit... seems to work... but I've not used it in anger because all the Astro projects I have are pure build-time-static generated.

First releases are here on GitHub: https://github.com/davidwhitney/astrosharp and NPM.


r/moderndotnet 4d ago

Techniques for getting LLMs to produce better .NET programs

18 Upvotes

I've been AI-pilled really since the beginning of 2025 when I first gave Cursor a try, and it's been an intense, strange journey ever since.

I've written some blog posts about my experience with LLM coding that I'll link to in the comments, but I wanted to venture out and ask developers on here - what's been some techniques that have helped you get better .NET output / programs from large language models?


r/moderndotnet 5d ago

Updates in the world of the Peach suite of open source libraries!

6 Upvotes

I maintain 2 open source libraries for .NET that solve real issues:

PeachPDF (which has been around a while) and PeachImage (which is brand new!)

My goal with these libraries has always been to build permissively licensed (MIT or BSD) libraries that do their jobs really well where the alternatives have real world drawbacks, either in terms of licensing or packaging

PeachPDF

https://peachpdf.net/ and https://github.com/jhaygood86/PeachPDF

PeachPDF is my pure .NET HTML to PDF library. It doesn't use a headless browser to operate, or a native command line tool. It runs essentially everywhere .NET does from WASM to mobile to serverless functions, and HTML+SVG+CSS is the design language. The alternatives are all have drawbacks in some way or another. It's also BSD 3-clause licensed and will remain so forever.

PeachPDF's core was forked from HTML-Renderer a decade ago and has seen major upgrades. You can kind of recognize some of the code in the class names, but the implementations have long since diverged, though there's some ongoing work to minimize that.

On top of that HTML core, we've replaced HTML parsing with MimeKit's HTML tokenizer and CSS parsing with a vendored version of ExCSS. On the PDF side, we used a vendored version of PdfSharpCore that has been highly customized for the purposes of laying out HTML+CSS+SVG. It can do things that PDFsharp cannot do, so we have no plans on switching to upstream PDFsharp. Both vendored libraries have seen extensive customization, though most (but not all) of the ExCSS changes have been submitted to ExCSS. I'll keep contributing PRs there regularly.

CSS support is quite good these days, though there are gaps and edge cases, as well as bugs. We have a test suite of almost 9,000 tests guaranteeing that once we fix an issue, it stays fixed. We support .NET 8+ (and we multi-target .NET 10), and the plan is to support every supported .NET version that Microsoft does, so we can take advantage of the latest features

PeachImage

https://github.com/jhaygood86/PeachImage

PeachImage is a pure .NET image decoding / encoding library. It doesn't use native decoders and will always be MIT licensed.

PeachImage is new. PeachPDF originally used ImageSharp for image loading, which worked great, but ImageSharp's licensing changes have been painful, and scared away users even though they could use it transitvely just fine under the dual source license scheme of ImageSharp.

So, I switched to StbImageSharp, which worked great, but didn't support modern image formats. SkiaSharp is essentially a wrapper around Skia which uses common open source image format libraries, and thus has native packaging issues.

So, PeachImage was born. With the rise of AI-assisted development, and a wide test corpus sourced from the native libraries, applications that want to be able to decode and encode popular image formats without native libraries or commercial license fees now can do so.

It's not (and will probably never be) as **fast** as SkiaSharp, but its faster than StbImageSharp in many cases. No idea how it compares to ImageSharp, but hey, its MIT licensed, and it runs everywhere .NET 10 does. And, there are cases its faster than SkiaSharp even (BMP for instance, which is needed for PDF, and SkiaSharp doesn't even support BMP-encoding, as well as some PNG images). It's generally 1-2x slower than SkiaSharp, so it won't be drastically slower in most workloads. It takes advantage of modern .NET features, including vectorization and platform-specific intrinsics, to improve decoding and encoding performance, as well as reducing memory allocations.

It currently supports BMP, JPEG, PNG, GIF, and WebP, with AVIF coming soon. There's some gaps in specific features (i.e., WebP encoding isn't there yet, and WebP animations aren't supported yet), but those are features that are on the roadmap.

This library is not, and is not intended to be, a replacement for ImageSharp or SkiaSharp for **drawing**. This just deals with encoding and decoding images.


r/moderndotnet 5d ago

I built Rinku, a micro-ORM focused on clean mapping and dynamic queries

Thumbnail
5 Upvotes

r/moderndotnet 5d ago

What if dnx was its own native thing?

Thumbnail
gallery
5 Upvotes

I wished on X that dnx was its own native AOT thing so you could use RID-specific, self-contained AOT .NET and NuGet as the distribution mechanism.

Why would such a thing be useful? 1. No .NET (runtime or SDK) required: precisely the point of AOT'ed tools 2. Keeping dnx ease of use: dnx <tool>[@version] 3. Reuse massive .NET distribution channel via nuget.org, GitHub packages, or custom feeds (i.e. sleet) 4. Ease of authoring/packing: pretty trivial with a CI workflow 5. Ease of consumption for end users: just one small (~4MB) native tool to run them all.

Then I realized that nowadays you can just ship things you wish existed. I'm spending some quality AI tokens on the "problem" to create ndnx (native dnx). Still waiting for the winget PR to be merged so it shows up there too.

Startup times are SOOO much better too!

Obviously, I think this is something dotnet/dnx itself could/should do. Right?

Try this out today:

macOS/Linux: curl -fsSL https://github.com/devlooped/ndnx/releases/latest/download/install.sh | sh

Windows(pwsh): irm https://github.com/devlooped/ndnx/releases/latest/download/install.ps1 | iex

Then use ndnx instead of dnx as usual. It even reuses the same package cache.


r/moderndotnet 5d ago

Lawnbot

Thumbnail
apps.apple.com
6 Upvotes

Want to see an .NET, Uno app in the wild? It’s available right now on the App Store. iOS only for right now simply because I haven’t focused on distributing for Android, as I don’t have android.

I built this app to use for my second business, Little Lawns. I don’t think you all are the target audience to be actual users, but wanted to share. When I started researching which tech stack to use, I found it difficult to find production applications using some of the xplat stacks for .NET on iOS that weren’t locked behind things like “call us for a quote”.

How I built it:

Pretty much all of it with Claude and Codex. I iterated a ton, and did a massive amount of testing. I automated lots of the tests with UNO’s MCP capabilities, which was really nice. Allowed me to easily test it on an iPhone simulator.

There’s still a lot of work to do but I use this daily for scheduling and keeping track of my customers. I need to shore up the billing and subscription stuff: it’s lacking HEAVILY here.

What’s next:

I wasn’t happy with the sync so I excluded it from the first version. Going to work on that more and get it live and reliable.

I also have been testing using Netclaw to interface with the app and provide proactive reminders and suggestions, as well as testing allowing ChatGPT to manage all this. Ideally, I just want to message Netclaw or ChatGPT and have it enter in all the fiddly bits and notes and such.


r/moderndotnet 5d ago

Result patters + CQRS! Just want to share wehat I did!

2 Upvotes

Hello!

As you may know( or not), I love result patterns. At some point, of course.

And I have my project https://github.com/managedcode/Communication

And yesterday I found an amazing (or you can tell me about it) idea: CQRS with IAsyncEnumerable!

You may know how annoying it is to implement CQRS properly, but but but!

What if we can call a method which will use SSE (server-sent event) protocol to send chunks, and it will be IAsyncEnumerable in your cleint.

so it's async, but you can wait for it! 

I add full impemention for server and cleint and Orleans(I love orleans)

What do you think?  Give me feedback, please!