Introduction
Build widgets
SDK
Useful links
Search
/
Action/Tool widgets
This guide explains how to build mini web applications that can be converted into Nostr smart widgets using the smart-widget-handler package.
Overview
Smart Widget Mini Apps are lightweight web applications that extend functionality within Nostr clients. They run in their own context but can communicate with the host Nostr client to provide seamless integration.
Types of Mini Apps
Nostr clients recognize two types of mini apps:
Action Mini Apps
- Purpose: Perform actions with data from the Nostr client
- Data flow: One-way (client → mini app)
- Use case: Mini games, formatting tools
Tool Mini Apps
- Purpose: Process data and return results to the Nostr client
- Data flow: Two-way (client ↔ mini app)
- Use case: Text generators, data analysis, content lookup
📌 Note: The distinction between
ActionandToolis primarily to help Nostr clients handle the widget's UI and data flow appropriately and to provide the necessary UX for each type.
Quick Start
Create a new project:
mkdir my-nostr-widget
cd my-nostr-widget
npm init -y
npm install react react-dom smart-widget-handler
npm install -D vite @vitejs/plugin-react
Create a basic structure:
my-nostr-widget/
├── public/
│ └── .well-known/
│ └── widget.json
├── src/
│ ├── App.jsx
│ └── main.jsx
└── package.json
Integration with Host App
The smart-widget-handler package provides a bridge for communication between your mini app and the host application.
Installation
If not installed
npm install smart-widget-handler
Basic Usage
import SWhandler from "smart-widget-handler";
// Initialize communication with host app
useEffect(() => {
SWhandler.client.ready();
}, []);
// Listen for messages from host app
useEffect(() => {
let listener = SWhandler.client.listen((event) => {
if (event.kind === "user-metadata") {
// Handle user metadata
setUserMetadata(event.data?.user);
setHostOrigin(event.data?.host_origin);
}
if (event.kind === "err-msg") {
// Handle error messages
setErrorMessage(event.data);
}
if (event.kind === "nostr-event") {
// Handle Nostr events
const { pubkey, id } = event.data?.event || {};
// Process event data
}
});
return () => {
// Clean up listener when component unmounts
listener?.close();
}
}, []);
Action Mini Apps vs. Tool Mini Apps
Action Mini Apps. Exp
Action mini apps can only receive data from the host application. They are ideal for widgets that perform a specific action without needing to return data.
Example:
// In an Action Mini App
import SWhandler from "smart-widget-handler";
function ActionApp() {
const [userMetadata, setUserMetadata] = useState(null);
useEffect(() => {
SWhandler.client.ready();
const listener = SWhandler.client.listen((event) => {
if (event.kind === "user-metadata") {
setUserMetadata(event.data?.user);
}
});
return () => listener?.close();
}, []);
return (
<div>
{userMetadata ? (
<div>
<h1>Hello, {userMetadata.display_name || userMetadata.name}</h1>
<button onClick={performAction}>Perform Action</button>
</div>
) : (
<div>Loading user data...</div>
)}
</div>
);
}
Tool Mini Apps. Exp
Tool mini apps can both receive data from and return data to the host application. This makes them suitable for widgets that need to provide information back to the host app.
Example:
// In a Tool Mini App
import SWhandler from "smart-widget-handler";
function ToolApp() {
const [userMetadata, setUserMetadata] = useState(null);
const [hostOrigin, setHostOrigin] = useState(null);
useEffect(() => {
SWhandler.client.ready();
const listener = SWhandler.client.listen((event) => {
if (event.kind === "user-metadata") {
setUserMetadata(event.data?.user);
setHostOrigin(event.data?.host_origin);
}
});
return () => listener?.close();
}, []);
const sendDataToHost = (data) => {
if (hostOrigin) {
// Send context data back to the host app
SWhandler.client.sendContext(data, hostOrigin);
}
};
return (
<div>
{userMetadata ? (
<div>
<h1>Hello, {userMetadata.display_name || userMetadata.name}</h1>
<button onClick={() => sendDataToHost("This is data from the tool mini app")}>
Send Data to Host
</button>
</div>
) : (
<div>Loading user data...</div>
)}
</div>
);
}
Publishing Nostr Events
Mini apps can request the host application to sign and publish Nostr events:
const signEvent = (tempEvent) => {
if (hostOrigin) {
SWhandler.client.requestEventPublish(tempEvent, hostOrigin);
}
};
// Example of creating and publishing a simple note
const publishNote = () => {
const eventTemplate = {
kind: 1, // Regular note
content: "Hello from my mini app!",
tags: [["t", "miniapp"], ["t", "test"]]
};
signEvent(eventTemplate);
};
Widget Manifest
To make your mini app discoverable as a widget, you need to create a manifest file at /.well-known/widget.json:
{
"pubkey": "your-nostr-pubkey-in-hex",
"widget": {
"title": "My Amazing Widget",
"appUrl": "https://your-app-url.com",
"iconUrl": "https://your-app-url.com/icon.png",
"imageUrl": "https://your-app-url.com/thumbnail.png",
"buttonTitle": "Launch Widget",
"tags": ["tool", "utility", "nostr"]
}
}
This manifest serves two important purposes:
- Verifies the authenticity of your mini app
- Provides metadata for Nostr clients to display your widget
Deployment and Publication Workflow
-
Build your mini app
-
Deploy to a hosting service
- Vercel, Netlify, GitHub Pages, etc.
- Ensure the
/.well-known/widget.jsonfile is accessible
-
Register with YakiHonne Widget Editor
- Go to the YakiHonne Widget Editor
- Select
ActionorToolbased on your mini app type - Enter your mini app URL
- The editor will fetch your manifest and validate it
- Configure any additional settings
- Publish to Nostr
Benefits of Mini Apps
- Web3/Web2/Nostr Integration: Create apps that bridge different ecosystems
- FOSS Projects: Leverage open-source libraries and frameworks
- Customizability: Build widgets to suit specific needs
- Discoverability: Widget manifest makes your mini apps discoverable
Common Use Cases
Action Mini Apps
- Note composers with special formatting
- Media uploaders
- Event creators
- NFT minters
- Payment widgets
Tool Mini Apps
- Analytics providers
- Search tools
- Data aggregators
- Content recommendation engines
- Information lookup services