Adding a Blog to MarkoPress
Turn your MarkoPress site into a full-featured blog with RSS feeds, tags, and SEO
# Adding a Blog to MarkoPress
Transform your MarkoPress site into a powerful blogging platform. This comprehensive guide covers everything from creating posts to advanced features like RSS feeds, tag pages, and SEO optimization.
# What You’ll Build
By the end of this tutorial, you’ll have:
- ✅ Beautiful blog with automatic routing
- ✅ RSS feed for subscribers
- ✅ Tag-based organization
- ✅ SEO-optimized posts
- ✅ Author profiles
- ✅ Reading time estimates
- ✅ Social sharing integration
- ✅ Related posts section
# Prerequisites
- Completed Building a Static Site
- Basic knowledge of markdown
- Text editor (VS Code, etc.)
# Understanding Blog Structure
MarkoPress blogs use file-based routing:
content/
└── blog/
├── 2024-01-15-first-post.md # → /blog/first-post
├── 2024-01-20-second-post.md # → /blog/second-post
└── 2024-02-01-third-post.md # → /blog/third-post
URL format: /blog/{filename-without-date}
# Step 1: Enable Blog Plugin
Ensure the blog plugin is enabled in your config.
# Check Configuration
Edit markopress.config.ts:
import { defineConfig } from 'markopress';
export default defineConfig({
content: {
blog: 'content/blog', // Blog directory
},
plugins: [
'@markopress/plugin-content-blog',
],
});
# Step 2: Write Your First Post
Create a blog post with frontmatter.
# Create the File
Create content/blog/2024-02-03-my-first-post.md:
---
title: "My First Blog Post"
description: "Hello world! This is my first post."
date: 2024-02-03
author: "Your Name"
tags: ["announcement", "first-post"]
categories: ["News"]
excerpt: "Welcome to my blog! This is my first post using MarkoPress."
---
# My First Blog Post
Welcome to my blog! This is my first post using MarkoPress.
## Why I Started Blogging
I decided to start a blog to:
- Share my knowledge
- Connect with others
- Build an online presence
- Improve my writing
## What to Expect
I'll be writing about:
- Web development
- Design
- Technology
- Personal growth
Thanks for reading!
# View Your Post
Run npm run dev and visit /blog/my-first-post.
You’ll see:
- Beautiful typography
- Post metadata (date, author, tags)
- Automatic routing
- Responsive layout
# Step 3: Blog Frontmatter
Use frontmatter to add metadata to posts.
# Available Fields
---
title: "Post Title" # Required
description: "Post description" # Required for SEO
date: 2024-02-03 # Required (YYYY-MM-DD)
author: "Author Name" # Optional
tags: ["tag1", "tag2"] # Optional (creates tag pages)
categories: ["Category"] # Optional
excerpt: "Short summary" # Optional (for previews)
draft: false # Optional (excludes from build if true)
---
# Complete Example
---
title: "Advanced MarkoPress Techniques"
description: "Learn advanced features and best practices"
date: 2024-02-03
author: "Jane Developer"
tags: ["tutorial", "advanced", "markopress"]
categories: ["Tutorials"]
excerpt: "Dive deep into MarkoPress advanced features"
draft: false
---
# Content here...
# Step 4: Create Blog Homepage
Create a landing page for your blog.
# Blog Index Page
Create content/pages/blog.md:
---
title: "Blog"
description: "Latest posts and tutorials"
---
# Blog
Welcome to my blog! Here you'll find tutorials, thoughts, and updates.
## Featured Posts
### [Advanced MarkoPress Techniques](/blog/2024-02-03-advanced-techniques)
Learn advanced features and best practices for building production-ready sites.
*February 3, 2024 • 5 min read*
### [Custom Theme Development](/blog/2024-01-27-custom-themes)
Create stunning custom themes with MarkoPress's powerful theming system.
*January 27, 2024 • 8 min read*
## Recent Posts
* [Getting Started with MarkoPress](/blog/2024-01-15-getting-started) - January 15, 2024
* [SEO Best Practices](/blog/2024-01-10-seo) - January 10, 2024
* [Performance Optimization](/blog/2024-01-05-performance) - January 5, 2024
## Categories
- [Tutorials](/blog/category/tutorials) - 15 posts
- [Updates](/blog/category/updates) - 8 posts
- [Case Studies](/blog/category/case-studies) - 5 posts
## Tags
#web-development (12) • #design (8) • #tutorial (15) • #performance (6)
# Step 5: RSS Feed
MarkoPress automatically generates RSS feeds.
# Feed Location
Your RSS feed is available at:
/api/rss/xml
# Subscribe in Feed Reader
Users can subscribe with:
- Feedly
- NewsBlur
- Inoreader
- Any RSS reader
# Customize Feed
Edit your config to customize the feed:
export default defineConfig({
site: {
title: 'My Blog',
description: 'My awesome blog',
},
themeConfig: {
// Feed info
feed: {
title: 'My Blog - RSS Feed',
description: 'Latest posts from My Blog',
},
},
});
# Step 6: Tag Pages
Create pages for each tag automatically.
# Enable Tag Pages
Tags are automatically generated from frontmatter. Create posts with tags:
---
title: "Post Title"
tags: ["tutorial", "beginner"]
---
# Tag Page URLs
Each tag gets a page at:
/blog/tags/tutorial
/blog/tags/beginner
# Custom Tag Layout
Create a custom layout for tag pages by overriding the blog layout.
# Step 7: Author Profiles
Add author information to posts.
# Author Metadata
---
title: "Post Title"
author: "Jane Developer"
authorUrl: "https://twitter.com/janedev"
authorBio: "Web developer and designer"
---
# Multiple Authors
For sites with multiple authors, create an authors directory:
content/
├── authors/
│ ├── jane.md
│ └── john.md
└── blog/
└── post.md
content/authors/jane.md:
---
name: "Jane Developer"
bio: "Web developer and designer"
url: "https://twitter.com/janedev"
avatar: "/authors/jane.jpg"
---
Reference in post:
---
author: "jane"
---
# Step 8: Reading Time
Automatically calculate reading time for posts.
# Add Reading Time Plugin
Create plugins/reading-time.ts:
import type { MarkoPressPlugin, ContentContext, PostData } from 'markopress/plugin';
export default function readingTimePlugin(): MarkoPressPlugin {
return {
name: 'reading-time-plugin',
contentLoaded(ctx: ContentContext) {
const posts = ctx.getPosts();
for (const post of posts) {
const words = post.content.split(/\s+/).length;
const minutes = Math.ceil(words / 200); // 200 words per minute
post.frontmatter.readingTime = `${minutes} min read`;
ctx.addPost(post);
}
},
};
}
# Use in Config
import readingTimePlugin from './plugins/reading-time';
export default defineConfig({
plugins: [
readingTimePlugin(),
],
});
# Display in Template
Add to your blog layout:
<if(input.post.readingTime)>
<span class="reading-time">
${input.post.readingTime}
</span>
</if>
# Step 9: Social Sharing
Add social sharing buttons to posts.
# Share Component
Create src/tags/ShareButtons.marko:
class {
shareToTwitter() {
const url = encodeURIComponent(window.location.href);
const text = encodeURIComponent(input.title);
window.open(
`https://twitter.com/intent/tweet?text=${text}&url=${url}`,
'_blank'
);
}
shareToLinkedIn() {
const url = encodeURIComponent(window.location.href);
window.open(
`https://www.linkedin.com/sharing/share-offsite/?url=${url}`,
'_blank'
);
}
copyLink() {
navigator.clipboard.writeText(window.location.href);
alert('Link copied!');
}
}
<div class="share-buttons">
<button onClick=>shareToTwitter()>
Share on Twitter
</button>
<button onClick=>shareToLinkedIn()>
Share on LinkedIn
</button>
<button onClick=>copyLink()>
Copy Link
</button>
</div>
<style>`
.share-buttons {
display: flex;
gap: 0.5rem;
margin-top: 2rem;
}
.share-buttons button {
padding: 0.5rem 1rem;
background: var(--bg-primary);
border: 2px solid var(--border-color);
border-radius: 8px;
cursor: pointer;
transition: all 0.2s;
}
.share-buttons button:hover {
border-color: var(--accent-color);
}
`</style>
# Use in Post Layout
<div class="blog-post">
<h1>${input.title}</h1>
<div class="post-content">
<include(input.content/>
</div>
<components.ShareButtons title=input.title/>
</div>
# Step 10: SEO Optimization
Optimize your blog for search engines.
# Meta Tags
Add meta tags to post frontmatter:
---
title: "Post Title"
description: "Post description for SEO"
---
# Content
MarkoPress automatically creates:
<meta name="description" content="Post description">
<meta property="og:title" content="Post Title">
<meta property="og:description" content="Post description">
<meta property="og:type" content="article">
# Structured Data
Add JSON-LD for blog posts:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "${input.title}",
"description": "${input.description}",
"datePublished": "${input.date}",
"author": {
"@type": "Person",
"name": "${input.author}"
}
}
</script>
# Sitemap
MarkoPress automatically includes blog posts in sitemap.xml.
# Step 11: Related Posts
Show related posts at the end of each post.
# Related Posts Plugin
Create plugins/related-posts.ts:
import type { MarkoPressPlugin, PostData } from 'markopress/plugin';
export default function relatedPostsPlugin(): MarkoPressPlugin {
return {
name: 'related-posts-plugin',
contentLoaded(ctx) {
const posts = ctx.getPosts();
for (const post of posts) {
const postTags = post.tags || [];
const related = posts
.filter(p => p.id !== post.id)
.filter(p => {
const pTags = p.tags || [];
return pTags.some(t => postTags.includes(t));
})
.slice(0, 3);
post.frontmatter.relatedPosts = related;
ctx.addPost(post);
}
},
};
}
# Display Related Posts
<if(input.relatedPosts && input.relatedPosts.length)>
<section class="related-posts">
<h3>Related Posts</h3>
<ul>
<for|post| of=input.relatedPosts>
<li>
<a href=post.routePath>${post.title}</a>
</li>
</for>
</ul>
</section>
</if>
# Step 12: Post Series
Create multi-part tutorial series.
# Series Metadata
---
title: "Part 1: Getting Started"
series: "Complete MarkoPress Guide"
seriesOrder: 1
---
# Series Plugin
export default function seriesPlugin(): MarkoPressPlugin {
return {
name: 'series-plugin',
contentLoaded(ctx) {
const posts = ctx.getPosts();
const seriesMap = new Map();
for (const post of posts) {
const series = post.frontmatter.series;
if (!series) continue;
if (!seriesMap.has(series)) {
seriesMap.set(series, []);
}
seriesMap.get(series).push(post);
}
for (const [series, seriesPosts] of seriesMap) {
for (const post of seriesPosts) {
post.frontmatter.seriesPosts = seriesPosts;
ctx.addPost(post);
}
}
},
};
}
# Display Series Navigation
<if(input.seriesPosts)>
<nav class="series-nav">
<h4>Series: ${input.series}</h4>
<ol>
<for|post| of=input.seriesPosts.sort((a, b) => a.seriesOrder - b.seriesOrder)>
<li class=${post.id === input.id ? 'current' : ''}>
<if(post.id === input.id)>
<span>${post.title}<div data-marko-tag="0"></div>
<a href=post.routePath>${post.title}</a>
</if>
</li>
</for>
</ol>
</nav>
</if>
# Step 13: Analytics
Track blog performance.
# Google Analytics
Add to markopress.config.ts:
export default defineConfig({
themeConfig: {
analytics: {
googleAnalyticsId: 'GA_MEASUREMENT_ID',
},
},
});
# Plausible Analytics
export default defineConfig({
themeConfig: {
analytics: {
plausibleDomain: 'yourdomain.com',
},
},
});
# Step 14: Comments
Add comments to your blog.
# Disqus Integration
Create src/tags/Comments.marko:
<div id="disqus_thread"></div>
<script>
var disqus_config = function () {
this.page.url = '${input.url}';
this.page.identifier = '${input.id}';
};
(function() {
var d = document, s = d.createElement('script');
s.src = 'https://YOUR-DISQUS-SHORTNAME.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>
Please enable JavaScript to view the comments.
</noscript>
# Use in Layout
<div class="blog-post">
<!-- Post content -->
<components.Comments url=input.url id=input.id/>
</div>
# Best Practices
# 1. Consistent URLs
Use consistent URL patterns:
/blog/yyyy-mm-dd-post-title
# 2. Optimize Images
Compress images before uploading:
# Use imageoptim or squoosh-cli
imageoptim blog-image.jpg
# 3. Internal Linking
Link to related posts:
Check out [my previous post](/blog/2024-01-15-previous-post) for more details.
# 4. Update Old Posts
Keep content fresh by updating old posts with new information.
# 5. Use Categories Wisely
- Limit to 3-5 categories
- Make them broad enough to grow
- Use tags for specific topics
# Advanced Features
# Draft Posts
Create posts that won’t be published:
---
title: "Draft Post"
draft: true
---
# Scheduled Posts
Set future dates to schedule posts:
---
title: "Future Post"
date: 2024-12-25
---
# Post Expiration
Add expiration dates:
---
title: "Temporary Announcement"
expires: 2024-03-01
---
# Syndication
Automatically share new posts to social media using webhooks.
# Troubleshooting
# Posts Not Showing
- Check file is in
content/blog/ - Verify frontmatter is valid
- Ensure
draft: falseor nodraftfield - Run
npm run buildand check for errors
# RSS Feed Empty
- Ensure blog plugin is enabled
- Check posts have valid dates
- Verify feed URL:
/api/rss/xml
# Tags Not Working
- Check tag names in frontmatter
- Ensure tags are arrays:
["tag1", "tag2"] - Rebuild the site
# Next Steps
Your blog is now ready! Here’s what to do next:
- ✅ Write your first 5 posts
- ✅ Set up analytics
- ✅ Add comments (optional)
- ✅ Customize your theme
- ✅ Share your posts
# Continue Learning
Happy blogging! 🎉
- Adding a Blog to MarkoPress
- What You'll Build
- Prerequisites
- Understanding Blog Structure
- Step 1: Enable Blog Plugin
- Step 2: Write Your First Post
- Step 3: Blog Frontmatter
- Step 4: Create Blog Homepage
- Step 5: RSS Feed
- Step 6: Tag Pages
- Step 7: Author Profiles
- Step 8: Reading Time
- Step 9: Social Sharing
- Step 10: SEO Optimization
- Step 11: Related Posts
- Step 12: Post Series
- Step 13: Analytics
- Step 14: Comments
- Best Practices
- Advanced Features
- Troubleshooting
- Next Steps
- Continue Learning