discord-multiimage
v1.0.9
Published
Display multiple images in Discord with grid or stacked layouts.
Downloads
8
Maintainers
Readme
🖼️ discord-multiimage
Transform messy Discord image spam into beautiful, unified galleries
The zero-friction way to send multiple images in Discord without the clutter
🎯 The Problem
Discord bots that send multiple images create visual chaos:
🤖 Bot: Here are your results!
[Embed 1: Single image with title]
[Embed 2: Single image with title]
[Embed 3: Single image with title]
[Embed 4: Single image with title]Result: Cluttered chat, repetitive titles, inconsistent spacing, poor mobile experience.
✨ The Solution
discord-multiimage creates native-looking galleries that feel like Discord designed them:
🤖 Bot: Here are your results!
[Single unified embed with 4 images in perfect grid layout]Result: Clean, professional, mobile-friendly image presentations.
🚀 Quick Start
npm install discord-multiimage🧱 Grid Mode – Merge into One Embed
Ideal for displaying 2–4 images in a single unified layout.
const { mergeImagesInGrid } = require('discord-multiimage');
const { EmbedBuilder } = require('discord.js');
const imageUrls = [
'https://example.com/screenshot1.png',
'https://example.com/screenshot2.png',
'https://example.com/screenshot3.png'
];
const { file, imageUrl } = await mergeImagesInGrid(imageUrls);
const embed = new EmbedBuilder()
.setTitle('Game Screenshots')
.setImage(imageUrl)
.setColor('#5865F2');
await interaction.reply({ embeds: [embed], files: [file] });🧩 Stacked Mode – Clean Multiple Embeds
Great for scrollable galleries like art portfolios or product shots.
const { buildStackedImageData } = require('discord-multiimage');
const { EmbedBuilder } = require('discord.js');
const { imageUrls, invisibleTitle, groupUrl } = buildStackedImageData([
'https://example.com/art1.jpg',
'https://example.com/art2.jpg',
'https://example.com/art3.jpg'
], {
groupUrl: 'https://portfolio.example.com' // Required for grouping
});
const embeds = imageUrls.map(url =>
new EmbedBuilder()
.setTitle(invisibleTitle) // Invisible but needed for Discord to group (Optional: You can use any title yet it will appear as a link)
.setURL(groupUrl)
.setImage(url)
.setColor('#FF6B6B')
);
await channel.send({ embeds });🪄 One Unified API – Auto Mode Switch
Use createMultiImageData() to let your bot dynamically choose layout style.
const { createMultiImageData } = require('discord-multiimage');
const { EmbedBuilder } = require('discord.js');
const result = await createMultiImageData({
mode: 'grid', // or 'stacked'
imageUrls: ['https://example.com/img1.png', 'https://example.com/img2.png'],
options: {
spacing: 6,
backgroundColor: '#2f3136'
}
});
if (result.file) {
const embed = new EmbedBuilder().setImage(result.imageUrl);
await interaction.reply({ embeds: [embed], files: [result.file] });
} else {
const embeds = result.imageUrls.map(url =>
new EmbedBuilder().setImage(url).setURL(result.groupUrl).setTitle('\u200B')
);
await channel.send({ embeds });
}🎨 Visual Examples
Grid Layouts (Auto-Generated)
| 2 Images | 3 Images | 4 Images |
|:---:|:---:|:---:|
| Side-by-side(16:9 ratio) | Large + Stack(4:3 ratio) | Perfect Grid(1:1 ratio) |
|
| 
|

|
Before vs After Comparison
Bot: Here are the match results!
📊 Match Statistics
[Image: Player stats screenshot]
📊 Match Statistics
[Image: Team composition]
📊 Match Statistics
[Image: Game timeline]
📊 Match Statistics
[Image: Final scoreboard]Bot: Here are the match results!
📊 Match Statistics
[Beautiful 2x2 grid showing all 4 images
in one clean, professional embed]🛠️ Advanced Configuration
Grid Mode Options
const { file, imageUrl } = await mergeImagesInGrid(urls, {
spacing: 4, // Pixels between images (default: 2)
maxWidth: 800, // Maximum canvas width (default: 600)
backgroundColor: '#36393f', // Canvas background color
cornerRadius: 8 // Rounded corners for images
});Stacked Mode Options
const { imageUrls, invisibleTitle, groupUrl } = buildStackedImageData(urls, {
groupUrl: 'https://your-site.com/gallery', // Required for grouping
titleText: '\u200B' // Custom invisible character (default: zero-width space)
});🎯 Use Cases & Examples
🎮 Gaming Bots
// Show match highlights in one clean embed
const highlights = await mergeImagesInGrid([
killcam1, killcam2, scoreboard, playerStats
]);🎨 Art & Portfolio Bots
// Create scrollable art galleries
const gallery = buildStackedImageData(artworkUrls, {
groupUrl: 'https://artist.portfolio.com'
});📊 Analytics & Monitoring
// Combine multiple chart screenshots
const dashboard = await mergeImagesInGrid([
salesChart, trafficChart, conversionChart
]);🏪 E-commerce & Marketplace
// Product image galleries
const productGallery = buildStackedImageData([
mainPhoto, sideView, detailShot, packagingPhoto
]);🤔 Grid vs Stacked - Decision Guide
| Scenario | Recommended Mode | Why | |--------------|---------------------|---------| | Screenshots to compare side-by-side | Grid | Visual comparison is easier | | Art portfolio or photo gallery | Stacked | Users want to focus on each image | | Dashboard with multiple charts | Grid | Overview of all metrics at once | | Step-by-step tutorial images | Stacked | Sequential viewing preferred | | Before/after comparisons | Grid | Direct visual comparison | | Large collection (5+ images) | Stacked | Grid limited to 4 images max |
🧩 Compatibility
- ✅ Works with Discord.js v14+
- ⚠️ Requires Node.js ≥ 16.9
- 🖼️ Uses skia-canvas — make sure your environment supports native modules
⚡ Performance & Technical Details
Dependencies
- Core:
discord.jsv14+ - Image Processing:
skia-canvas(faster than node-canvas) - Zero bloat: No unnecessary dependencies
Image Processing
- Automatic resizing to fit Discord's embed limits
- Smart aspect ratio preservation
- WebP optimization for smaller file sizes
- Cross-platform canvas rendering
Discord Compatibility
- ✅ Mobile optimized - perfect scrolling and zoom
- ✅ Desktop native - looks like built-in Discord features
- ✅ Embed limits - respects Discord's 25MB file size limits
- ✅ Rate limiting - works with standard Discord.js rate limiting
🚨 Common Pitfalls & Solutions
❌ Stacked embeds not grouping?
Problem: Embeds appear separately instead of grouped.
// Missing required URL
.setURL(groupUrl) // ← This is required for grouping!❌ Images loading slowly?
Problem: Large images taking too long to process.
// Optimize with smaller max width
await mergeImagesInGrid(urls, { maxWidth: 400 });❌ Grid looking weird on mobile?
Problem: Images don't scale properly on small screens.
// Discord handles this automatically with our layouts!
// No additional code needed - it just works ✨🤝 Contributing
We love contributions! Here's how to get started:
- Fork the repository
- Clone your fork:
git clone https://github.com/sajidurdev/discord-multiimage.git - Install dependencies:
npm install - Create a feature branch:
git checkout -b amazing-feature - Make your changes and add tests
- Submit a pull request
Development Setup
git clone https://github.com/sajidurdev/discord-multiimage.git
cd discord-multiimage
npm install
npm test📄 License
MIT © sajidurdev
Free to use in any project - commercial or open source. Attribution appreciated but not required.
Made with ❤️ for the Discord community
📚 Usage Guide • 🐛 Report Bug • 💡 Request Feature • 💬 Discord Server
⭐ Star this repo if it helped you build better Discord bots! ⭐
