@bernierllc/social-media-manager
v1.2.0
Published
Platform-agnostic social media orchestration service for multi-platform posting with content transformation and scheduling
Readme
@bernierllc/social-media-manager
Platform-agnostic social media orchestration service for multi-platform posting with content transformation and scheduling.
Features
- Multi-Platform Posting: Post to Twitter, LinkedIn, Facebook, Instagram, Mastodon, and Bluesky simultaneously
- Content Transformation: Automatically transform generic content to platform-specific formats
- Intelligent Scheduling: Schedule posts with jitter (uniform, normal, or exponential distribution)
- Content Validation: Validate content against platform constraints before posting
- Platform Management: Connect, disconnect, and monitor platform connections
- Batch Operations: Post or schedule multiple posts at once
- NeverHub Integration: Content-type matching and transformation pipeline system
Installation
npm install @bernierllc/social-media-managerQuick Start
import { SocialMediaManager } from '@bernierllc/social-media-manager';
const manager = new SocialMediaManager({
platforms: {
twitter: { enabled: true },
linkedin: { enabled: true },
},
schedulerConfig: {
enableJitter: true,
defaultJitter: {
enabled: true,
minMinutes: -5,
maxMinutes: 5,
distribution: 'uniform',
},
timezone: 'UTC',
},
});
// Post to all connected platforms
const result = await manager.postToAll({
content: {
text: 'Hello from all platforms!',
images: [{ url: 'https://example.com/image.jpg' }],
hashtags: ['social', 'automation'],
},
platforms: ['twitter', 'linkedin'],
});
console.log(`Posted to ${result.summary.successCount} platforms`);Multi-Platform Posting
Post to All Platforms
const result = await manager.postToAll({
content: {
text: 'Universal message for all platforms',
images: [{ url: 'image.jpg' }],
hashtags: ['announcement'],
},
platforms: ['twitter', 'linkedin', 'facebook'],
});
if (result.success) {
console.log('Posted to all platforms successfully!');
} else if (result.summary.partialSuccess) {
console.log(`Posted to ${result.summary.successCount} out of ${result.summary.totalPlatforms} platforms`);
console.log('Errors:', result.errors);
}Post to Specific Platforms
const result = await manager.postToPlatforms(
['twitter', 'mastodon'],
{
content: {
text: 'Short-form post for Twitter and Mastodon',
hashtags: ['tech', 'news'],
},
platforms: ['twitter', 'mastodon'],
}
);Platform-Specific Content
const result = await manager.postToAll({
content: {
text: 'Generic content',
},
platforms: ['twitter', 'linkedin'],
platformSpecificContent: {
twitter: {
text: 'Short tweet optimized for Twitter',
hashtags: ['twitter'],
},
linkedin: {
text: 'Professional post optimized for LinkedIn with more detail and context.',
hashtags: ['linkedin', 'professional'],
},
},
});Scheduling with Jitter
Schedule a Post
const result = await manager.schedulePost({
content: {
text: 'Scheduled post',
},
platforms: ['twitter', 'linkedin'],
scheduledTime: new Date('2025-12-01T12:00:00Z'),
jitter: {
enabled: true,
minMinutes: -5,
maxMinutes: 5,
distribution: 'uniform',
},
});
console.log('Schedule ID:', result.scheduleId);
console.log('Scheduled times:', result.scheduledTimes);Jitter Distributions
// Uniform distribution (equal probability)
const uniform = await manager.schedulePost({
content: { text: 'Post' },
platforms: ['twitter'],
scheduledTime: new Date('2025-12-01T12:00:00Z'),
jitter: {
enabled: true,
minMinutes: -10,
maxMinutes: 10,
distribution: 'uniform',
},
});
// Normal distribution (bell curve)
const normal = await manager.schedulePost({
content: { text: 'Post' },
platforms: ['twitter'],
scheduledTime: new Date('2025-12-01T12:00:00Z'),
jitter: {
enabled: true,
minMinutes: -10,
maxMinutes: 10,
distribution: 'normal',
},
});
// Exponential distribution (weighted toward minimum)
const exponential = await manager.schedulePost({
content: { text: 'Post' },
platforms: ['twitter'],
scheduledTime: new Date('2025-12-01T12:00:00Z'),
jitter: {
enabled: true,
minMinutes: 0,
maxMinutes: 15,
distribution: 'exponential',
},
});Manage Scheduled Posts
// List all scheduled posts
const allPosts = await manager.listScheduledPosts();
// Filter by status
const pendingPosts = await manager.listScheduledPosts({
status: ['pending'],
});
// Filter by platform
const twitterPosts = await manager.listScheduledPosts({
platforms: ['twitter'],
});
// Cancel a scheduled post
await manager.cancelScheduledPost(scheduleId);Content Transformation
Transform Content
const genericContent = {
text: 'Long article text that needs to be adapted for each platform...',
images: [{ url: 'large-image.jpg', width: 5000, height: 5000 }],
hashtags: Array(50).fill('tag'),
};
// Transform for Twitter (will truncate text, resize images, limit hashtags)
const twitterContent = await manager.transformContent(genericContent, 'twitter');
// Transform for LinkedIn (will apply professional tone)
const linkedinContent = await manager.transformContent(genericContent, 'linkedin');
// Transform for Instagram (will ensure media is present)
const instagramContent = await manager.transformContent(genericContent, 'instagram');Validate Content
const content = {
text: 'Test post',
images: [{ url: 'image.jpg' }],
};
const validation = await manager.validateContentForPlatform(content, 'twitter');
if (!validation.valid) {
console.error('Validation errors:', validation.errors);
console.warn('Validation warnings:', validation.warnings);
}Optimize Content
const optimized = await manager.optimizeForPlatform(
{
text: 'Post with too many hashtags',
hashtags: Array(50).fill('tag'),
},
'twitter'
);Platform Management
Connect Platform
const connection = await manager.connectPlatform('twitter', {
apiKey: 'your-api-key',
apiSecret: 'your-api-secret',
accessToken: 'your-access-token',
accessTokenSecret: 'your-access-token-secret',
});
console.log('Connected:', connection.connected);
console.log('Username:', connection.username);Disconnect Platform
await manager.disconnectPlatform('twitter');Test Connection
const test = await manager.testPlatformConnection('twitter');
console.log('Connected:', test.connected);
console.log('Healthy:', test.healthy);
console.log('Response time:', test.responseTime, 'ms');List Connections
const connections = await manager.listConnectedPlatforms();
for (const conn of connections) {
console.log(`${conn.platform}: ${conn.connected ? 'Connected' : 'Disconnected'}`);
}Get Platform Status
const status = await manager.getPlatformStatus();
for (const [platform, platformStatus] of Object.entries(status)) {
console.log(`${platform}:`, {
connected: platformStatus.connected,
healthy: platformStatus.healthy,
});
}Batch Operations
Batch Post
const result = await manager.postBatch({
requests: [
{
content: { text: 'Post 1' },
platforms: ['twitter'],
},
{
content: { text: 'Post 2' },
platforms: ['linkedin'],
},
{
content: { text: 'Post 3' },
platforms: ['facebook'],
},
],
parallelExecution: true,
maxConcurrency: 3,
});
console.log(`${result.summary.successful} out of ${result.summary.total} posts succeeded`);Batch Schedule
const result = await manager.scheduleBatch([
{
content: { text: 'Post 1' },
platforms: ['twitter'],
scheduledTime: new Date('2025-12-01T12:00:00Z'),
},
{
content: { text: 'Post 2' },
platforms: ['linkedin'],
scheduledTime: new Date('2025-12-01T13:00:00Z'),
},
]);Content Type Registry
The package includes a content-type registry system for NeverHub integration:
import { CONTENT_TYPE_REGISTRY, ContentTypeMatching } from '@bernierllc/social-media-manager';
const matching = new ContentTypeMatching();
// Find compatible platforms
const platforms = await matching.findCompatibleTypes('generic-social-content');
console.log('Supported platforms:', platforms);
// Get transformation pipeline
const pipeline = await matching.getTransformationPipeline(
'generic-social-content',
'social-media-content:twitter'
);
console.log('Transformations:', pipeline);Statistics and Cleanup
Get Schedule Statistics
const stats = manager.getScheduleStatistics();
console.log('Total scheduled:', stats.total);
console.log('Pending:', stats.pending);
console.log('Posted:', stats.posted);
console.log('Failed:', stats.failed);
console.log('Cancelled:', stats.cancelled);Clean Up Old Posts
// Remove completed/cancelled posts older than 30 days
const removed = manager.cleanupOldScheduledPosts(30);
console.log(`Removed ${removed} old posts`);TypeScript Support
Full TypeScript support with comprehensive type definitions:
import type {
SocialMediaManagerConfig,
GenericSocialContent,
MultiPlatformPostRequest,
SchedulePostRequest,
JitterConfig,
} from '@bernierllc/social-media-manager';License
Copyright (c) 2025 Bernier LLC. See LICENSE for details.
