# mest uppenbart.MinimalBlog - Hur enkelt kan en ASP-Blog

<!--category-- ASP.NET, Markdown, Blogging -->
<datetime class="hidden">2025-12-01T12:00</datetime>

## Inleiding

Om du följt den här bloggen, så har du kanske märkt att min bloggingplattform är: ..., låt ' kalla det. ", entusiastiskt utvecklad, .", PostgreSQL och vektordatabaser, ,, semantisk och full, M SK7, textsökning med GIN-indexer,,, automatiserad översättning till 14, språk, МSK10, flera hostade tjänster, MSC11, Hangfires jobbscheduling, MST12, Prometheus mätningar, Mst13, Serilogspårning, M st14, HTMX-interaktioner, M ST15, och angripa mina egna nugetpaket, M St16, och tillräckligt många Dockercontainer för att göra ett skepp avundsjuk.

**Det är helt avsiktligt.** Denna plats är mitt vardagslabb - en lekplats där jag experimenterar med tekniker , testimplementeringsstrategierM SK2 mäter prestanseigenheter , och bygger återanvändbara paket *förmodade* att vara över "-", eftersom det är så jag lär mig, :", genom att lösa problem som de flesta bloggar inte har.

Men här är det som händer. **du behöver förmodligen inget av det för att köra en blogg**

Det var därför jag skapade **mostlylucid.MinimalBlog** - för att visa vad som händer när man tar bort alla experiment och fokuserar på de absoluta nödvändigheterna . Ingen databas, . Ingen byggande pipeline, . Ingen komplexitet, M SK4 Bara markera ned filer i en folder, MSC5, som dyker upp på webben, Mska6. Så här ser en blogg ut när du inte använder den som ett laboratorium, M Ska8

> NOTA: Titta på slutet av artikeln för en länk till källan [nuget package](https://www.nuget.org/packages?q=mostlylucid&includeComputedFrameworks=true&prerel=true&sortby=relevance) så snart jag får tid att se till att det är säkrat.

[TOC]

## filosofin: mindre är mer

Hela projektet är utformat kring ett princip **hålla det enkelt**. Inget databas, ,, ingen byggande ledning, ,, inget JavaScript-framework,., bara ASP, M SK4, NET, | | 9.0,, markera för markdown-testning, m.in. ,, och ungefär 500, rader kodex total, MSC8, det där är ', det är det.
NOTA: Du skulle kunna till och med göra den här kundsidan genom att använda [markerdown-it](https://github.com/markdown-it/markdown-it) och sedan bara ha serverns webbplatskarta statisk `.md` och gör den till och med SIMPLER men det här är ett ASP-Blog

## Projektstrukturen

Låt oss titta på hur projektet organiseras.

```
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
```

## Heart: MarkdownBlogService

Blogens kärna är `MarkdownBlogService` klass. Det ' är anmärkningsvärt enkelt- bara M SK3 rader kod som hanterar

1. Att läsa markerdown-filer från ett katalog
2. Att parera metadata ( titel, kategorierM SK2 publiceringsdatum )
3. Markdown konverterar till HTML med hjälp av Markdig
4. Att kaska allt i minnet

Här är hur det fungerar'

### Loading Beiträge

Servicen skanner ett konfigurerat katalog för `.md` och sätter dem alla i minnet:

```csharp
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()!;
}
```

Notera det smarta filtreringet: `Count(c => c == '.') == 1` försäkrar att vi bara får base `.md` files, inte översatta versioner som `post.ar.md` eller `post.de.md` (ifall du vill lägga till översättningar senare

### Att analysera metadata

Varje markerdown-plik följer en enkel konvention

```markdown
# Post Title

<!-- category -- Category1, Category2 -->
<datetime class="hidden">2024-11-30T12:00</datetime>

Your content here...
```

Parsaren extraherar denna metadata med hjälp av vanliga uttryck och Markdig AST:

```csharp
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: <!-- category -- Cat1, Cat2 -->
    var categoryMatch = CategoryRegex().Match(markdown);
    var categories = categoryMatch.Success
        ? categoryMatch.Groups[1].Value.Split(',', StringSplitOptions.TrimEntries)
        : [];

    // Extract date: <datetime class="hidden">2024-01-01T00:00</datetime>
    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")
    };
}
```

### Cachingsstrategi

Varje metod i tjänsten använder `IMemoryCache` för att undvika att re- läsa och re - analysera filer på varje pyyntö

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

Cacheinträg har en 30-minuts-slivande utgång och 2-sam absolut utgång

## Application Setup: Programm

Hela applikationsuppsättningen är bara 43 linjer : Razor Pages, minnescachet M SK3 utdatascachen , två enton-tjänster MSC5 statiskt fileserverande Mska6 och en MetaWeblog XML Mske7 RPC slutpunkt M Ska8 Allt kaserat som enton, eftersom inget förändras om files inte ändras.

## UI: Enkela rasorsidor

Interfejsen är en ren server. `@Html.Raw(post.HtmlContent)` med en `[OutputCache]` attributet för timmen-längd HTML-kassning. Fyra sidor totalt , var och en under M SK3 linjer

## Stylisering: 55 Linjer av CSS

Hela den visuella designen hanteras av en enda CSS-Datei med bara 55 linjer . Den använder CSS-passingseigenheter för att uttyda och skapar en ren

```css
: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 ... */
```

Inget preprocessor . Inga byggande steg

## Bonusfeature: MetaWeblog API

För författare som föredrar markerdown-editorer som [Markdown-monster](https://markdownmonster.west-wind.com/), projektet inkluderar en full MetaWeblog API-implementation . Den här XML-APIn allows externa redaktörer att

- Lyssposter
- Create new posts
- Redigera existerande poster
- Lösa poster
- Uploada bilder
- Rekrytera kategorier

Implementeringen är under `MetaWeblogService.cs` och hanterar den kompletta XML-processen-RPC-protocoln , analyserar begäran och genererar svar. Det betyder att du kan skriva dina bloggar i din favoritredigerare och publicera dem direkt på din blogg

## Konfiguration

Hela konfigurationsdatet är bara 14 linjer :

```json
{
  "MarkdownPath": "../Mostlylucid/Markdown",
  "ImagesPath": "wwwroot/images",
  "MetaWeblog": {
    "Username": "admin",
    "Password": "changeme",
    "BlogUrl": "http://localhost:5000"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information"
    }
  }
}
```

- `MarkdownPath` - var dina markerdown-filer finns
- `ImagesPath` - där bilder lagras
- `MetaWeblog` --berättelser för extern redaktörs tillgång

## Att använda NuGet-paket

> Som nämnt tidigare kommer den snart att vara tillgänglig men inte ännu :)

Bloget är nu tillgängligt som ett NuGet-paket, vilket gör det obetydligt att lägga till någon ASP-version.

```bash
dotnet add package mostlylucid.MinimalBlog
```

Sedan i din `Program.cs`:

```csharp
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();
```

Att "'" är det "-", bara två metoder som säger "(".`AddMinimalBlog` och `UseMinimalBlog`) och du har en arbetsblog

## Att köra ett exemplarsprojekt

Att köra det inkluderade exemplarprojektet:

```bash
cd Mostlylucid.MinimalBlog
dotnet run
```

Att besöka `http://localhost:5000` och du' kommer att se bloggen med markerdown-filer från den konfigurerade vägen

## Att skapa innehåll

Att skapa en ny bloggpost:

1. Skep en ny `.md` file i din konfigurerade `MarkdownPath`
2. Lägg till standardmetadata
   ```markdown
   # Your Post Title
   
   <!-- category -- YourCategory, AnotherCategory -->
   <datetime class="hidden">2024-11-30T12:00</datetime>
   
   Your content here...
   ```
3. spara filet
4. Cavitet kommer att försvinna inom 30 minuter | ( | eller starta appn igen

För att lägga till bilder, placera dem bara i din konfigurerade `ImagesPath` katalog och länka till dem i din markerdown

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

## Vad saknas?

Denna minimala blogg innehåller inte intentionellt

- **Kommentaar** - Använd en tredje persons service
- **söka** - Håll din innehåll organiserad med kategorier
- **Tags** - Kategorier räcker för små bloggar
- **RSS/Atom** - enkelt att lägga till om du behöver det
- **Authentikation** - MetaWeblog API använder bara grundläggande auth
- **Analytik** - Add JavaScript snippet if desired
- **SEO-optimering** - Fungerar bra med grundläggande metatag
- **Reagerande bilder** - Browser hanterar det
- **Dark/light tema toggle** - Ett tema räcker

Dessa egenskaper är alla *möjlig* att lägga till ",", men de är inte inbegripda standardmässigt eftersom de flesta små bloggar inte behöver dem.

## Förmågor och egenskaper

Trots sin enkelhet **fort**:

- **Memory caching** betyder att ingen file I/O finns efter den första ladan
- **Utgångsキャッシュing** betyder att det inte finns någon Razor rendering efter första begäran
- **Ingen databas** betyder att ingen fråga involverar överhead
- **Ingen JavaScript** innebär snabbare webblader
- **Enkel CSS** betyder minimalt styleblads解析

För en liten till mellanblog (under 1000 postituser), kommer den här arkitekturen att överträffa de flesta databaser

## När man ska använda det här vs. den mest uppenbara bloggen

Använda **Mostlylucid.MinimalBlog** när:

- Du' startade en personlig blogg
- Du har färre än 500 träffar
- Du behöver inte fler språk
- Du vill hålla sakerna enkla
- Du' är bekväm med markerdown-filer
- Du vill bara skriva och publicera

Använd **full Mostlylucid platform** när:

- Du använder din blogg som en **lärandelaboratorium** för nya teknologier
- Du vill experimentera med användningsstrategier, övervakning, och performanceoptimering
- Du behöver specifika egenskaper som multilinguell support, full-textsökningM SK2 eller kommentarer
- Du bygger paket och behöver en riktig testbädd
- Du dokumenterar komplexa tekniska implementeringar
- Resan till att bygga plattformen är lika viktig som innehållet den hyser

## slutsats : Enkelhet som en egenskap

I den moderna web-utvecklingsvärlden, når vi ofta komplexa lösningar standardmässigt. Bra att ha en blogg ? Bättre att sätta upp en databas , Konfigurera en ORM M SK4 ställ upp migrationer

Men ibland är det enkla lösningen *högra* lösning. Det mest uppenbara .MinimalBlog bevisar att du kan bygga en funktionell, snabbM SK3 och underhållningsbar bloggplattform med

- **342 linjer av C** (MarkdownBlogService
- **~120 linjer av Razor-märkte** (4 sidor
- **55 linjer av CSS**
- **1 NuGets beroende** (Markdig)

Det's **mindre än 520 rader kodex totalt** för en komplett bloggplattform.

Projektet fungerar som både en funktionell bloggplattform och en påminnelse.

Ni kan hitta hela källkoden i [Mostlylucid.MinimalBlog directory](https://github.com/scottgal/mostlylucidweb/tree/main/Mostlylucid.MinimalBlog) av huvudskivan. I' kommer att släppa nugetpaketet så snart jag är nöjd med koden

Happy blogging!