Skip to main content

Overview

The Blog Marketing Platform provides a dual-layer content organization system using Categories for broad classification and Keywords (tags) for granular tagging. This structure improves content discoverability, SEO, and user navigation.

Categories vs Keywords

Categories

Broad classification
  • Technology, Marketing, Design, etc.
  • Hierarchical structure (parent-child)
  • Limited per post (typically 1-3)
  • Featured in navigation

Keywords (Tags)

Specific topics
  • SEO, React, Content Strategy, etc.
  • Flat structure (no hierarchy)
  • Multiple per post (unlimited)
  • Used for search and filtering

Categories

Category Structure

Categories include rich metadata and hierarchy support:
interface Category {
  id: number;
  name: string;
  slug: string;              // URL-friendly identifier
  description: string;
  color: string;             // Hex color for UI display
  icon: string;              // Icon identifier
  postsCount: number;        // Number of posts in category
  isActive: boolean;         // Visibility status
  createdAt: string;
  updatedAt: string;
  createdBy: number | null;
  parentId?: number | null;  // Parent category for hierarchy
  displayOrder?: number;     // Sort order
}

Creating Categories

Only users with crear_categoria permission can create categories:
import { createCategory } from '@/services/categoriesService';

const newCategory = await createCategory({
  name: 'Content Marketing',
  description: 'Strategies and tips for effective content marketing',
  color: '#3B82F6',
  icon: 'FileText',
  isActive: true
});

console.log(`Category created with slug: ${newCategory.slug}`);
The system automatically generates URL-friendly slugs from category names. For example, “Content Marketing” becomes “content-marketing”.

Managing Categories

Get All Categories

import { getAllCategories } from '@/services/categoriesService';

const categories = await getAllCategories();
categories.forEach(cat => {
  console.log(`${cat.name}: ${cat.postsCount} posts`);
});

Get Active Categories Only

import { getActiveCategories } from '@/services/categoriesService';

const activeCategories = getActiveCategories();

Update Category

import { updateCategory } from '@/services/categoriesService';

const updated = await updateCategory(categoryId, {
  name: 'Digital Marketing',
  description: 'Updated description',
  color: '#10B981'
});

Toggle Category Status

Enable or disable a category:
import { toggleCategoryStatus } from '@/services/categoriesService';

const toggled = await toggleCategoryStatus(categoryId);
if (toggled) {
  console.log('Category status changed');
}

Delete Category

import { deleteCategory } from '@/services/categoriesService';

const deleted = await deleteCategory(categoryId);
if (!deleted) {
  console.error('Cannot delete category with existing posts');
}
Categories containing posts cannot be deleted. Reassign or delete posts first, or disable the category instead using toggleCategoryStatus().

Hierarchical Categories

Create parent-child category relationships:
// Create parent category
const parent = await createCategory({
  name: 'Technology',
  description: 'Tech-related content',
  color: '#3B82F6'
});

// Create child categories
const webDev = await createCategory({
  name: 'Web Development',
  description: 'Web development tutorials',
  color: '#3B82F6',
  parentId: parent.id
});

const mobileDev = await createCategory({
  name: 'Mobile Development',
  description: 'Mobile app development',
  color: '#3B82F6',
  parentId: parent.id
});

Hierarchical Structure Query

Retrieve categories in hierarchical format:
import { getCategoriesJerarquicas } from '@/services/categoriesService';

const hierarchical = await getCategoriesJerarquicas();
// Returns:
// [
//   {
//     id: 1,
//     name: 'Technology',
//     children: [
//       { id: 2, name: 'Web Development', parentId: 1 },
//       { id: 3, name: 'Mobile Development', parentId: 1 }
//     ]
//   },
//   ...
// ]

Assigning Categories to Posts

Posts can have multiple categories:
import { addCategoriasToPost } from '@/services/postsService';
import { createPost } from '@/services/postsService';

// Method 1: During post creation
const post = await createPost({
  title: 'Getting Started with React',
  content: '...',
  categoryId: 2, // Primary category (legacy)
  // or use new multi-category field:
  // categories: [2, 5, 8]
});

// Method 2: Add categories to existing post
await addCategoriasToPost(post.id, [2, 5, 8]);

Keywords (Tags)

Keyword Structure

Keywords are simple, flexible tags:
interface Keyword {
  id: number;
  keyword: string;    // The tag text
  slug: string;       // URL-friendly version
}

// Posts include keywords:
interface Post {
  keywords?: Array<{
    id: number;
    keyword: string;
    slug: string;
  }>;
  tags?: string[];    // Alternative format (just strings)
}

Adding Keywords to Posts

Add Existing Keywords

import { addKeywordsToPost } from '@/services/postsService';

// Add keywords by ID
await addKeywordsToPost(postId, [10, 15, 20, 25]);

Create and Add New Keywords

import { createAndAddKeywords } from '@/services/postsService';

// Create new keywords and add to post
await createAndAddKeywords(postId, [
  'react',
  'javascript',
  'web development',
  'frontend',
  'tutorial'
]);

During Post Creation

import { createPost } from '@/services/postsService';

const post = await createPost({
  title: 'Modern JavaScript Features',
  content: '...',
  tags: ['javascript', 'es6', 'programming', 'tutorial']
});

// Tags are automatically converted to keywords

Managing Keywords

Get Post Keywords

import { getPostKeywords } from '@/services/postsService';

const keywords = await getPostKeywords(postId);
keywords.forEach(kw => {
  console.log(`${kw.keyword} (ID: ${kw.id})`);
});

Find or Create Keyword

Search for existing keyword or create new:
import { findOrCreateKeyword } from '@/services/postsService';

const keyword = await findOrCreateKeyword('content-strategy');
if (keyword) {
  await addKeywordsToPost(postId, [keyword.id]);
}

Remove Keywords

import { removeKeywordsFromPost } from '@/services/postsService';

// Remove specific keywords
await removeKeywordsFromPost(postId, [10, 15]);

// Remove all keywords
await removeKeywordsFromPost(postId);

Most Used Keywords

Find popular keywords across all posts:
import { getKeywordsMasUsadas } from '@/services/postsService';

const topKeywords = await getKeywordsMasUsadas(50);
topKeywords.forEach(kw => {
  console.log(`${kw.keyword}: ${kw.count} posts`);
});

Category Analytics

General Statistics

import { getCategoriesStats } from '@/services/categoriesService';

const stats = await getCategoriesStats();
// Returns:
// {
//   total: 20,
//   active: 18,
//   inactive: 2,
//   totalPosts: 500
// }

console.log(`Average posts per category: ${stats.totalPosts / stats.total}`);

Category Engagement

Track how categories perform:
import { getCategoriesEngagement } from '@/services/categoriesService';

const engagement = await getCategoriesEngagement();
// Returns:
// [
//   { 
//     category: 'Technology',
//     views: 15000,
//     engagement: 8.5,
//     avgTimeOnPage: 245
//   },
//   ...
// ]

// Find best performing category
const best = engagement.reduce((max, cat) => 
  cat.engagement > max.engagement ? cat : max
);

Top Performing Categories

import { getCategoriesMejorRendimiento } from '@/services/categoriesService';

const topCategories = await getCategoriesMejorRendimiento();
topCategories.forEach((cat, index) => {
  console.log(`#${index + 1}: ${cat.name} - ${cat.postsCount} posts`);
});

SEO Benefits

Category SEO

  • Category Pages: Each category has a dedicated page (/category/slug)
  • Meta Tags: Category descriptions used in meta tags
  • Breadcrumbs: Categories appear in breadcrumb navigation
  • Sitemaps: Categories included in XML sitemaps

Keyword SEO

  • Tag Pages: Each keyword has a page listing related posts
  • Internal Linking: Keywords create natural internal links
  • Related Content: Keywords help suggest related posts
  • Search: Keywords improve on-site search results
// SEO-friendly category URLs
const categoryUrl = `/category/${category.slug}`;
// Example: /category/content-marketing

// SEO-friendly keyword URLs  
const keywordUrl = `/tag/${keyword.slug}`;
// Example: /tag/react

Content Organization Strategy

Category Strategy

Best Practices:
  • Keep categories broad (5-15 total)
  • Use 2-level hierarchy maximum
  • Ensure even distribution
  • Review quarterly

Keyword Strategy

Best Practices:
  • Use 5-10 keywords per post
  • Mix broad and specific terms
  • Be consistent with naming
  • Update as content evolves

Filtering Content

Filter by Category

// Get all posts in a category
const categoryPosts = allPosts.filter(post => 
  post.categoryId === categoryId
);

// Or with multiple categories
const multiCategoryPosts = allPosts.filter(post =>
  post.categories?.some(cat => [1, 2, 3].includes(cat.id))
);

Filter by Keywords

// Get posts with specific keyword
const keywordPosts = allPosts.filter(post =>
  post.keywords?.some(kw => kw.keyword === 'react')
);

// Multiple keywords (OR logic)
const multiKeywordPosts = allPosts.filter(post =>
  post.keywords?.some(kw => 
    ['react', 'javascript', 'frontend'].includes(kw.keyword)
  )
);

Category Colors and Icons

Categories support visual customization:
const categoryThemes = {
  'Technology': { color: '#3B82F6', icon: 'Laptop' },
  'Marketing': { color: '#10B981', icon: 'TrendingUp' },
  'Design': { color: '#8B5CF6', icon: 'Palette' },
  'Business': { color: '#F59E0B', icon: 'Briefcase' },
  'Tutorial': { color: '#06B6D4', icon: 'BookOpen' }
};

await createCategory({
  name: 'Technology',
  color: '#3B82F6',
  icon: 'Laptop',
  // ...
});

Best Practices

1

Plan Your Taxonomy

Design category structure before creating content. Consider user needs and content types.
2

Use Consistent Naming

Establish naming conventions for both categories and keywords. “Web Development” not “web dev” or “WebDev”.
3

Monitor Usage

Track which categories and keywords perform best. Remove unused tags.
4

Balance Distribution

Avoid having all posts in one category. Aim for even distribution across categories.
5

Update Regularly

Review and refine your taxonomy quarterly. Add new categories as content evolves.

Common Patterns

function getRelatedPosts(currentPost: Post, limit: number = 5) {
  return allPosts
    .filter(post => 
      post.id !== currentPost.id &&
      post.categoryId === currentPost.categoryId
    )
    .sort((a, b) => b.views - a.views)
    .slice(0, limit);
}
function getRelatedPostsByKeywords(currentPost: Post, limit: number = 5) {
  const currentKeywords = currentPost.keywords?.map(kw => kw.keyword) || [];
  
  return allPosts
    .filter(post => post.id !== currentPost.id)
    .map(post => {
      const matchingKeywords = post.keywords?.filter(kw =>
        currentKeywords.includes(kw.keyword)
      ).length || 0;
      
      return { post, score: matchingKeywords };
    })
    .filter(item => item.score > 0)
    .sort((a, b) => b.score - a.score)
    .slice(0, limit)
    .map(item => item.post);
}

Category Navigation Menu

import { getAllCategories } from '@/services/categoriesService';

async function buildCategoryMenu() {
  const categories = await getAllCategories();
  
  return categories
    .filter(cat => cat.isActive && cat.postsCount > 0)
    .sort((a, b) => (a.displayOrder || 0) - (b.displayOrder || 0))
    .map(cat => ({
      label: cat.name,
      href: `/category/${cat.slug}`,
      count: cat.postsCount,
      color: cat.color,
      icon: cat.icon
    }));
}

Build docs developers (and LLMs) love