npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bernierllc/social-media-content-type-instagram

v1.2.0

Published

Instagram-specific content type definition and validation

Readme

@bernierllc/social-media-content-type-instagram

Instagram-specific content type definition and validation for the BernierLLC Content Management Suite.

Features

  • Complete Instagram Content Types - Feed posts, Stories, Reels, and Carousels
  • Platform Validation - Enforce Instagram's constraints (2200 char captions, 30 hashtag limit, etc.)
  • Content Transformation - Convert generic social content and blog posts to Instagram format
  • Fluent Builder API - Easy content creation with method chaining
  • Aspect Ratio Optimization - Automatic media resizing for Instagram's 5 supported ratios
  • Story & Reel Converters - Transform content into ephemeral and short-form video formats
  • Hashtag Optimization - Intelligent hashtag management following Instagram best practices
  • TypeScript Support - Full type safety with comprehensive interfaces

Installation

npm install @bernierllc/social-media-content-type-instagram

Usage

The package provides three main classes for working with Instagram content:

  1. InstagramContentBuilder - Fluent API for building Instagram posts
  2. InstagramContentValidator - Validate content against Instagram's rules
  3. InstagramContentTransformer - Convert content from other formats

Quick Start

import { InstagramContentBuilder } from '@bernierllc/social-media-content-type-instagram';

const builder = new InstagramContentBuilder();

const post = builder
  .setCaption('Beautiful sunset at the beach! 🌅')
  .addMedia({
    type: 'image',
    url: 'https://example.com/sunset.jpg',
    aspectRatio: 'square'
  })
  .addHashtags(['photography', 'sunset', 'nature'])
  .setLocation({ name: 'California Beach' })
  .build();

console.log(post);
// {
//   caption: 'Beautiful sunset at the beach! 🌅\n\n#photography #sunset #nature',
//   media: [{ type: 'image', url: '...', aspectRatio: 'square' }],
//   postType: 'feed',
//   location: { name: 'California Beach' }
// }

Core API

Content Validation

import { InstagramContentValidator, INSTAGRAM_CONSTRAINTS } from '@bernierllc/social-media-content-type-instagram';

const validator = new InstagramContentValidator();

// Validate complete content
const result = validator.validate(content);
console.log(result.valid);        // true/false
console.log(result.errors);       // Array of validation errors
console.log(result.warnings);     // Array of warnings
console.log(result.suggestions);  // Array of optimization suggestions

// Check specific validations
validator.validateCaption('My caption');      // boolean
validator.validateMedia(mediaArray);          // boolean
validator.validateHashtags(hashtagArray);     // boolean
validator.validateStory(storyContent);        // InstagramValidationResult
validator.validateReel(reelContent);          // InstagramValidationResult

Content Transformation

import { InstagramContentTransformer } from '@bernierllc/social-media-content-type-instagram';

const transformer = new InstagramContentTransformer();

// From generic social content
const instagramPost = transformer.fromGeneric({
  text: 'Check out this post!',
  images: ['https://example.com/image.jpg'],
  hashtags: ['social', 'media']
});

// From blog post
const carouselPost = transformer.fromBlogPost({
  title: 'My Blog Post',
  excerpt: 'This is a great post about...',
  content: 'Full content here',
  featuredImage: 'https://example.com/featured.jpg',
  images: ['https://example.com/1.jpg', 'https://example.com/2.jpg'],
  tags: ['blogging', 'tutorial']
});

// Convert to story
const story = transformer.convertToStory(content);

// Convert to reel
const reel = transformer.convertToReel(content);

// Optimize for Instagram
const optimized = transformer.optimizeForInstagram(content);

Fluent Builder

import { InstagramContentBuilder } from '@bernierllc/social-media-content-type-instagram';

const builder = new InstagramContentBuilder();

// Build a complete post
const post = builder
  .setCaption('Amazing carousel post!')
  .setPostType('carousel')
  .addMedia({ type: 'image', url: 'https://example.com/1.jpg', aspectRatio: 'square' })
  .addMedia({ type: 'image', url: 'https://example.com/2.jpg', aspectRatio: 'portrait' })
  .addMedia({ type: 'image', url: 'https://example.com/3.jpg', aspectRatio: 'landscape' })
  .addHashtags(['carousel', 'instagram', 'photos'])
  .addMentions(['partner_account', 'photographer'])
  .setLocation({ name: 'New York City', latitude: 40.7128, longitude: -74.0060 })
  .addCollaborator('collaborator_username')
  .setShareToFacebook(true)
  .setAltText(['Image 1 description', 'Image 2 description', 'Image 3 description'])
  .build();

// Validate before building
const validationResult = builder.validate();
if (!validationResult.valid) {
  console.error('Validation errors:', validationResult.errors);
}

Instagram Content Types

Feed Posts

Standard Instagram posts with 1-10 media items:

interface InstagramContent {
  caption: string;                // Max 2200 characters
  media: InstagramMedia[];        // 1-10 items
  postType: 'feed' | 'carousel' | 'story' | 'reel';
  altText?: string[];             // One per media item
  location?: InstagramLocation;
  collaborators?: string[];       // Collab posts
  productTags?: InstagramProductTag[];
}

Stories (24-hour ephemeral)

interface InstagramStory {
  media: InstagramMedia;          // Single media item
  duration: number;               // 3-15 seconds
  stickers?: InstagramSticker[];  // Interactive elements
  link?: InstagramStoryLink;      // Swipe-up (10k+ followers)
  polls?: InstagramStoryPoll[];
  questions?: InstagramStoryQuestion[];
  countdowns?: InstagramCountdown[];
  music?: InstagramMusic;
}

Reels (short-form video)

interface InstagramReel {
  video: InstagramMedia;          // Vertical video (9:16)
  caption: string;                // Max 2200 characters
  coverImage?: string;
  audio: InstagramAudio;          // Original, trending, or saved
  shareToFeed: boolean;
}

Carousels (multi-image posts)

Carousels support 1-10 images or videos with a shared caption:

const carousel = builder
  .setCaption('Swipe to see more!')
  .addMediaBatch([
    { type: 'image', url: 'https://example.com/1.jpg', aspectRatio: 'square' },
    { type: 'image', url: 'https://example.com/2.jpg', aspectRatio: 'square' },
    { type: 'video', url: 'https://example.com/vid.mp4', aspectRatio: 'square' }
  ])
  .build();

Instagram Constraints

import { INSTAGRAM_CONSTRAINTS } from '@bernierllc/social-media-content-type-instagram';

// Caption limits
INSTAGRAM_CONSTRAINTS.maxCaptionLength          // 2200
INSTAGRAM_CONSTRAINTS.captionPreviewLength       // 125 (before "more...")

// Hashtag limits
INSTAGRAM_CONSTRAINTS.maxHashtags                // 30
INSTAGRAM_CONSTRAINTS.recommendedHashtagsMin     // 3
INSTAGRAM_CONSTRAINTS.recommendedHashtagsMax     // 5

// Media limits
INSTAGRAM_CONSTRAINTS.maxCarouselItems           // 10
INSTAGRAM_CONSTRAINTS.maxMentions                // 20

// Story/Reel durations
INSTAGRAM_CONSTRAINTS.minStoryDuration           // 3 seconds
INSTAGRAM_CONSTRAINTS.maxStoryDuration           // 15 seconds
INSTAGRAM_CONSTRAINTS.minReelDuration            // 3 seconds
INSTAGRAM_CONSTRAINTS.maxReelDuration            // 90 seconds

// Aspect ratios
INSTAGRAM_CONSTRAINTS.imageDimensions.square     // 1080x1080
INSTAGRAM_CONSTRAINTS.imageDimensions.portrait   // 1080x1350
INSTAGRAM_CONSTRAINTS.imageDimensions.landscape  // 1080x566
INSTAGRAM_CONSTRAINTS.imageDimensions.story      // 1080x1920
INSTAGRAM_CONSTRAINTS.imageDimensions.reel       // 1080x1920

Utility Classes

AspectRatioOptimizer

import { AspectRatioOptimizer } from '@bernierllc/social-media-content-type-instagram';

const optimizer = new AspectRatioOptimizer();

// Determine optimal ratio from dimensions
const ratio = optimizer.determineOptimalRatio(1080, 1350);
// Returns: 'portrait'

// Calculate target dimensions
const dims = optimizer.calculateDimensions('square');
// Returns: { width: 1080, height: 1080 }

// Check if valid for post type
const valid = optimizer.isValidForPostType('story', 'story');
// Returns: true

StoryConverter

import { StoryConverter } from '@bernierllc/social-media-content-type-instagram';

const converter = new StoryConverter();

// Convert content to story
const story = converter.convertToStory(content);

// Create story with stickers
const interactiveStory = converter.createStoryWithStickers(media, {
  hashtags: ['instagram', 'stories'],
  mentions: ['username'],
  location: 'New York City'
});

ReelConverter

import { ReelConverter } from '@bernierllc/social-media-content-type-instagram';

const converter = new ReelConverter();

// Convert content to reel
const reel = converter.convertToReel(content, 'trending');

// Create reel with audio
const customReel = converter.createReelWithAudio(
  videoMedia,
  'Check out this reel!',
  { type: 'trending', audioId: '12345', audioName: 'Trending Song' },
  { coverImage: 'https://example.com/cover.jpg', shareToFeed: true }
);

CarouselCreator

import { CarouselCreator } from '@bernierllc/social-media-content-type-instagram';

const creator = new CarouselCreator();

// Create carousel
const carousel = creator.createCarousel(mediaArray, 'My carousel!');

// Add media
const updated = creator.addMedia(carousel, newMedia);

// Remove media
const removed = creator.removeMedia(carousel, 1);

// Reorder media
const reordered = creator.reorderMedia(carousel, 0, 2);

HashtagOptimizer

import { HashtagOptimizer } from '@bernierllc/social-media-content-type-instagram';

const optimizer = new HashtagOptimizer();

// Extract hashtags from text
const hashtags = optimizer.extractHashtags('Post #instagram #social #media');
// Returns: ['instagram', 'social', 'media']

// Optimize count (limit to 3-5)
const optimized = optimizer.optimizeHashtags(hashtagArray, 5);

// Format for caption
const formatted = optimizer.formatHashtags(['test', 'instagram']);
// Returns: '#test #instagram'

// Validate hashtag
const valid = optimizer.validateHashtag('instagram_2025');
// Returns: true

// Suggest hashtags
const suggestions = optimizer.suggestHashtags(text, keywords);

Best Practices

Hashtag Strategy

Instagram recommends 3-5 hashtags for best engagement, though the platform allows up to 30:

// Recommended
builder.addHashtags(['photography', 'sunset', 'nature']);  // 3 hashtags

// Allowed but not recommended
builder.addHashtags(Array.from({ length: 30 }, (_, i) => `tag${i}`));  // 30 hashtags

Caption Preview

The first 125 characters appear before "more...". Put your key message first:

builder.setCaption(
  'Key message here! Link in bio 👆\n\nAdditional details and story...'
);

Aspect Ratios

Different post types support different aspect ratios:

  • Feed/Carousel: Square (1:1), Portrait (4:5), Landscape (1.91:1)
  • Stories: Vertical 9:16 only
  • Reels: Vertical 9:16 only

Carousel Engagement

Carousels typically get higher engagement than single-image posts. Use them for storytelling:

const carousel = builder
  .setCaption('Swipe to see the transformation! ➡️')
  .addMediaBatch([
    { type: 'image', url: 'before.jpg', aspectRatio: 'square' },
    { type: 'image', url: 'during.jpg', aspectRatio: 'square' },
    { type: 'image', url: 'after.jpg', aspectRatio: 'square' }
  ])
  .build();

Integration Status

Logger Integration

Status: Not applicable

Justification: This is a pure content type definition package with no runtime operations, side effects, or error conditions that require logging. The InstagramContentValidator, InstagramContentBuilder, and InstagramContentTransformer classes are stateless utility classes that perform validation, building, and transformation operations. All errors are thrown as exceptions that calling code can handle, and there are no background operations, network calls, or state changes that would benefit from structured logging.

Pattern: Pure functional utility - no logger integration needed. Logging is handled by consuming packages that use this content type.

NeverHub Integration

Status: Planned

Justification: This package can optionally register itself with NeverHub for service discovery. Content type packages can register themselves with NeverHub so that services can discover available content types at runtime. This enables dynamic content type discovery and allows services to adapt to available content types without hard-coded dependencies. The registration schema is available via INSTAGRAM_CONTENT_TYPE_REGISTRATION.

Pattern: Optional service discovery integration - package can register content type with NeverHub for runtime discovery.

Example Integration:

import { INSTAGRAM_CONTENT_TYPE_REGISTRATION } from '@bernierllc/social-media-content-type-instagram';

// Register with NeverHub (if available)
if (typeof detectNeverHub === 'function') {
  neverhub.registerContentType(INSTAGRAM_CONTENT_TYPE_REGISTRATION);
}

Docs-Suite Integration

Status: Ready

Format: TypeDoc-compatible JSDoc comments are included throughout the source code. All public APIs are documented with examples and type information.

Dependencies

  • @bernierllc/crypto-utils (^1.0.2) - Media hash generation
  • validator (^13.12.0) - URL and string validation

Related Packages

  • @bernierllc/social-media-content-type-twitter - Twitter/X content types
  • @bernierllc/social-media-content-type-linkedin - LinkedIn content types
  • @bernierllc/social-media-content-type-bluesky - Bluesky content types
  • @bernierllc/social-media-content-type-facebook - Facebook content types (pending)
  • @bernierllc/social-media-content-type-mastodon - Mastodon content types (pending)
  • @bernierllc/social-media-instagram (pending) - Instagram service layer
  • @bernierllc/social-media-manager (pending) - Multi-platform orchestration

TypeScript Support

This package is written in TypeScript and includes complete type definitions:

import type {
  InstagramContent,
  InstagramMedia,
  InstagramStory,
  InstagramReel,
  InstagramAspectRatio,
  InstagramValidationResult,
  InstagramMetadata,
  InstagramConstraints
} from '@bernierllc/social-media-content-type-instagram';

Testing

This package includes comprehensive tests with 98%+ coverage:

npm test              # Run tests in watch mode
npm run test:run      # Run tests once
npm run test:coverage # Run tests with coverage report

Building

npm run build  # Compile TypeScript to dist/
npm run clean  # Remove dist/ directory
npm run lint   # Run ESLint

License

Copyright (c) 2025 Bernier LLC. All rights reserved.

This package is part of the BernierLLC Content Management Suite and is licensed under a limited-use license. See LICENSE file for details.