Chrome's Writer API: Generate Free, On-Device AI Content in Your Extension

AppBooster Team · · 9 min read
Chrome Writer API cover illustration showing on-device AI content generation

Your extension helps users write — reviews, emails, support tickets, bios. They want a “draft this for me” button. You want to ship it without paying per-token cloud bills, without routing private text through a third-party server, and without asking users to paste an API key.

Chrome’s Writer API makes that possible. Starting in Chrome 137, you call Writer.create(), feed it a writing task, and get polished text back — generated on-device by Gemini Nano. No keys. No billing. No data leaving the browser.

If your extension touches user-generated content, this is the AI API you ship next.


Why the Chrome Writer API Matters for Extension Developers

Adding text generation to an extension today means picking your poison:

  • Cloud API (OpenAI, Anthropic) — per-token costs that scale linearly with users
  • Self-hosted model — infrastructure overhead, latency, and a privacy policy rewrite
  • Template-based generation — rigid, robotic output that users immediately recognize as canned

The Writer API eliminates all three. Gemini Nano is shared across Chrome itself — downloaded once, used by every site and extension. Your extension gets free, private, instant content generation with no backend, no billing dashboard, and no privacy disclosure.

The killer feature for extensions: on-device means you can generate drafts based on the user’s Gmail, CRM notes, or internal docs without ever transmitting that data anywhere.


Hardware Requirements: What Your Users Need

Before building, know the minimum specs:

RequirementSpecification
OSWindows 10/11, macOS 13+, Linux, ChromeOS (Chromebook Plus)
Storage22 GB free (model auto-removes if space drops below 10 GB)
RAM16 GB with 4+ cores (CPU) or >4 GB VRAM (GPU)
NetworkUnmetered connection for initial model download
BrowserChrome 137+

Not yet supported: Android, iOS, mobile Chrome, Firefox, Safari, Web Workers.

Pro tip: The Gemini Nano model is shared browser-wide. If another extension or site already triggered the download, your users pay zero install cost.


Quick Start: Generate Text in 3 Steps

1. Check Feature Availability

if (!("Writer" in self)) {
  console.log("Writer API not supported in this browser");
  // Fallback to cloud API or disable feature
}

const availability = await Writer.availability();
// Returns: "available" | "downloadable" | "downloading" | "unavailable"

2. Create a Writer Instance

const writer = await Writer.create();

If the model needs downloading, show progress to the user:

const writer = await Writer.create({
  monitor(m) {
    m.addEventListener("downloadprogress", (e) => {
      console.log(`Downloading AI model: ${Math.round(e.loaded * 100)}%`);
    });
  },
});

3. Generate Content

const draft = await writer.write("Write a professional reply to this customer complaint", {
  context: "The customer is upset about a delayed shipment",
});
console.log(draft);

Three steps. No credentials. No SDK install. No billing page.


Configuration: Control Tone, Format, and Length

The Writer.create() method accepts options that shape the output without prompt engineering:

const writer = await Writer.create({
  tone: "formal",       // "formal" | "neutral" (default) | "casual"
  format: "markdown",   // "markdown" (default) | "plain-text"
  length: "medium",     // "short" (default) | "medium" | "long"
  sharedContext: "This is for a SaaS customer support team",
});
OptionValuesDefaultWhat It Does
toneformal, neutral, casualneutralControls writing style formality
formatmarkdown, plain-textmarkdownOutput format
lengthshort, medium, longshortControls output verbosity
sharedContextAny stringBackground context applied to all .write() calls

sharedContext is your secret weapon. Set it once when creating the writer, and every generation inherits that context without burning tokens repeating it in each prompt.


Real Extension Use Cases

The Writer API isn’t a demo toy. Here’s what you can ship today:

AI Review Drafting

Help users write Chrome Web Store reviews, product reviews, or testimonials:

const writer = await Writer.create({
  tone: "casual",
  length: "medium",
  sharedContext: "Writing a product review for the Chrome Web Store",
});

const review = await writer.write(
  "Write a positive review about a password manager extension that saved me time",
  { context: "The extension auto-fills forms and syncs across devices" }
);

Smart Email Composer

Draft professional emails based on bullet points:

const writer = await Writer.create({
  tone: "formal",
  format: "plain-text",
  length: "medium",
});

const email = await writer.write(
  "Write a follow-up email to a client about a delayed project deliverable",
  { context: "Project was due last Friday. New ETA is next Wednesday. Client is a VP." }
);

Support Ticket Helper

Generate well-structured bug reports from rough user descriptions:

const writer = await Writer.create({
  tone: "neutral",
  format: "markdown",
  length: "long",
  sharedContext: "Generating a support ticket for a web application",
});

const ticket = await writer.write(
  "Create a bug report from this description: login page crashes when I click submit with empty fields"
);

Bio & Introduction Generator

Help users draft professional intros for portfolios or social profiles:

const writer = await Writer.create({
  tone: "casual",
  length: "short",
});

const bio = await writer.write(
  "Write a short professional bio",
  { context: "Software engineer, 5 years experience, specializes in React and Node.js, based in San Francisco" }
);

Streaming Responses for Better UX

For any output longer than a sentence, stream it so users see text appearing in real-time:

const stream = writer.writeStreaming(
  "Write a detailed product comparison",
  { context: "Comparing Notion vs Obsidian for personal knowledge management" }
);

for await (const chunk of stream) {
  outputElement.textContent = chunk;
}

Golden rule: Always stream for medium or long outputs. Users staring at a blank box while AI generates behind the scenes will think your extension froze.


Language Support

The Writer API supports multilingual generation with explicit language configuration:

const writer = await Writer.create({
  expectedInputLanguages: ["en"],        // Input will be in English
  expectedContextLanguages: ["en"],      // Context will be in English
  outputLanguage: "es",                  // Generate output in Spanish
});

const result = await writer.write("Write a welcome message for new users");
// Output will be in Spanish

Use BCP 47 language tags (en, es, fr, ja, vi, etc.). This is cleaner than appending “respond in Spanish” to every prompt.


Reusing Writers and Cleanup

A single Writer instance can generate multiple pieces of content:

const writer = await Writer.create({ tone: "formal", length: "short" });

const intro = await writer.write("Write an introduction for a case study");
const conclusion = await writer.write("Write a conclusion for a case study");
const cta = await writer.write("Write a call-to-action for a case study");

When done, clean up:

writer.destroy();

Always destroy writers when you’re done. Each instance consumes memory. Leak them and your extension will degrade browser performance — earning one-star reviews.

Cancelling In-Progress Generation

const controller = new AbortController();

const writer = await Writer.create({ signal: controller.signal });

// Cancel if user navigates away or clicks "stop"
controller.abort();
writer.destroy();

Access Control: iframes and Cross-Origin

By default, the Writer API is only available in:

  • Top-level windows
  • Same-origin iframes

To enable it in a cross-origin iframe, the parent page must set a Permissions Policy:

<iframe src="https://other-origin.com" allow="writer"></iframe>

Not available in: Web Workers, Service Workers.

For extensions, this mostly matters if your extension injects iframes. Content scripts running in the main page context work fine.


The Graceful Fallback Pattern

Not every user will have Gemini Nano. Here’s the production pattern:

async function generateContent(prompt, context) {
  // Check if Writer API exists
  if (!("Writer" in self)) {
    return fallbackToCloudAPI(prompt, context);
  }

  const availability = await Writer.availability();

  if (availability === "available") {
    const writer = await Writer.create({ tone: "neutral", length: "medium" });
    const result = await writer.write(prompt, { context });
    writer.destroy();
    return result;
  }

  if (availability === "downloadable" || availability === "downloading") {
    // Show download progress to user
    const writer = await Writer.create({
      tone: "neutral",
      length: "medium",
      monitor(m) {
        m.addEventListener("downloadprogress", (e) => {
          showProgressBar(Math.round(e.loaded * 100));
        });
      },
    });
    const result = await writer.write(prompt, { context });
    writer.destroy();
    return result;
  }

  // Hardware doesn't meet requirements — fall back
  return fallbackToCloudAPI(prompt, context);
}

The 86% rule applies here. Most users decide within minutes whether your extension is worth keeping. If the “draft for me” button silently fails with no fallback, you’ve lost them.


Writer vs. Rewriter: When to Use Which

Chrome ships two Writing Assistance APIs. Here’s the split:

ScenarioUse WriterUse Rewriter
Generate text from scratchYes
Rewrite existing user textYes
Draft an email from bullet pointsYes
Make existing text more formalYes
Create a review from a ratingYes
Shorten a long paragraphYes

Rule of thumb: If you’re starting from a blank page, use Writer. If you’re improving existing text, use Rewriter.


Current Status & What’s Next

DetailStatus
API StatusOrigin Trial (Chrome 137–148)
ModelGemini Nano (on-device)
RegistrationChrome Origin Trials
SpecWriting Assistance APIs

The Writer API is in origin trial now — you can ship it to real users today. The API surface may evolve before stable release, so keep your fallback patterns tight and pin your origin trial tokens.

Important: Using the origin trial requires acknowledging Google’s Generative AI Prohibited Uses Policy.


Key Takeaways

  1. Zero cost, zero latency, zero privacy risk — Gemini Nano runs entirely on-device
  2. Three steps from zero to AI-powered content generation in your extension
  3. Built-in tone, format, and length controls — no prompt engineering hacks needed
  4. sharedContext eliminates repetition — set once, apply to every generation
  5. Always implement fallbacks — not every device supports on-device AI yet
  6. Stream long outputs — never leave users staring at a blank box
  7. Clean up writers — memory leaks kill reviews

The Writer API is the easiest path to shipping AI content generation in a Chrome extension. No billing, no backend, no excuses.


Ready to build? Register for the Origin Trial, start generating, and when your AI-powered extension is ready for the Chrome Web Store, AppBooster has the tools to help you launch, optimize, and grow.

Share this article

Build better extensions with free tools

Icon generator, MV3 converter, review exporter, and more — no signup needed.

Related Articles