Skip to content

weggetor/MDBlog

Repository files navigation

MDBlog - Markdown-Based Blog System

A modern, file-based blog system built with Blazor and .NET 10 that uses markdown files for content and SQLite for metadata caching.

Features

Markdown-Based: Write posts in Markdown with YAML front matter
File-System Storage: No complex database - just upload markdown files
SQLite Caching: Fast metadata queries with automatic indexing
Theme System: Customizable themes with CSS, JavaScript, and configuration
Advanced Markdown: Tables, code blocks, task lists, and more (via Markdig)
Syntax Highlighting: Beautiful code highlighting with Highlight.js (10+ languages)
SEO Optimized: Meta tags, Open Graph, Twitter Cards
Responsive Design: Mobile-optimized layouts
Animated Header: Theme-specific features like collapsing headers
Tag System: Organize and filter posts by tags
Pagination: Configurable posts per page
View Tracking: Built-in analytics for post views
Static File Serving: Images and documents served directly from post directories
Placeholder Images: Auto-generated SVG placeholders for posts without cover images
IIS Ready: Production-ready web.config included

Quick Start

Prerequisites

  • .NET 10 SDK or later
  • Visual Studio 2022 or VS Code

Running Locally

  1. Clone the repository
  2. Open the solution in Visual Studio
  3. Press F5 to run

The blog will be available at https://localhost:5001

Creating Blog Posts

  1. Create a directory in BlogPosts/ with format: YYYY-MM-DD-url-slug Example: BlogPosts/2024-11-15-my-first-post/

  2. Create a post.md file with YAML front matter:

---
title: "My First Post"
date: 2024-11-15
author: "Your Name"
summary: "A brief description of your post"
tags: [blazor, dotnet, tutorial]
image: "images/cover.jpg"
published: true
metaDescription: "SEO-friendly description"
metaKeywords: "blazor, markdown, blog"
---

# My First Post

Your markdown content here...

## Images

![Image](images/photo.jpg)

## Code Blocks

```csharp
public class Example
{
    public string Name { get; set; }
}

```

  1. Add images to images/ subdirectory (optional)
  2. Restart the application to scan for new posts

Project Structure

MDBlog/
├── BlogPosts/                          # Blog post storage (Git ignored)
│   ├── .gitkeep                        # Keeps directory in Git
│   ├── README.md                       # BlogPosts documentation
│   └── YYYY-MM-DD-post-slug/
│       ├── post.md                     # Markdown content
│       └── images/                     # Post images
├── Components/
│   ├── Pages/
│   │   ├── BlogList.razor              # Post listing with pagination
│   │   ├── BlogPostDetail.razor        # Single post view
│   │   ├── BlogTag.razor               # Tag filter view
│   │   ├── Home.razor                  # Home page
│   │   ├── Error.razor                 # Error handler
│   │   └── NotFound.razor              # 404 handler
│   ├── Layout/
│   │   └── MainLayout.razor            # Theme-aware layout
│   ├── App.razor                       # App root with dynamic theme loading
│   ├── Routes.razor                    # Routing configuration
│   └── _Imports.razor                  # Global usings
├── Data/
│   └── BlogDbContext.cs                # SQLite database context
├── HostedServices/
│   └── BlogInitializationService.cs    # Background post scanner
├── Models/
│   ├── BlogConfiguration.cs            # Configuration model
│   ├── BlogPost.cs                     # Post entity
│   ├── PostMetadata.cs                 # YAML metadata
│   └── ThemeConfiguration.cs           # Theme configuration model
├── Services/
│   ├── BlogPostService.cs              # Post management service
│   └── ThemeService.cs                 # Theme loading service
├── Themes/                              # Theme system
│   ├── Default/                        # Default theme (included)
│   │   ├── theme.json
│   │   ├── theme.css
│   │   ├── theme.js
│   │   └── assets/images/
│   └── .gitkeep
├── wwwroot/
│   ├── css/
│   │   └── blog.css                    # Legacy styles
│   ├── js/
│   └── images/
│       └── blog-post-placeholder.svg   # Fallback cover image
├── appsettings.json                    # Configuration (includes theme selection)
├── blog.db                             # SQLite database (auto-created, Git ignored)
├── web.config                          # IIS configuration
├── THEMES.md                           # Theme creation guide
└── README.md                           # This file

Configuration

Edit appsettings.json to customize your blog:

{
  "Blog": {
    "PostsDirectory": "BlogPosts",
    "PostsPerPage": 5,
    "MarkdownFileName": "post.md",
    "CacheDurationMinutes": 60,
    "SiteName": "bitboxx.net",
    "SiteDescription": "dotnetnuke blog, modules & more",
    "Author": "Torsten Weggen",
    "BaseUrl": "https://localhost:5001",
    "Theme": "Default",
    "ThemesDirectory": "Themes"
  }
}

Theme System

MDBlog features a powerful theme system that allows you to customize your blog's appearance without modifying the core code.

Built-in Themes

Default Theme:

  • Clean, minimal design
  • Blue and white color scheme
  • Professional appearance
  • No JavaScript dependencies
  • Perfect for generic blogs and documentation

Bitboxx Theme (Example):

  • Matrix-inspired aesthetic
  • Green (#00ff41) on dark background
  • Collapsing header animation
  • Scrolling ticker with recent posts
  • Custom JavaScript features
  • Perfect for tech blogs

Switching Themes

Change the active theme in appsettings.json:

{
  "Blog": {
    "Theme": "Default",  // or "Bitboxx" or "YourCustomTheme"
    "ThemesDirectory": "Themes"
  }
}

Restart the application to apply the new theme.

Theme Structure

Each theme is a self-contained directory:

Themes/
├── Default/              # Generic theme (included)
│   ├── theme.json       # Theme configuration
│   ├── theme.css        # Theme styles
│   ├── theme.js         # Theme JavaScript (optional)
│   └── assets/          # Theme-specific assets
│       └── images/
└── YourTheme/           # Your custom theme
    ├── theme.json
    ├── theme.css
    ├── theme.js
    └── assets/

Creating Custom Themes

See THEMES.md for comprehensive documentation on creating custom themes.

Quick start:

  1. Create theme directory:
mkdir -p Themes/MyTheme/assets/images
  1. Create theme.json:
{
  "name": "My Theme",
  "author": "Your Name",
  "version": "1.0.0",
  "header": {
    "style": "Simple",
    "height": 80
  },
  "javascript": {
    "enabled": false
  }
}
  1. Create theme.css with your styles

  2. Activate in appsettings.json:

{
  "Blog": {
    "Theme": "MyTheme"
  }
}

Theme Features

Themes can customize:

  • Colors - Primary, secondary, links, text
  • Fonts - Body, headings, code blocks
  • Layout - Header style, spacing, containers
  • Components - Posts, tags, pagination, navigation
  • JavaScript - Custom interactivity and animations
  • Assets - Logos, backgrounds, custom images

Theme Configuration Options

Header Styles:

  • Simple - Clean, minimal header
  • Matrix - Animated header with effects
  • Minimal - Ultra-compact header

JavaScript Integration: Themes can include custom JavaScript for:

  • Animated headers
  • Scrolling effects
  • Interactive components
  • Custom navigation

Mobile Optimization: All themes include responsive breakpoints for:

  • 📱 Mobile (≤768px)
  • 💻 Tablet (769px-1024px)
  • 🖥️ Desktop (>1024px)

For complete theme documentation, see THEMES.md.

YAML Front Matter

Supported fields in markdown files:

Field Type Required Default Description
title string ✅ Yes - Post title
date date ❌ No From directory name Publication date
author string ❌ No From config Author name
summary string ❌ No - Brief excerpt for listings
tags array ❌ No [] List of tags
image string ❌ No - Cover image path (relative)
published boolean ❌ No true Visibility control
metaDescription string ❌ No Summary SEO meta description
metaKeywords string ❌ No - SEO keywords

Directory Naming Convention

Post directories must follow: YYYY-MM-DD-url-slug

Examples:

  • 2024-01-15-getting-started-with-blazor/
  • 2024-02-20-markdown-best-practices/
  • 2024-03-10-deploying-to-azure/

Benefits:

  • 📅 Chronological sorting
  • 🔗 URL-friendly slugs
  • 🔍 SEO optimized
  • 📂 Easy to manage

Image Handling

Using Images in Markdown

Use relative paths in your markdown:

![Alt text](images/photo.jpg)

The system automatically converts these to absolute URLs:

<img src="/BlogPosts/2024-11-15-my-post/images/photo.jpg" />

Cover Images

Specify in YAML front matter:

image: "images/cover.jpg"

If no image is specified, an auto-generated placeholder SVG is used.

Directory Structure for Images

BlogPosts/2024-11-15-my-post/
├── post.md
└── images/
    ├── cover.jpg      # Cover image
    ├── photo1.png     # Content images
    └── photo2.jpg

Code Highlighting

Syntax highlighting is automatically applied to code blocks. Just specify the language:

public class Example
{
    public string Name { get; set; }
}

Supported languages:

  • C# (csharp)
  • JavaScript (javascript)
  • TypeScript (typescript)
  • Python (python)
  • PowerShell (powershell)
  • SQL (sql)
  • JSON (json)
  • XML (xml)
  • HTML (html)
  • CSS (css)
  • And many more...

Theme: VS2015 Dark (customizable in App.razor)

Design Features

Customizable Themes

MDBlog includes a powerful theme system with built-in themes:

Default Theme:

  • Clean, professional appearance
  • Blue (#007bff) and white colors
  • Standard sans-serif fonts
  • Mobile-optimized layout
  • No JavaScript dependencies
  • Perfect for business blogs and documentation

Bitboxx Theme:

  • Matrix-inspired aesthetic
  • Dark green (#00b82e) on light background
  • Animated header that collapses on scroll (230px → 80px)
  • Scrolling ticker showing recent posts
  • Monospace fonts in header (Courier New)
  • Custom JavaScript animations
  • Perfect for tech blogs and retro aesthetics

Theme Switching: Simply change "Theme": "Default" to "Theme": "Bitboxx" in appsettings.json and restart!

Responsive Design

All themes are mobile-first with optimized layouts:

Desktop (>768px):

  • Full-width headers with all features
  • Spacious padding for comfortable reading
  • Multi-column layouts where appropriate

Mobile (≤768px):

  • Compact headers (collapsible in Bitboxx theme)
  • Minimal padding to maximize content space
  • Single-column layouts
  • Touch-friendly navigation

Custom Theme Creation

Create your own themes to match your brand! See THEMES.md for:

  • Theme structure and files
  • Configuration options
  • CSS guidelines
  • JavaScript integration
  • Responsive breakpoints
  • Best practices

Database

SQLite Auto-Generation

The SQLite database (blog.db) is automatically created on first run:

// In BlogInitializationService
await dbContext.Database.EnsureCreatedAsync();
await blogService.RefreshPostsFromFileSystemAsync();

What's stored:

  • Post metadata (title, date, author, tags, etc.)
  • View counts
  • Cache timestamps

Not stored:

  • Markdown content (read from files on-demand)
  • Images (served as static files)

Deleting the Database

You can safely delete blog.db anytime:

rm blog.db blog.db-shm blog.db-wal

It will be regenerated on next startup! ✅

Git Configuration

What's Ignored (.gitignore)

# SQLite database (auto-generated)
*.db
*.db-shm
*.db-wal

# Blog content (user content, not source code)
BlogPosts/
!BlogPosts/.gitkeep
!BlogPosts/README.md

# Build output
publish/

Why?

  • Database is regenerated from markdown files
  • Blog posts are user content, managed separately
  • Only source code is tracked in Git

Workflow

Development:

git clone repo
# Add your own test posts
git add <source-files-only>
git commit -m "Feature"
# blog.db and BlogPosts/ are NOT committed

Production:

git pull
# Upload posts via FTP/rsync separately
dotnet publish
# blog.db created automatically from posts

Technologies Used

Deployment

IIS (Windows Server)

See IIS-DEPLOYMENT.md for detailed instructions.

Quick steps:

  1. Publish:
dotnet publish -c Release
  1. Deploy: Copy publish/ contents to IIS directory

  2. Configure IIS:

  • Application pool: .NET 10
  • Enable HTTPS
  • Add web.config transformations if needed
  1. Start the site in IIS Manager

Your blog should now be live! 🌐

Common Issues

  • HTTP Error 500.30 - Failed to start Windows Process Activation Service (WAS)

    • Solution: Ensure the correct .NET version is installed and assigned in IIS
  • 404 Not Found for posts or assets

    • Solution: Check routing in Routes.razor and ensure posts exist in BlogPosts/
  • Database file not found on startup

    • Solution: Ensure blog.db is in the root directory and accessible
  • Theme not applying changes

    • Solution: Restart the application after changing the theme in appsettings.json

For more troubleshooting tips, see Troubleshooting.md in the docs folder.

Frequently Asked Questions

1. How do I update MDBlog to the latest version?

  • Pull the latest changes from the repository
  • Update your NuGet packages to the latest versions
  • Run migrations if there are any database changes
  • Restart the application

2. Can I use my own domain name?

Yes! Configure your domain's DNS to point to your server's IP address, then update the BaseUrl in appsettings.json to match your domain.

3. How can I contribute to MDBlog?

We welcome contributions! Please fork the repository, make your changes, and submit a pull request. See CONTRIBUTING.md for more details.

4. Where can I find the documentation?

Documentation is available in the docs/ folder and online at MDBlog Docs.

For more FAQs, please refer to FAQ.md in the docs folder.


Let's get blogging! 📝

About

Blog for Markdown Files - generates from file system

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published