Blog
Tools We Use to Build Papyrus
A guided tour of the stack — what we picked, what we replaced, what's working in 2026 and what we'll probably swap out next year.
Tools We Use to Build Papyrus
Periodically asked. Here's the answer in 2026.
Backend
- .NET 10 — the runtime. C# 13, primary constructors, file-scoped namespaces. Talent pool in Kenya is strong; productivity is high.
- ASP.NET Core Minimal APIs — endpoints colocated with feature modules
- Entity Framework Core 10 — ORM. Global query filters do tenant isolation
- SQL Server 2022 — primary DB. We considered PostgreSQL; talent and operational tooling won the day for SQL Server in our context.
- Redis 7 (Memurai on Windows) — cache. Falls back to in-memory when Redis is unavailable.
- MassTransit + RabbitMQ — event bus for cross-feature communication
- Qdrant Cloud — vector store for semantic search and RAG
- Tesseract 5 — OCR (server-side)
- ML.NET + ONNX Runtime — for classification models
Frontend
- Blazor Server — main web UI. We get to write C# end-to-end. Latency is fine for our use cases.
- MudBlazor — component library
- Vanilla CSS — no framework; we use CSS custom properties heavily for theming
- Markdig — markdown rendering (used heavily by the Resources wiki, less by the product itself)
Mobile
- .NET MAUI 10 — cross-platform mobile (Android, iOS, macOS, Windows)
- BlazorWebView — we render Blazor components inside MAUI
- SQLite — local cache and offline queue
AI / ML stack
- Hosted LLM provider — for embeddings and Tier 3 LLM calls (RAG synthesis, Copilot). Pluggable behind an internal
IOpenAiService-style interface so we can swap providers without touching feature code. - ML.NET — for our in-house classifiers
- ONNX Runtime — for running classifiers on device (Tier 1 edge inference)
- Custom retraining pipeline — runs quarterly with human-corrected labels
DevOps / Operations
- GitHub Actions — CI/CD
- Web Deploy + IIS — deployment (yes, still IIS; we're on Windows Server with the .NET ecosystem)
- Serilog + Seq — structured logging
- OpenTelemetry — tracing and metrics
- .NET Aspire — dev orchestration
- Polly 8 — HTTP resilience
Infrastructure
- Contabo VPS / Windows Server / IIS — hosting
- Let's Encrypt — SSL
- Cloudflare — DNS, CDN for static assets
Integrations
- Safaricom Daraja — M-Pesa
- Stripe — international card payments
- KRA eTIMS — Kenyan tax invoicing
- MailKit — SMTP outbound
- Fido2NetLib — WebAuthn / passkeys
- WebPush — browser push notifications
- Sustainsys.Saml2 — SAML SSO
What we replaced
A few things we've moved on from:
- Self-hosted Qdrant → Qdrant Cloud (operational cost)
- PostgreSQL evaluation → SQL Server (talent + tooling)
- Hangfire → IHostedService for background jobs (simpler when you have MassTransit)
- AutoMapper → continuing to use it but we've eyed Mapperly for performance
What we'll probably change
Honest predictions:
- Mobile: MAUI is fine but Blazor inside it is awkward. We may move to native UI per platform within 18 months.
- Vector store: we're watching pgvector + Postgres. If SQL Server doesn't get good vector support, we might switch the DB for the vector use case.
- AI provider: we have one hosted LLM provider in production today; multi-provider abstractions and local-model fallbacks are on the roadmap so we can route per cost, latency, or data-residency need.
- Push notifications: WebPush + FCM + APNS is three places to keep in sync. Some convergence in the standards would help; we'll adopt that when it arrives.
What we won't change
- .NET — the productivity is real
- Multi-tenancy via shared DB with query filters — has held up well
- The audit log architecture — hash chaining works
- Pricing in KES for African customers — pricing in dollar was a mistake we won't repeat
Closing
This stack is a snapshot of what works for our team and market in 2026. It's not universal advice. The stack that fits your team and market is the one you can ship with. Don't copy our choices; copy our willingness to change them when the data demands it.