Store data. Talk to things. Run work in the background.
Birko is a modular .NET framework for the plumbing you would otherwise rewrite for every project and every backend. One store API over 13 storage backends — the same code works whether your data lives in SQLite, PostgreSQL, MongoDB, Elasticsearch or a JSON file.
What it gives you
Pick the pieces you need
Everything below sits beside the data layer, not on top of it. You can use Birko's REST client without using its stores, and vice versa.
Save and query objects
One store API over 13 backends — sync and async, with bulk operations and lazy schema init that creates tables and indexes on first use.
Use a real SQL database
Attribute-mapped models across SQL Server, PostgreSQL, MySQL, SQLite and TimescaleDB, with a platform-agnostic migration framework — write once, run anywhere.
Call or serve APIs
REST, gRPC, GraphQL, SOAP, WebSocket and SSE — plus Bluetooth, Modbus, NFC, IR and camera adapters for the hardware end.
Talk to an LLM
One interface over Claude, OpenAI, Gemini, Ollama and Azure, with a coding/media/task agent catalogue, orchestration and retry-and-fallback resilience.
Run jobs and state machines
Background job queues over 8 persistence backends, and a workflow engine with guards, actions and Mermaid/DOT export.
Log people in
PBKDF2 and BCrypt hashing, AES, JWT, OAuth, RBAC, ASP.NET Core integration, HashiCorp Vault and Azure Key Vault.
Build a web UI
55 Shadow-DOM components with reactive state, a hash router and a three-level app shell. No framework, no build magic.
Build a desktop app
An Avalonia-first XAML shell with an Avalonia-free MVVM core and four runtime-swappable themes — sharing design tokens byte-for-byte with the web CSS.
The one idea worth understanding first
Shared projects, not packages
Birko is consumed as source via .projitems. Your project compiles Birko's code
together with your own — no binary dependencies, and you can step into framework code in the
debugger.
The consequence that trips everyone up once: a project pulls in more than you asked for. The graph is dense — asking for SQLite stores also needs models, view-models, patterns, rules and helpers, because they reference each other's types directly.
So don't build the import list up one project at a time. Start from Birko.Sandbox's list — 38 imports, known to compile, covering stores, SQL, migrations, caching, workflow, jobs, health, REST, GraphQL and security — and delete what you do not use.
In practice
The whole loop
Declare a model, point a store at a file, and you have CRUD. The table is created automatically on first use — no migration needed to get started.
Every sample on this page is taken from the wiki, where a CI job compiles each snippet against the current framework. The guide cannot quietly stop matching the code.
using Birko.Data.Models; using Birko.Data.SQL.Attributes; [Table("Products")] public class Product : AbstractDatabaseModel { [MaxLengthField(200)] public string Name { get; set; } = string.Empty; [PrecisionField(18), ScaleField(2)] public decimal Price { get; set; } } // AbstractDatabaseModel gives you a Guid primary key. // Precision and scale are separate attributes — use both, // or decimals come back as whole numbers.
using Birko.Data.SQL.SqLite.Stores; var store = new SQLiteStore<Product>(); store.SetSettings(new SqLiteSettings(@"C:\data", "shop.db")); // create var id = store.Create(new Product { Name = "Widget", Price = 9.99m }); // read one var product = store.Read(id); // query — filter, orderBy, limit, offset var cheap = store.Read(x => x.Price < 10m, null, null, null); // update product!.Price = 12.50m; store.Update(product); // count and delete var total = store.Count(); store.Delete(product);
// Same model, same calls. Only construction changes. using Birko.Data.InMemory.Stores; var store = new InMemoryStore<Product>(); // no settings needed — the recommended test double // …or MongoDB using Birko.Data.MongoDB.Stores; var store = new MongoDBStore<Product>(); store.SetSettings(settings); // Create / Read / Update / Delete / Count are identical // from here on. That is the point of the store API.
Storage backends
The repository
177 library projects, by area
Every project is a top-level directory in one repo, with its tests under tests/.
Counted from the source tree, not from a hand-kept list.
The ten single-project areas: Contracts, Configuration, Helpers, CQRS, Rules, Validation, Structures, Random, Redis and DesignTokens.
Getting started
About ten minutes
To working CRUD against a real SQLite database. The wiki walks each step with files you can copy.
Read the guide-
Clone it next to your project
Birko is consumed as source. The recommended layout nests the framework under
Birko\Frameworkwith your own repos in a siblingBirko\Consumers. -
Point at it with
$(BirkoSrc)One
Directory.Build.propsat your repo root resolves/p:BirkoSrc=…, then theBIRKO_SRCenvironment variable, then a sensible default — so CI and Docker override it without editing files. -
Create one aggregator project
It imports the
.projitemsyou need; your other projects reference it. One aggregator avoids the duplicate-type errors you get when several projects import overlapping shared projects independently. -
Write a model and use it
The table is created on first use. No migration needed until you want one.
Ecosystem
Where things live
The framework itself — 177 library projects at the repo root, 167 test projects under tests/, plus the wiki and the full docs set.
Frontend libraries — Core, Components, Shell and Testing. TypeScript, built with esbuild, no framework dependency.
Birko.Web.PlaygroundLive component gallery — the whole b-* library running in your browser, with a design-token editor and theme export. Nothing to install.
Runnable reference consumer — wires up one slice of each layer and prints OK/FAIL. Small, real, and the import list to copy from.