Loading run...
;
+ if (error) return
+ {title &&
{title}
}
+
+
+
+
+
+ {progress?.current && progress?.total
+ ? `${progress.current}/${progress.total} items`
+ : "Processing..."}
+
+ {percentage}%
+
+
+ {progress?.currentItem && (
+
Current: {progress.currentItem}
+ )}
+
+ );
+}
+```
+
+### Status indicator with logs
+
+This example demonstrates how to create a status indicator component that can be used to display the status of a run, and also logs that are emitted by the task:
+
+```tsx
+"use client";
+
+import { useRealtimeRun } from "@trigger.dev/react-hooks";
+
+interface StatusIndicatorProps {
+ runId: string;
+ publicAccessToken: string;
+}
+
+export function StatusIndicator({ runId, publicAccessToken }: StatusIndicatorProps) {
+ const { run } = useRealtimeRun(runId, {
+ accessToken: publicAccessToken,
+ });
+
+ const status = run?.metadata?.status as string | undefined;
+ const logs = run?.metadata?.logs as string[] | undefined;
+
+ const getStatusColor = (status: string | undefined) => {
+ switch (status) {
+ case "completed":
+ return "text-green-600 bg-green-100";
+ case "failed":
+ return "text-red-600 bg-red-100";
+ case "running":
+ return "text-blue-600 bg-blue-100";
+ default:
+ return "text-gray-600 bg-gray-100";
+ }
+ };
+
+ return (
+
+
Deployment Progress
+
+ {/* Stage indicators */}
+
+ {DEPLOYMENT_STAGES.map((stage, index) => {
+ const isActive = currentStageIndex === index;
+ const isCompleted = currentStageIndex > index;
+ const isFailed = run?.status === "FAILED" && currentStageIndex === index;
+
+ return (
+
+
+ {isCompleted ? "β" : index + 1}
+
+
+ {stage}
+
+ {isActive && (
+
+ )}
+
+ );
+ })}
+
+
+ {/* Recent logs */}
+ {logs && logs.length > 0 && (
+
+
+ {logs.slice(-5).map((log, index) => (
+
+ $
+ {log}
+
+ ))}
+
+
+ )}
+
+ );
+}
+```
+
+### Type safety
+
+Define TypeScript interfaces for your metadata to get full type safety:
+
+```tsx
+"use client";
+
+import { useRealtimeRun } from "@trigger.dev/react-hooks";
+
+interface TaskMetadata {
+ progress?: {
+ current: number;
+ total: number;
+ percentage: number;
+ currentItem: string;
+ };
+ status?: "initializing" | "processing" | "completed" | "failed";
+ user?: {
+ id: string;
+ name: string;
+ };
+ logs?: string[];
+}
+
+export function TypedMetadataComponent({
+ runId,
+ publicAccessToken,
+}: {
+ runId: string;
+ publicAccessToken: string;
+}) {
+ const { run } = useRealtimeRun(runId, {
+ accessToken: publicAccessToken,
+ });
+
+ // Type-safe metadata access
+ const metadata = run?.metadata as TaskMetadata | undefined;
+
+ return (
+
+ {metadata?.progress &&
Progress: {metadata.progress.percentage}%
}
+
+ {metadata?.user && (
+
+ User: {metadata.user.name} ({metadata.user.id})
+
+ )}
+
+ {metadata?.status &&
Status: {metadata.status}
}
+
+ );
+}
+```
+
+## Common options
+
+### accessToken & baseURL
+
+You can pass the `accessToken` option to the Realtime hooks to authenticate the subscription.
+
+```tsx
+import { useRealtimeRun } from "@trigger.dev/react-hooks";
+
+export function MyComponent({
+ runId,
+ publicAccessToken,
+}: {
+ runId: string;
+ publicAccessToken: string;
+}) {
+ const { run, error } = useRealtimeRun(runId, {
+ accessToken: publicAccessToken,
+ baseURL: "https://my-self-hosted-trigger.com", // Optional if you are using a self-hosted Trigger.dev instance
+ });
+
+ if (error) return Loading...
;
+ if (error) return