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!).
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) .
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
Kärnan i bloggen är MarkdownBlogService Det är anmärkningsvärt enkelt-bara 120 rader kod som hanterar:
Så här fungerar det:
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).
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")
};
}
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.
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 ä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.
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.
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:
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.
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 borImagesPath - där bilder lagrasMetaWeblog - referenser för extern editoråtkomstSom 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.
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.
För att skapa ett nytt blogginlägg:
.md fil i din inställda MarkdownPath# Your Post Title
Your content here...
För att lägga till bilder, placera dem helt enkelt i din konfigurerade ImagesPath katalog och referera dem i din markering:

Denna minimal blogg innehåller inte avsiktligt:
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.
Trots sin enkelhet, denna blogg är snabb:
För en liten till medelstor blogg (under 1000 inlägg) kommer denna arkitektur överträffa de flesta databas-stödda bloggplattformar.
Användning Mestlylucid.MinimalBlog när:
Använd full Mostlylucid plattform när:
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:
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!
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.