
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
strapi-plugin-semantic-search
Advanced tools
Intelligent semantic search plugin for Strapi 5 powered by OpenAI embeddings. Automatically generates embeddings for your content and provides powerful semantic search capabilities.
Intelligent content discovery powered by OpenAI embeddings
Transform your Strapi CMS into an AI-powered content platform with automatic embedding generation and semantic search capabilities.
cd src/plugins/semantic-search
npm install openai@^5.8.2 axios@^1.10.0
Add your OpenAI API key to .env:
OPENAI_API_KEY=your_openai_api_key_here
Update config/plugins.ts:
export default ({ env }) => ({
'semantic-search': {
enabled: true,
resolve: './src/plugins/semantic-search'
},
});
Add embedding fields to your content types:
{
"embedding": {
"type": "json"
},
"embeddingMetadata": {
"type": "json"
}
}
npm run develop
By default, the plugin processes these content types and fields:
// Default configuration
{
'api::article.article': ['title', 'content', 'summary'],
'api::blog.blog': ['title', 'body', 'excerpt']
}
Configure which content types and fields to process by updating config/plugins.js:
// config/plugins.js
module.exports = ({ env }) => ({
'semantic-search': {
enabled: true,
resolve: './src/plugins/semantic-search',
config: {
contentTypes: {
'api::article.article': ['title', 'content', 'summary', 'tags'],
'api::blog.blog': ['title', 'body', 'excerpt', 'category'],
'api::product.product': ['name', 'description', 'features', 'benefits'],
'api::course.course': ['title', 'overview', 'learningOutcomes']
}
}
}
});
| Option | Type | Description |
|---|---|---|
contentTypes | Object | Maps content type UIDs to arrays of field names |
Content Type Format: Use Strapi's UID format: api::collection-name.collection-name
Field Names:
The plugin validates your configuration on startup:
api::article.article['title', 'content']api:: prefix, empty fields, etc.Invalid configurations will log warnings and fallback to defaults.
Embeddings are generated automatically when you create or update content. The plugin extracts text from the fields you've configured for each content type (see Configuration section above).
POST /api/semantic-search/search
Request:
{
"query": "artificial intelligence and machine learning",
"contentType": "api::article.article",
"limit": 10,
"threshold": 0.1
}
Response:
{
"success": true,
"data": {
"query": "artificial intelligence and machine learning",
"contentType": "api::article.article",
"results": [
{
"id": 1,
"title": "Deep Learning Fundamentals",
"similarityScore": 0.8945,
"content": "...",
"createdAt": "2025-01-15T10:30:00.000Z"
}
],
"metadata": {
"totalResults": 5,
"queryProcessing": {
"embeddingDimensions": 1536
}
}
}
}
POST /api/semantic-search/multi-search
Request:
{
"query": "productivity and remote work",
"contentTypes": ["api::article.article", "api::blog.blog"],
"limit": 15,
"aggregateResults": true
}
GET /api/semantic-search/stats
Response:
{
"success": true,
"data": {
"api::article.article": {
"total": 50,
"withEmbeddings": 50,
"coverage": "100.00%"
},
"api::blog.blog": {
"total": 25,
"withEmbeddings": 23,
"coverage": "92.00%"
}
}
}
The plugin automatically processes these content types:
api::Default fields processed for embedding generation:
const textFields = [
'title', 'name', 'content', 'body',
'summary', 'description', 'excerpt'
];
| Parameter | Type | Default | Description |
|---|---|---|---|
query | string | required | Search query text |
contentType | string | required | Strapi content type UID |
limit | number | 10 | Maximum results (max: 50) |
threshold | number | 0.1 | Minimum similarity score |
filters | object | {} | Additional database filters |
semantic-search/
├── package.json # Plugin metadata and dependencies
├── strapi-server.js # Plugin entry point
└── server/
├── index.js # Server exports
└── src/
├── index.js # Main plugin logic
├── controllers/ # API request handlers
│ ├── index.js
│ └── search-controller.js
├── services/ # Business logic
│ ├── index.js
│ ├── embedding-service.js # OpenAI integration
│ ├── vector-service.js # Similarity calculations
│ └── search-service.js # Search orchestration
└── routes/ # API endpoint definitions
└── index.js
Embeddings are stored as JSON in your existing database:
{
"embedding": [0.1234, -0.5678, 0.9012, ...], // 1536 dimensions
"embeddingMetadata": {
"model": "text-embedding-ada-002",
"generatedAt": "2025-01-15T10:30:00.000Z",
"dimensions": 1536,
"processedText": "Machine learning fundamentals...",
"originalLength": 1250,
"processedLength": 1180
}
}
Understanding similarity score ranges:
| Score Range | Relevance | Description |
|---|---|---|
| 0.85 - 1.0 | Highly Relevant | Direct topic match |
| 0.75 - 0.85 | Relevant | Related concepts |
| 0.65 - 0.75 | Somewhat Relevant | Tangential connection |
| 0.1 - 0.65 | Low Relevance | Weak semantic relation |
# Install plugin dependencies
cd src/plugins/semantic-search
npm install
# Return to project root
cd ../../../
# Start development server
npm run develop
# Test embedding generation
curl -X POST http://localhost:1337/api/semantic-search/search \
-H "Content-Type: application/json" \
-d '{"query": "test query", "contentType": "api::article.article"}'
# Check statistics
curl http://localhost:1337/api/semantic-search/stats
Enable debug logging in your Strapi configuration:
// config/logger.js
module.exports = {
level: 'debug',
transports: [
{
type: 'console',
options: {
pool: true,
format: 'combined',
level: 'debug'
}
}
]
};
# Required
OPENAI_API_KEY=your_production_openai_key
# Optional
NODE_ENV=production
Monitor these key metrics:
Add support for additional content types:
// In registerEmbeddingLifecycles function
const contentTypes = [
'api::article.article',
'api::blog.blog',
'api::product.product', // Add your content type
'api::course.course' // Add another content type
];
Modify text field extraction:
// In extractTextContent function
const textFields = [
'title', 'content', 'summary',
'customField', // Add custom field
'description' // Add more fields as needed
];
Add custom filtering logic:
// In search service
const searchWithCustomFilters = async (query, contentType, customFilters) => {
const filters = {
...customFilters,
publishedAt: { $notNull: true }, // Only published content
featured: true // Only featured content
};
return await semanticSearch(query, contentType, { filters });
};
1. Plugin not loading:
config/plugins.ts configuration2. Embeddings not generating:
3. Search returning no results:
4. Performance issues:
# Check plugin loading
tail -f logs/strapi.log | grep "semantic-search"
# Test OpenAI connectivity
curl -X POST https://api.openai.com/v1/embeddings \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"input": "test", "model": "text-embedding-ada-002"}'
# Validate embedding storage
curl http://localhost:1337/api/semantic-search/stats
MIT License
This plugin is part of the semantic search demo project. Contributions and improvements are welcome.
Built with OpenAI Embeddings and Strapi 5
FAQs
Intelligent semantic search plugin for Strapi 5 powered by OpenAI embeddings. Automatically generates embeddings for your content and provides powerful semantic search capabilities.
We found that strapi-plugin-semantic-search demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.