In diesem Tutorial entwickeln Sie einen möglichst kleinen, aber brauchbaren Prototyp auf Basis von Chrome Manifest V3: Auf Pin-Seiten erscheint ein privates Textfeld, dessen Inhalt über die numerische Pin-ID zugeordnet und in chrome.storage.local gespeichert wird. Das Beispiel ist bewusst nur ein Prototyp und kein produktionsreifer Nachbau der früheren Pinterest-Notizen.
Pinterest kann sein DOM jederzeit und ohne Ankündigung ändern. Kapseln Sie deshalb alle Selektoren, ahmen Sie keine geschützten Markenelemente von Pinterest nach und testen Sie sämtliche unterstützten Seitentypen sowie Sprach- und Regionsvarianten.
1. Die Manifest-V3-Erweiterung anlegen
Legen Sie einen Ordner mit manifest.json und content.jsan. Die Manifest-Referenz von Chrome führt die verfügbaren Schlüssel verbindlich auf.
{
"manifest_version": 3,
"name": "Pin-Kontext-Prototyp",
"version": "0.1.0",
"description": "Speichert eine private lokale Notiz zu einem Pinterest-Pin.",
"permissions": ["storage"],
"content_scripts": [{
"matches": ["https://*.pinterest.com/*"],
"js": ["content.js"],
"run_at": "document_idle"
}]
}
Das Host-Muster ist weit gefasst, weil Pinterest innerhalb der Seite navigiert, ohne sie vollständig neu zu laden. Unterstützt Ihre Funktion nur bestimmte Routen oder länderspezifische Domains, grenzen Sie den Zugriff entsprechend ein und dokumentieren Sie diesen Umfang.
2. Einen stabilen Schlüssel aus der Pin-URL ableiten
Verknüpfen Sie Notizen weder mit der Position einer Karte noch mit ihrem sichtbaren Titel. Lesen Sie stattdessen die numerische ID aus einem kanonischen /pin/…/ -Pfad aus und geben Sie andernfalls null zurück.
function getPinId(url = location.href) {
try {
const { pathname } = new URL(url);
const match = pathname.match(/\/pin\/(\d+)\/?/);
return match ? match[1] : null;
} catch {
return null;
}
}
Testen Sie gültige Pin-Detail-URLs, URLs mit Abfrageparametern, Seiten ohne Pin, fehlerhafte URLs und die URL-Muster aller Sprach- und Regionsvarianten, die Sie offiziell unterstützen. Ordnen Sie niemals stillschweigend eine Notiz zu, wenn die ID nicht eindeutig feststeht.
3. Einen versionierten Datensatz speichern
Definieren Sie das Schema ausdrücklich, damit spätere Migrationen möglich bleiben:
async function readNote(pinId) {
const key = 'pin-note:' + pinId;
const result = await chrome.storage.local.get(key);
return result[key] ?? { version: 1, pinId, text: '', updatedAt: null };
}
async function writeNote(pinId, text) {
const key = 'pin-note:' + pinId;
const record = {
version: 1,
pinId,
text,
updatedAt: new Date().toISOString()
};
await chrome.storage.local.set({ [key]: record });
return record;
}
Für storage.localgelten laut Chrome standardmäßig 10 MB. Mit der gesonderten unlimitedStorage -Berechtigung lässt sich dieses Limit aufheben. Chrome weist außerdem darauf hin, dass der lokale Erweiterungsspeicher beim Entfernen der Erweiterung gelöscht wird. Lesen Sie die aktuelle Dokumentation der Storage API und planen Sie eine Exportfunktion ein, bevor Nutzer wichtige Daten in der Erweiterung ablegen.
4. Einen gekapselten, barrierefreien Editor einbinden
Ein Shadow DOM verringert unbeabsichtigte Konflikte mit den Seitenstilen. Das Beispiel hängt den Editor direkt an den Seiteninhalt an und ist dadurch nicht von einem störanfälligen Pinterest-Klassennamen abhängig:
async function mountEditor(pinId) {
if (document.querySelector('[data-pin-context-root]')) return;
const host = document.createElement('aside');
host.dataset.pinContextRoot = '';
host.setAttribute('aria-label', 'Private Pin-Notiz');
document.body.append(host);
const root = host.attachShadow({ mode: 'open' });
const label = document.createElement('label');
label.textContent = 'Private Notiz';
const editor = document.createElement('textarea');
editor.id = 'pin-note-editor';
label.htmlFor = editor.id;
editor.setAttribute('aria-label', 'Private Notiz zu diesem Pin');
const status = document.createElement('span');
status.setAttribute('role', 'status');
const saved = await readNote(pinId);
editor.value = saved.text;
root.append(label, editor, status);
bindAutosave(editor, status, pinId);
}
Weisen Sie Text in der Bedienoberfläche über textContentzu und übergeben Sie nicht vertrauenswürdige Inhalte niemals an innerHTML. Ergänzen Sie gut sichtbare Fokusmarkierungen, ausreichenden Kontrast, eine echte Beschriftung, vollständige Tastaturbedienung und Statustext, der den Fokus nicht an sich zieht.
5. Speichern, ohne bei jedem Tastenanschlag zu schreiben
function bindAutosave(editor, status, pinId) {
let saveTimer;
editor.addEventListener('input', () => {
status.textContent = 'Nicht gespeichert';
clearTimeout(saveTimer);
saveTimer = setTimeout(async () => {
try {
await writeNote(pinId, editor.value);
status.textContent = 'Lokal gespeichert';
} catch (error) {
console.error('Pin-Notiz konnte nicht gespeichert werden', error);
status.textContent = 'Speichern fehlgeschlagen';
}
}, 400);
});
}
In einer Produktionsversion sollten Sie ausstehende Eingaben vor einem Seitenwechsel noch speichern, das gegenseitige Überschreiben durch zwei Tabs verhindern, eine maximale Notizgröße festlegen und Fehler wegen überschrittener Speicherlimits sichtbar melden.
6. Pinterests clientseitige Navigation berücksichtigen
Ein Handler, der nur einmal beim Laden ausgeführt wird, erfasst Wechsel zwischen Feed und Detailansicht nicht. Verwenden Sie eine idempotente Abgleichsfunktion und beobachten Sie Änderungen, ohne den Editor bei jeder DOM-Mutation neu einzubinden:
let scheduled = false;
async function reconcile() {
scheduled = false;
const pinId = getPinId();
const existing = document.querySelector('[data-pin-context-root]');
if (!pinId) {
existing?.remove();
return;
}
if (existing?.dataset.pinId === pinId) return;
existing?.remove();
await mountEditor(pinId);
const mounted = document.querySelector('[data-pin-context-root]');
if (mounted) mounted.dataset.pinId = pinId;
}
new MutationObserver(() => {
if (scheduled) return;
scheduled = true;
requestAnimationFrame(reconcile);
}).observe(document.documentElement, { childList: true, subtree: true });
reconcile();
Eine Produktionsversion sollte den Navigationszustand nach Möglichkeit auch direkt überwachen und nicht mehr benötigte Observer trennen. Messen Sie die Laufzeit in langen Feeds: Auch eine fachlich korrekte Funktion ist schlecht umgesetzt, wenn sie die Seite spürbar verlangsamt.
7. Die Sicherheitsvorgaben von Manifest V3 einhalten
Manifest V3 verbietet remote gehosteten ausführbaren Code. Liefern Sie sämtliches ausführbares JavaScript im Erweiterungspaket mit, behalten Sie die standardmäßige Content Security Policy bei, sofern eine Änderung nicht sachlich begründet ist, vermeiden Sie dynamische Codeausführung und fordern Sie nur die tatsächlich benötigten Berechtigungen an. Die Übersicht zu Manifest V3 von Chrome erläutert das Plattformmodell.
8. Funktionen für ein verlässliches Produkt ergänzen
- JSON-Export und -Import mit Schemavalidierung und Konfliktbehandlung;
- ein menschenlesbarer Export für die Wiederherstellung;
- Suche und optionale Tags;
- Anzeige der Speichernutzung und des verfügbaren Limits;
- Löschen einzelner Notizen sowie sämtlicher Daten;
- eine Datenschutzerklärung, die dem beobachtbaren Verhalten entspricht;
- Migrationstests zwischen den Schemaversionen;
- klare Warnungen vor Datenverlust bei Deinstallation oder fehlender Synchronisierung;
- Fehlertelemetrie nur mit konsequenter Datenminimierung und transparenter Offenlegung.
9. Fehlerfälle gezielt testen
- Laden Sie die entpackte Erweiterung über
chrome://extensions. - Rufen Sie einen Feed, eine Pinnwand, eine Pin-Detailseite und eine Route ohne Pin auf.
- Wechseln Sie ohne vollständiges Neuladen zwischen zwei Pins und prüfen Sie, ob deren Notizen sauber getrennt bleiben.
- Öffnen Sie denselben Pin in zwei Tabs und testen Sie das Verhalten bei konkurrierenden Änderungen.
- Deaktivieren Sie den Speicherzugriff oder simulieren Sie ein überschrittenes Speicherlimit und prüfen Sie die Warnmeldung.
- Exportieren Sie einen Testdatensatz, löschen Sie ihn und stellen Sie ihn anschließend wieder her.
- Testen Sie Tastaturbedienung, Zoom, Screenreader-Beschriftungen sowie Seiten im hellen und dunklen Farbschema.
Die technische Kernbotschaft
Das Textfeld ist der einfache Teil. Eine vertrauenswürdige Pinterest-Erweiterung braucht eine stabile Zuordnung, robuste Behandlung des Seitenlebenszyklus, eine barrierefreie Oberfläche, eng begrenzte Berechtigungen, dokumentierte Speicherung und einen erprobten Weg zum Datenexport. Schaffen Sie diese Grundlagen, bevor Sie den Funktionsumfang erweitern.
Bauen Sie Ihr Pinterest-System weiter aus
Lesen Sie als Nächstes den passenden Leitfaden:
Notestopin für Chrome ausprobieren
Füge jedem Pin private Notizen hinzu, ordne sie mit Tags und finde deine gespeicherten Inhalte später schnell wieder.
Zu Chrome hinzufügen