astrosharp
v0.0.3
Published
Write the coded parts of Astro (components, loaders, actions, endpoints, middleware) in C#.
Maintainers
Readme
astrosharp
Write the coded parts of an Astro site in C# instead of TypeScript. Components, content loaders, actions, endpoints and middleware can all be authored in C#, while Node and Vite continue to drive the build. This is a build-time and ergonomics project, not a runtime replacement: the .NET SDK runs alongside Node and executes the C# you write.
Requirements
- Node 20 or newer.
- The .NET SDK 10.0 or newer, on your PATH as
dotnet. That is the only extra requirement — the compiled .NET host ships inside this package, so there is nothing else to install and no separate .NET project to maintain. The integration checks for a suitable SDK at startup and fails with an actionable message ifdotnetis missing, too old, or runtime-only.
Install
npm install astrosharp// astro.config.mjs
import { defineConfig } from 'astro/config';
import astrosharp from 'astrosharp';
export default defineConfig({ integrations: [astrosharp()] });Write C# under src/, next to your .astro files, and run astro build. The integration
generates and manages a throwaway .csproj under .astrosharp/.
What you can write
A component is an ordinary Razor component. A .razor file under src/pages becomes a route by
its filename, exactly like .astro:
<h2>@Title</h2>
@code {
[Parameter] public string Title { get; set; } = "";
}A content loader implements IContentLoader, and is wired up from src/content.config.ts:
import { sharpLoader } from 'astrosharp/content';
export const collections = {
blog: defineCollection({ loader: sharpLoader('blog'), schema: /* ... */ }),
};An action implements IAstroAction<TInput, TOutput>. An endpoint implements
IAstroEndpoint and serves the route its file names — src/pages/api/status.json.cs serves
/api/status.json — taking HttpRequestMessage and returning HttpResponseMessage.
Middleware implements IAstroMiddleware. The ambient
Astro global is available in C# pages and components — Astro.Url, Astro.Params, Astro.Props,
Astro.Locals, Astro.Request, Astro.Cookies and more — mirroring the .astro API.
Astro.Session, Astro.Cache and Astro.Csp are there too, for on-demand rendered routes:
@{
var visits = Astro.Session.Get<int>("visits");
Astro.Session.Set("visits", visits + 1);
Astro.Cache.Set(maxAgeSeconds: 60, tags: new[] { "profile" });
Astro.Csp.InsertDirective("img-src 'self'");
}A @{ ... } block at the top of a component is the nearest equivalent to Astro's ---
frontmatter: plain statements that run as the component renders. It is not the same as @code { },
which declares class members — fields, properties and methods — and cannot hold loose statements.
Reads are synchronous where Astro's equivalents are async: the state is resolved before the render
and recorded mutations are replayed after it, because a Razor component cannot await mid-markup. So
a value written with Set is not visible to a later Get in the same render. On a prerendered
route all three report themselves unavailable and writes are discarded rather than throwing.
Astro.Logger writes into Astro's own build output, at the right level, and unlike the three above
it works everywhere — prerendered routes and dev included:
Astro.Logger.Info("built 12 products");
Astro.Logger.Warn("no price for SKU-4");
Astro.Logger.Error("feed unavailable, using cache");Messages appear once the component has finished rendering rather than at the moment of the call, and are still emitted if the render throws.
NuGet packages are declared in your package.json, since npm rejects a nuget: protocol in
dependencies:
{
"nugetDependencies": { "Humanizer": "2.14.1" }
}Options
| Option | Default | Purpose |
| --- | --- | --- |
| srcDir | "src" | Directory holding your .razor and .cs files |
| targetFramework | "net10.0" | Target framework for the generated project |
| packages | {} | Extra NuGet packages, merged with nugetDependencies |
| dotnet | "dotnet" | Path to the .NET CLI |
| host / library | bundled | Override the bundled .NET assemblies (advanced) |
| experimental.serverRendering | "off" | "sidecar" or "wasm" for on-demand rendering |
Documentation
In the repository, github.com/davidwhitney/AstroSharp:
docs/README.md— the index. Mirrors Astro's own documentation, page for page, showing the TypeScript and the C# equivalent for each topic.docs/how-it-works.md— how the machinery fits together.
License
MIT © David Whitney
