React hooks and components for integrating with the Vana Network.
Drop in secure, type-safe data upload and social sharing instead of building custom iframe integrations, managing authentication, or writing boilerplate message protocols.
Solves:
Tightly integrated with Vana App infrastructure – components point to
app.vana.com and handle all the plumbing.
npm install @opendatalabs/vana-react
# or
yarn add @opendatalabs/vana-react
# or
pnpm add @opendatalabs/vana-react
An embeddable iframe widget that facilitates data upload operations for Vana Apps.
import { VanaAppUploadWidget } from "@opendatalabs/vana-react";
function App() {
const handleResult = (result: any) => {
console.log("Upload successful:", result);
};
const handleError = (error: string) => {
console.error("Upload error:", error);
};
const handleAuth = (walletAddress: string) => {
console.log("Authenticated:", walletAddress);
};
return (
<VanaAppUploadWidget
appId="your-app-id"
onResult={handleResult}
onError={handleError}
onAuth={handleAuth}
schemaId={123}
prompt="Upload your data"
operation="prompt_gemini_agent"
operationParams={{ goal: "Analyze user data" }}
theme={{ "--primary": "#007bff" }}
isOpen={true}
onClose={() => console.log("Widget closed")}
/>
);
}
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
appId |
string |
Yes | - | Your Vana application ID |
onResult |
(data: AgentOperationResult) => void |
Yes | - | Callback when data upload completes successfully |
onError |
(error: string) => void |
Yes | - | Callback when an error occurs |
onAuth |
(walletAddress: string) => void |
Yes | - | Callback when wallet authentication succeeds |
isOpen |
boolean |
No | true |
Controls visibility; iframe stays mounted for prefetching (fullscreen) |
onClose |
() => void |
No | - | Fires when child posts uploader:closed |
onReady |
() => void |
No | - | Fires after child ready and config sent; safe for animation timing |
iframeOrigin |
string |
No | https://app.vana.com |
Origin URL for the iframe |
schemaId |
number |
No | - | Schema ID for data validation |
prompt |
string |
No | - | LLM inference prompt (legacy; prefer operation + operationParams) |
operation |
string |
No | - | Agent operation (e.g. prompt_gemini_agent, llm_inference) |
operationParams |
Record<string, unknown> |
No | - | Params forwarded to personal server with the operation |
filters |
Record<string, string> |
No | - | JSONPath filters per schema for data pre-filtering |
theme |
VanaAppUploadTheme |
No | - | CSS custom properties (e.g. { "--primary": "#6366f1" }) |
zIndex |
number |
No | 1000 |
Z-index for stacking control |
The VanaAppUploadWidget component supports React forwardRef to expose the
underlying iframe element:
const iframeRef = useRef<HTMLIFrameElement>(null);
<VanaAppUploadWidget
ref={iframeRef}
appId="your-app-id"
{...otherProps}
/>
// Access iframe programmatically
iframeRef.current?.contentWindow?.postMessage(...);
Origin Validation: The widget validates the iframe's origin on the first
ready message before posting configuration. This protects against:
Always use https://app.vana.com (or your authenticated domain) as the
iframeOrigin prop. If you need to redirect or proxy the iframe, ensure the
final destination origin matches your security policy.
className: No longer used; widget layout is fully controlled internally for
fullscreen experience. Accepted for backward compatibility but has no effect.resize postMessage: Ignored; widget is full-viewport by design. Height
adjustment via postMessage is no longer supported.A customizable social sharing component designed for Vana Data Apps. Provides seamless sharing to social platforms with copy-to-clipboard functionality and countdown notifications.
import { VanaAppSocialShareWidget } from "@opendatalabs/vana-react";
function MyDataApp() {
const handleShare = (platform: string) => {
console.log(`User shared on ${platform}`);
};
return (
<VanaAppSocialShareWidget
appName="Ice Cream Flavor"
shareContent="ChocoVision Leader (Dark Chocolate)"
shareEmoji="🍦"
funnyNote="Apparently I'm in the same league as Beyoncé!"
title="Share your flavor"
onShare={handleShare}
classNames={{
root: "text-center",
button: "w-12 h-12 rounded-full bg-white shadow-md hover:scale-105",
}}
theme={{ iconSize: 20 }}
/>
);
}
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
appName |
string |
Yes | - | Name of your Vana app (e.g., "Ice Cream Flavor") |
shareContent |
string |
Yes | - | Main content to share (e.g., user's result) |
shareEmoji |
string |
No | - | Emoji to prepend to share content |
funnyNote |
string |
No | - | Engaging note to add after content |
title |
string |
No | "Share" |
Title displayed above share buttons |
callToAction |
string |
No | "Try @ app.vana.com" |
CTA text in share message |
hashtag |
string |
No | "#DATAREVOLUTION" |
Hashtag to append to message |
theme |
VanaAppSocialShareTheme |
No | {} |
Theme configuration (iconSize) |
onShare |
(platform: SocialPlatform) => void |
No | - | Callback when user shares |
onShowToast |
(message: ToastMessage) => void |
No | - | Custom toast handler (uses internal if not set) |
classNames |
VanaAppSocialShareClassNames |
No | {} |
Class names for all component parts |
hideTitle |
boolean |
No | false |
Hide the title section |
renderButton |
(platform, Icon) => ReactNode |
No | - | Custom render function for buttons |
buttonComponent |
React.ComponentType<ShareButtonProps> |
No | - | Custom button component |
| Property | Type | Description |
|---|---|---|
root |
string |
Root container class |
title |
string |
Title section class (includes icon and text) |
buttons |
string |
Buttons container class |
button |
string |
Base class for all buttons |
toast |
string |
Toast container class (if using internal toast) |
toastContent |
string |
Toast content wrapper class |
progress |
string |
Progress bar class for countdown |
npm run dev
npm test
npm run build
npm run lint
npm run typecheck
MIT © OpenDataLabs