// Program.cs
using SvelteNet.AspNetCore;
builder.Services.AddRazorPages();
builder.Services.AddSvelteNet(); // client-only by default
// Opt into SSR with .AddJintSSR(), .AddNodeSSR(), or .AddBunJsSSR()
var app = builder.Build();
app.UseStaticFiles();
app.UseSvelteNet(); // remote endpoints (+ optional startup scaffolding)
app.MapRazorPages();// Pages/Index.cshtml.cs
using SvelteNet;
using SvelteNet.AspNetCore;
public class IndexModel : SveltePage
{
[SvelteProp] public string Title { get; set; } = "Hello";
[SvelteProp] public List<Todo> Todos { get; set; } = [];
}@* Pages/Index.cshtml *@
@model IndexModel
@section Head { @Model.SvelteHead() }
@Model.Svelte()SveltePage renders in the page filter, before the view runs, so these stay synchronous
even when the server render awaits remote queries. @await Model.SvelteAsync() renders on
demand if you bypass the normal handler pipeline.
dotnet build generates the frontend types (the SvelteNet.Build.targets MSBuild target runs the scaffolder against the built assembly — no app run needed, and dotnet watch regenerates on every rebuild):
.svelte-net/
types/
models.d.ts ← generated: ambient TS interfaces for C# models
Svelte/Index.d.ts ← generated: interface IndexData { title: string; todos: Todo[]; ... }
routes.d.ts ← generated: global RouteId union
server/ ← generated by Vite: private bundle used only when SSR is registered
Svelte/
Index.svelte ← scaffolded once, then yours
vite.config.ts ← scaffolded once: plugins: [sveltenet()]
tsconfig.json ← scaffolded once: includes .svelte-net declarations
package.json ← scaffolded once
Nested pages mirror their project-relative component path, for example
Svelte/Admin/Users.svelte gets .svelte-net/types/Svelte/Admin/Users.d.ts.
Declarations are ambient, so components need no
generated type imports:
<script lang="ts">
let { data }: { data: IndexData } = $props();
</script>Then npm install (or bun/pnpm) and:
- Development:
dotnet watch run+npm run devin two terminals (see below). - Production:
npm run build, then deploy.wwwroot/clientis served statically. Vite also emits.svelte-net/server, but SvelteNet does not execute it unless you selected an SSR renderer. The server output is deliberately not underwwwroot.
SSR is an explicit application choice:
builder.Services.AddSvelteNet().AddJintSSR(); // in-process; no external CLI
builder.Services.AddSvelteNet().AddNodeSSR(); // requires node on PATH
builder.Services.AddSvelteNet().AddBunJsSSR(); // requires bun on PATHSee SSR renderers for backend options and custom integrations.