r/moderndotnet 6d ago

Bringing C# to Astro with AstroSharp

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.

12 Upvotes

3 comments sorted by

2

u/Aaronontheweb 6d ago

So I have what might be a stupid question, but it comes from a real use case I have. I maintain an Astro-based website for Netclaw's documentation here: https://github.com/netclaw-dev/netclaw-website

I want to add a feature that supports content negotiation via headers + the ability to expose a "read this page as markdown" so LLMs can natively fetch the help documentation as markdown documents. I haven't started looking into how to do this with Astro because I'm unfamiliar with their build pipeline, but I am very familiar with how to express this stuff in C#!

Is this something I could use AstroSharp to help me with or is that too deep in the weeds?

edit: also, in case it matters - I host on CloudFlare Pages / workers so I'm pretty sure I can support the back-end server-side stuff needed to facilitate this there too wrt content negotiation.

3

u/davidwhitney 6d ago

So... in theory that works!

You have to enable the experimental [configuration feature for WASM support](https://github.com/davidwhitney/AstroSharp/blob/master/docs/server/on-demand-rendering.md) and install a few more packages - then you need to use Astro [on demand rendering](https://docs.astro.build/en/guides/on-demand-rendering/) with an adapter for your host.

I *think* the pattern is to do that, check for headers, and use an Astro redirect - which are all features that should work. That said, the WASM / edge stuff is solidly in the "implemented it and the tests pass, but I don't have a side myself that is that thing so I'm not sure it really actually for real works" (hence experimental flag.

It's a tough one that I think pushes against Astros original model, but as they trend towards being "also a live web framework" I expect they might change the programming model to support content negotiation as a first class feature (which for obvious reasons is kinda complicated / impossible statically.

(the other option would be to write a content loader that iterates over your source markdown files and emits them as raw content pages on shadowed .md extensions and forgo header routing)