Se stai seguendo questo blog, potresti aver notato che la mia principale piattaforma di blogging è... chiamiamolo "enthusiastically engineering." PostgreSQL E database vettoriali, ricerca semantica e full-text con indici GIN, traduzione automatica in 14 lingue, servizi ospitati multipli, programmazione dei lavori di Hangfire, metriche Prometheus, Serilog tracing, interazioni HTMX, utilizzo dei miei pacchetti di nuget e abbastanza contenitori Docker per rendere gelosa una nave.
E' del tutto intenzionale. Questo sito è il mio laboratorio vivente - un parco giochi dove sperimento tecnologie, strategie di test deployment, misuro le caratteristiche delle prestazioni e costruisco pacchetti riutilizzabili. supposta per essere eccessivamente ingegnerizzato perché è così che imparo: risolvendo i problemi che la maggior parte dei blog non hanno in realtà, quindi confezionando quelle soluzioni come librerie open-source altri possono utilizzare.
Ma il fatto e' questo: Probabilmente non hai bisogno di niente di tutto questo per gestire un blog.
E' per questo che ho creato Per lo piùlucid.MinimalBlog - mostrare cosa succede quando si toglie via tutta la sperimentazione e concentrarsi sull'essenziale assoluto. Nessun database. Nessuna pipeline build. Nessuna complessità. Basta marcare i file in una cartella, che appaiono sul web. Questo è come un blog quando non si sta utilizzando come un laboratorio.
NOTA: Vedere la fine dell'articolo per un link alla fonte, ho intenzione di rilasciare questo come un pacchetto nuget non appena ottengo il tempo per assicurarmi che sia affidabile al 100% e che il suo perf non sia troppo orribile (quindi cerca gli articoli di prova k6 presto!).
L'intero progetto è stato progettato attorno ad un unico principio: Semplice.. Nessun database, nessuna pipeline di compilazione, nessun framework JavaScript. Solo ASP.NET 9.0, Markdig per analisi di markdown, e circa 500 linee di codice totale.
NOTA: Potete anche fare questo lato del client utilizzando i tipi di markdown-it quindi basta avere la mappa del sito del server statico .md files and make it even SIMPLER but...beh questo è un blog ASP.NET (un po 'un po').
Vediamo come è organizzato il progetto:
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
Il cuore del blog è il MarkdownBlogService classe. E 'molto semplice-solo 120 linee di codice che gestiscono:
Ecco come funziona:
Il servizio esegue la scansione di una directory configurata per .md file e li carica tutti in memoria:
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()!;
}
Notare il filtro intelligente: Count(c => c == '.') == 1 assicura che otteniamo solo la base .md file, non versioni tradotte come post.ar.md oppure post.de.md (nel caso in cui si desidera aggiungere traduzioni più tardi).
Ogni file markdown segue una semplice convenzione:
# Post Title
Your content here...
Il parser estrae questi metadati usando espressioni regolari e la 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")
};
}
Ogni metodo utilizzato nel servizio IMemoryCache per evitare la rilettura e la rielaborazione dei file su ogni richiesta:
public IReadOnlyList<BlogPost> GetAllPosts()
{
return cache.GetOrCreate("all_posts", entry =>
{
entry.SetOptions(CacheOptions);
return LoadAllPosts();
}) ?? [];
}
Le voci della cache hanno una scadenza scorrevole di 30 minuti e una scadenza assoluta di 2 ore. Semplice, efficace.
L'intera configurazione dell'applicazione è di sole 43 righe: Razor Pages, memory cache, output cache, due servizi singleton, servizio di file statico e un endpoint XML-RPC MetaWeblog. Tutto in cache come singleton perché nulla cambia a meno che i file non siano modificati.
L'interfaccia utente è pura HTML resa dal server. No JavaScript, no HTMX, no Alpine.js. La homepage elenca i messaggi, la pagina post renders @Html.Raw(post.HtmlContent) con [OutputCache] attributo per la cache HTML lunga un'ora. Quattro pagine totali, ciascuna sotto 30 righe.
L'intero design visivo è gestito da un unico file CSS con solo 55 linee. Utilizza le proprietà personalizzate CSS per loro e crea un look pulito e scuro ispirato a GitHub:
: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 ... */
Nessun preprocessore. Nessun passo di compilazione. Nessuna migliaia di classi di utilità. Solo CSS pulito e leggibile che funziona.
Per gli scrittori che preferiscono redattori dedicati markdown come Mostro Markdown, il progetto include una completa implementazione MetaWeblog API. Questa API XML-RPC consente agli editor esterni di:
L'attuazione è in MetaWeblogService.cs e gestisce il protocollo XML-RPC completo, analizzando le richieste e generando risposte. Ciò significa che puoi scrivere i tuoi post sul blog nel tuo editor preferito e pubblicarli direttamente sul tuo blog.
L'intero file di configurazione è solo 14 righe:
{
"MarkdownPath": "../Mostlylucid/Markdown",
"ImagesPath": "wwwroot/images",
"MetaWeblog": {
"Username": "admin",
"Password": "changeme",
"BlogUrl": "http://localhost:5000"
},
"Logging": {
"LogLevel": {
"Default": "Information"
}
}
}
MarkdownPath - dove vivono i file markdownImagesPath - dove vengono memorizzate le immaginiMetaWeblog - credenziali per l'accesso esterno all'editorCome detto sopra sarà presto disponibile ma non ancora:)
Il blog è ora disponibile come pacchetto NuGet, rendendo banale aggiungere a qualsiasi applicazione ASP.NET Core:
dotnet add package mostlylucid.MinimalBlog
Poi nella tua 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();
Questo è tutto - solo due chiamate metodo (AddMinimalBlog e UseMinimalBlog) e hai un blog di lavoro.
Per eseguire il progetto campione incluso:
cd Mostlylucid.MinimalBlog
dotnet run
Visita http://localhost:5000 e vedrete il blog con i file markdown dal percorso configurato.
Per creare un nuovo post sul blog:
.md file nel tuo file configurato MarkdownPath# Your Post Title
Your content here...
Per aggiungere immagini, basta inserirle nella configurazione ImagesPath directory e riferimento nel tuo markdown:

Questo blog minimo intenzionalmente non include:
Queste caratteristiche sono tutte possibile per aggiungere, ma non sono inclusi per impostazione predefinita perché la maggior parte dei piccoli blog non hanno bisogno di loro.
Nonostante la sua semplicità, questo blog è veloce:
Per un blog da piccolo a medio (sotto i 1000 post), questa architettura supererà la maggior parte delle piattaforme di blog supportate da database.
Uso Per lo più Lucid.MinimalBlog quando:
Utilizzare il piena piattaforma Mostlylucid quando:
Nel moderno mondo di sviluppo web, spesso raggiungiamo soluzioni complesse per impostazione predefinita. Hai bisogno di un blog? Meglio impostare un database, configurare un ORM, impostare migrazioni, aggiungere cache, implementare la ricerca, configurare i lavori di background...
Ma a volte la soluzione semplice è il destra MinimalBlog dimostra che è possibile costruire una piattaforma blog funzionale, veloce e manutenibile con:
E' meno di 520 righe di codice totale per una piattaforma completa di blogging.
Il progetto serve sia come una piattaforma blog funzionale che come un promemoria: prima di aggiungere complessità, chiediti se ne hai davvero bisogno. A volte una cartella piena di file markdown è tutto ciò di cui hai bisogno.
È possibile trovare il codice sorgente completo nel Directory MinimalBlog del repository principale. Rilascerò il pacchetto nuget non appena sarò soddisfatto del codice.
Happy blogging!
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.