Open source · .NET 9 · MIT licence
Elevare
An open-source content management system written on .NET 9, with a drag-and-drop page builder, approval workflows and multi-language content.
The site you are reading right now runs on Elevare too.

- .NET 9Blazor Server and ASP.NET Core MVC
- PostgreSQLTwo applications, one database
- GrapesJSVisual page builder
- 730+Automated tests
- MITUse it, change it, ship it
01 · The story
Why I built it
When I set up this site, I wanted to design the whole journey myself: how content gets written, who signs it off, and how it reaches the reader. Rather than bolting plugins onto an off-the-shelf system until it roughly fit, I decided to build one that started from the need itself.
That is how Elevare began: as the admin panel for my own site. Over time it grew a page builder, approval workflows, multi-language support, SEO tooling and backups. Once it had matured, I released it as open source so anyone could use it, read it and improve it.
02 · Architecture
Two applications, one database
Elevare is made of two applications that run independently. There is no API between them; they share one PostgreSQL database and follow a single rule.
Data flows one way
The CMS owns the schema and writes the content; the site only reads. The only things the site writes are visit statistics, form submissions and error logs.
A contract that cannot drift
The site reads the CMS tables through its own read-only models. Contract tests catch a renamed column at build time rather than in production.
Changes land immediately
The site keeps rendered pages for up to an hour, but the CMS clears that cache after every successful save. Your edit shows up on the next page view.
03 · Features
What it can do
Everything a content team needs day to day, in a single panel.
Visual page builder
Build pages by dragging GrapesJS blocks into place, and share a preview link with others before anything goes live.
Linked and copied templates
Parts that must be identical everywhere, like the header, are linked: edit the template and every page follows. A copied template gives a page a starting point of its own.
Approval workflows
You decide the steps and who signs off at each one. The change comparison looks at the text readers see, not at the HTML.
Role-based permissions
Permissions are edited in the panel and enforced on the server on every request. Hiding a button is never the only thing standing in the way.
Multi-language content
Each language has its own URL prefix and two separate switches: can it be authored, and is it live. An unfinished translation cannot leak.
SEO tooling
Per-page meta tags and structured data, robots.txt and llms.txt edited in the panel, a generated sitemap and a live SEO score in the editor.
Smart redirects
Renaming, deleting or archiving a page writes its redirect automatically. The screen leads with dead targets, loops and chains.
Lightweight images
Every upload gets WebP and resized copies, and the site picks the right size. One image produces the whole favicon set.
Forms
Spam protection, canned replies and attachments checked by their actual content. Only people with the permission can download them.
The Trash
Anything deleted can be restored. A restored site code comes back switched off, because re-serving a script to every visitor is a decision of its own.
Site codes
Analytics, a consent banner or a chat widget are added to every page, and can be switched off on individual pages.
Live settings
SMTP, CAPTCHA and S3 credentials are stored encrypted and apply the moment you save them. Even switching from local disk to S3 needs no restart.
04 · Screens
A few frames from the panel





05 · Under the hood
Engineering notes
Some of the decisions behind Elevare never show up on screen, but they are exactly what keeps the system dependable.
Errors are not exceptions
Handlers return a Result. Every error has a stable code that doubles as its translation key, and a code without a Turkish message fails the build.
A pipeline with a fixed order
Every request passes the same steps in the same order: a concurrency guard, logging, permission check, validation, the save itself and the cache clear. Forgetting a permission check is not possible.
A cache outage is not a site outage
When Redis is unreachable the site does not fail; it simply runs as if there were no cache. The cache only ever speeds things up and is never a single point of failure.
No silently overwritten saves
If the same page is open in two places, the editor sends the fingerprint the page had when it was opened. If it changed in between, the save is refused and the user decides.
Soft delete
Deleted rows stay in the database. Permanent deletion happens in exactly one place, and it refuses to destroy a page that holds form submissions or sub-pages.
Warnings are errors
The build runs with TreatWarningsAsErrors, with Sonar and the .NET analyzers on. Every rule that is switched off carries a comment saying why.
06 · Stack
What it is built with
| Layer | Technology |
|---|---|
| Admin panel | Blazor Server (.NET 9) |
| Public site | ASP.NET Core MVC, output cache, Brotli compression |
| Database | PostgreSQL 15, Entity Framework Core |
| Page builder | GrapesJS with Elevare's own blocks |
| Application layer | MediatR (CQRS), FluentValidation |
| Identity and access | ASP.NET Core Identity, JWT, role-based permissions |
| Background jobs | Hangfire |
| Caching | Redis (optional) or in-memory cache |
| Logging | Serilog, optionally Seq |
| Deployment | Docker Compose, GitHub Actions |
07 · Getting started
Up and running in three commands
If you have Docker installed, you need nothing else: no .NET SDK, no PostgreSQL.
Get the code
git clone https://github.com/Oguzhankaraguzel/elevare.git cd elevareCreate the settings file
cp .env.example .envFill in the blanks in .env. The stack refuses to start with any of them empty, so nothing ever runs on a default password.
Start it
docker compose up -d --buildThe panel opens at http://localhost:5150 and the site at http://localhost:5160.
All of the code is on GitHub
Drop by the repository to look around, report a bug or contribute. Every bit of feedback moves Elevare a little further.
