Oğuzhan KARAGÜZEL

OĞUZHAN KARAGÜZEL

Software Developer

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.

The Elevare page builder: blocks on the left, the page in the middle, settings on the right

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.

CMSBlazor ServerThe admin panel: pages, templates, approvals, settings
writes→
PostgreSQLElevareDBThe CMS owns the schema
reads←
SiteASP.NET Core MVCThe published pages visitors see

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.

01

Visual page builder

Build pages by dragging GrapesJS blocks into place, and share a preview link with others before anything goes live.

02

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.

03

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.

04

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.

05

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.

06

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.

07

Smart redirects

Renaming, deleting or archiving a page writes its redirect automatically. The screen leads with dead targets, loops and chains.

08

Lightweight images

Every upload gets WebP and resized copies, and the site picks the right size. One image produces the whole favicon set.

09

Forms

Spam protection, canned replies and attachments checked by their actual content. Only people with the permission can download them.

10

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.

11

Site codes

Analytics, a consent banner or a chat widget are added to every page, and can be switched off on individual pages.

12

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.

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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

LayerTechnology
Admin panelBlazor Server (.NET 9)
Public siteASP.NET Core MVC, output cache, Brotli compression
DatabasePostgreSQL 15, Entity Framework Core
Page builderGrapesJS with Elevare's own blocks
Application layerMediatR (CQRS), FluentValidation
Identity and accessASP.NET Core Identity, JWT, role-based permissions
Background jobsHangfire
CachingRedis (optional) or in-memory cache
LoggingSerilog, optionally Seq
DeploymentDocker 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.

  1. Get the code

    git clone https://github.com/Oguzhankaraguzel/elevare.git
    cd elevare
  2. Create the settings file

    cp .env.example .env

    Fill in the blanks in .env. The stack refuses to start with any of them empty, so nothing ever runs on a default password.

  3. Start it

    docker compose up -d --build

    The 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.