Creare un'estensione Chrome per note Pinterest

Salo Di Salo 5 min di lettura
Creare un'estensione Chrome per note Pinterest

Questo tutorial crea il più piccolo prototipo utile per Chrome con Manifest V3: un'area di testo privata inserita nelle pagine dei Pin, associata all'ID numerico del Pin e salvata in chrome.storage.local. È volutamente un prototipo, non una copia delle vecchie note di Pinterest pronta per la produzione.

Il DOM di Pinterest può cambiare senza preavviso. Isola i selettori, non imitare gli elementi protetti del marchio Pinterest e testa tutti i tipi di pagina e le varianti linguistiche che dichiari di supportare.

1. Crea l'estensione con Manifest V3

Crea una cartella contenente manifest.json e content.js. Il riferimento di Chrome per il manifest è la fonte autorevole per le chiavi disponibili.

{
  "manifest_version": 3,
  "name": "Prototipo contesto Pin",
  "version": "0.1.0",
  "description": "Salva una nota locale privata per un Pin Pinterest.",
  "permissions": ["storage"],
  "content_scripts": [{
    "matches": ["https://*.pinterest.com/*"],
    "js": ["content.js"],
    "run_at": "document_idle"
  }]
}

Il pattern dell'host è ampio perché Pinterest usa la navigazione lato client. Se la funzione supporta meno percorsi o domini nazionali, restringi l'accesso e documenta con precisione tale ambito.

2. Ricava una chiave stabile dall'URL del Pin

Non usare come chiave la posizione di una scheda o il suo titolo visibile. Estrai l'ID numerico da un percorso canonico /pin/…/ e restituisci null in tutti gli altri casi.

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;
  }
}

Testa URL di dettaglio validi, parametri di query, pagine che non contengono un Pin, URL non validi e ogni pattern locale che dichiari di supportare. Non associare mai una nota in silenzio quando l'ID è incerto.

3. Salva un record con versione

Definisci lo schema in modo esplicito per rendere possibili le migrazioni future:

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;
}

Chrome documenta un limite predefinito di 10 MB per storage.local, mentre il permesso separato unlimitedStorage permette di aumentarlo. Chrome precisa inoltre che i dati locali vengono cancellati quando l'estensione viene rimossa. Consulta la versione aggiornata della documentazione dell'API Storage e progetta l'esportazione prima di incoraggiare gli utenti ad affidare dati importanti all'estensione.

4. Inserisci un editor isolato e accessibile

Uno Shadow DOM riduce le collisioni accidentali tra gli stili. L'esempio aggiunge l'editor al corpo della pagina, così non dipende da un fragile nome di classe di Pinterest:

async function mountEditor(pinId) {
  if (document.querySelector('[data-pin-context-root]')) return;

  const host = document.createElement('aside');
  host.dataset.pinContextRoot = '';
  host.setAttribute('aria-label', 'Nota privata del Pin');
  document.body.append(host);

  const root = host.attachShadow({ mode: 'open' });
  const label = document.createElement('label');
  label.textContent = 'Nota privata';
  const editor = document.createElement('textarea');
  editor.id = 'pin-note-editor';
  label.htmlFor = editor.id;
  editor.setAttribute('aria-label', 'Nota privata per questo 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);
}

Inserisci il testo dell'interfaccia con textContent, senza passare contenuti non attendibili a innerHTML. Aggiungi uno stile di focus visibile, contrasto sufficiente, una vera etichetta, accesso da tastiera e un testo di stato che non sposti il focus.

5. Salva senza scrivere a ogni pressione di tasto

function bindAutosave(editor, status, pinId) {
  let saveTimer;
  editor.addEventListener('input', () => {
    status.textContent = 'Non salvata';
    clearTimeout(saveTimer);
    saveTimer = setTimeout(async () => {
      try {
        await writeNote(pinId, editor.value);
        status.textContent = 'Salvata in locale';
      } catch (error) {
        console.error('Salvataggio della nota non riuscito', error);
        status.textContent = 'Impossibile salvare';
      }
    }, 400);
  });
}

In produzione, salva anche le modifiche in sospeso prima di cambiare pagina, impedisci che due schede si sovrascrivano, definisci una dimensione massima per le note e mostra chiaramente gli errori di quota.

6. Gestisci la navigazione lato client di Pinterest

Un gestore eseguito una sola volta al caricamento non rileva i passaggi tra feed e pagina di dettaglio. Usa una funzione di riconciliazione idempotente e osserva i cambiamenti senza reinserire l'editor a ogni mutazione:

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();

Una versione di produzione dovrebbe anche osservare direttamente lo stato della navigazione quando possibile e scollegare gli observer non più necessari. Misura le prestazioni sui feed lunghi: una funzione corretta che rallenta la pagina rimane una cattiva estensione.

7. Rispetta i vincoli di sicurezza di Manifest V3

Manifest V3 vieta il codice eseguibile ospitato da remoto. Includi tutto il JavaScript eseguibile nel pacchetto dell'estensione, conserva la Content Security Policy predefinita salvo una ragione giustificata per modificarla, evita l'esecuzione dinamica di codice e richiedi soltanto i permessi necessari. La panoramica di Chrome su Manifest V3 spiega il modello della piattaforma.

8. Aggiungi le funzioni necessarie a un prodotto reale

9. Testa i casi di errore

  1. Carica l'estensione non pacchettizzata da chrome://extensions.
  2. Visita un feed, una bacheca, la pagina di dettaglio di un Pin e un percorso senza Pin.
  3. Passa da un Pin all'altro senza ricaricare la pagina e verifica che le note rimangano isolate.
  4. Apri lo stesso Pin in due schede e prova la gestione dei conflitti.
  5. Disattiva lo storage o simula il superamento della quota e verifica l'avviso.
  6. Esporta un record di prova, eliminalo e ripristinalo.
  7. Testa la navigazione da tastiera, lo zoom, le etichette per screen reader e le pagine con aspetto chiaro o scuro.

La lezione tecnica

L'area di testo è la parte facile. Un'estensione Pinterest affidabile richiede un'identità stabile, una gestione robusta del ciclo di vita, un'interfaccia accessibile, permessi limitati, uno storage documentato e una via di uscita collaudata. Costruisci queste fondamenta prima di ampliare le funzioni.

Continua a migliorare il tuo sistema Pinterest

Prosegui con la guida più adatta al prossimo passo:

Salo

L'autore

Salo è un product designer e un utente esperto. Scrive di organizzazione digitale, metodi di lavoro su Pinterest e strumenti per pensare meglio.

Prova l'estensione Notestopin per Chrome

Aggiungi note private a qualsiasi Pin, organizzale con i tag e ritrova facilmente ciò che hai salvato.

Aggiungi a Chrome