# Browser Capabilities

Powerful browser APIs that make apps feel like real software. Use these patterns to add persistence, sharing, and rich input/output without any server.

## localStorage Persistence

Auto-save user data so nothing is lost on refresh.

```javascript
// Save on every change
function save(key, data) {
  localStorage.setItem(key, JSON.stringify(data));
}

// Restore on load
function load(key, fallback) {
  try { return JSON.parse(localStorage.getItem(key)) || fallback; }
  catch { return fallback; }
}

// Export/import for portability
function exportData(key) {
  const blob = new Blob([localStorage.getItem(key)], { type: 'application/json' });
  const a = document.createElement('a');
  a.href = URL.createObjectURL(blob);
  a.download = `${key}-backup.json`;
  a.click();
}
```

**When to use:** Any app where users enter data — notes, settings, scores, form state, drawing history. Default to saving automatically, not on explicit "save" button.

## URL-as-State (Shareable Links)

Encode app state in the URL so users can bookmark and share specific results.

```javascript
// Save state to URL hash (no page reload)
function updateURL(state) {
  const params = new URLSearchParams(state);
  history.replaceState(null, '', '#' + params.toString());
}

// Restore state from URL on load
function loadFromURL(defaults) {
  const params = new URLSearchParams(location.hash.slice(1));
  const state = { ...defaults };
  for (const [k, v] of params) state[k] = v;
  return state;
}
```

**When to use:** Calculators, converters, visualizers, color pickers, any tool where the output depends on inputs. User pastes URL -> sees exact same result.

**Examples:** `#expression=2*pi*r`, `#hex=ff6600`, `#text=hello&font=mono`

## Clipboard API

Read and write rich data — not just plain text.

```javascript
// Paste images from clipboard
document.addEventListener('paste', async (e) => {
  for (const item of e.clipboardData.items) {
    if (item.type.startsWith('image/')) {
      const blob = item.getAsFile();
      const url = URL.createObjectURL(blob);
      img.src = url; // display pasted image
    }
  }
});

// Paste HTML/table data (from Excel, Google Sheets)
document.addEventListener('paste', (e) => {
  const html = e.clipboardData.getData('text/html');
  if (html) {
    // Parse table from spreadsheet paste
    const doc = new DOMParser().parseFromString(html, 'text/html');
    const rows = [...doc.querySelectorAll('tr')].map(tr =>
      [...tr.cells].map(td => td.textContent.trim())
    );
  }
});

// Copy rich content
async function copyAsHTML(html) {
  await navigator.clipboard.write([
    new ClipboardItem({ 'text/html': new Blob([html], { type: 'text/html' }) })
  ]);
}
```

**When to use:** Image editors (paste screenshot), data tools (paste from spreadsheet), converters (copy formatted output).

## Drag & Drop with File Reading

Accept files by dragging onto the app.

```javascript
const dropZone = document.getElementById('drop');

dropZone.addEventListener('dragover', (e) => {
  e.preventDefault();
  dropZone.classList.add('drag-over');
});

dropZone.addEventListener('dragleave', () => dropZone.classList.remove('drag-over'));

dropZone.addEventListener('drop', (e) => {
  e.preventDefault();
  dropZone.classList.remove('drag-over');
  for (const file of e.dataTransfer.files) {
    const reader = new FileReader();
    reader.onload = () => processFile(file.name, reader.result);
    if (file.type.startsWith('text/') || file.name.endsWith('.json') || file.name.endsWith('.csv')) {
      reader.readAsText(file);
    } else {
      reader.readAsDataURL(file); // images, binary
    }
  }
});
```

Style the drop zone: dashed border, change color on dragover, show "Drop files here" text.

**When to use:** Any app that processes files — image editors, CSV analyzers, JSON viewers, file converters.

## File Output (Download)

Let users save generated results as files.

```javascript
function downloadFile(filename, content, type = 'text/plain') {
  const blob = new Blob([content], { type });
  const a = document.createElement('a');
  a.href = URL.createObjectURL(blob);
  a.download = filename;
  a.click();
  URL.revokeObjectURL(a.href);
}

// Download text
downloadFile('output.csv', csvString, 'text/csv');

// Download canvas as image
canvas.toBlob(blob => {
  const a = document.createElement('a');
  a.href = URL.createObjectURL(blob);
  a.download = 'image.png';
  a.click();
});
```

**When to use:** Converters, generators, exporters, image editors — any app that produces a result the user wants to keep.

## Combining Patterns

The best utility apps combine several of these:

1. **Input**: Paste from clipboard OR drag file OR type in textarea
2. **Process**: Instant (no submit button), update on every input change
3. **Output**: Display result + Copy button + Download button
4. **Persist**: Auto-save settings/history to localStorage
5. **Share**: Encode state in URL hash

This "paste in, get result, copy out" pattern is the most common and most useful shape for tool apps.