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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@snapkit-studio/nextjs

v1.7.3

Published

Next.js image loader for Snapkit image optimization

Readme

@snapkit-studio/nextjs

Next.js image loader and React component for Snapkit image optimization service.

npm version npm downloads TypeScript

Features

  • Next.js Image Integration: Seamless integration with Next.js Image component
  • Flexible CDN Configuration: Use Snapkit CDN or integrate with your existing infrastructure (CloudFront, GCS, Cloudflare)
  • Automatic Optimization: Dynamic image transformation with DPR-based srcset
  • Client Component: 현재 Image 컴포넌트는 클라이언트 전용이며 'use client' 지시자가 필요합니다.
  • Environment Auto-Detection: Automatically reads framework-specific environment variables
  • Format Auto-Selection: Intelligent format selection (WebP, AVIF, etc.)
  • Client-First Enhancements: Built-in network adaptation and event handler support
  • TypeScript Support: Full TypeScript definitions included
  • Well Tested: 90%+ test coverage with comprehensive edge case handling

Installation

npm install @snapkit-studio/nextjs
# or
yarn add @snapkit-studio/nextjs
# or
pnpm add @snapkit-studio/nextjs

Quick Start

1. CDN Configuration

Choose between Snapkit CDN for zero-config optimization or custom CDN integration:

Option A: Snapkit CDN (Recommended)

# .env.local - Snapkit CDN
NEXT_PUBLIC_IMAGE_CDN_PROVIDER=snapkit
NEXT_PUBLIC_SNAPKIT_ORGANIZATION=your-organization-name

Option B: Custom CDN Integration

# .env.local - Custom CDN (CloudFront example)
NEXT_PUBLIC_IMAGE_CDN_PROVIDER=custom
NEXT_PUBLIC_IMAGE_CDN_URL=https://d1234567890.cloudfront.net

# Google Cloud Storage example
# NEXT_PUBLIC_IMAGE_CDN_PROVIDER=custom
# NEXT_PUBLIC_IMAGE_CDN_URL=https://storage.googleapis.com/my-bucket

# Cloudflare or any custom domain
# NEXT_PUBLIC_IMAGE_CDN_PROVIDER=custom
# NEXT_PUBLIC_IMAGE_CDN_URL=https://images.example.com

2. Use with Next.js Image Component

'use client';

// app/components/Hero.tsx
import { Image } from '@snapkit-studio/nextjs';

export function Hero() {
  return (
    <Image
      src="/hero-image.jpg"
      width={1200}
      height={600}
      alt="Hero image"
      quality={85}
      transforms={{
        format: 'auto',
      }}
    />
  );
}

Usage Patterns

Pattern 1: CDN Configuration (Recommended)

Configure your CDN provider through environment variables for consistent optimization across all images.

Snapkit CDN

# .env.local - Snapkit CDN configuration
NEXT_PUBLIC_IMAGE_CDN_PROVIDER=snapkit
NEXT_PUBLIC_SNAPKIT_ORGANIZATION=your-organization-name

Custom CDN

# .env.local - Custom CDN configuration
NEXT_PUBLIC_IMAGE_CDN_PROVIDER=custom
NEXT_PUBLIC_IMAGE_CDN_URL=https://your-cdn-domain.com

Environment Variables Reference:

  • NEXT_PUBLIC_IMAGE_CDN_PROVIDER: CDN provider type (snapkit or custom)
  • NEXT_PUBLIC_SNAPKIT_ORGANIZATION: Your Snapkit organization identifier (required for Snapkit CDN)
  • NEXT_PUBLIC_IMAGE_CDN_URL: Your custom CDN base URL (required for custom CDN)

The configuration is automatically detected by the library using getCdnConfig() from @snapkit-studio/core.

'use client';

import { Image } from '@snapkit-studio/nextjs';

// Optimized image (zero config beyond env vars)
<Image src="/photo.jpg" width={800} height={600} alt="Photo" />

// Interactive image with event handlers
<Image
  src="/interactive.jpg"
  width={800}
  height={600}
  alt="Interactive"
  onLoad={() => console.log('loaded')}
/>

Pattern 2: Manual CDN Override (Advanced)

Use when you need different CDN settings per image instance.

import { Image } from '@snapkit-studio/nextjs';
import { SnapkitImageEngine } from '@snapkit-studio/core';

// Create custom engine with different CDN
const customEngine = new SnapkitImageEngine({
  cdnConfig: {
    provider: 'custom',
    baseUrl: 'https://different-cdn.example.com'
  },
  defaultQuality: 90,
  defaultFormat: 'auto'
});

<Image
  src="/high-quality-photo.jpg"
  width={1920}
  height={1080}
  alt="High quality photo"
  transforms={{
    format: 'avif',
    quality: 90,
  }}
/>

Pattern 3: Direct Loader Usage

For maximum control or integration with custom image components.

import { snapkitLoader } from '@snapkit-studio/nextjs';

// Get optimized URL directly
const optimizedUrl = snapkitLoader({
  src: '/my-image.jpg',
  width: 800,
  quality: 85,
});

console.log(optimizedUrl);
// Output: "https://your-org-name.snapkit.studio/transform/w_800,q_85,f_auto/my-image.jpg"

Image Transforms

interface ImageTransforms {
  /** Output format: 'auto', 'webp', 'avif', 'jpeg', 'png' */
  format?: string;

  /** Image quality: 1-100 */
  quality?: number;

  /** Image width in pixels */
  width?: number;

  /** Image height in pixels */
  height?: number;

  /** Blur radius: 0-100 */
  blur?: number;

  /** Additional transforms... */
  [key: string]: any;
}

Component Architecture

@snapkit-studio/nextjs는 단일 Image 컴포넌트를 제공합니다.

  • 현재 버전은 클라이언트 전용이며, 사용 시 반드시 파일 상단에 'use client' 지시자를 추가해야 합니다.
  • 서버 컴포넌트(React Server Components) 지원은 준비 중이며, 로드맵에 포함되어 있습니다.
  • 클라이언트 측에서 네트워크 기반 품질 조정, 이벤트 핸들러 등 고급 기능을 제공합니다.

Examples

'use client';

import { Image } from '@snapkit-studio/nextjs';

export function HeroBanner() {
  return (
    <section>
      <Image
        src="/hero-banner.jpg"
        width={1920}
        height={1080}
        alt="Hero banner"
        priority
      />
    </section>
  );
}
'use client';

import { Image } from '@snapkit-studio/nextjs';
import { useState } from 'react';

export function Gallery() {
  const [loadedImages, setLoadedImages] = useState<Set<string>>(new Set());

  const handleImageLoad = (src: string) => {
    setLoadedImages(prev => new Set([...prev, src]));
  };

  return (
    <div className="gallery">
      <Image
        src="/gallery-image.jpg"
        width={800}
        height={600}
        alt="Gallery image"
        onLoad={() => handleImageLoad('gallery-image.jpg')}
        onError={() => console.log('Failed to load image')}
      />
    </div>
  );
}

Advanced Configuration

Custom Organization Name

// Override environment variable per component
import { Image } from '@snapkit-studio/nextjs';

export function Gallery({ images }: { images: string[] }) {
  return (
    <div className="grid grid-cols-3 gap-4">
      {images.map((src, index) => (
        <Image
          key={index}
          src={src}
          width={400}
          height={300}
          alt={`Gallery image ${index + 1}`}
          organizationName="custom-org"
          transforms={{ format: 'auto', quality: 80 }}
        />
      ))}
    </div>
  );
}

Advanced Transforms

<Image
  src="/portrait.jpg"
  width={600}
  height={800}
  alt="Portrait"
  quality={85}
  transforms={{
    format: 'webp',
    blur: 2,                    // Slight blur effect
  }}
/>

Next.js Configuration

next.config.js Setup

/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    // Allow Snapkit and custom CDN domains
    domains: [
      'your-org-name-cdn.snapkit.studio',  // Snapkit CDN
      'd1234567890.cloudfront.net',        // AWS CloudFront
      'storage.googleapis.com',            // Google Cloud Storage
      'images.example.com',                // Custom domain
    ],

    // Use custom loader globally (optional)
    loader: 'custom',
    loaderFile: './snapkit-loader.js',
  },
};

module.exports = nextConfig;

Custom Loader File (snapkit-loader.js)

// snapkit-loader.js
import { snapkitLoader } from '@snapkit-studio/nextjs';

export default snapkitLoader;

Live Demo

Experience all features in action with our interactive demo:

🚀 Live Demo → - Real-time examples with source code

Explore features including:

  • Multiple patterns built with the single Image component
  • DPR-aware optimization and automatic srcSet
  • Live preview of image transformations
  • Server-rendered picture element output
  • Full tour of Snapkit’s optimization pipeline

Migration Guide

📖 Complete Migration Guide - Comprehensive step-by-step guide with troubleshooting

Quick Migration Examples

From Next.js Built-in Image

// Before: Next.js built-in
import Image from 'next/image';

<Image
  src="/image.jpg"
  width={800}
  height={600}
  alt="Image"
/>

// After: Snapkit optimization with Snapkit Image
'use client';
import { Image } from '@snapkit-studio/nextjs';

<Image
  src="/image.jpg"
  width={800}
  height={600}
  alt="Image"
  quality={85}
  transforms={{ format: 'auto' }}
/>

From Other Image Services

// Before: Cloudinary
import Image from 'next/image';

<Image
  src="https://res.cloudinary.com/demo/image/upload/w_800,q_85/sample.jpg"
  width={800}
  height={600}
/>

// After: Snapkit with Snapkit Image
'use client';
import { Image } from '@snapkit-studio/nextjs';

<Image
  src="/sample.jpg"
  width={800}
  height={600}
  quality={85}
  transforms={{ format: 'auto' }}
/>

API Reference

Functions

snapkitLoader(params: ImageLoaderParams): string

Default image loader using global configuration.

Parameters:

  • src: Image source path
  • width: Target width in pixels
  • quality: Image quality (1-100)

Returns: Optimized image URL

createSnapkitLoader(): ImageLoader

Create a custom image loader with specific configuration.

Returns: Image loader function

Testing

The package includes comprehensive test coverage with automatic coverage reporting:

# Run tests
npm test

# Run with coverage report
npm run test:coverage

# Watch mode for development
npm test -- --watch

Test Coverage

The package maintains high test coverage standards:

  • Coverage Threshold: 80% minimum for branches, functions, lines, and statements
  • Test Framework: Vitest with jsdom environment and v8 coverage provider
  • Coverage Reports: Text (console), JSON, HTML, and LCOV formats
  • Coverage Exclusions: Test setup files, configuration files, type definitions, and test utilities

Coverage reports are generated in multiple formats:

  • Text: Console output during test runs
  • HTML: Detailed coverage report in coverage/ directory
  • LCOV: For CI/CD integration and coverage tools
  • JSON: Machine-readable coverage data

Test Environment

Tests run in a jsdom environment to simulate browser behavior for React Server Components and Client Components testing.

Browser Support

  • AVIF: Chrome 85+, Firefox 93+, Edge 91+ (Chromium), Safari 16+
  • WebP: Chrome 23+, Firefox 65+, Edge 79+ (Chromium), Safari 14+
  • Lazy Loading: Chrome 76+, Firefox 75+, Edge 79+, Safari 15.4+
  • Intersection Observer: Chrome 58+, Firefox 55+, Edge 79+, Safari 12.1+

Note: Only Chromium-based Edge (79+) is supported. Legacy EdgeHTML Edge (18 and below) is not supported.

Format Selection: Automatically selects the best supported format in order: AVIF → WebP → JPEG. Falls back to JPEG in browsers that don't support modern formats.

Contributing

Contributions are welcome! Please read our contributing guide for details on our code of conduct and development process.

License

MIT © Snapkit