Blog Plugin
Complete blog management with posts, categories, and tags
Blog Plugin
The Blog Plugin provides a complete blogging platform with posts, categories, tags, and all the features needed to run a professional blog.
Installation
npm install @deessejs/plugin-blogConfiguration
// deesse.config.ts
import { defineConfig } from '@deessejs/core'
import { blogPlugin } from '@deessejs/plugin-blog'
export const config = defineConfig({
plugins: [
blogPlugin({
// Enable/disable features
features: {
categories: true,
tags: true,
featuredImage: true,
excerpt: true,
readingTime: true,
author: true,
comments: false, // Use comments plugin separately
sharing: true,
relatedPosts: true,
},
// Post options
posts: {
statusWorkflow: ['draft', 'review', 'published', 'archived'],
defaultStatus: 'draft',
allowScheduledPublishing: true,
},
// Display options
display: {
postsPerPage: 10,
excerptLength: 160,
dateFormat: 'MMMM DD, YYYY',
},
}),
],
})Collections
Posts
The main content collection with all blog post fields:
{
name: 'posts',
fields: [
{
name: 'title',
type: 'string',
required: true,
},
{
name: 'slug',
type: 'string',
unique: true,
},
{
name: 'content',
type: 'richtext',
required: true,
},
{
name: 'excerpt',
type: 'text',
admin: {
description: 'Short description for listings and SEO',
},
},
{
name: 'featuredImage',
type: 'media',
},
{
name: 'status',
type: 'enum',
enum: ['draft', 'review', 'published', 'archived'],
defaultValue: 'draft',
},
{
name: 'publishedAt',
type: 'datetime',
},
{
name: 'author',
type: 'reference',
relation: 'users',
},
{
name: 'categories',
type: 'relation',
relation: 'categories',
many: true,
},
{
name: 'tags',
type: 'relation',
relation: 'tags',
many: true,
},
{
name: 'readingTime',
type: 'number',
admin: {
readOnly: true,
},
},
{
name: 'views',
type: 'number',
defaultValue: 0,
},
],
}Categories
Hierarchical categories for organizing posts:
{
name: 'categories',
fields: [
{
name: 'name',
type: 'string',
required: true,
},
{
name: 'slug',
type: 'string',
unique: true,
},
{
name: 'description',
type: 'text',
},
{
name: 'parent',
type: 'reference',
relation: 'categories',
admin: {
description: 'Parent category for hierarchy',
},
},
{
name: 'image',
type: 'media',
},
{
name: 'color',
type: 'string',
admin: {
description: 'Hex color for category badge',
},
},
],
}Tags
Flexible tags for content organization:
{
name: 'tags',
fields: [
{
name: 'name',
type: 'string',
required: true,
unique: true,
},
{
name: 'slug',
type: 'string',
unique: true,
},
{
name: 'description',
type: 'text',
},
],
}Admin Pages
The plugin adds the following admin pages:
Posts Page
- List all posts with filters (status, category, author)
- Quick actions (publish, archive, delete)
- Bulk operations
- Column customization
Categories Page
- Hierarchical tree view
- Drag-and-drop reordering
- Category stats (post count)
Tags Page
- List all tags
- Tag popularity (usage count)
- Merge tags functionality
API Routes
# Get all posts
GET /api/blog/posts
# Get published posts (public)
GET /api/blog/posts/published
# Get post by slug
GET /api/blog/posts/:slug
# Get posts by category
GET /api/blog/posts?category=tech
# Get posts by tag
GET /api/blog/posts?tag=nextjs
# Search posts
GET /api/blog/posts?search=react
# Get categories
GET /api/blog/categories
# Get tags
GET /api/blog/tags
# Get related posts
GET /api/blog/posts/:slug/relatedFrontend Components
PostList Component
import { PostList } from '@deessejs/plugin-blog/components'
export default function BlogPage() {
return (
<PostList
pagination={10}
filters={{
status: 'published',
category: 'tech',
}}
sort={{ field: 'publishedAt', direction: 'desc' }}
/>
)
}PostCard Component
import { PostCard } from '@deessejs/plugin-blog/components'
export function BlogCard({ post }) {
return (
<PostCard
post={post}
showAuthor
showDate
showReadingTime
showExcerpt
variant="horizontal"
/>
)
}CategoryFilter Component
import { CategoryFilter } from '@deessejs/plugin-blog/components'
export default function Layout() {
return (
<CategoryFilter
showCount
layout="tree"
collapsible
/>
)
}TagCloud Component
import { TagCloud } from '@deessejs/plugin-blog/components'
export default function Sidebar() {
return (
<TagCloud
maxTags={20}
sortBy="popularity"
/>
)
}Hooks
useBlogPosts
'use client'
import { useBlogPosts } from '@deessejs/plugin-blog/hooks'
export default function Blog() {
const { posts, loading, error, pagination } = useBlogPosts({
status: 'published',
limit: 10,
sort: '-publishedAt',
})
if (loading) return <div>Loading...</div>
if (error) return <div>Error: {error.message}</div>
return (
<div>
{posts.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.excerpt}</p>
</article>
))}
</div>
)
}useBlogPost
'use client'
import { useBlogPost } from '@deessejs/plugin-blog/hooks'
export default function PostPage({ slug }) {
const { post, loading, error } = useBlogPost(slug)
if (loading) return <div>Loading...</div>
if (error) return <div>Error: {error.message}</div>
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
</article>
)
}Server Components
getBlogPosts
import { getBlogPosts } from '@deessejs/plugin-blog/server'
export default async function BlogPage() {
const posts = await getBlogPosts({
where: { status: 'published' },
include: { author: true, categories: true, tags: true },
orderBy: { publishedAt: 'desc' },
take: 10,
})
return (
<div>
{posts.map(post => (
<article key={post.id}>
<h2>{post.title}</h2>
</article>
))}
</div>
)
}getBlogPost
import { getBlogPost } from '@deessejs/plugin-blog/server'
export default async function PostPage({ params }) {
const post = await getBlogPost({
where: { slug: params.slug },
include: { author: true, categories: true, tags: true },
})
return (
<article>
<h1>{post.title}</h1>
</article>
)
}URL Structure
The plugin sets up these routes automatically:
/blog # Blog home
/blog/:slug # Individual post
/blog/category/:slug # Category archive
/blog/tag/:slug # Tag archive
/blog/page/:page # Paginated posts
/admin/blog # Admin posts page
/admin/blog/categories # Admin categories page
/admin/blog/tags # Admin tags pageSEO Integration
Works seamlessly with the SEO plugin:
// app/blog/[slug]/page.tsx
import { getBlogPost } from '@deessejs/plugin-blog/server'
export async function generateMetadata({ params }) {
const post = await getBlogPost({ where: { slug: params.slug } })
return {
title: post.seoTitle || post.title,
description: post.metaDescription || post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
images: post.featuredImage ? [post.featuredImage] : [],
type: 'article',
publishedTime: post.publishedAt,
authors: [post.author.name],
},
}
}Sitemap Integration
Automatically includes blog posts in sitemap:
// The plugin automatically registers with the sitemap plugin
// Posts with status 'published' are includedRSS Feed
Generates RSS feed for published posts:
# RSS feed available at
/rss/blog
# With query parameters
/rss/blog?category=tech
/rss/blog?tag=nextjsReading Time
Automatically calculates reading time:
// Calculated based on word count (200 words per minute)
// Can be customized in plugin config
blogPlugin({
readingTime: {
wordsPerMinute: 200,
includeImages: true, // Add time for images
imageSeconds: 12, // Seconds per image
},
})Related Posts
Automatically suggests related posts based on:
- Shared categories
- Shared tags
- Publication date proximity
blogPlugin({
relatedPosts: {
maxResults: 3,
algorithm: 'categories', // or 'tags', 'mixed'
},
})Next Steps
- Explore the SEO Plugin
- Learn about Changelog Plugin
- Return to Plugins Overview