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

@multidots/sanity-plugin-hero-block

v1.0.4

Published

Hero Block plugin for Sanity

Readme

Sanity Plugin Hero Block

A comprehensive and customizable hero block plugin for Sanity Studio v3 with support for images, videos, overlays, and call-to-action buttons.

Features

📝 Content Management

  • Heading and subheading text fields
  • Content alignment options (left, center, right)
  • Customizable text colors

🔘 Call-to-Action Button

  • Optional button with custom text
  • Link support (internal and external URLs)
  • Open in new tab option

🎨 Styling & Background Options

  • Background Type: Choose between color or media
    • Color: Hex color picker for solid backgrounds
    • Media: Choose between image or video
      • Image: Upload images through Sanity asset integration
      • Video: Two video options
        • Upload Video: Upload video files (MP4, WebM, OGG support)
        • YouTube/Vimeo: Embed external videos (YouTube, Vimeo)
  • Overlay Settings:
    • Color overlay for media backgrounds
    • Adjustable opacity settings
  • Styling Options
    • Button background and text color customization
    • Content text color options

📱 Responsive Design

  • Mobile-first responsive layout
  • Optimized for all device sizes

🔧 Developer Features

  • TypeScript support with full type definitions
  • Self-contained styling with styled-components
  • Sanity v3/v4 compatible
  • Comprehensive error handling and asset fallbacks

Available Fields

Content

  • Heading Text - Main hero title that appears prominently at the top of the block, ideal for grabbing attention with key messaging
  • Subheading - Secondary descriptive text positioned below the heading to provide additional context or supporting information
  • Content Alignment - Control text positioning with left, center, or right alignment options to match your design needs
  • Text Color - Customize the color of all text content using hex values to ensure brand consistency and readability

Call-to-Action Button

  • Button Text - Customizable button label text to create compelling calls-to-action that drive user engagement
  • Button Link - Set destination URLs for both internal page navigation and external website links
  • Open in New Tab - Toggle option to open linked pages in a new browser tab, ideal for external resources
  • Button Colors - Full control over button appearance with separate background and text color customization

Background Options

  • Background Type - Flexible choice between a solid color background or rich media (images/videos) to suit different design needs
  • Background Color - Select any color using a hex color picker when a solid background is preferred
  • Background Media - Upload and manage both image and video assets directly through Sanity's asset pipeline
  • Video Source - Choose between uploading your own video files or embedding videos from YouTube and Vimeo platforms

Overlay Settings

  • Overlay Color - Add a colored overlay layer on top of media backgrounds to improve text readability or create visual effects
  • Overlay Opacity - Fine-tune the transparency level of the color overlay from 0% (fully transparent) to 100% (fully opaque)

Installation

npm install @multidots/sanity-plugin-hero-block

Setup

1. Add Plugin to Sanity Config

Add it as a plugin in sanity.config.ts (or .js):

import {defineConfig} from 'sanity'
import {heroBlockPlugin} from '@multidots/sanity-plugin-hero-block'

export default defineConfig({
  // ... other config
  plugins: [
    heroBlockPlugin(),
    // ... other plugins
  ],
})

2. Add to Your Schema

Include the hero block in your page or document schemas:

// In your page schema
import {heroBlockType} from '@multidots/sanity-plugin-hero-block'

export const pageSchema = defineType({
  name: 'page',
  type: 'document',
  fields: [
    defineField({
            name: "heroBlock",
            type: "heroBlock",
        }),
  ]
})

3. Update GROQ Queries

Ensure your GROQ queries properly expand asset references:

*[_type == "page" && slug.current == $slug][0]{
  content[]{
    ...,
    _type == "heroBlock" => {
      ...,
      "heroImage": heroImage{
        ...,
        asset->{
          _id,
          url
        }
      },
      heroVideoType,
      heroVideoUrl,
      "heroVideo": heroVideo{
        ...,
        asset->{
          _id,
          url
        }
      }
    }
  }
}

4. Frontend Component Usage

For a clean and maintainable frontend implementation, create a dedicated component wrapper first, then use it in your pages. This approach provides better code organization and reusability.

Create a Component Wrapper

First, create a HeroBlock.tsx component in your components directory:

// components/HeroBlock.tsx
import { HeroBlock } from "@multidots/sanity-plugin-hero-block";
import { urlFor } from "@/sanity/lib/image";
import { projectId, dataset } from "@/sanity/env";

interface HeroBlockComponentProps {
  heroBlock: any; // Replace with your specific type
}

export default function HeroBlockComponent({ heroBlock }: HeroBlockComponentProps) {
  // Return null if no hero block data is provided
  if (!heroBlock) {
    return null;
  }

  return (
    <HeroBlock 
      heroBlock={heroBlock} 
      urlFor={urlFor}           // For image asset processing
      projectId={projectId}     // For video asset URL construction
      dataset={dataset}         // For video asset URL construction
    />
  );
}

Use in Your Page Component

Then, import and use the component in your page:

// app/page.tsx or pages/[slug].tsx
import HeroBlockComponent from "@/components/HeroBlock";

export default function Page({ heroBlockData }) {
  return (
    <div>
      {/* Hero Block Section */}
      <HeroBlockComponent heroBlock={heroBlockData} />
      
      {/* Other page content */}
      <main>
        {/* Your page content here */}
      </main>
    </div>
  );
}

Why This Approach?

🔧 Better Organization: Separating the hero block into its own component keeps your page components clean and focused.

♻️ Reusability: You can easily use the same hero block component across multiple pages without code duplication.

🛠️ Easier Maintenance: All hero block-specific logic and configuration stays in one place, making updates and debugging simpler.

🎯 Type Safety: You can add proper TypeScript interfaces specific to your data structure.

🔍 Error Handling: Built-in null checks prevent rendering errors when data is unavailable.

Schema Fields

Content Fields

  • headingText (string, required) - Main hero heading
  • subHeading (string, required) - Secondary text below heading

Call to Action

  • callToActionText (string, optional) - Button text
  • callToActionLink (url, optional) - Button destination URL
  • openInNewTab (boolean, optional) - Whether link opens in new tab

Background Settings

  • heroBgType (string) - Background type: "color" or "media"
  • heroBgColor (color) - Background color (when type is "color")
  • heroBgMedia (string) - Media type: "image" or "video" (when type is "media")
  • heroImage (image) - Background image asset
  • heroVideoType (string) - Video source type: "url" or "upload" (when media type is "video")
  • heroVideoUrl (url) - Video URL for external videos like YouTube and Vimeo (when video type is "url")
  • heroVideo (file) - Background video asset for uploaded files (when video type is "upload", accepts video/* formats)

Overlay Settings (for media backgrounds)

  • heroOverlayColor (color) - Overlay color
  • heroOverlayOpacity (number) - Overlay opacity (0-1)

Styling Options

  • contentAlignment (string) - Text alignment: "left", "center", or "right"
  • contentColor (color) - Text color for heading and subheading
  • buttonBgColor (color) - Call-to-action button background color
  • buttonTextColor (color) - Call-to-action button text color

Component API

Props

interface HeroBlockProps {
  heroBlock: HeroBlockType;
  urlFor?: (source: any) => ImageUrlBuilder;  // Sanity image URL builder
  projectId?: string;                         // Sanity project ID (for video URLs)
  dataset?: string;                          // Sanity dataset (for video URLs)
}

HeroBlockType Interface

interface HeroBlockType {
  headingText: string;
  subHeading: string;
  callToAction?: {
    callToActionText?: string;
    callToActionLink?: string;
    openInNewTab?: boolean;
  };
  heroBgType: 'color' | 'media';
  heroBgColor?: { hex: string };
  heroBgMedia?: 'image' | 'video';
  heroImage?: {
    asset: {
      _ref: string;
      _type: 'reference';
      url?: string;
    };
    alt?: string;
  };
  heroVideoType?: 'url' | 'upload';
  heroVideoUrl?: string;
  heroVideo?: {
    asset: {
      _ref: string;
      _type: 'reference';
      url?: string;
    };
  };
  heroOverlay?: {
    heroOverlayColor?: { hex: string };
    heroOverlayOpacity?: number;
  };
  contentAlignment: 'left' | 'center' | 'right';
  contentColor?: { hex: string };
  buttonBgColor?: { hex: string };
  buttonTextColor?: { hex: string };
}

Screenshots

Hero Block Backend Settings: https://share.cleanshot.com/n0MbHpMxh0lt3Mfzt0kl

Hero Block Backend Settings

Hero Block Style Settings: https://share.cleanshot.com/n1KxfK55SZfc1l5jQcV5

Hero Block Style Settings

Hero Block Frontend Color BG: https://share.cleanshot.com/ZGcRbsgjcKtRMfNNxRjR

Hero Block Frontend Color BG

Hero Block Frontend Image BG: https://share.cleanshot.com/mwkHC2NJkgsqpGYMqMbt

Hero Block Frontend Image BG

Hero Block Frontend Video BG: https://share.cleanshot.com/1p6RgSfgVzcq61QTHcRl

Hero Block Frontend Video BG

Demo Video

https://share.cleanshot.com/wwGkZbDyG4mCsf4wSHcH

Troubleshooting

Video Not Playing

For Uploaded Videos:

  1. Ensure your GROQ query expands video assets: asset->{ url }
  2. Check that video files are in web-compatible formats (MP4, WebM, OGG)
  3. Verify projectId and dataset props are provided for fallback URL construction
  4. Ensure heroVideoType is set to "upload"
  5. Mobile-specific: Check that videos are optimized for mobile bandwidth
  6. Autoplay issues: Mobile browsers may block autoplay - ensure videos are muted

For Video URLs (YouTube/Vimeo):

  1. Verify the video URL is publicly accessible
  2. Check that heroVideoType is set to "url"
  3. Ensure heroVideoUrl contains a valid URL
  4. For YouTube: Use standard watch URLs (https://www.youtube.com/watch?v=...)
  5. For Vimeo: Use standard video URLs (https://vimeo.com/...)
  6. Some videos may not allow embedding - check video privacy settings

Images Not Loading

  1. Ensure urlFor helper is passed to the component
  2. Verify your GROQ query expands image assets: asset->{ url }
  3. Check that images are properly uploaded to Sanity

Development

This plugin uses @sanity/plugin-kit with default configuration for build & watch scripts.

Testing in Studio

See Testing a plugin in Sanity Studio for hot-reload development setup.

Building

npm run build

Development with Watch

npm run watch

License

MIT © Multidots