Skip to content

surajroboto/pagebuilder-screenshots

Repository files navigation

Thumbnail Generator

A flexible and powerful thumbnail and screenshot generator for web pages and CMS content blocks. Perfect for generating preview images for your website's pages and components.

Features

  • 🎯 Block-level screenshots: Capture individual content blocks from CMS-driven pages
  • 📄 Full page screenshots: Generate complete page thumbnails
  • 🔧 Highly configurable: Customize viewport, selectors, output formats, and more
  • 🏗️ CMS integration: Built-in support for Sanity CMS
  • 📦 Multiple formats: PNG and JPEG output with quality control
  • 🖥️ CLI interface: Easy command-line usage
  • 📚 TypeScript support: Full type safety and IntelliSense
  • 🎨 Custom naming: Flexible filename generation strategies

Installation

npm install @surajsuthar/thumbnail-generator

Peer Dependencies

If you want enhanced logging, install the optional peer dependency:

npm install @workspace/logger

Quick Start

Command Line Usage

# Basic usage with environment variables
thumbnail-generator

# Specify a page slug
thumbnail-generator /about

# Custom configuration
thumbnail-generator --base-url https://mywebsite.com --output-dir ./thumbnails /products

# With Sanity CMS integration
thumbnail-generator --sanity-project-id abc123 --sanity-dataset production

# With custom script and pagebuilder
thumbnail-generator --pagebuilder sanity --script ./example-script.js /about

Programmatic Usage

import { ThumbnailGenerator, createSanityAdapter } from '@surajsuthar/thumbnail-generator';

const generator = new ThumbnailGenerator({
  baseUrl: 'https://mywebsite.com',
  outputDir: './thumbnails'
});

const result = await generator.generateThumbnails({
  slug: '/about',
  overwrite: true
});

console.log(result);
// {
//   fullPagePath: './thumbnails/fullpage_about.png',
//   blockPreviewPaths: ['./thumbnails/preview-hero.jpg', './thumbnails/preview-content.jpg']
// }

With Sanity CMS

import { ThumbnailGenerator, createSanityAdapter } from '@surajsuthar/thumbnail-generator';

const sanityAdapter = createSanityAdapter({
  projectId: 'your-project-id',
  dataset: 'production',
  token: 'your-api-token'
});

const generator = new ThumbnailGenerator({
  baseUrl: 'https://mywebsite.com',
  outputDir: './thumbnails'
}, sanityAdapter);

await generator.generateThumbnails({ slug: '/about' });

Configuration

ThumbnailGeneratorConfig

interface ThumbnailGeneratorConfig {
  // Required
  baseUrl: string;

  // Optional
  outputDir?: string;                    // Default: "static/thumbnails"
  viewport?: ViewportConfig;             // Default: { width: 1920, height: 1080 }
  blockSelectors?: BlockSelectors;       // Default: { element: "[data-block-type]", typeAttribute: "data-block-type" }
  navigationOptions?: NavigationOptions; // Default: { waitUntil: "networkidle2", timeout: 30000 }
  blockScreenshotOptions?: ScreenshotOptions; // Default: { type: "jpeg", quality: 90 }
  pageScreenshotOptions?: ScreenshotOptions;  // Default: { type: "png", fullPage: true }
  blockSelectorTimeout?: number;         // Default: 10000ms
  logger?: LoggerInterface;              // Default: Console logger
  interactive?: boolean;                 // Default: true
  customScript?: string;                 // Path to custom JS file to execute on page
  filenameGenerators?: {
    block?: (blockType: string) => string;
    page?: (slug: string, prefix?: string) => string;
  };
}

Advanced Usage

Custom Script Execution

You can execute custom JavaScript on the page before taking screenshots. This is useful for:

  • Hiding cookie banners or overlays
  • Waiting for specific elements to load
  • Scrolling to load lazy-loaded images
  • Applying custom styles or modifications
const generator = new ThumbnailGenerator({
  baseUrl: 'https://mywebsite.com',
  customScript: './example-script.js'
});

await generator.generateThumbnails({
  slug: '/about',
  pagebuilder: 'sanity' // Optional: specify your pagebuilder
});

Example script (example-script.js):

// This script runs in the browser context
(async () => {
  // Hide cookie banners
  const banner = document.querySelector('.cookie-banner');
  if (banner) banner.style.display = 'none';
  
  // Wait for lazy images to load
  window.scrollTo(0, document.body.scrollHeight);
  await new Promise(resolve => setTimeout(resolve, 1000));
  window.scrollTo(0, 0);
})();

CLI usage:

thumbnail-generator --pagebuilder sanity --script ./example-script.js /about

Custom Block Selectors

const generator = new ThumbnailGenerator({
  baseUrl: 'https://mywebsite.com',
  blockSelectors: {
    element: '.cms-block',
    typeAttribute: 'data-component'
  }
});

Custom Filename Generation

const generator = new ThumbnailGenerator({
  baseUrl: 'https://mywebsite.com',
  filenameGenerators: {
    block: (blockType) => `block-${blockType.toLowerCase()}.png`,
    page: (slug, prefix) => `${prefix}_${slug.replace('/', '')}.jpg`
  }
});

Custom Viewport and Screenshot Options

const generator = new ThumbnailGenerator({
  baseUrl: 'https://mywebsite.com',
  viewport: { width: 1280, height: 720 },
  blockScreenshotOptions: {
    type: 'png',
    // quality not applicable for PNG
  },
  pageScreenshotOptions: {
    type: 'jpeg',
    quality: 80,
    fullPage: false // Only visible area
  }
});

Environment Variables

Variable Description CLI Alternative
SANITY_STUDIO_PRESENTATION_URL Base URL for website --base-url
SANITY_STUDIO_PROJECT_ID Sanity project ID --sanity-project-id
SANITY_STUDIO_DATASET Sanity dataset --sanity-dataset
SANITY_API_TOKEN Sanity API token --sanity-token

CLI Options

Usage:
  thumbnail-generator [options] [slug]

Options:
  -s, --slug <slug>              Page slug to capture (default: "/")
  -u, --base-url <url>           Base URL for the website
  -o, --output-dir <dir>         Output directory for thumbnails
  --overwrite                    Overwrite existing files without prompting
  -y, --non-interactive          Run in non-interactive mode
  -p, --pagebuilder <name>       Pagebuilder name (e.g., sanity, wordpress, etc.)
  --script <path>                Path to custom JavaScript file to execute on the page
  --sanity-project-id <id>       Sanity project ID
  --sanity-dataset <dataset>     Sanity dataset
  --sanity-token <token>         Sanity API token
  -h, --help                     Show help message

API Reference

ThumbnailGenerator

Constructor

new ThumbnailGenerator(config: ThumbnailGeneratorConfig, cmsAdapter?: CMSAdapter)

Methods

generateThumbnails(options?: ThumbnailGeneratorOptions): Promise<ScreenshotResult | null>

Utility Functions

import {
  ensureDirectory,
  generateBlockPreviewFilename,
  generateScreenshotFilename
} from '@surajsuthar/thumbnail-generator';

Examples

CI/CD Integration

# .github/workflows/thumbnails.yml
name: Generate Thumbnails
on: [push, pull_request]

jobs:
  thumbnails:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'
      - run: npm install
      - run: npm run build
      - run: npx thumbnail-generator --non-interactive --overwrite
        env:
          SANITY_STUDIO_PRESENTATION_URL: ${{ secrets.PRESENTATION_URL }}
          SANITY_API_TOKEN: ${{ secrets.SANITY_TOKEN }}

Custom CMS Adapter

import { ThumbnailGenerator } from '@surajsuthar/thumbnail-generator';
import type { CMSAdapter } from '@surajsuthar/thumbnail-generator';

class CustomCMSAdapter implements CMSAdapter {
  async getBlockTypes(slug: string): Promise<string[]> {
    // Your custom logic to fetch block types
    const response = await fetch(`https://api.mycms.com/pages/${slug}`);
    const data = await response.json();
    return data.blocks.map((block: any) => block.type);
  }
}

const generator = new ThumbnailGenerator({
  baseUrl: 'https://mywebsite.com'
}, new CustomCMSAdapter());

Development

Running Tests

The project includes a comprehensive test suite with 46 tests covering all core functionality:

# Run all tests
pnpm test

# Run tests in watch mode for development
pnpm test:watch

# Generate test coverage report
pnpm test:coverage

Test Structure

  • tests/util.test.ts - Utility function tests (100% coverage)
  • tests/index.test.ts - Core functionality tests
  • tests/example.test.ts - Integration-style usage pattern tests

See tests/README.md for detailed information about the test suite.

Building

# Build TypeScript to dist/
pnpm build

# Watch mode for development
pnpm dev

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Write tests for your changes
  4. Ensure all tests pass (pnpm test)
  5. Commit your changes (git commit -m 'Add some amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

License

MIT © Suraj Suthar

Changelog

v1.0.0

  • Initial release
  • Support for Sanity CMS
  • CLI interface
  • TypeScript support
  • Configurable screenshot options
  • Custom filename generation

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors