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. Components are plain C# classes that return a tree of HTML from Render(): state is a
field, and an event handler is a delegate.
[Route("/counter")]
public sealed partial class Counter : Component
{
private int _count;
protected override Component? Render() =>
Button.OnClick(() => _count++)[$"Current count: {_count}"];
}curl -sSL https://rask.sh/rask.sh | shOn Windows, in PowerShell: irm https://rask.sh/rask.ps1 | iex.
Prerequisites: none. The installer adds whatever is missing — the .NET 10 SDK, the wasm-tools
workload, Node — all under $HOME, no sudo. Already have the SDK and want only the tool?
dotnet tool install -g Rask.Cli. See installation.
Adding Rask to a project you already have is one package:
dotnet add package RaskRask is a superset, not a rival: your React, Vue, Svelte, Angular or Lit components, a real Blazor component, a TypeScript SPA or a Nuxt or Next.js app all run on it — and it builds on ASP.NET Core and EF Core rather than replacing them. Pick one per project — all four sit on the same C# back end. Islands also compose inside a Rask component tree, so those two mix freely.
C# components, server-rendered, with every state change streaming to the browser as a minimal diff
over a WebSocket. Add --wasm and the same components also publish as a WebAssembly bundle from that
same project — no second project, no separate build. The bundle is fetched once the page goes idle, and
a page that can run client-side moves there on the next navigation; until then, and for any page that
reaches a database, it stays live over the socket.
rask new Shop→ Render modes · Building components
A .tsx, .vue, .svelte or Lit file as an ordinary Rask component. Derive from
ReactComponent, PreactComponent, SolidComponent, VueComponent, SvelteComponent,
AngularComponent or LitComponent, drop the front-end file beside
it, and place it anywhere the chain goes — a leaf inside a card, or a whole route. Props are declared
in C#, 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. This is the one pillar Rask does not bring on its
own: add Rask.External, and Node, because your React does.
public sealed partial class Chart : ReactComponent
{
public required IReadOnlyList<Point> Series { get; set; }
}→ Islands
A TypeScript single-page app on an ASP.NET host — React, Preact, Vue, Angular, Solid, Svelte or Lit.
The client's TypeScript is generated from your C# message records on every build, so
await rask.dispatch(getOrder({ id })) is typed and renaming a C# property breaks the build rather
than the wire.
rask new Shop --template reactNuxt, Next.js, SvelteKit, TanStack Start, SolidStart or Analog owning the whole front end — its own
routing, its own rendering, its own Node server — with Rask as the backend behind it. The two ship as
one container on one port: Rask fronts every request, supervises Node as a child process and
forwards to it over loopback, so ASP.NET auth, rate limiting, logging and health stay in front of the
framework and the session has one owner. The client was imported from the framework's own creator —
nuxi, create-next-app, sv, @tanstack/cli — and is committed, so rask new writes it with no
network and no Node, plus a node-server build and a dev proxy.
scripts/refresh-templates.sh is how a newer upstream gets in. Add Rask.Meta.Hosting, and Node at
runtime, because the framework needs it.
rask new Shop --template nuxtrask dev # run it — the first migration is already applied
rask db add AddProducts && rask db update # after you change the model
rask deploy --host root@box --domain shop.example.com # bare box → Docker + auto-HTTPS, zero-downtimeRun rask with no arguments for a wizard.
Auth, jobs, mail, cache, events and file storage are on by default, and every one of them keeps its records in the app's own SQLite database (an upload's bytes go to disk or a bucket) — no broker, no Redis, no second service to run. A fresh app can register somebody, sign them in, confirm their address and reset their password with no auth code written.
- Auth — accounts out of the box: register, sign in, sign out, route guards, and the first account to register is the administrator.
- Background jobs — enqueued, delayed and recurring work on your database, at-least-once with exponential backoff.
- Email — transactional mail queued in the same database and delivered over SMTP off the request thread; bodies are Rask components.
- Outbox — domain events committed in the same transaction as your data and relayed at-least-once, with no message broker.
-
Cache — the standard
IDistributedCacheplus a typedICachewithGetOrAddAsync. - Data · CQRS — audit stamps, soft delete, optimistic concurrency and domain events on EF Core, and a source-generated, reflection-free mediator.
- Production SQLite — WAL and busy-timeout pragmas, continuous Litestream backup, scheduled snapshots.
-
Logging — the
ILoggerpipeline kept in a SQLite file of its own, with retention by age and row count. -
Operator console —
/_rask: queue depth, dead letters and the errors behind them, cache contents and a log tail, behind an authorization policy. - PWA · Web Push — installable, offline apps, and push sent from your backend on your own VAPID keys.
- File storage — uploads on disk, in S3-compatible storage or in Azure Blob, with a row per file on your database and public or expiring links.
-
Deploy —
rask deploytakes a bare VPS to a live HTTPS site with zero-downtime swaps.
They build on the standard .NET pieces — EF Core, hosted services, ILogger, IDistributedCache,
ASP.NET Core authentication — so adding one is a package reference, not a new stack to learn or a new
box to operate.
| The One Person Framework | The doctrine, the batteries, and why one server beats a rented stack |
| Getting started · Tutorial | The UI end to end; then a whole product, one pillar per chapter |
| Building components · Routing · Forms | How markup is written, the URLs it answers, and the form pipeline |
The rask CLI · Deployment
|
new / dev / db / deploy; Docker over SSH, auto-HTTPS, bare-VPS setup |
| Data · CQRS · Auth · Jobs · File storage · SQLite | The database-backed pillars |
| HTTP APIs | API controllers and minimal APIs, hosted properly and called through a client generated from them |
| Migrating from Blazor · Diagnostics | Day-to-day differences side by side; every RASK build error and its fix |
The full index is docs/, and the other packages are listed in
NUGET.md. To see it running, rask.sh is a Rask app — landing page,
guides and every live demo — built from src/Rask.Site.
Rask is the Norwegian/Danish/Swedish word for fast.
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). Production use at your own discretion — issues and PRs welcome.
MIT.