A utility package to find related posts or blogs based on semantic similarity of titles, categories, and tags. Works with standard content objects and Astro blog collections.
bash
npm install relatedposts @xenova/transformers
`
bash
`bash
import getRelated, { getRelatedAstro } from 'relatedposts';
`
Function
The getRelated function evaluates and returns a list of Comparison objects that are most similar to a given Input object. Similarity is determined using semantic embeddings for titles, exact matching for categories, and overlap analysis for tags. The results are sorted by their similarity scores in descending order.
Note: This function uses machine learning embeddings and is asynchronous. The first call may take longer as it downloads and initializes the transformer model (~90MB).
Parameters
1. input (Input):
* An object representing the input data to be compared against.
* Fields:
* title (string): The title of the input.
* category (string): The category of the input.
* tags (string[]): An array of tags associated with the input.
Example:
typescript
`typescript
const input = {
title: "The quick brown dog",
category: "Animals",
tags: ["quick", "brown", "dog"],
};
`
2. comparisons (Comparison[]):
* An array of objects representing the items to be compared against the input.
* Fields:
* title (string): The title of the comparison item.
* category (string): The category of the comparison item.
* tags (string[]): An array of tags associated with the comparison item.
Example:
typescript
`typescript
const comparisons = [
{
title: "The quick brown fox",
category: "Animals",
tags: ["quick", "brown", "fox"],
},
{
title: "The lazy dog",
category: "Animals",
tags: ["lazy", "dog"],
},
{
title: "A fast brown cat",
category: "Animals",
tags: ["fast", "brown", "cat"],
},
];
`
3. numResults (number, optional):
* The number of results to return. Defaults to 5.
4. options (Options, optional):
* An object containing weights to influence the similarity score calculations.
* Fields:
* weights (Weights, optional): Object containing weight values for different similarity components.
* title (number, optional): Weight for the title similarity score. Defaults to 1.
* category (number, optional): Weight for the category similarity score. Defaults to 1.
* tags (number, optional): Weight for the tags similarity score. Defaults to 1.
Example:
typescript
`typescript
const options = {
weights: {
title: 2.0, // Title similarity is twice as important
category: 1.5, // Category matching is 1.5x as important
tags: 1.0 // Tags have standard weight
}
};
`
Returns
* A Promise that resolves to an array of ScoredComparison objects.
* Fields:
* All fields of the original Comparison object.
* score (number): The computed similarity score (0-1 range) based on semantic similarity, category matching, and tag overlap.
Example output:
typescript
`typescript
const results = [
{
title: "A fast brown cat",
category: "Animals",
tags: ["fast", "brown", "cat"],
score: 0.87, // High semantic similarity between "quick dog" and "fast cat"
},
{
title: "The quick brown fox",
category: "Animals",
tags: ["quick", "brown", "fox"],
score: 0.82, // Very similar words and structure
},
{
title: "The lazy dog",
category: "Animals",
tags: ["lazy", "dog"],
score: 0.71, // Same animal type but different characteristics
},
];
`
Usage
typescript
`typescript
// Basic usage
const results = await getRelated(input, comparisons, 5);
console.log(results);
// With custom weights
const results = await getRelated(input, comparisons, 3, {
weights: {
title: 2.0,
category: 1.0,
tags: 0.5
}
});
console.log(results);
`
getRelatedAstro Function
The getRelatedAstro function is specifically designed for Astro blog collections. It works with Astro's data structure where content is nested under a data property and uses ID-based filtering to exclude the current blog post from related suggestions.
$3
1. currentId (string):
- The ID of the current blog post to exclude from results
2. blogs (AstroBlog[]):
- Array of Astro blog objects with nested data structure
3. numResults (number, optional):
- Number of results to return. Defaults to 5
4. options (Options, optional):
- Same weight options as getRelated function
$3
`typescript
interface AstroBlog {
id: string;
collection: string;
data: {
title: string;
category?: string;
tags?: string[];
publishDate?: string;
// ... other frontmatter properties
};
body: string;
}
`
$3
`typescript
import { getRelatedAstro } from 'relatedposts';
// Example: Finding related posts in an Astro project
const currentPostId = "my-current-post.md";
const allBlogPosts = [
{
id: "my-current-post.md",
collection: "blog",
data: {
title: "Getting Started with TypeScript",
category: "Development",
tags: ["typescript", "programming", "tutorial"],
publishDate: "2025-10-13"
},
body: "..."
},
{
id: "advanced-typescript.md",
collection: "blog",
data: {
title: "Advanced TypeScript Patterns",
category: "Development",
tags: ["typescript", "advanced", "patterns"],
publishDate: "2025-10-10"
},
body: "..."
}
// ... more blog posts
];
const relatedPosts = await getRelatedAstro(currentPostId, allBlogPosts, 3);
console.log(relatedPosts);
`
$3
`typescript
const relatedPosts = [
{
title: "Advanced TypeScript Patterns",
category: "Development",
tags: ["typescript", "advanced", "patterns"],
score: 0.89
},
{
title: "JavaScript Best Practices",
category: "Development",
tags: ["javascript", "best-practices"],
score: 0.76
}
];
``