sektorCMS
sektorCMS is a small content system for a personal site, written in C# with ASP.NET Core and Blazor. It is meant to be read: every part is a short file you can open and change.
It handles:
- Projects with a description, links, platforms and downloadable releases
- Products with a price and purchase link
- Posts written in Markdown
- Release files you upload once and visitors download from a stable link such as
/download/my-app/latest - A JSON API and an admin area to manage all of it
- Colours, fonts and hover effects set from plain JSON files
What you need
- The .NET 10 SDK
- MariaDB or MySQL
First run
Create an empty database and a login that only has rights on it.
CREATE DATABASE cms CHARACTER SET utf8mb4; CREATE USER 'cms'@'localhost' IDENTIFIED BY 'choose-a-long-password'; GRANT ALL PRIVILEGES ON cms.* TO 'cms'@'localhost';Keep the password out of the code. From the project folder, store the connection string with .NET user secrets:
dotnet user-secrets set "ConnectionStrings:DefaultConnection" "Server=localhost;Database=cms;User=cms;Password=choose-a-long-password"Create the tables and start the site:
dotnet ef database update dotnet runOn the first start the app creates one blog and a few example projects.
Open
/Account/Registerand create your account.Make that account the site admin, then restart the app:
dotnet user-secrets set "Setup:SuperAdminEmail" "you@example.com"Log in at
/loginand open/admin.
Settings
Set these in appsettings.json or, for anything secret, with dotnet user-secrets or environment variables (Api__Key for Api:Key).
| Setting | What it does |
|---|---|
ConnectionStrings:DefaultConnection |
How to reach the database |
Setup:SuperAdminEmail |
The account that gets the SuperAdmin role at startup |
Api:Key |
Secret for changing content through the API. At least 16 characters. Leave it unset to keep the API read-only |
Site:Blog |
Name of the blog to show when there is more than one. Defaults to the first |
Storage:Path |
Where uploaded release files are kept. Defaults to App_Data/releases |
Storage:Media |
Where uploaded screenshots and gifs are kept. Defaults to App_Data/media. Keep it outside the app folder on a server so updates do not remove it |
Database:ServerVersion |
The MariaDB version the app talks to, for example 10.11.14. Defaults to 13.0.2 |
Where things are
| Folder | What is in it |
|---|---|
Data/Classes/Objects |
The data classes: Project, Product, Page (a post), ReleaseFile, Blog and so on, plus ApplicationDbContext |
Data/Classes/Utils |
The services: SiteService (what the public site shows), ReleaseStorage (uploaded files), SektorApi (the API), Seeder |
Data/Migrations |
Database changes made with dotnet ef migrations add |
Data/Style |
Colours.json, Theme.json and Actions.json, turned into /theme.css |
Components/Pages |
The public pages |
Components/Pages/Admin |
The admin pages |
Components/Cms |
Small shared pieces: the Markdown view, the project card |
Docs |
The Markdown files you are reading |
Publishing a release
You can upload from /admin/projects (choose Releases) or from a script with the API:
curl -X POST https://example.com/api/projects/my-app/releases \
-H "X-Api-Key: YOUR_API_KEY" \
-F file=@MyApp-1.2.0.exe \
-F version=1.2.0 \
-F platform=WINDOWS \
-F architecture=amd64
Visitors then get the newest file from /download/my-app/latest. The project page lists every version with its size and SHA-256 checksum.
Screenshots and gifs
Upload images at /admin/media. Each upload shows its address, for example /media/my-app/home.png. Paste the address into the project's Screenshots field, one per line, with an optional caption after a |:
/media/my-app/home.png | The home screen
/media/my-app/demo.gif | A short demo
The first image is also used as the cover of the project card.
Projects whose source code is private only show the downloads. Untick Source code is public on the project to hide the repository links.
Styling
Edit the JSON files in Data/Style and refresh the page. There is nothing to rebuild.
Colours.jsongives names to colours, for example"Primary": "006BB7".Theme.jsonsets fonts, colours and sizes per area (navigation bar, headings, links, buttons, forms, footer). The worddefaultmeans "same as theDefaultsection".Actions.jsonsets what hover, click, focus, disabled and similar states look like.
Notes
- Posts, descriptions and docs use Markdown. Raw HTML inside Markdown is switched off on purpose.
- Pages and products are only shown when they are Active, Published and Public.
- Registration is open by default. Only accounts with the
SuperAdminrole can reach/admin.