Chrome Extension Storage Quickstart — Developer Guide

4 min read

Storage Quickstart

Overview

Brief intro: @theluckystrike/webext-storage gives you a fully-typed wrapper around chrome.storage with schema validation, default values, and reactive watchers.

Install

npm install @theluckystrike/webext-storage

Step 1: Define a Schema

Use defineSchema() to declare keys with their default values. TypeScript infers the types automatically.

import { defineSchema } from "@theluckystrike/webext-storage";

const schema = defineSchema({
  theme: "dark" as "dark" | "light",
  fontSize: 14,
  notifications: true,
  blockedSites: [] as string[],
});

Explain that defineSchema() is an identity function — it just returns what you pass in, but enables TypeScript inference.

Step 2: Create a Storage Instance

Use createStorage() with your schema. Explain the area option (“local” vs “sync”).

import { createStorage } from "@theluckystrike/webext-storage";

const storage = createStorage({ schema, area: "local" });

Mention that under the hood this creates a TypedStorage<S> instance.

Step 3: Reading Values

Single key — get(key)

const theme = await storage.get("theme");
// Returns "dark" (the default) if nothing stored yet

Multiple keys — getMany(keys)

const { theme, fontSize } = await storage.getMany(["theme", "fontSize"]);

All keys — getAll()

const all = await storage.getAll();
// { theme: "dark", fontSize: 14, notifications: true, blockedSites: [] }

Explain that get() returns the schema default if the key hasn’t been set.

Step 4: Writing Values

Single key — set(key, value)

await storage.set("theme", "light");
// Type error: await storage.set("theme", 42);

Multiple keys — setMany(items)

await storage.setMany({ theme: "light", fontSize: 16 });

Explain runtime validation: validateType() checks values match the schema’s expected typeof.

Step 5: Removing Values

Single — remove(key)

await storage.remove("theme");
// Next get("theme") returns "dark" (the schema default)

Multiple — removeMany(keys)

await storage.removeMany(["theme", "fontSize"]);

All schema keys — clear()

await storage.clear();

Note: clear() only removes keys in YOUR schema, not all of chrome.storage.

Step 6: Watching for Changes

Use watch(key, callback) to react to storage changes. Returns an Unwatch function.

const unwatch = storage.watch("theme", (newValue, oldValue) => {
  console.log(`Theme changed: ${oldValue} -> ${newValue}`);
  document.body.className = newValue;
});

// Later:
unwatch();

Explain: uses chrome.storage.onChanged.addListener under the hood, filtered by area and key.

Step 7: Complete Example — Options Page

Full realistic example combining all methods in an options page scenario.

API Reference Summary

Method Signature Returns
get get<K>(key: K) Promise<S[K]>
getMany getMany<K>(keys: K[]) Promise<Pick<S, K>>
getAll getAll() Promise<SchemaType<S>>
set set<K>(key: K, value: S[K]) Promise<void>
setMany setMany(items: Partial<S>) Promise<void>
remove remove<K>(key: K) Promise<void>
removeMany removeMany<K>(keys: K[]) Promise<void>
clear clear() Promise<void>
watch watch<K>(key: K, cb: WatchCallback<S[K]>) Unwatch

Next Steps

Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.

No previous article
No next article