如果你一直关注这个博客, 你可能会注意到我的主要博客平台是... 让我们把它称为“热心工程”。 PostgreSQL 和矢量数据库,语义和全文搜索 GIN 索引, 自动翻译成14种语言, 多个主机服务, 挂机工作时间安排, Prometheus 度量仪, Serilog 跟踪, HTMX 互动, 使用我自己的纽扣包, 以及足够多的多克容器 使船嫉妒。
这完全是故意的 这个网站是我的活实验室 一个操场 我在那里实验技术 测试部署策略 测量性能特征 假定 被过度设计,因为这就是我学习的方法: 通过解决大多数博客实际上并不存在的问题, 然后把这些解决方案包装成开放源码图书馆, 其他人也可以使用。
但事情是这样的: 你可能不需要 任何这些来运行一个博客。
这就是为什么我创造了 多数是混杂的。 最小的Blog 没有数据库,没有管道,没有复杂。只要在文件夹中标记文件,在网络上出现。这是博客在不将其作为实验室时的样子。
注:关于与来源的链接,见本条结尾部分,我计划将此作为附件1予以公布。 核金包包 一旦我得到时间确保它百分之百可靠, 而且它不是太可怕(所以尽快寻找 K6 测试物品! ) 。
整个项目是围绕一项原则设计的: 保持简单没有数据库,没有建设管道,没有 JavaScript 框架,只有 ASP.NET 9.0, 马克迪 用于加分分析, 还有大约500行代码总计。
注意:你甚至可以使用 标记自下调 然后只有服务器站点地图静态 .md 这个博客是 ASP. NET 博客(kinda sorta {。
让我们看看这个项目是如何组织的:
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
博客的核心是 MarkdownBlogService 类。非常简单,只是120行代码 处理:
以下是它是如何工作的:
服务扫描已配置的目录 .md 并把它们全部装入内存 :
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()!;
}
注意聪明的过滤: Count(c => c == '.') == 1 确保我们只有基础 .md 文件, 不是翻译版本的 post.ar.md 或 post.de.md (如果您想稍后添加译文)
每个标记文件遵循简单的常规 :
# Post Title
Your content here...
解析器使用正则表达式和 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")
};
}
服务使用的每一种方法 IMemoryCache 以避免在每次请求时重读和重新标注文件:
public IReadOnlyList<BlogPost> GetAllPosts()
{
return cache.GetOrCreate("all_posts", entry =>
{
entry.SetOptions(CacheOptions);
return LoadAllPosts();
}) ?? [];
}
缓存条目有30分钟的滑动过期和2小时的绝对过期。 简单、 有效 。
整个应用程序设置只有43行: Razor Pages, 内存缓存, 输出缓存, 两个单通服务, 静态文件服务, 和一个 MetaWeblog XML- RPC 端点。 全部缓存为单通, 因为除非文件被修改, 否则不会发生任何变化 。
用户界面是纯服务器发送的 HTML 。 No JavaScript, no HTMX, no Alpine.js。 主页列表、 邮页 @Html.Raw(post.HtmlContent) 具有 a 和 [OutputCache] 小时 HTML 缓存属性。共四页,每行30行以下。
整个视觉设计由仅55行的单个 CSS 文件处理。 它使用 CSS 定制的特性处理这些设计, 并创建了干净、 黑暗的 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 ... */
没有预处理器,没有建筑步骤,没有数千个通用课程,只有干净的、可读的、有效的CSS。
对于那些喜欢专门减记编辑的作家来说 Markdown 怪物XML-RPC API允许外部编辑:
正在执行 MetaWeblogService.cs 并处理完整的 XML- RPC 协议, 解析请求和生成回复。 这意味着您可以在您最喜爱的编辑中写入您的博客文章, 并直接发布到您的博客中 。
整个配置文件只有 14 行 :
{
"MarkdownPath": "../Mostlylucid/Markdown",
"ImagesPath": "wwwroot/images",
"MetaWeblog": {
"Username": "admin",
"Password": "changeme",
"BlogUrl": "http://localhost:5000"
},
"Logging": {
"LogLevel": {
"Default": "Information"
}
}
}
MarkdownPath - 你的标记文件在哪里运行ImagesPath - 存放图像MetaWeblog - 外部编辑访问证书如上所述,它将提供但尚不能提供:)
这个博客现在以NuGet 软件包的形式提供,
dotnet add package mostlylucid.MinimalBlog
然后在你的 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();
仅用两种方法调用(AddMinimalBlog 和 UseMinimalBlog你有一个工作博客。
管理包括样本项目:
cd Mostlylucid.MinimalBlog
dotnet run
访问访问访问访问 http://localhost:5000 你会看到这个博客 从配置路径上加了标记文件。
创建新博客文章:
.md 在您配置的文件中 MarkdownPath# Your Post Title
Your content here...
要添加图像,只需将其放在您的配置中 ImagesPath 并在您的标记中引用目录 :

这个最小的博客故意不包括:
这些特征都是 可能(可能) 添加,但是它们不是默认包含的, 因为大多数小博客都不需要它们。
尽管简简单简洁, 快速快速:
对于一个中小博客(不到1000个文章)来说,
使用使用 最优精华。 最小Blog 时间:
使用 完全最湿润的平台平台 时间:
在现代网络开发世界中,我们常常默认地寻求复杂的解决方案。 需要一个博客吗? 更好地建立数据库,配置ORM, 设置迁移, 添加缓存, 执行搜索, 配置背景工作...
但有时简单的解决办法是 右右右右右 MinimalBlog 证明您可以建立一个功能性、快速和可维护的博客平台, 包括:
那是 不到520行总代码 一个完整的博客平台。
此工程既是一个功能性博客平台,又是一个提醒: 在您添加复杂性之前, 请先问问自己是否真的需要它。 有时您需要的只是一个包含标记文件的文件夹 。
您可以在 The 中找到完整的源代码 最优精细化。 最小Blog 目录 我对密码一满意我就把金币包放出来
博客快乐!
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.