# mostlylucid.MinimalBlog - Comment simple peut un blog ASPM SK2NET vraiment êtreMSC3

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

## Introduction

Si vous ' avez suivi ce blog , vous auriez peut-être remarqué que ma principale plateforme de blogging est... laissezM SK3 l'appeler " enthusiastiquement conçueMNK5 PostgreSQL ET bases de données vectoriellesMMK6 sémantique et complèteMRK7 recherche textuelle avec les indices GINMK8 traduction automatisée vers des languesMEK9 MNK10 plusieurs services hébergésMZK11 planification du travail HangfireMKK12 métriques PrometheusMGK13 traçage SerilogMDK14 interactions HTMXMKZ15 assignez mes propres paquets nugetMBK16 et suffisamment de contenants Docker pour faire envie d'un navireMHK17

**Cela est tout à fait délibéré.** Ce site est mon laboratoire de vie - un terrain de jeux où je fais des expériences avec les technologies , stratégies de déploiement d'essais M SK2 mesurer les caractéristiques de performance , et construire des paquets réutilisables MSC4 Il's *présumé* pour être superposé à l’ingénierie, car c’est ainsi que je apprends à résoudre les problèmes que la plupart des blogs ne possèdent pas.

Mais ici, c’est ce qui est important. **Vous n’avez probablement pas besoin de ce genre d’information pour faire un blog.**

C'est la raison pour laquelle j'ai créé MSK **mostlylucid.MinimalBlog** - pour montrer ce qui se passe lorsque vous éliminez toutes les expériences et vous concentrez sur les éléments essentiels absolus . Aucune base de données, . Aucun pipeline de construction,. Pas de complexité,. Seules des fichiers marquages dans un dossier,MSC5 apparaissant sur le Web,M SK6 C'est ainsi qu'un blog ressemble quand vous ne l'utilisez pas comme laboratoire.

> NOTE: Voir la fin de l’article pour obtenir un lien à la source, Je planifie de le publier en tant que [Nuget package](https://www.nuget.org/packages?q=mostlylucid&includeComputedFrameworks=true&prerel=true&sortby=relevance) Dès que j’aurai le temps de s’assurer qu’il est fiable, 's 100% et il n’est pas trop terrible pour 's perf.

[TOC]

## La philosophie: Moins est plus

L’ensemble du projet est conçu autour d’un principe : **Gardez-le simple**. Aucune base de données , aucun pipeline de construction M SK2 aucun cadre JavaScript . Just ASPM SK4NET MSC5 Markdig pour le partage à marquage, et environ 500 lignes de code totales
NOTE: Vous pouvez même faire ce côté client en utilisant les likes de [marquage à la baisse-it](https://github.com/markdown-it/markdown-it) puis le site du serveur est statique `.md` Les fichiers et faire même SIMPLER mais...well c'est un blog ASP.NET M SK2kinda sorta 🤓).

## Structure du projet

Let's voir comment le projet est organisé :

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

## Le coeur: MarkdownBlogService

Le cœur du blog est le `MarkdownBlogService` class. Il' est remarquablement simple -juste M SK3 lignes de code qui traitent

1. Lire les fichiers de marquage en descendant d'un répertoire
2. Parsage des métadonnées (titre,catégories ,date de publicationM SK3
3. Conversion de la marque en HTML à l'aide de Markdig
4. Cacher tout en mémoire

Voici comment il fonctionne' :

### Les postes sont en train d'être chargés

Le service scanne un répertoire configuré pour `.md` les fichiers et les charge tous en mémoire:

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

Notez le filtrage intelligent: `Count(c => c == '.') == 1` assure que nous ne obtenons qu'une base `.md` fichiers, versions non traduites comme `post.ar.md` ou `post.de.md` (dans le cas où vous souhaitez ajouter des traductions ultérieurement).

### Tracer les métadonnées

Chaque fichier de marquage suit une convention simple:

```markdown
# Post Title

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

Your content here...
```

Le parteur extrait ces métadonnées en utilisant des expressions régulières et le 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")
    };
}
```

### Stratégie de stockage

Chaque méthode utilisée dans le service `IMemoryCache` pour éviter de lire et de corriger les fichiers à chaque demande

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

Les entrées de cache ont une durée d’expiration 30-minute et une durée absolue d’échéance 2-heure.

## Établissement de l'application: Programme.cs

L'ensemble de la mise en place de l'application est simplement 43 lignes : Pages Razor, cache de mémoireM SK3 cache d' sortieMSC4 deux services à un seul tonneMska5 service de fichier statiqueM Ska6 et un XML MetaWeblogMSKA7 point final RPCM ska8 Tout est caché sous un seul ton parce que rien ne change tant que les fichiers n'ont pas été modifiésMka9

## Les pages UI: Simple Razor Pages

L'interface est un serveur pur-rendered HTML. Pas de JavaScriptM SK2 pas HTMX , pas AlpineMST4jsMSC5 La page d'accueil liste les articlesMSL6 la page des articles rend `@Html.Raw(post.HtmlContent)` avec un `[OutputCache]` attribut pour l’heure-cacheur HTML long. Quatre pages totalesM SK2 chacune sous MSC3 lignes .

## Styling: 55 Lignes de CSS

L'ensemble du design visuel est géré par un seul fichier CSS avec seulement 55 lignes. Il utilise les propriétés personnalisées de CSS pour le remaniement et crée une présentation propreMSC2 dark GitHubM SK3inspired look :

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

Pas de préprocesseur. Pas d'étape de construction. Pas de milliers de classes d'utilitéM SK2 Juste propre , CSS lisible qui fonctionne

## Caractéristique de bonus: API MetaWeblog

Pour les écrivains qui préfèrent des rédacteurs désignés comme [Monster de Markdown](https://markdownmonster.west-wind.com/), le projet inclut une mise en œuvre complète de l’API MetaWeblog . Cette API XML-RPC permet aux rédacteurs externes de

- Liste des postes
- Créer de nouveaux postes
- Modifier les postes existants
- Supprimer les postes
- Ajouter des images
- Récupérer les catégories

La mise en œuvre est en cours. `MetaWeblogService.cs` et gère le protocole XML complet-RPCM SK1 partage des demandes et génération de réponses. Cela signifie que vous pouvez écrire vos articles sur votre blog dans votre rédacteur préféré et les publier directement à votre blog .

## Configuration

L'ensemble du fichier de configuration est simplement 14 lignes:

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

- `MarkdownPath` - où vivent vos fichiers de marquage
- `ImagesPath` - où les images sont stockées
- `MetaWeblog` - Pouvoirs d'accès à l'éditeur externe

## Utilisation comme paquet NuGet

> Comme indiqué ci-dessus, il sera bientôt disponible mais pas encore :)

Le blog est maintenant disponible sous la forme d’un paquet NuGet, ce qui fait qu’il est trivial de l’ajouter à n’importe quelle application ASP

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

Ensuite, dans votre `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();
```

Ce n’est que deux appels de méthode (`AddMinimalBlog` et `UseMinimalBlog`) et vous avez un blog de travail

## Effectuer le projet d'échantillonnage

Pour exécuter le projet-échantillon inclus:

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

Visite `http://localhost:5000` et vous verrez le blog avec des fichiers de marquage à partir du chemin configuré.

## Création du contenu

Pour créer un nouveau blog post:

1. Créer une nouvelle `.md` fichier dans votre configuration `MarkdownPath`
2. Ajouter les métadonnées standards:
   ```markdown
   # Your Post Title
   
   <!-- category -- YourCategory, AnotherCategory -->
   <datetime class="hidden">2024-11-30T12:00</datetime>
   
   Your content here...
   ```
3. Réserver le fichier
4. Le cache expirera dans les 30 minutes (ou redémarrer l’application)

Pour ajouter des images,, placez-les simplement dans votre configuration `ImagesPath` le répertoire et les référer à votre note de bord:

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

## Qu’est-ce que le SCC0 manque? Le SCC1 n’a pas de but.

Ce blog minimal n’inclut pas intentionnellement

- **Commentaires** - Utiliser un service de tiers- si nécessaire
- **Rechercher** - Gardez votre contenu organisé avec des catégories
- **Mots clés** - Les catégories sont suffisantes pour les petits blogs
- **RSS/Atom** - Simple à ajouter si vous en avez besoin
- **Authentification** - L'API MetaWeblog n'utilise que l'auth de base
- **Analyses** - Ajouter un fragment de JavaScript si nécessaire
- **Optimisation du SEO** - fonctionne bien avec les métadonnées de base
- **Images réactives** - Le navigateur le gère
- **Dark/light theme toggle** - Un thème suffit

Ces caractéristiques sont toutes *possible* pour ajouter, mais ils' ne sont pas inclus par défaut parce que la plupart des petits blogs n’ont pas besoin de ceux-ci

## Caractéristiques du rendement

Malgré sa simplicité, ce blog est **le plus rapidement possible**:

- **Cache de mémoire** signifie qu'il n'y a pas de fichier I/O après la première charge
- **Cache des sorties** signifie qu'il n'y a pas de rendu Razor après la première demande
- **Aucune base de données** signifie qu'il n'y a pas de frais supplémentaires
- **Aucun JavaScript** signifie que les pages sont chargées plus rapidement
- **CSS simple** signifie une analyse minimale des feuilles de style

Pour un blog de petite à moyenne taille (dans le cadre des articles 1000), cette architecture sera supérieure à la plupart des bases de donnéesM SK3plate-formes de blogs appuyéesMSC4

## Quand utiliser ce vs. le blog complet Mostlylucid

Utilisation **.MinimalBlog** quand:

- Vous'entamez un blog personnel
- Vous avez moins de 500 postes
- Vous n’avez pas besoin de plusieurs langues
- Vous voulez garder les choses simples
- Vous'êtes à l’aise avec les fichiers de marquage
- Vous voulez simplement écrire et publier

Utilisez le **plate-forme Mostlylucid complète** quand:

- Vous utilisez votre blog comme un **Laboratoire d'apprentissage** pour les nouvelles technologies
- Vous voulez expérimenter avec des stratégies de déploiement, surveillance, et optimisation du rendement
- Vous avez besoin de fonctionnalités spécifiques comme le support multilingue, complet- recherche texteM SK2 ou commentaires
- Vous construisez des paquets et vous avez besoin d’un lit de test réel
- Vous documentez des mises en œuvre techniques complexes
- Le voyage de construction de la plate-forme est aussi précieux que le contenu qu'elle héberge

## Conclusion: Simplicité en tant que fonction

Dans le monde du développement Web moderne, nous cherchons souvent par défaut des solutions complexes.

Mais parfois, la solution simple est *de la droite* solution. Mostlylucid.MinimalBlog prouve que vous pouvez construire une plateforme de blog fonctionnelle, rapide et entretenable avec M SK4

- **342 lignes de CM SK1** (MarkdownBlogService + MetaWeblogService | + Programme
- **~120 lignes de marquage Razor** (4 pagesM SK1
- **55 lignes de CSS**
- **1 dépendance NuGet** (MarkdigM SK1

Que's **moins de 520 lignes de code total** pour une plateforme de blogging complète.

Le projet sert à la fois comme plateforme de blog fonctionnel et comme rappel.: avant d’ajouter une complexité, demandez-vous si vous en avez vraiment besoin.

Vous pouvez trouver le code source complet dans [Mostlylucid.MinimalBlog directory](https://github.com/scottgal/mostlylucidweb/tree/main/Mostlylucid.MinimalBlog) du répertoire principal. I'Je publierai le paquet nuget dès que je serai satisfait de ce code

Blogage heureux!