Smart widget previewer

On this page



DOCS








Smart widget previewer

A React component for previewing and interacting with Nostr Smart Widgets kind:30033. This package allows you to easily display smart widgets in your React applications with full interaction support.

Installation

npm install smart-widget-previewer

or

yarn add smart-widget-previewer

Overview

Smart Widget Previewer renders Nostr Smart Widgets kind:30033 in your React applications, supporting all widget features:

  • Basic widgets with images, inputs, and multiple buttons
  • Action/Tool widgets with specialized behavior
  • Interactive buttons for various purposes (redirect, nostr, zap, post, app)
  • Dynamic content updates when interacting with post-type buttons

Basic Example

import React from 'react';
import { Widget } from 'smart-widget-previewer';

function WidgetPreview() {
  // Example Nostr smart widget event
  const widgetEvent = {
    id: "widget_event_id",
    pubkey: "widget_creator_pubkey",
    created_at: 1681234567,
    kind: 30033,
    tags: [
      ["d", "unique-identifier"],
      ["l", "basic"],
      ["image", "https://example.com/widget-image.jpg"],
      ["input", "Search for something..."],
      ["button", "Visit Website", "redirect", "https://example.com"],
      ["button", "Zap Creator", "zap", "creator@lightning.address"]
    ],
    sig: "widget_signature"
  };

  // Handle button interactions
  const handleNostrButton = (url) => {
    console.log('Nostr button clicked with URL:', url);
    // Process nostr URL or identifier
    return url; // Return processed URL if needed
  };

  const handleZapButton = (address) => {
    console.log('Zap button clicked with address:', address);
    // Process lightning address or invoice
    return address; // Return processed address if needed
  };

  return (
    <div className="widget-container">
      <h2>Smart Widget Preview</h2>
      
      <Widget 
        event={widgetEvent}
        onNostrButton={handleNostrButton}
        onZapButton={handleZapButton}
        width={400}
        widthUnit="px"
      />
    </div>
  );
}

export default WidgetPreview;

Widget Component Props

The Widget component accepts the following props:

PropTypeDescription
eventObjectRequired - Nostr event object for the smart widget
onNextWidgetFunctionCallback for when a new widget is returned after interaction
onZapButtonFunctionCallback for handling zap button clicks, receives lightning address
onNostrButtonFunctionCallback for handling nostr button clicks, receives nostr URL
onActionWidgetFunctionCallback for handling action/tool widget clicks
widthNumberWidth of the widget (defaults to 100% if not specified)
widthUnitStringUnit for width: "px", "em", "rem", or "%" (defaults to "%")
buttonStyleClassNameStringCustom CSS class(es) for widget buttons
inputStyleClassNameStringCustom CSS class(es) for widget input field
widgetBackgroundColorStringCustom background color (hex or RGB)
widgetBorderColorStringCustom border color (hex or RGB)
widgetBorderRaduisStringCustom border radius in pixels
userHexPubkeyStringCurrent user's public key in hex format
errorMessageStringCustom error message for invalid widgets

Widget Types and Behavior

Basic Widgets

Basic widgets can include:

  • Image (required)
  • Input field (optional)
  • Up to 6 buttons with different actions
// Example of a basic widget event
const basicWidget = {
  id: "widget_event_id",
  pubkey: "widget_creator_pubkey",
  created_at: 1681234567,
  kind: 30033,
  tags: [
    ["d", "unique-identifier"],
    ["l", "basic"],
    ["image", "https://example.com/widget-image.jpg"],
    ["input", "Enter your search..."],
    ["button", "Visit Website", "redirect", "https://example.com"],
    ["button", "View Profile", "nostr", "nostr:npub1..."],
    ["button", "Send Zap", "zap", "user@lightning.address"]
  ],
  sig: "widget_signature"
};

Action/Tool Widgets

Action/Tool widgets are designed for single actions:

  • Image (required)
  • Icon (required but included in tags)
  • Exactly 1 button (if including input, the button must be of type 'app')
  • Clicking anywhere on the widget triggers the button action
// Example of an action widget event
const actionWidget = {
  id: "widget_event_id",
  pubkey: "widget_creator_pubkey",
  created_at: 1681234567,
  kind: 30033,
  tags: [
    ["d", "unique-identifier"],
    ["l", "action"],
    ["image", "https://example.com/widget-image.jpg"],
    ["icon", "https://example.com/widget-icon.png"],
    ["button", "Take Action", "app", "https://app.example.com/action"]
  ],
  sig: "widget_signature"
};

Button Types

The widget supports different types of buttons:

TypeDescriptionBehavior
redirectStandard linkOpens URL in new tab
nostrNostr actionCalls onNostrButton with the URL
zapLightning paymentCalls onZapButton with the address
postForm submissionSubmits input data and can update the widget
appApp integrationCalls onActionWidget with the URL

Handling Widget Interactions

Post Button Interaction

When a user interacts with a "post" type button, the widget will:

  1. Submit the input value along with widget information to the specified URL
  2. Process the response, which should be a new widget event
  3. Update the displayed widget with the new content
  4. Call onNextWidget with the new widget event
// Example handling the next widget update
function handleNextWidget(newWidgetEvent) {
  console.log('New widget received:', newWidgetEvent);
  // You can store this widget in state or handle it as needed
  return newWidgetEvent;
}

<Widget 
  event={widgetEvent}
  onNextWidget={handleNextWidget}
  userHexPubkey="user_pubkey_for_authentication"
/>

Action/Tool Widget Interaction

When a user clicks on an action/tool widget, the onActionWidget callback is called:

function handleActionWidget(url) {
  console.log('Action widget clicked with URL:', url);
  // Handle the action, such as opening a mini app or modal
}

<Widget 
  event={actionWidgetEvent}
  onActionWidget={handleActionWidget}
/>

Styling Widgets

You can customize the appearance of widgets using the provided props:

<Widget 
  event={widgetEvent}
  buttonStyleClassName="my-custom-button-class"
  inputStyleClassName="my-custom-input-class"
  widgetBackgroundColor="#f5f5f5"
  widgetBorderColor="#e0e0e0"
  widgetBorderRaduis="15"
  width={350}
  widthUnit="px"
/>

Complete Example

import React, { useState } from 'react';
import { Widget } from 'smart-widget-previewer';

function WidgetContainer() {
  const [currentWidget, setCurrentWidget] = useState({
    id: "widget_event_id",
    pubkey: "widget_creator_pubkey",
    created_at: 1681234567,
    kind: 30033,
    tags: [
      ["d", "unique-identifier"],
      ["l", "basic"],
      ["image", "https://example.com/widget-image.jpg"],
      ["input", "Search for content..."],
      ["button", "Search", "post", "https://api.example.com/search"],
      ["button", "View Creator", "nostr", "nostr:npub1..."],
      ["button", "Support", "zap", "creator@lightning.address"]
    ],
    sig: "widget_signature"
  });

  // Handle when a post button returns a new widget
  const handleNextWidget = (newWidget) => {
    setCurrentWidget(newWidget);
    return newWidget;
  };

  // Handle nostr button clicks
  const handleNostrButton = (url) => {
    console.log('Processing nostr URL:', url);
    // Here you would integrate with your Nostr client
    // Example: openNostrProfile(url);
    return url;
  };

  // Handle zap button clicks
  const handleZapButton = (address) => {
    console.log('Processing lightning address:', address);
    // Here you would integrate with your Lightning wallet
    // Example: openZapModal(address);
    return address;
  };

  // Handle action widget clicks
  const handleActionWidget = (url) => {
    console.log('Opening action at URL:', url);
    // Here you would handle the action
    // Example: openActionInFrame(url);
  };

  return (
    <div className="widget-demo">
      <h1>Smart Widget Demo</h1>
      
      <div className="widget-wrapper">
        <Widget 
          event={currentWidget}
          onNextWidget={handleNextWidget}
          onNostrButton={handleNostrButton}
          onZapButton={handleZapButton}
          onActionWidget={handleActionWidget}
          width={450}
          widthUnit="px"
          widgetBackgroundColor="#ffffff"
          widgetBorderColor="#dddddd"
          widgetBorderRaduis="12"
          userHexPubkey="user_hex_pubkey_here"
          errorMessage="Widget could not be displayed"
        />
      </div>
    </div>
  );
}

export default WidgetContainer;

Browser Compatibility

Smart Widget Previewer is compatible with all modern browsers that support React.

On this page