pal-tamas/rask

The .NET One Person Framework — build, run, and ship a whole product solo, in C#, on one server. C# components render server-side over WebSockets or on WebAssembly, or host a typed TypeScript SPA (React, Vue, Angular, Svelte, Solid, Preact, Lit); SQLite-first data, auth, jobs, mail, cache, CQRS & one-command deploy.

31

stars

946

commits

C#

primary language

Sep 4, 2026

updated

rask.sh/
angular
aspnetcore
blazor-alternative
cqrs
csharp
dotnet
entity-framework-core
one-person-framework
pwa
react
server-side-rendering
source-generator
sqlite
svelte
tailwindcss
typescript
vue
webassembly
web-framework
websockets

README

Rask

The .NET One Person Framework — build, run, and ship a whole product solo, in C#, on one server.

Site ↗ · Docs ↗ · Playground ↗

The Counter component typed out in an editor: a tooltip explains the [ … ] indexer as H1[ is written, then the caret stops after Button. and a completion list opens showing Class, Id, OnClick and Style, each with its own doc comment.

You write components as plain C# classes that return a tree of HTML from Render(). State is a field, an event handler is a delegate, and the component re-renders itself — no .razor, no JSX, no JavaScript, nothing to write in another language:

[Route("/counter")]
public sealed partial class Counter : Component
{
    private int _count;

    protected override Component? Render() =>
    [
        H1["Counter"],
        P[$"Current count: {_count}"],
        Button.OnClick(() => _count++)["Click me"]
    ];
}

Rask is the .NET One Person Framework. One developer builds, runs and ships a complete product — the UI, the data, the auth, the background work and the deployment — from one C# codebase on one server, with SQLite as the production database. No PaaS to rent, no stack of services to glue, no second language to context-switch into. The same component runs two ways: server-rendered with live updates over a WebSocket, or fully client-side on WebAssembly as an installable offline PWA.

Quickstart

An empty folder to a live, HTTPS, database-backed product, by one person in one sitting:

curl -sSL https://pal-tamas.github.io/rask/rask.sh | sh   # the CLI, and everything it shells out to

rask new Shop --auth                                      # scaffold: the whole stack + a cookie login
# …write a Products slice — docs/tutorial/02-first-feature.md has the code
rask db add InitialCreate && rask db update                # create + apply the SQLite migration
rask dev                                                   # run it, hot-reloading, at /products
rask deploy --host root@box --domain shop.example.com      # ship it: bare box → Docker + auto-HTTPS, zero-downtime

Every step is a first-party command, and every stateful pillar it touches — auth, jobs, mail, cache, events — rides the app's own SQLite database. Run rask with no arguments for a wizard.

Prerequisites: none. The installer adds whatever is missing — the .NET 10 SDK, the wasm-tools workload that browser bundles need, Node for the SPA templates — all under $HOME, no sudo. On Windows: irm https://pal-tamas.github.io/rask/rask.ps1 | iex. Already have the .NET 10 SDK and want only the tool? dotnet tool install -g Rask.Cli. Options, install locations and uninstall: docs/installation.md.

Want the pages to run in the browser too? rask new Shop --wasm publishes a WebAssembly bundle from that same project, and a page that can run client-side moves there once it has downloaded — no second project, no separate build. Until then, and for any page that reaches a database, it stays live over the socket. See render modes.

Prefer React? rask new Shop --template react scaffolds a Vite client on an ASP.NET host, with the front end's TypeScript generated from your C# message records on every build — so await rask.dispatch(getOrder({ id })) is typed, and renaming a property breaks the build rather than the wire. The client is a TypeScript SPA — React, Preact, Vue, Angular, Solid, Svelte or Lit, but not JavaScript, since every guarantee here is one a compiler makes. See docs/spa.md. (Needs Node.js.)

Want React inside a Rask app rather than instead of one? Derive a component from ReactComponent and drop a Chart.tsx beside it — it becomes an ordinary component you place anywhere the chain goes, a leaf in a card or a whole route. Props are declared in C# and checked in both directions, callbacks re-enter C# over the channel every handler already uses, and the live diff leaves the subtree alone because its own renderer owns it. LitComponent pairs with a .ts the same way. Rename a C# property and the front end stops compiling. Needs Node, because your React does. See docs/external-components.md.

Packages

Pick one host package per project, then add what you need. Everything below targets .NET 10 and is trim/AOT-safe.

PackageVersionWhat it's for
Hosts & tooling
Rask.ServerRask.ServerASP.NET host — state changes stream to the browser as minimal diffs over a WebSocket
Rask.WasmRask.WasmBrowser-WebAssembly host — the same components client-side, installable as an offline PWA
Rask.Wasm.HostingRask.Wasm.HostingServes a published WASM bundle from an ASP.NET host
Rask.Spa.HostingRask.Spa.HostingServes a built TypeScript SPA, and generates its TypeScript from your C# contracts
Rask.ExternalRask.ExternalA .tsx or Lit file as an ordinary Rask component, with props owned by C# (needs Node)
Rask.CliRask.Clinew · dev · db · deploy · info · doctor — the whole lifecycle, one tool
Rask.BootstrapRask.BootstrapTyped Bootstrap 5.3 components, zero-JS interactivity, typed utility classes
Rask.TestingRask.TestingRender a component in a unit test and assert on its HTML
Vertical-slice back end
Rask.CqrsRask.CqrsSource-generated, reflection-free queries / commands / notifications via IDispatcher
Rask.Cqrs.ClientRask.Cqrs.ClientA WASM client dispatches to its server through the same IDispatcher call — no HttpClient
Rask.Cqrs.ServerRask.Cqrs.ServerThe endpoint pair those messages arrive on — authenticated by default, no /api/* to write
Rask.DataRask.DataEntity<TId> + EF interceptors: audit stamps, soft delete, optimistic concurrency, domain events — and BulkInsertAsync, the bulk insert EF Core leaves out
Rask.OutboxRask.OutboxCrash-safe domain events, committed in the same transaction as your data
Rask.JobsRask.JobsDurable enqueued / delayed / recurring background work, with retries
Rask.MailRask.MailDurable transactional email over SMTP — bodies are Rask components
Rask.CacheRask.CacheIDistributedCache + a typed ICache.GetOrCreateAsync, on the app DB
Rask.LoggingRask.LoggingThe application log in a database of its own, so it survives a restart — searchable, with retention
Rask.DashboardRask.DashboardAn operator dashboard at /_rask: queue depth, dead letters, one-click retry, the log
Production SQLite
Rask.SQLiteRask.SQLiteWAL, busy-timeout, non-blocking write retries — one file as a real production database
Rask.SQLite.EntityFrameworkCoreRask.SQLite.EntityFrameworkCoreThose pragmas (and opt-in busy retry) on a DbContext
Rask.SQLite.LitestreamRask.SQLite.LitestreamContinuous streaming replication off-box, managed for you
Rask.SQLite.SnapshotsRask.SQLite.SnapshotsScheduled backups
Rask.SQLite.BrowserRask.SQLite.BrowserA real SQLite database inside the browser tab that survives a reload
Forms, push & realtime
Rask.Validation.DataAnnotationsRask.Validation.DataAnnotationsDataAnnotationsValidator inside a Form
Rask.Validation.FluentValidationRask.Validation.FluentValidationFluentValidationValidator inside a Form
Rask.WebPushRask.WebPushServer-side Web Push (VAPID + RFC 8291), zero external dependencies
Rask.SignalingRask.SignalingThe WebRTC signaling IWebRtc needs

Rask.Server and Rask.Wasm pull in Rask.Core, Rask.Html and the source generators transitively.

Package → project type → entry-point API (click to expand)
PackageProject typeEntry-point API
Rask.Servernet10.0 ASP.NETservices.AddRask() + app.UseRask<TApp>()
Rask.Wasmnet10.0-browserWasmHostBuilder.CreateDefault() + host.RunAsync<TApp>()
Rask.Wasm.Hostingnet10.0 ASP.NET (with a <ProjectReference> to the WASM project)app.UseRask()
Rask.Validation.DataAnnotationsany host that hosts your formsdrop DataAnnotationsValidator inside a Form
Rask.Validation.FluentValidationany host that hosts your formsdrop FluentValidationValidator.Validator(myValidator) inside
Rask.Bootstrapany host with your componentslink BootstrapStyles in Head, then chain the Bs* components
Rask.WebPushany backend (Server app or a WASM PWA's ASP.NET host)services.AddRaskWebPush(...) + inject IWebPushSender
Rask.Cqrsany .NET app (standalone; Server, WASM, or non-Rask)services.AddRaskCqrs() + inject IDispatcher
Rask.Cqrs.Clienta WASM app talking to its own serverservices.AddRaskCqrsClient() — the same IDispatcher, now remote
Rask.Cqrs.Serverthe ASP.NET host those clients dispatch toservices.AddRaskCqrsServer() + app.MapRaskCqrs()
Rask.Dataan EF Core app wanting a DDD base entity + interceptorsclass X : Entity<Guid> + services.AddRaskData() + modelBuilder.ApplyRaskConventions()
Rask.Outboxan EF Core app wanting durable domain-event deliveryrecord E(...) : IOutboxEvent + services.AddRaskOutbox<Ctx>() + modelBuilder.AddRaskOutbox()
Rask.Jobsan EF Core app wanting durable background jobsrecord J(...) : IJob + ICommandHandler<J> + services.AddRaskJobs<Ctx>() + modelBuilder.AddRaskJobs()
Rask.Mailan EF Core app wanting durable transactional emailservices.AddRaskMail<Ctx>(o => o.From = ...) + modelBuilder.AddRaskMail() + inject IMailQueue
Rask.Cachean EF Core app wanting a database-backed cacheservices.AddRaskCache<Ctx>() + modelBuilder.AddRaskCache() + inject ICache / IDistributedCache
Rask.Loggingany app that wants its log to survive a restartservices.AddRaskLogging("Data Source=logs.db") — no TContext, no migration; inject ILogStore to read it back
Rask.Dashboardoperating an app that uses the DB-backed pillarsservices.AddRaskDashboard<Ctx>() + an AddAuthorization policy named RaskDashboardPolicies.Access, then browse /_rask
Rask.SQLiteany .NET app using SQLite (server, mobile, trimmed/AOT)services.AddRaskSqlite(cs) + inject IRaskSqliteConnectionFactory (incl. non-blocking ExecuteInImmediateTransactionAsync)
Rask.SQLite.EntityFrameworkCorean EF Core app that wants the pragmas (+ opt-in busy retry)o.UseRaskSqlite(cs) on the DbContextOptionsBuilder
Rask.SQLite.Litestreamserver-side SQLite app wanting managed backupservices.AddRaskSqliteLitestream(...) + RestoreSqliteFromLitestreamAsync()
Rask.SQLite.Snapshotsserver-side SQLite app wanting scheduled backupsservices.AddRaskSqliteSnapshots(...) (or inject ISqliteSnapshotter)
Rask.SQLite.Browsera WASM app wanting a real SQLite database that survives a reloadservices.AddRaskBrowserSqlite("app") + o.UseSqlite(BrowserSqlite.ConnectionString("app"))
Rask.Signalingnet10.0 ASP.NET hosting the WebRTC signaling IWebRtc needsservices.AddRaskSignaling() + app.MapRaskSignaling() — needs app.UseWebSockets()
Rask.Testingyour *.Tests project (references your app)RaskTest.Render(MyComponent.Title("hi")) → assert on .Html

Documentation

The .NET One Person FrameworkThe doctrine, the batteries, and why one server beats a rented stack
Installing Rask · Getting started · Tutorial: zero to deployThe one-line installer; the UI end to end; then a whole product, one pillar per chapter
Building components · Elements & the DSLHow markup is written: naming a component and chaining onto it, and what the IDE offers at each step
Composition · Lifecycle · Routing · FormsContext, callbacks, children; mount/update/dispose; URLs and the form pipeline
The rask CLI · Deploymentnew / dev / db / deploy; Docker over SSH, auto-HTTPS, bare-VPS setup
Data · CQRS · Auth · Jobs · Email · Cache · Outbox · Logging · SQLiteThe DB-backed pillars
Bootstrap · Browser APIs · Mobile & PWATyped Bootstrap 5.3, 53 typed Web-API wrappers, installable PWAs
Best practices · Testing · Accessibility · AOTPatterns and pitfalls; unit + E2E; a11y; opt-in full WASM AOT
Migrating from Blazor · DiagnosticsDay-to-day differences side by side; every RASK build error and its fix

The full index is docs/. To click through a real app and read its source, the docs site ↗ is a live Rask app, the playground ↗ compiles Rask C# in the browser with Roslyn-powered IntelliSense, and samples/ runs locally (dotnet run --project samples/Rask.Example.Server).

Rask is the Norwegian/Danish/Swedish word for fast, and the engine earns it: after first paint a state change ships a minimal diff — a counter tick on a 24 KB page goes out as ~41 bytes. It ships fewer bytes on the wire than Blazor on every scenario in the head-to-head suite, allocates ~40× less per update and holds a ~30% leaner retained tree per mounted page. The CI-enforced numbers are in the Rask vs Blazor baselines ↗.

Status

Rask is pre-1.0; APIs may change between minor versions. It targets .NET 10 (net10.0 for ASP.NET hosts, net10.0-browser for WASM). Unit suites cover the core, generators, hosts, the back-half packages and validation, plus a Playwright E2E suite; Rask.Example.Wasm publishes with zero IL trimming warnings. Production use at your own discretion — issues and PRs welcome.

License

MIT.

Contributors

pal-tamas

920 commits

dependabot[bot]

26 commits

pal-tamas/rask

The .NET One Person Framework — build, run, and ship a whole product solo, in C#, on one server. C# components render server-side over WebSockets or on WebAssembly, or host a typed TypeScript SPA (React, Vue, Angular, Svelte, Solid, Preact, Lit); SQLite-first data, auth, jobs, mail, cache, CQRS & one-command deploy.

31

stars

946

commits

C#

primary language

Sep 4, 2026

updated

rask.sh/
angular
aspnetcore
blazor-alternative
cqrs
csharp
dotnet
entity-framework-core
one-person-framework
pwa
react
server-side-rendering
source-generator
sqlite
svelte
tailwindcss
typescript
vue
webassembly
web-framework
websockets

README

Rask

The .NET One Person Framework — build, run, and ship a whole product solo, in C#, on one server.

Site ↗ · Docs ↗ · Playground ↗

The Counter component typed out in an editor: a tooltip explains the [ … ] indexer as H1[ is written, then the caret stops after Button. and a completion list opens showing Class, Id, OnClick and Style, each with its own doc comment.

You write components as plain C# classes that return a tree of HTML from Render(). State is a field, an event handler is a delegate, and the component re-renders itself — no .razor, no JSX, no JavaScript, nothing to write in another language:

[Route("/counter")]
public sealed partial class Counter : Component
{
    private int _count;

    protected override Component? Render() =>
    [
        H1["Counter"],
        P[$"Current count: {_count}"],
        Button.OnClick(() => _count++)["Click me"]
    ];
}

Rask is the .NET One Person Framework. One developer builds, runs and ships a complete product — the UI, the data, the auth, the background work and the deployment — from one C# codebase on one server, with SQLite as the production database. No PaaS to rent, no stack of services to glue, no second language to context-switch into. The same component runs two ways: server-rendered with live updates over a WebSocket, or fully client-side on WebAssembly as an installable offline PWA.

Quickstart

An empty folder to a live, HTTPS, database-backed product, by one person in one sitting:

curl -sSL https://pal-tamas.github.io/rask/rask.sh | sh   # the CLI, and everything it shells out to

rask new Shop --auth                                      # scaffold: the whole stack + a cookie login
# …write a Products slice — docs/tutorial/02-first-feature.md has the code
rask db add InitialCreate && rask db update                # create + apply the SQLite migration
rask dev                                                   # run it, hot-reloading, at /products
rask deploy --host root@box --domain shop.example.com      # ship it: bare box → Docker + auto-HTTPS, zero-downtime

Every step is a first-party command, and every stateful pillar it touches — auth, jobs, mail, cache, events — rides the app's own SQLite database. Run rask with no arguments for a wizard.

Prerequisites: none. The installer adds whatever is missing — the .NET 10 SDK, the wasm-tools workload that browser bundles need, Node for the SPA templates — all under $HOME, no sudo. On Windows: irm https://pal-tamas.github.io/rask/rask.ps1 | iex. Already have the .NET 10 SDK and want only the tool? dotnet tool install -g Rask.Cli. Options, install locations and uninstall: docs/installation.md.

Want the pages to run in the browser too? rask new Shop --wasm publishes a WebAssembly bundle from that same project, and a page that can run client-side moves there once it has downloaded — no second project, no separate build. Until then, and for any page that reaches a database, it stays live over the socket. See render modes.

Prefer React? rask new Shop --template react scaffolds a Vite client on an ASP.NET host, with the front end's TypeScript generated from your C# message records on every build — so await rask.dispatch(getOrder({ id })) is typed, and renaming a property breaks the build rather than the wire. The client is a TypeScript SPA — React, Preact, Vue, Angular, Solid, Svelte or Lit, but not JavaScript, since every guarantee here is one a compiler makes. See docs/spa.md. (Needs Node.js.)

Want React inside a Rask app rather than instead of one? Derive a component from ReactComponent and drop a Chart.tsx beside it — it becomes an ordinary component you place anywhere the chain goes, a leaf in a card or a whole route. Props are declared in C# and checked in both directions, callbacks re-enter C# over the channel every handler already uses, and the live diff leaves the subtree alone because its own renderer owns it. LitComponent pairs with a .ts the same way. Rename a C# property and the front end stops compiling. Needs Node, because your React does. See docs/external-components.md.

Packages

Pick one host package per project, then add what you need. Everything below targets .NET 10 and is trim/AOT-safe.

PackageVersionWhat it's for
Hosts & tooling
Rask.ServerRask.ServerASP.NET host — state changes stream to the browser as minimal diffs over a WebSocket
Rask.WasmRask.WasmBrowser-WebAssembly host — the same components client-side, installable as an offline PWA
Rask.Wasm.HostingRask.Wasm.HostingServes a published WASM bundle from an ASP.NET host
Rask.Spa.HostingRask.Spa.HostingServes a built TypeScript SPA, and generates its TypeScript from your C# contracts
Rask.ExternalRask.ExternalA .tsx or Lit file as an ordinary Rask component, with props owned by C# (needs Node)
Rask.CliRask.Clinew · dev · db · deploy · info · doctor — the whole lifecycle, one tool
Rask.BootstrapRask.BootstrapTyped Bootstrap 5.3 components, zero-JS interactivity, typed utility classes
Rask.TestingRask.TestingRender a component in a unit test and assert on its HTML
Vertical-slice back end
Rask.CqrsRask.CqrsSource-generated, reflection-free queries / commands / notifications via IDispatcher
Rask.Cqrs.ClientRask.Cqrs.ClientA WASM client dispatches to its server through the same IDispatcher call — no HttpClient
Rask.Cqrs.ServerRask.Cqrs.ServerThe endpoint pair those messages arrive on — authenticated by default, no /api/* to write
Rask.DataRask.DataEntity<TId> + EF interceptors: audit stamps, soft delete, optimistic concurrency, domain events — and BulkInsertAsync, the bulk insert EF Core leaves out
Rask.OutboxRask.OutboxCrash-safe domain events, committed in the same transaction as your data
Rask.JobsRask.JobsDurable enqueued / delayed / recurring background work, with retries
Rask.MailRask.MailDurable transactional email over SMTP — bodies are Rask components
Rask.CacheRask.CacheIDistributedCache + a typed ICache.GetOrCreateAsync, on the app DB
Rask.LoggingRask.LoggingThe application log in a database of its own, so it survives a restart — searchable, with retention
Rask.DashboardRask.DashboardAn operator dashboard at /_rask: queue depth, dead letters, one-click retry, the log
Production SQLite
Rask.SQLiteRask.SQLiteWAL, busy-timeout, non-blocking write retries — one file as a real production database
Rask.SQLite.EntityFrameworkCoreRask.SQLite.EntityFrameworkCoreThose pragmas (and opt-in busy retry) on a DbContext
Rask.SQLite.LitestreamRask.SQLite.LitestreamContinuous streaming replication off-box, managed for you
Rask.SQLite.SnapshotsRask.SQLite.SnapshotsScheduled backups
Rask.SQLite.BrowserRask.SQLite.BrowserA real SQLite database inside the browser tab that survives a reload
Forms, push & realtime
Rask.Validation.DataAnnotationsRask.Validation.DataAnnotationsDataAnnotationsValidator inside a Form
Rask.Validation.FluentValidationRask.Validation.FluentValidationFluentValidationValidator inside a Form
Rask.WebPushRask.WebPushServer-side Web Push (VAPID + RFC 8291), zero external dependencies
Rask.SignalingRask.SignalingThe WebRTC signaling IWebRtc needs

Rask.Server and Rask.Wasm pull in Rask.Core, Rask.Html and the source generators transitively.

Package → project type → entry-point API (click to expand)
PackageProject typeEntry-point API
Rask.Servernet10.0 ASP.NETservices.AddRask() + app.UseRask<TApp>()
Rask.Wasmnet10.0-browserWasmHostBuilder.CreateDefault() + host.RunAsync<TApp>()
Rask.Wasm.Hostingnet10.0 ASP.NET (with a <ProjectReference> to the WASM project)app.UseRask()
Rask.Validation.DataAnnotationsany host that hosts your formsdrop DataAnnotationsValidator inside a Form
Rask.Validation.FluentValidationany host that hosts your formsdrop FluentValidationValidator.Validator(myValidator) inside
Rask.Bootstrapany host with your componentslink BootstrapStyles in Head, then chain the Bs* components
Rask.WebPushany backend (Server app or a WASM PWA's ASP.NET host)services.AddRaskWebPush(...) + inject IWebPushSender
Rask.Cqrsany .NET app (standalone; Server, WASM, or non-Rask)services.AddRaskCqrs() + inject IDispatcher
Rask.Cqrs.Clienta WASM app talking to its own serverservices.AddRaskCqrsClient() — the same IDispatcher, now remote
Rask.Cqrs.Serverthe ASP.NET host those clients dispatch toservices.AddRaskCqrsServer() + app.MapRaskCqrs()
Rask.Dataan EF Core app wanting a DDD base entity + interceptorsclass X : Entity<Guid> + services.AddRaskData() + modelBuilder.ApplyRaskConventions()
Rask.Outboxan EF Core app wanting durable domain-event deliveryrecord E(...) : IOutboxEvent + services.AddRaskOutbox<Ctx>() + modelBuilder.AddRaskOutbox()
Rask.Jobsan EF Core app wanting durable background jobsrecord J(...) : IJob + ICommandHandler<J> + services.AddRaskJobs<Ctx>() + modelBuilder.AddRaskJobs()
Rask.Mailan EF Core app wanting durable transactional emailservices.AddRaskMail<Ctx>(o => o.From = ...) + modelBuilder.AddRaskMail() + inject IMailQueue
Rask.Cachean EF Core app wanting a database-backed cacheservices.AddRaskCache<Ctx>() + modelBuilder.AddRaskCache() + inject ICache / IDistributedCache
Rask.Loggingany app that wants its log to survive a restartservices.AddRaskLogging("Data Source=logs.db") — no TContext, no migration; inject ILogStore to read it back
Rask.Dashboardoperating an app that uses the DB-backed pillarsservices.AddRaskDashboard<Ctx>() + an AddAuthorization policy named RaskDashboardPolicies.Access, then browse /_rask
Rask.SQLiteany .NET app using SQLite (server, mobile, trimmed/AOT)services.AddRaskSqlite(cs) + inject IRaskSqliteConnectionFactory (incl. non-blocking ExecuteInImmediateTransactionAsync)
Rask.SQLite.EntityFrameworkCorean EF Core app that wants the pragmas (+ opt-in busy retry)o.UseRaskSqlite(cs) on the DbContextOptionsBuilder
Rask.SQLite.Litestreamserver-side SQLite app wanting managed backupservices.AddRaskSqliteLitestream(...) + RestoreSqliteFromLitestreamAsync()
Rask.SQLite.Snapshotsserver-side SQLite app wanting scheduled backupsservices.AddRaskSqliteSnapshots(...) (or inject ISqliteSnapshotter)
Rask.SQLite.Browsera WASM app wanting a real SQLite database that survives a reloadservices.AddRaskBrowserSqlite("app") + o.UseSqlite(BrowserSqlite.ConnectionString("app"))
Rask.Signalingnet10.0 ASP.NET hosting the WebRTC signaling IWebRtc needsservices.AddRaskSignaling() + app.MapRaskSignaling() — needs app.UseWebSockets()
Rask.Testingyour *.Tests project (references your app)RaskTest.Render(MyComponent.Title("hi")) → assert on .Html

Documentation

The .NET One Person FrameworkThe doctrine, the batteries, and why one server beats a rented stack
Installing Rask · Getting started · Tutorial: zero to deployThe one-line installer; the UI end to end; then a whole product, one pillar per chapter
Building components · Elements & the DSLHow markup is written: naming a component and chaining onto it, and what the IDE offers at each step
Composition · Lifecycle · Routing · FormsContext, callbacks, children; mount/update/dispose; URLs and the form pipeline
The rask CLI · Deploymentnew / dev / db / deploy; Docker over SSH, auto-HTTPS, bare-VPS setup
Data · CQRS · Auth · Jobs · Email · Cache · Outbox · Logging · SQLiteThe DB-backed pillars
Bootstrap · Browser APIs · Mobile & PWATyped Bootstrap 5.3, 53 typed Web-API wrappers, installable PWAs
Best practices · Testing · Accessibility · AOTPatterns and pitfalls; unit + E2E; a11y; opt-in full WASM AOT
Migrating from Blazor · DiagnosticsDay-to-day differences side by side; every RASK build error and its fix

The full index is docs/. To click through a real app and read its source, the docs site ↗ is a live Rask app, the playground ↗ compiles Rask C# in the browser with Roslyn-powered IntelliSense, and samples/ runs locally (dotnet run --project samples/Rask.Example.Server).

Rask is the Norwegian/Danish/Swedish word for fast, and the engine earns it: after first paint a state change ships a minimal diff — a counter tick on a 24 KB page goes out as ~41 bytes. It ships fewer bytes on the wire than Blazor on every scenario in the head-to-head suite, allocates ~40× less per update and holds a ~30% leaner retained tree per mounted page. The CI-enforced numbers are in the Rask vs Blazor baselines ↗.

Status

Rask is pre-1.0; APIs may change between minor versions. It targets .NET 10 (net10.0 for ASP.NET hosts, net10.0-browser for WASM). Unit suites cover the core, generators, hosts, the back-half packages and validation, plus a Playwright E2E suite; Rask.Example.Wasm publishes with zero IL trimming warnings. Production use at your own discretion — issues and PRs welcome.

License

MIT.

See what people are saying

Contributors

pal-tamas

920 commits

dependabot[bot]

26 commits

Languages

C#

93.5%

TypeScript

4.6%

Shell

1.3%