Blog Post

Building a Telegram-Powered Gallery Management System: From Chat to Website in Seconds

How I built a revolutionary gallery management system that lets me upload images to my portfolio website directly from Telegram, complete with automated processing, Git workflows, and instant deployment.

June 30, 2025 (1w ago)
Hemachander Rajkumar

Building a Telegram-Powered Gallery Management System: From Chat to Website in Seconds

Ever wished you could update your portfolio website's gallery just by sending a photo in a chat? Well, I built exactly that! This is the story of how I created a unique gallery management system that bridges the gap between casual messaging and professional web deployment.

The Vision: Seamless Content Management

As a developer, I wanted to showcase my work through a beautiful gallery on my portfolio website. But traditional content management systems felt clunky for something as simple as adding photos. I wanted something that felt natural, instant, and didn't require opening a browser or dealing with admin panels.

The solution? A Telegram bot that transforms casual photo sharing into a professional web deployment pipeline.

The Architecture: Where Chat Meets CI/CD

Here's how this magical system works:

1. The Telegram Interface

@bot.message_handler(commands=['gallery'])
def handle_gallery_command(message):
    """Start gallery management session"""
    user_id = message.from_user.id
    gallery_sessions[user_id] = {
        'active': True,
        'images': [],
        'start_time': datetime.now()
    }
    
    markup = create_gallery_help_keyboard()
    bot.reply_to(message, 
        "🖼️ *Gallery Management Started!*\n\n"
        "Send me images and I'll add them to your website gallery.\n"
        "Use the buttons below to choose destinations:", 
        reply_markup=markup, parse_mode='Markdown')

2. Intelligent Image Processing

When you send a photo, the bot doesn't just save it—it becomes a smart content processor:

  • Validates image format and size
  • Optimizes for web performance (resizing, compression)
  • Generates unique filenames to prevent conflicts
  • Creates metadata for proper organization
def process_and_save_image(file_info, destination, alt_text="Gallery image"):
    """Process image with optimization and metadata generation"""
    # Download and optimize image
    image = Image.open(BytesIO(downloaded_file))
    
    # Resize if too large (max 1920px width)
    if image.width > 1920:
        ratio = 1920 / image.width
        new_height = int(image.height * ratio)
        image = image.resize((1920, new_height), Image.Resampling.LANCZOS)
    
    # Generate unique filename with timestamp
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    unique_id = secrets.token_hex(4)
    filename = f"img_{timestamp}_{unique_id}.jpg"
    
    return filename, optimized_image_data

3. Interactive Destination Selection

Here's where it gets cool—the bot presents you with interactive buttons to choose where your image should appear:

  • Homepage Slider - For featured content
  • Gallery Page - For the main gallery collection
  • Both Pages - Maximum visibility
def create_destination_keyboard():
    """Create inline keyboard for image destination selection"""
    keyboard = InlineKeyboardMarkup()
    keyboard.row(
        InlineKeyboardButton("🏠 Homepage", callback_data="dest_homepage"),
        InlineKeyboardButton("🖼️ Gallery", callback_data="dest_gallery")
    )
    keyboard.row(
        InlineKeyboardButton("🌟 Both Pages", callback_data="dest_both")
    )
    return keyboard

4. Git Workflow Automation

Once you've selected destinations, the magic happens:

def create_gallery_branch_and_commit(images_data):
    """Create Git branch, commit changes, and create PR"""
    # Create new branch
    branch_name = f"gallery-update-{datetime.now().strftime('%Y%m%d-%H%M%S')}"
    repo.git.checkout('-b', branch_name)
    
    # Process each image
    for image_data in images_data:
        # Save image files
        save_image_to_destinations(image_data)
        
        # Update metadata.json
        update_gallery_metadata(image_data)
    
    # Git operations
    repo.git.add('.')
    repo.git.commit('-m', f"Add {len(images_data)} images to gallery via Telegram bot")
    repo.git.push('origin', branch_name)
    
    # Create Pull Request
    create_github_pr(branch_name, images_data)

5. Automated Deployment Pipeline

The system integrates with GitHub Actions for seamless deployment:

name: Deploy to Netlify
on:
  push:
    branches: [ main, master ]
 
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - name: Checkout repository
      uses: actions/checkout@v4
      
    - name: Setup Node.js
      uses: actions/setup-node@v4
      with:
        node-version: '18'
        cache: 'npm'
        
    - name: Build Next.js application
      run: npm run build
      env:
        NODE_ENV: production
        CI: false
        
    - name: Deploy to Netlify
      uses: nwtgck/actions-netlify@v3.0
      with:
        publish-dir: './out'
        production-branch: main

The Frontend: Dynamic Gallery Loading

The website dynamically loads gallery images from the metadata system:

// Homepage slider component
const [images, setImages] = useState<GalleryImage[]>([]);
 
useEffect(() => {
  fetch('/gallery/metadata.json')
    .then(res => res.json())
    .then(data => {
      const homepageImages = data.homepage || [];
      setImages(homepageImages.sort((a, b) => a.order - b.order));
    })
    .catch(() => {
      // Fallback to default images
      setImages(defaultImages);
    });
}, []);

The User Experience: From Chat to Website

Here's what the complete workflow looks like:

  1. Start: Send /gallery to the Telegram bot
  2. Upload: Send one or more photos
  3. Choose: Select destination using interactive buttons
  4. Confirm: Send /gallerydone to finalize
  5. Automatic: Bot creates Git branch, commits, and creates PR
  6. Deploy: GitHub Actions builds and deploys to Netlify
  7. Live: Images appear on your website within minutes!

Technical Challenges Solved

Path Resolution in CI/CD

One interesting challenge was TypeScript path resolution differences between local and CI environments:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  }
}

Image Optimization

Balancing quality and performance required careful tuning:

# Optimize JPEG quality based on image size
if image.width > 1200:
    quality = 85
elif image.width > 800:
    quality = 90
else:
    quality = 95
 
image.save(output_path, 'JPEG', quality=quality, optimize=True)

Session Management

Handling multiple users and concurrent uploads:

gallery_sessions = {}  # In-memory session storage
current_images = {}    # Track images per user
 
def cleanup_expired_sessions():
    """Remove sessions older than 30 minutes"""
    current_time = datetime.now()
    expired_sessions = [
        user_id for user_id, session in gallery_sessions.items()
        if (current_time - session['start_time']).seconds > 1800
    ]
    for user_id in expired_sessions:
        del gallery_sessions[user_id]

The Impact: Content Creation Revolutionized

This system has completely transformed how I manage my portfolio:

  • Speed: From photo to website in under 2 minutes
  • Convenience: No need to open laptops or browsers
  • Quality: Automatic optimization ensures fast loading
  • Professional: Git workflow maintains code quality
  • Scalable: Easy to add new destinations or features

What Makes This Special

This isn't just another file upload system. It's a content management revolution that:

  1. Bridges platforms - Chat app to professional website
  2. Maintains quality - Professional Git workflow with PR reviews
  3. Optimizes automatically - No manual image processing needed
  4. Scales effortlessly - Add new features without breaking existing workflow
  5. Feels natural - Uses familiar chat interface

Future Enhancements

The system is designed for extensibility. Future features could include:

  • AI-powered alt text generation
  • Automatic image categorization
  • Batch operations with drag-and-drop
  • Integration with other platforms (Discord, Slack, etc.)
  • Advanced image filters and effects

Conclusion: The Future of Content Management

This Telegram-powered gallery system represents a new paradigm in content management—one where the barrier between casual interaction and professional deployment disappears.

It's not just about uploading images; it's about creating a seamless bridge between inspiration and publication. When you see something worth sharing, you shouldn't have to context-switch between apps, remember login credentials, or navigate complex interfaces.

The future of content management is conversational, automated, and delightfully simple.


Want to build something similar? The complete source code and setup instructions are available in my portfolio repository. Feel free to adapt it for your own projects!

Technical Stack

  • Backend: Python with python-telegram-bot
  • Frontend: Next.js with TypeScript
  • Deployment: GitHub Actions + Netlify
  • Image Processing: Pillow (PIL)
  • Version Control: Git with automated PR creation
  • Hosting: Netlify with custom domain support

This blog post was written after successfully implementing and deploying the gallery management system described above.