> Canonical URL: https://codingcat.dev/post/chrome-built-in-ai-gemini-nano-prompt-api-guide

# Chrome Built-in AI and Gemini Nano: A Production Guide to the Prompt, Summarizer, and Rewriter APIs

✏️ Blog PostFebruary 18, 2026[AI & MCP Agents](/topic/ai)

# Chrome Built-in AI and Gemini Nano: A Production Guide to the Prompt, Summarizer, and Rewriter APIs

![Alex Patterson and AJ the Cat pointing at Chrome Built-in AI and Gemini Nano running inside the browser with 0ms network latency](https://cdn.sanity.io/images/hfh83o0w/production/e657304ba873f4983782c8dca28f533cffe8be7f-1376x768.jpg?w=1376&q=82&fit=max&auto=format)[![Alex Patterson](https://cdn.sanity.io/images/hfh83o0w/production/a606dfaa381aab08ddbe16a33fe1d3e1fb37c927-400x400.jpg?w=96&h=96&q=82&fit=max&auto=format)Alex Patterson](/author/alex-patterson)✏️ Visual Architecture Diagram

## how this post connects together.

Follow AJ from first principles to production-ready architecture.

Let’s build it!✏️ Visual Diagram: Chrome Built-in AI and Gemini Nano: A Production…✓ Good PatternVISUAL DIAGRAM[Diagram Walkthrough]Step-by-step diagram breakdown for Chrome Built-in AI and Gemini Nano: A Production Guide to the Prompt, Summarizer, and Rewriter APIs: start with Chrome Built, implement Hands-On Implementation, and ship to production.AAA Contrast Verified

For the past two years, adding a simple text summarizer, tone rewriter, or draft assistant to a web application meant standing up a server-side proxy, managing API keys, paying per million tokens, and eating a 450ms network roundtrip on every single user interaction. With [**Chrome Built-in AI**](https://developer.chrome.com/docs/ai/built-in) shipping **Gemini Nano**  directly inside the browser binary, web developers can now run foundation model inference on the user's local GPU or NPU with zero token cost, zero server egress, and full offline capability.

In this guide, we will break down how Chrome's Built-in AI architecture works under the hood, walk through the `LanguageModel` (Prompt API), `Summarizer`, `Rewriter`, and `Translator` Web APIs in TypeScript, and show how we wire up progressive model download telemetry and session cloning in Astro and React.

## The Mental Model: Why Move Inference into the Browser Sandbox?

When you bundle your own WebAssembly or WebGPU weights per origin, every website forces the user to download a separate 1.5GB model file. Chrome Built-in AI solves the cold-cache problem at the browser level: Chrome downloads and updates a single shared **Gemini Nano**  checkpoint managed by the browser'sOptimization Guide service, and exposes task-specific and general-purpose JavaScript interfaces to any origin that requests them.

![Dark-mode Architecture Diagram comparing cloud-only LLM roundtrips against Chrome Built-in AI local Gemini Nano execution](https://cdn.sanity.io/images/hfh83o0w/production/c9617e309078bfed4462252067ff0ca6dfac248e-1376x768.jpg?w=1376&q=82&fit=max&auto=format)Architecture Diagram: Cloud-Only LLM Proxy (left, Coral anti-pattern) vs. Chrome Built-in AI with Local Gemini Nano and 0ms network RTT (right, Mint recommended pattern).

## Chrome Built-in AI API Surface Comparison

Rather than forcing every developer to write brittle system prompts for common text transformations, Chrome splits Built-in AI into high-level task APIs and the flexible `LanguageModel` Prompt API:

Browser APIGlobal InterfacePrimary Configuration OptionsIdeal Production WorkloadPrompt APIwindow.LanguageModelsystemPrompt, initialPrompts, temperature, topK, responseConstraint (JSON Schema)Custom structured extraction, interactive chat, and classification with JSON Schema output constraints.Summarizer APIwindow.Summarizertype ('key-points' | 'tldr' | 'teaser' | 'headline'), format ('markdown' | 'plain-text'), lengthSummarizing long documentation pages, podcast transcripts, or comment threads client-side.Writer & Rewriter APIswindow.Writer / window.Rewritertone ('more-formal' | 'more-casual' | 'as-is'), length ('shorter' | 'longer'), sharedContextInline rich-text editor helpers in Sanity Studio, support ticket polishing, and PR descriptions.Translator & LanguageDetectorwindow.Translator / window.LanguageDetectorsourceLanguage, targetLanguage (BCP-47 tags)Instant privacy-preserving localization of user-generated content without cloud translation fees.

## Step 1: Probing Availability and Handling Model Downloads

Never assume the local model weights are already cached on disk. Before calling `LanguageModel.create()`, always inspect `LanguageModel.availability()` (which returns `'available'`, `'downloadable'`, `'downloading'`, or `'unavailable'`) and attach a `monitor` callback to surface download progress in your UI:

```
// src/lib/ai/chrome-language-model.ts
export type BuiltInAvailability = "available" | "downloadable" | "downloading" | "unavailable";

export interface PromptSessionOptions {
  systemPrompt?: string;
  temperature?: number;
  topK?: number;
  onDownloadProgress?: (loadedRatio: number) => void;
  signal?: AbortSignal;
}

interface ChromeLanguageModelFactory {
  availability(options?: Record): Promise;
  params(): Promise;
  create(options?: Record): Promise;
}

export interface ChromeLanguageModelSession {
  prompt(input: string, options?: { responseConstraint?: object; signal?: AbortSignal }): Promise;
  promptStreaming(input: string, options?: { responseConstraint?: object; signal?: AbortSignal }): ReadableStream;
  measureInputUsage(input: string): Promise;
  readonly inputUsage: number;
  readonly inputQuota: number;
  clone(options?: { signal?: AbortSignal }): Promise;
  destroy(): void;
}

function getLanguageModelFactory(): ChromeLanguageModelFactory | null {
  const g = globalThis as unknown as {
    LanguageModel?: ChromeLanguageModelFactory;
    ai?: { languageModel?: ChromeLanguageModelFactory };
  };
  return g.LanguageModel ?? g.ai?.languageModel ?? null;
}

export async function createBrowserPromptSession(
  options: PromptSessionOptions = {}
): Promise {
  const factory = getLanguageModelFactory();
  if (!factory) return null;

  const status = await factory.availability();
  if (status === "unavailable") {
    return null;
  }

  const defaults = await factory.params();
  return await factory.create({
    systemPrompt:
      options.systemPrompt ??
      "You are a concise, code-first web architecture assistant on CodingCat.dev.",
    temperature: options.temperature ?? defaults.defaultTemperature,
    topK: options.topK ?? defaults.defaultTopK,
    signal: options.signal,
    monitor(m: EventTarget) {
      m.addEventListener("downloadprogress", (event: Event) => {
        const e = event as unknown as { loaded?: number; total?: number };
        if (typeof e.loaded === "number" && options.onDownloadProgress) {
          const ratio = e.total ? e.loaded / e.total : e.loaded;
          options.onDownloadProgress(Math.min(1, Math.max(0, ratio)));
        }
      });
    },
  });
}
```

## Step 2: Structured JSON Output with responseConstraint and Session Cloning

Two of the most impactful capabilities in Chrome's Prompt API are `responseConstraint` (which forces Gemini Nano's token sampler to adhere strictly to a JSON Schema without hallucinating invalid syntax) and `session.clone()` (which forks the KV-cache of an initialized system prompt so you can process multiple items without re-evaluating the system context). Here is how we combine both to classify and tag technical tutorials client-side:

```
// src/lib/ai/classify-article-client.ts
import { createBrowserPromptSession } from "./chrome-language-model";

const TAG_EXTRACTION_SCHEMA = {
  type: "object",
  properties: {
    primaryPillar: {
      type: "string",
      enum: ["Courses", "Podcasts", "Blog"],
    },
    difficulty: {
      type: "string",
      enum: ["beginner", "intermediate", "advanced"],
    },
    technicalTags: {
      type: "array",
      items: { type: "string" },
      maxItems: 5,
    },
    oneSentenceSummary: {
      type: "string",
    },
  },
  required: ["primaryPillar", "difficulty", "technicalTags", "oneSentenceSummary"],
  additionalProperties: false,
};

export async function analyzeDraftInBrowser(markdownDraft: string) {
  const baseSession = await createBrowserPromptSession({
    systemPrompt:
      "Analyze developer tutorials for CodingCat.dev and extract structured metadata.",
  });

  if (!baseSession) {
    throw new Error("Chrome Built-in AI (Gemini Nano) is not available on this device.");
  }

  try {
    // Check token budget before prompting so we never blow the context window
    const tokenCost = await baseSession.measureInputUsage(markdownDraft);
    const remainingTokens = baseSession.inputQuota - baseSession.inputUsage;
    const boundedInput =
      tokenCost > remainingTokens ? markdownDraft.slice(0, 6000) : markdownDraft;

    // Clone the warm session so repeated runs reuse the system prompt KV cache
    const workerSession = await baseSession.clone();
    try {
      const rawJson = await workerSession.prompt(
        `Extract metadata for this draft:\n\n${boundedInput}`,
        { responseConstraint: TAG_EXTRACTION_SCHEMA }
      );
      return JSON.parse(rawJson);
    } finally {
      workerSession.destroy();
    }
  } finally {
    baseSession.destroy();
  }
}
```

## Step 3: Streaming Key-Point Summaries with the Summarizer API

When you specifically need TL;DR bullet points or executive summaries on a Blog Post or Podcast Episode transcript, use `window.Summarizer` instead of the raw Prompt API. Chrome tunes the underlying LoRA / task prompt specifically for factual density:

```
// src/lib/ai/summarize-transcript.ts
export async function streamTranscriptKeyPoints(
  transcriptText: string,
  onChunk: (partialMarkdown: string) => void
): Promise {
  const SummarizerApi = (globalThis as Record).Summarizer;
  if (!SummarizerApi) {
    throw new Error("Summarizer API is not supported in this browser.");
  }

  const availability = await SummarizerApi.availability();
  if (availability === "unavailable") {
    throw new Error("Summarizer model is unavailable on this hardware.");
  }

  const summarizer = await SummarizerApi.create({
    type: "key-points",
    format: "markdown",
    length: "medium",
    sharedContext:
      "This is a technical software engineering tutorial from CodingCat.dev.",
  });

  try {
    const stream: ReadableStream = summarizer.summarizeStreaming(transcriptText, {
      context: "Focus on architectural trade-offs, browser APIs, and production benchmarks.",
    });

    const reader = stream.getReader();
    let accumulated = "";
    while (true) {
      const { done, value } = await reader.read();
      if (done) break;
      // Handle both cumulative and delta streaming implementations across Chrome releases
      accumulated = value.startsWith(accumulated) ? value : accumulated + value;
      onChunk(accumulated);
    }
    return accumulated;
  } finally {
    if (typeof summarizer.destroy === "function") {
      summarizer.destroy();
    }
  }
}
```

## AJ Pro-Tip: User Activation and Context Quotas

> AJ Pro-Tip: Always Gate Model Creation Behind Transient User Activation. When `availability()` returns `'downloadable'`, Chrome requires a transient user gesture (such as a `click` event) before `LanguageModel.create()` or `Summarizer.create()` will initiate the background weight download. Call `availability()` on page load to render your button state, and call `create()` inside the button's click handler while monitoring `session.inputUsage / session.inputQuota` so long conversations never overflow Gemini Nano's local context window.

## **Try the Live Browser AI & WebMCP Playground**

You can test every pattern from this article live right now in our interactive [**Web AI & WebMCP Playground**](/demos/web-ai) on CodingCat.dev, or inspect our production discovery manifests on the [**Developers & Agent APIs**](/developers) page. If you are organizing a developer conference or engineering summit, check out my Web AI talk abstracts on [**alexpatterson.dev**](https://alexpatterson.dev) and explore more hands-on [**Courses**](/courses), [**Podcasts**](/podcasts), and [**Blog Posts**](/blog) right here on CodingCat.dev.

## recent blog posts.

[All Blog Posts&rarr;](/blog)[![The Heads of AI wearing black company logo t-shirts and shaking hands in a circular web of cloud and GPU investments](https://cdn.sanity.io/images/hfh83o0w/production/d1d83d596ce5899d797cd3aaf1bd0142038f282a-1376x768.jpg?w=1376&q=82&fit=max&auto=format)](/post/anthropic-s1-ipo-circular-ai-economy-etf-risk)October 26, 2026[![](/logos/amplify/amplify.svg)![](/logos/amplify/amplify.svg)AWS Amplify](/topic/amplify)[AI & MCP Agents](/topic/ai)

### [Anthropic's S-1, $518B in cloud commitments, and circular AI capex](/post/anthropic-s1-ipo-circular-ai-economy-etf-risk)

Anthropic just filed its Form S-1 for a Nasdaq IPO under ticker ANT, revealing $518B in take-or-pay cloud commitments to Google, AWS, and Microsoft. Here is how Mark Zuckerberg, Elon Musk, Jensen Huang, Sundar Pichai, Satya Nadella, Tim Cook, and Dario Amodei built a circular revenue machine, and what happens to your S&P 500 ETF if it stalls.

[![Alex Patterson](https://cdn.sanity.io/images/hfh83o0w/production/a606dfaa381aab08ddbe16a33fe1d3e1fb37c927-400x400.jpg?w=96&h=96&q=82&fit=max&auto=format)Alex Patterson](/author/alex-patterson)[![PHP2Shell (CVE-2026-109618): How AI Found a Decade-Old Bug in 70% of the Web](https://cdn.sanity.io/images/hfh83o0w/production/e83065d0a4e2f841ce64d3f4aea8ddbbf07e5cb9-1376x768.jpg?w=1376&q=82&fit=max&auto=format)](/post/php2shell-cve-2026-109618-ai-php-security-scramble)October 22, 2026[![](/logos/amplify/amplify.svg)![](/logos/amplify/amplify.svg)AWS Amplify](/topic/amplify)[AI & MCP Agents](/topic/ai)

### [PHP2Shell (CVE-2026-109618): How AI Found a Decade-Old Bug in 70% of the Web](/post/php2shell-cve-2026-109618-ai-php-security-scramble)

Two critical pre-authentication RCE flaws in PHP (CVE-2026-109618 and CVE-2026-109619), uncovered by AI models from OpenAI and Google Gemini, sparked a global patching scramble across 70% of the web. Here is how PHP2Shell works and how to patch your servers.

[![Alex Patterson](https://cdn.sanity.io/images/hfh83o0w/production/a606dfaa381aab08ddbe16a33fe1d3e1fb37c927-400x400.jpg?w=96&h=96&q=82&fit=max&auto=format)Alex Patterson](/author/alex-patterson)