useSummarizer
React adapter for @web-ai-sdk/summarizer. Auto-runs on mount, re-runs when article / text / language change, and streams chunks through state updates. For the conceptual overview see Summarizer.
Live demo
Pick a sample article or paste your own. The summary streams in as the model produces it.
Usage
import { useSummarizer } from "@web-ai-sdk/summarizer/react";
export function ArticleSummary({ article }: { article: HTMLElement | null }) { const { status, summary } = useSummarizer({ language: "en", article: article ?? undefined, createOptions: { type: "key-points", length: "short" }, });
if (status === "unavailable") return null; return <aside>{summary}</aside>;}The hook auto-runs whenever its meaningful inputs change. Empty / undefined article keeps the hook in "pending" without invoking the model.
State machine
pending ───► loading ───► streaming ───► done │unavailable ◄─── (no flag / │ no model) │ ▼ dismiss()pending: hook mounted, waiting forarticleto be defined.loading: warming theSummarizer.create()session (~1-3s cold start).streaming: chunks arriving.result.summarygrows as they land; render it directly for a typewriter effect.done: final summary inresult.summary.result.cachedistrueif the response came from the opt-in result cache.unavailable: API missing. Render nothing.
Caching tips
The hook exposes the same two caches as the vanilla summarize():
- Session cache (in-memory, always on): warm sessions are reused across calls with the same
{ language, sharedContext, createOptions }. Plan your inputs around these dimensions to keep cold-starts rare. - Result cache (opt-in): off by default; every call hits the model. Pass
cache: createSessionStorageCache()for per-tab caching,cache: createSessionStorageCache({ storage: localStorage })to persist across tabs, or anyMap-shaped object for in-memory-only.
result.cached lets you render a “From cache” hint or skip a re-fetch loop entirely.
Streaming UX
result.summary updates on every chunk during streaming. A naive <p>{result.summary}</p> already produces a typewriter effect because React re-renders on each state change. If chunks arrive faster than you want to repaint, debounce on the consumer side.
Reference
import type { UseSummarizerOptions, UseSummarizerReturn, SummarizerStatus } from "@web-ai-sdk/summarizer/react";
type SummarizerStatus = "pending" | "loading" | "streaming" | "done" | "unavailable";
interface UseSummarizerOptions extends Omit<SummarizeOptions, "onUpdate" | "signal"> { enabled?: boolean; // default: true // Inherited from SummarizeOptions (subset shown — see Summarizer guide): article?: HTMLElement; text?: string; language: string; title?: string; description?: string; cache?: SummaryCache; cacheKey?: string; sharedContext?: Record<string, string>; createOptions?: SummarizerCreateOptions; // type, length, format, etc. maxInputChars?: number; minSkeletonChars?: number; supportedLanguages?: readonly string[];}
interface UseSummarizerReturn { status: SummarizerStatus; summary: string | null; error: Error | null; fromCache: boolean; dismiss(): void; // sets status to "unavailable", clears summary}
declare const useSummarizer: (options: UseSummarizerOptions) => UseSummarizerReturn;