auth-security
Best practices for implementing JWT, API Keys, OAuth 2.1, and RBAC in a NitroStack application.
Best practices for linking tools to interactive frontend widgets using @Widget and @nitrostack/widgets SDK (including state sync, tool calling, display modes, media queries, and chat actions).
$ npx -y skills add nitrocloudofficial/nitrostack --skill ui-widgets --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/ui-widgetsContext preview
The summary Claude sees to decide when to auto-load this skill.
Best practices for linking tools to interactive frontend widgets using @Widget and @nitrostack/widgets SDK (including state sync, tool calling, display modes, media queries, and chat actions).
name: nitrostack-ui-widgets description: Best practices for linking tools to interactive frontend widgets using @Widget and @nitrostack/widgets SDK (including state sync, tool calling, display modes, media queries, and chat actions).
Use this skill when designing, building, or modifying interactive user interface widgets that display custom React content inside AI clients or NitroStudio.
---
To display a React-based widget for a tool's output, decorate the tool method with `@Widget`.
import { Tool, Widget, z } from '@nitrostack/core';
export class CatalogTools {
@Tool({
name: 'fetch_product',
description: 'Get product information by barcode.',
inputSchema: z.object({ barcode: z.string() }),
})
@Widget('product-details') // Maps to the "product-details" frontend component
async fetchProduct(input: { barcode: string }) {
return {
name: 'Super Nitro Energy Drink',
price: 2.99,
sku: input.barcode,
};
}
}---
In your React widget frontend application (typically a Next.js client component), use the `useWidgetSDK` hook to receive input data from the client host.
'use client';
import React from 'react';
import { useWidgetSDK } from '@nitrostack/widgets';
interface ProductData {
name: string;
price: number;
sku: string;
}
export default function ProductDetailsWidget() {
const { isReady, getToolOutput, theme } = useWidgetSDK();
const data = getToolOutput<ProductData>();
if (!isReady) {
return <div className="loading">Connecting to host...</div>;
}
if (!data) {
return <div className="error">No product data received.</div>;
}
return (
<div className={`product-card ${theme === 'dark' ? 'dark' : 'light'}`}>
<h3>{data.name}</h3>
<p className="price">${data.price.toFixed(2)}</p>
<span className="sku">SKU: {data.sku}</span>
</div>
);
}---
Use `useWidgetState` to manage and persist client-side widget state (e.g. selected tabs, filter values, input states). This state automatically synchronizes with the host application context, persisting it across page re-renders.
import React from 'react';
import { useWidgetState } from '@nitrostack/widgets';
export default function StationPanelWidget() {
const [state, setState] = useWidgetState(() => ({
selectedTab: 'overview',
showExtendedInfo: false,
}));
return (
<div>
<button onClick={() => setState({ ...state, selectedTab: 'alerts' })}>
View Alerts
</button>
<p>Current Tab: {state?.selectedTab}</p>
</div>
);
}---
You can invoke other backend MCP tools directly from the frontend widget using `callTool`. This is useful for tool chaining or triggering detailed audits.
import React, { useState } from 'react';
import { useWidgetSDK } from '@nitrostack/widgets';
export default function SystemDiagnostics() {
const { callTool, isReady } = useWidgetSDK();
const [isRunning, setIsRunning] = useState(false);
const [result, setResult] = useState<string | null>(null);
const runDiagnostic = async () => {
if (!isReady) return;
setIsRunning(true);
try {
const response = await callTool('run_diagnostic', { system: 'oxygen_scrubber' });
setResult(response.result as string);
} catch (err) {
setResult('Diagnostic execution failed.');
} finally {
setIsRunning(false);
}
};
return (
<button onClick={runDiagnostic} disabled={isRunning}>
{isRunning ? 'Running...' : 'Run Diagnostics'}
</button>
);
}---
Widgets can dynamically request size mode changes (fullscreen, inline, picture-in-picture) and adapt layouts to safe areas (dynamic islands/notches) or maximum height constraints.
import React from 'react';
import { useWidgetSDK } from '@nitrostack/widgets';
export default function StatusBoard() {
const {
requestFullscreen,
requestInline,
requestClose,
displayMode, // Reactive property ('fullscreen' | 'inline' | 'pip')
maxHeight, // Reactive maxHeight constraint (in pixels)
getSafeArea // Insets data: { top, right, bottom, left }
} = useWidgetSDK();
const safeArea = getSafeArea() || { top: 0, bottom: 0 };
return (
<div style={{ maxHeight: maxHeight || 400, paddingTop: safeArea.top }}>
<h3>Mode: {displayMode}</h3>
<button onClick={requestFullscreen}>Fullscreen</button>
<button onClick={requestInline}>Collapse</button>
<button onClick={requestClose}>Dismiss Widget</button>
</div>
);
}---
Widgets can interact with the host chat pane using external browser links and follow-up prompts.
import React from 'react';
import { useWidgetSDK } from '@nitrostack/widgets';
export default function MissionControl() {
const { openExternal, sendFThe full-stack TypeScript framework to build, test, and deploy production-ready MCP servers and AI-native apps.
Repo: nitrocloudofficial/nitrostack
Best practices for implementing JWT, API Keys, OAuth 2.1, and RBAC in a NitroStack application.
Best practices and guidelines for bootstrapping, defining modules, using dependency injection, managing server lifecycles, and handling events in the…
Best practices for implementing and applying Guards, Interceptors, Middleware, Pipes, and Exception Filters in the NitroStack SDK.
Guidelines and patterns for defining Tools, Resources, and Prompts in a NitroStack application with schema validation via Zod, including caching,…
Prisma ORM CLI commands reference covering init, generate, migrate, db, dev, studio, validate, format, debug, and mcp. Use for ORM/database CLI workflows, not…
Prisma Client API reference covering model queries, filters, operators, and client methods. Use when writing database queries, using CRUD operations, filtering…