Back to "Mest lucid.MinimalBlog - Hur enkelt kan en ASP.NET blogg verkligen vara?"

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

ASP.NET Blogging Markdown

Mest lucid.MinimalBlog - Hur enkelt kan en ASP.NET blogg verkligen vara?

Monday, 01 December 2025

Inledning

Om du har följt den här bloggen, kanske du har märkt att min huvudsakliga bloggplattform är ... låt oss kalla det "entusiastiskt konstruerad." PostgreSQL OCH vektordatabaser, semantisk OCH fulltextsökning med GIN-index, automatiserad översättning till 14 språk, flera värdtjänster, Hangfire jobb schemaläggning, Prometheus metrics, Serilog spårning, HTMX interaktioner, använda mina egna nuget paket, och tillräckligt med Docker containrar för att göra ett fartyg svartsjuk.

Det är helt avsiktligt. Denna webbplats är mitt levande labb - en lekplats där jag experimenterar med teknik, test distributionsstrategier, mäta prestanda egenskaper, och bygga återanvändbara paket. Det är förmodad Att vara överutvecklad eftersom det är så jag lär mig: genom att lösa problem som de flesta bloggar faktiskt inte har, sedan paketera dessa lösningar som open-source bibliotek andra kan använda.

Men så här är det: Du behöver förmodligen inte något av det för att köra en blogg.

Det är därför jag skapade mestadels lucid.MinimalBlog - för att visa vad som händer när du tar bort alla experiment och fokuserar på det absolut nödvändiga. Ingen databas. Ingen bygg pipeline. Ingen komplexitet. Bara markdown filer i en katalog, som visas på webben. Så här ser en blogg ut när du inte använder den som ett laboratorium.

OBS: Se slutet av artikeln för en länk till källan, Jag planerar att släppa detta som en nuget- paket så fort jag får tid att se till att det är 100% pålitlig och det är perf är inte TOO hemskt (så leta efter k6 testartiklar snart!).

Filosofin: Mindre är mer

Hela projektet är utformat kring en princip: hålla det enkelt. Ingen databas, ingen bygg pipeline, inget JavaScript ramverk. Bara ASP.NET 9.0, Markdig för nedräkning tolkning, och cirka 500 rader kod totalt. Det är allt. OBS: Du kan även göra denna klient sida genom att använda liknande av marked-it sedan bara ha server webbplats karta statiska .md filer och gör det till och med SIMPLER men...ja detta är en ASP.NET blogg (typa sorta) .

Projektstruktur

Låt oss titta på hur projektet är organiserat:

Mostlylucid.MinimalBlog/
├── Pages/
│   ├── Index.cshtml              # Homepage with post list
│   ├── Post.cshtml                # Individual post page
│   ├── Categories.cshtml          # List of all categories
│   ├── Category.cshtml            # Posts in a category
│   ├── _Layout.cshtml             # Shared layout
│   ├── _ViewImports.cshtml        # Shared imports
│   └── _ViewStart.cshtml          # Layout selection
├── wwwroot/
│   └── css/
│       └── site.css               # All the CSS you need
├── MarkdownBlogService.cs         # Core blog logic
├── MetaWeblogService.cs           # XML-RPC for external editors
├── Program.cs                     # Application setup
├── appsettings.json               # Configuration
└── Mostlylucid.MinimalBlog.csproj # Project file

Hjärtat: MarkdownBlogService

Kärnan i bloggen är MarkdownBlogService Det är anmärkningsvärt enkelt-bara 120 rader kod som hanterar:

  1. Läsa ner markeringsfiler från en katalog
  2. Tolkning av metadata (titel, kategorier, publiceringsdatum)
  3. Konverterar markering till HTML med Markdig
  4. Caching allt i minnet

Så här fungerar det:

Laddar inlägg

Tjänsten skannar en konfigurerad katalog för .md filer och laddar dem alla i minnet:

private List<BlogPost> LoadAllPosts()
{
    if (!Directory.Exists(_markdownPath)) return [];

    return Directory.GetFiles(_markdownPath, "*.md", SearchOption.TopDirectoryOnly)
        .Where(f => Path.GetFileName(f).Count(c => c == '.') == 1) // Only base .md files
        .Select(ParseFile)
        .Where(p => p is { IsHidden: false })
        .OrderByDescending(p => p!.PublishedDate)
        .ToList()!;
}

Lägg märke till den smarta filtreringen: Count(c => c == '.') == 1 säkerställer att vi bara får bas .md filer, inte översatta versioner som post.ar.md eller post.de.md (om du vill lägga till översättningar senare).

Tolkning av metadata

Varje markeringsfil följer en enkel konvention:

# Post Title




Your content here...

Parsern extraherar metadata med hjälp av reguljära uttryck och Markdig AST:

private BlogPost? ParseFile(string filePath)
{
    var markdown = File.ReadAllText(filePath);
    var slug = Path.GetFileNameWithoutExtension(filePath);
    var document = Markdown.Parse(markdown, _pipeline);

    // Extract title from first H1
    var title = document.Descendants<HeadingBlock>()
        .FirstOrDefault(h => h.Level == 1)?
        .Inline?.FirstChild?.ToString() ?? slug;

    // Extract categories: 
    var categoryMatch = CategoryRegex().Match(markdown);
    var categories = categoryMatch.Success
        ? categoryMatch.Groups[1].Value.Split(',', StringSplitOptions.TrimEntries)
        : [];

    // Extract date: 
    var dateMatch = DateTimeRegex().Match(markdown);
    var publishedDate = dateMatch.Success && DateTime.TryParse(dateMatch.Groups[1].Value, out var dt)
        ? dt : File.GetCreationTimeUtc(filePath);

    return new BlogPost
    {
        Slug = slug,
        Title = title,
        Categories = categories,
        PublishedDate = publishedDate,
        HtmlContent = Markdown.ToHtml(markdown, _pipeline),
        IsHidden = markdown.Contains("<hidden")
    };
}

Cachingstrategi

Varje metod i tjänsten använder IMemoryCache För att undvika omläsning och omtolkning av filer på varje begäran:

public IReadOnlyList<BlogPost> GetAllPosts()
{
    return cache.GetOrCreate("all_posts", entry =>
    {
        entry.SetOptions(CacheOptions);
        return LoadAllPosts();
    }) ?? [];
}

Cache poster har en 30-minuters glidande utgång och 2-timmars absolut utgång. Enkelt, effektivt.

Programinställning: Program.cs

Hela programinställningen är bara 43 rader: Razor-sidor, minnescache, utdatacache, två singleton-tjänster, statisk filservering, och en MetaWeblog XML-RPC-slutpunkt. Allt cachelagring som singletons eftersom ingenting ändras om inte filer ändras.

UI: Enkla Razor-sidor

UI är ren server-renderad HTML. No JavaScript, no HTMX, no Alpine.js. Hemsidan listar inlägg, postsidan återger @Html.Raw(post.HtmlContent) med en [OutputCache] attribut för timme-lång HTML-cache. Fyra sidor totalt, varje under 30 rader.

Styling: 55 rader CSS

Hela den visuella designen hanteras av en enda CSS-fil med bara 55 rader. Den använder CSS anpassade egenskaper för tema och skapar en ren, mörk GitHub-inspirerad look:

:root {
  --bg: #0d1117;
  --bg-card: #161b22;
  --text: #c9d1d9;
  --text-muted: #8b949e;
  --accent: #58a6ff;
  --border: #30363d;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  background: var(--bg);
  color: var(--text);
  line-height: 1.6;
  max-width: 48rem;
  margin: 0 auto;
  padding: 2rem 1rem;
}

/* ... more styles ... */

Ingen förbehandlare, inget byggsteg, inga tusentals bruksklasser, bara ren, läsbar CSS som fungerar.

Bonusfunktion: MetaWeblog API

För författare som föredrar dedikerade markdown redaktörer som Markeringsmonster, projektet innehåller en fullständig MetaWeblog API implementation. Detta XML-RPC API tillåter externa redaktörer att:

  • Förteckning över tjänster
  • Skapa nya inlägg
  • Redigera befintliga inlägg
  • Ta bort inlägg
  • Ladda upp bilder
  • Hämta kategorier

Genomförandet är i MetaWeblogService.cs och hanterar det fullständiga XML-RPC-protokollet, tolkning förfrågningar och generera svar. Detta innebär att du kan skriva dina blogginlägg i din favoritredigerare och publicera dem direkt till din blogg.

Inställning

Hela konfigurationsfilen är bara 14 rader:

{
  "MarkdownPath": "../Mostlylucid/Markdown",
  "ImagesPath": "wwwroot/images",
  "MetaWeblog": {
    "Username": "admin",
    "Password": "changeme",
    "BlogUrl": "http://localhost:5000"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information"
    }
  }
}
  • MarkdownPath - där dina markdown-filer bor
  • ImagesPath - där bilder lagras
  • MetaWeblog - referenser för extern editoråtkomst

Använda som NuGet-paket

Som nämnts ovan kommer SOON att vara tillgänglig men ännu inte :)

Bloggen är nu tillgänglig som ett NuGet-paket, vilket gör det trivialt att lägga till alla ASP.NET Core-program:

dotnet add package mostlylucid.MinimalBlog

Sedan i din Program.cs:

builder.Services.AddRazorPages();
builder.Services.AddMinimalBlog(options =>
{
    options.MarkdownPath = "Markdown";
    options.ImagesPath = "wwwroot/images";
    options.EnableMetaWeblog = false; // Optional, defaults to true
});

var app = builder.Build();

app.UseStaticFiles();
app.UseMinimalBlog();
app.MapRazorPages();
app.Run();

Det är det - bara två metod kallar (AddMinimalBlog och UseMinimalBlog) och du har en fungerande blogg.

Köra provprojektet

För att genomföra det medföljande urvalsprojektet:

cd Mostlylucid.MinimalBlog
dotnet run

Besök http://localhost:5000 och du kommer att se bloggen med markdown-filer från den inställda sökvägen.

Skapa innehåll

För att skapa ett nytt blogginlägg:

  1. Skapa en ny .md fil i din inställda MarkdownPath
  2. Lägg till standardmetadata:
    # Your Post Title
    
    
    
    
    Your content here...
    
  3. Spara filen
  4. Cachen kommer att löpa ut inom 30 minuter (eller starta om appen)

För att lägga till bilder, placera dem helt enkelt i din konfigurerade ImagesPath katalog och referera dem i din markering:

![Alt text](your-image.jpg)

Vad som saknas (med syfte)

Denna minimal blogg innehåller inte avsiktligt:

  • Anmärkningar - Använda en tredjepartstjänst vid behov
  • Sök - Håll ditt innehåll organiserat med kategorier
  • Etiketter - Kategorier räcker för små bloggar
  • RSS/Atom - Enkelt att lägga till om du behöver det
  • Behörighetskontroll - MetaWeblog API använder endast grundläggande auth
  • Analyser - Lägg till JavaScript sippet om så önskas
  • SEO-optimering - Fungerar bra med grundläggande metataggar
  • Responsiva bilder -Browser hanterar det
  • Mörkt/ljust tema växla - Ett tema räcker.

Dessa funktioner är alla möjligt att lägga till, men de ingår inte som standard eftersom de flesta små bloggar inte behöver dem.

Prestandaegenskaper

Trots sin enkelhet, denna blogg är snabb:

  • Minnescachelagring betyder ingen fil I/O efter första laddningen
  • Utmatningscache betyder ingen Razor rendering efter första begäran
  • Ingen databas betyder ingen förfrågan overhead
  • Inget JavaScript betyder snabbare sidbelastningar
  • Enkla CSS betyder minimal stilmall tolkning

För en liten till medelstor blogg (under 1000 inlägg) kommer denna arkitektur överträffa de flesta databas-stödda bloggplattformar.

När du ska använda denna vs. den full mestlylucid blogg

Användning Mestlylucid.MinimalBlog när:

  • Du startar en personlig blogg
  • Du har färre än 500 tjänster
  • Du behöver inte flera språk
  • Du vill hålla saker och ting enkla
  • Du är bekväm med markdown-filer
  • Du vill bara skriva och publicera

Använd full Mostlylucid plattform när:

  • Du använder din blogg som en Lärande laboratorium för ny teknik
  • Du vill experimentera med driftsättningsstrategier, övervakning och prestandaoptimering
  • Du behöver specifika funktioner som flerspråkigt stöd, fulltextsökning eller kommentarer
  • Du bygger paket och behöver en riktig testbädd.
  • Du dokumenterar komplexa tekniska implementationer.
  • Resan att bygga plattformen är lika värdefull som det innehåll den är värd

Slutsats: Enkelhet som ett inslag

I den moderna webbutveckling världen, vi ofta nå för komplexa lösningar som standard. Behöver en blogg? Bättre ställa in en databas, konfigurera en ORM, ställa in migreringar, lägga till caching, genomföra sökning, konfigurera bakgrundsjobb...

Men ibland är den enkla lösningen höger lösning. Mestlylucid.MinimalBlog visar att du kan bygga en funktionell, snabb och underhållsbar bloggplattform med:

  • 342 rader i C# (MarkdownBlogService + MetaWeblogService + Program.cs)
  • 120 linjer av Razor markup (4 sidor)
  • 55 linjer i CSS
  • 1 NuGet-beroende (Markdig)

Det är Mindre än 520 rader totalt för en komplett bloggplattform.

Projektet fungerar som både en funktionell bloggplattform och en påminnelse: innan du lägger till komplexitet, fråga dig själv om du verkligen behöver det. Ibland en mapp full av markdown filer är allt du behöver.

Du kan hitta den fullständiga källkoden i Mestlylucid.MinimalBlog katalog Jag släpper nuget-paketet så fort jag är nöjd med koden.

Glad bloggning!

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.