> ## Documentation Index
> Fetch the complete documentation index at: https://docs.drdj.me/llms.txt
> Use this file to discover all available pages before exploring further.

# LinkShot Extension

> Manifest V3 extension for screenshot capture, OCR, and share/link workflows.

Implementation root: `/linkshot-extension`. Marketing page: [`/linkshot`](https://dealdash.tech/linkshot).

## Responsibilities

* capture and annotate screenshots (region, desktop/window, and full-page scrolling capture via `Alt+Shift+F`)
* read view counts DOM-first from the page on TikTok/Instagram/YouTube/Facebook/X, with an optional server-side AI vision pass as a fallback for desktop/full-page shots
* create and manage shareable `drdj.me` links through backend APIs
* write view-check data through the existing DealDash APIs used by the website

## What's new in 1.6.0

* **New brand mark** — the "Marquee Link Badge" icon (dark tile, white chain link, mint capture brackets); store/marketing assets in `store-assets/logos/final/`.
* **Full-page scrolling capture** (`Alt+Shift+F`) — stitches a long page into one tall image. Pure stitch geometry lives in `linkshot-extension/src/lib/fullpagePlan.ts` (unit-tested).
* **DOM-first view detection** — exact counts are read from the page text; the local Tesseract engine was removed from the extension.
* **Provider-agnostic server OCR** — the optional fallback (`server/lib/ocr.ts`) runs on Anthropic, OpenRouter, OpenAI, or any OpenAI-compatible endpoint via `LINKSHOT_OCR_*` env. No provider configured = graceful no-op.
* **Optional "Highlight last opened video"** — outlines the grid tile of the post you last opened so the screenshot shows which post the count belongs to. Off by default; requests site access only when enabled.

## Website Quick View

DealDash surfaces LinkShot data inside the authenticated `/screenshots` page.
The extension keeps writing through its existing APIs; the website organizes
that data for review.

The page has three tabs:

* `Gallery`: screenshots owned by the signed-in user plus team-shared screenshots they can access.
* `LinkShot To-Do`: extension-style view-check cards grouped by `Overdue`, `Due today`, `Upcoming`, and `Completed`.
* `View Logs`: audit rows with checked dates, total views, parsed per-platform views, source URLs, screenshot previews, and ownership context. Owned rows and team-shared rows where the current user is team owner/admin can be corrected on the website; ordinary team-shared rows stay read-only.

The extension should stay lightweight. It captures screenshots, supports quick
To-Do follow-up, copy/open actions, and hidden-item triage. Full search and log
editing belongs on `/screenshots`, which the extension can open through deep
links such as `/screenshots?tab=todo` and
`/screenshots?tab=logs&dealId=...&videoId=...`.

Ownership labels mean:

* `Owned`: the signed-in user owns the screenshot or deal record and can use the existing link, share, and delete actions.
* `Team shared`: the record is visible through team sharing. Team owners/admins can correct shared LinkShot view logs on the website; ordinary shared records stay read-only unless the user owns the underlying screenshot.

Screenshots referenced by a shared deal log only show previews when the user
owns the screenshot or the screenshot was explicitly shared with them. Otherwise
the website shows a redacted attachment count.

## Data Contract

The website quick view reads data from:

* `/api/screenshots?scope=mine-and-shared`
* `/api/deals/due-views?scope=mine-and-shared&includeLogs=true&includeScreenshots=true`
* `/api/deals/view-logs`
* `/api/deals/bulk-import/process` for final bulk-import writes from pasted URL groups

The extension may still preview matches before import, but final bulk-import
writes should use the shared process endpoint. This keeps manual extension
imports aligned with website and agent imports: matched owned deals get new
view-check videos, missing deals require promo codes, and team-shared/read-only
matches are not mutated.

Default read API behavior remains backward compatible with the Chrome
extension. Do not add website-only assumptions to extension read payloads.

For To-Do screenshot context, the extension requests authorized screenshot
summaries from the due-views API and merges them with the screenshot lookup
fallback. Linked proof screenshots can power OCR suggestions and quick attach
even when the secondary lookup returns no rows. Embedded screenshot summaries
are used only when their `videoId` is absent or matches the current To-Do card.

For endpoint details, see [API Surface](../backend/api-surface.mdx).
For MCP/agent access, see [DealDash Agent Bridge Plugin](../internal/dealdash-agent-bridge-plugin.mdx).

## High-Risk Areas

* offscreen/document permissions
* clipboard/file handling security
* auth synchronization with DealDash backend
* shared screenshot and shared deal visibility boundaries
* keeping extension defaults backward compatible

## Auth Persistence

LinkShot stores DealDash auth in extension storage and keeps it across browser
restart, page refresh, sidepanel reopen, temporary network failure, and
temporary website hydration gaps. The website content script must not clear
extension auth only because DealDash localStorage is briefly empty. Auth is
cleared only by explicit website logout through the same-origin
`DEALDASH_EXTENSION_LOGOUT` event or explicit logout from inside the extension
settings UI. Background auth mutation messages are accepted only from known
DealDash dashboard origins or from the extension itself.

API calls that receive a 401 ask the background worker to refresh auth and retry
once with the refreshed token. Refresh failure or network failure does not erase
saved auth; the UI may show reconnect state while keeping the stored session.

## Change Workflow

```bash theme={null}
cd /linkshot-extension
pnpm install
pnpm build
```

Website-only LinkShot visibility and editing work belongs in the main DealDash
app, not in `/linkshot-extension`, unless the extension data-writing contract
itself needs to change.

## Design Contract

* LinkShot uses the DealDash green / WhatsApp-like palette:
  `#111b21`, `#202c33`, `#233138`, and primary `#1a7a5e`.
* Do not introduce black/blue primary styling into LinkShot.
* Keep normal controls compact and rectangular: 6-8px radius for buttons, tabs,
  cards, inputs, and chips. Avoid large capsule controls in the sidepanel.
* Required extension actions must remain present: copy, capture, attach/edit
  screenshots, annotate, bulk import, history, sync/auth, To-Do, hidden-item
  management, and open-in-DealDash links.
* Hidden management must be non-destructive. Viewing hidden items must not
  restore them unless the user explicitly chooses restore.
* OCR suggestions are assistive. Manual view entry remains the source of truth.
* Saving LinkShot view proof is gated: every platform row with entered views
  must have screenshot proof, and every attached screenshot row must have
  views. Any row with views or screenshot proof must also have a source URL.
  Missing source URLs are shown explicitly instead of blank clickable rows.
  The proof-complete badge uses the same source URL requirement, so saved views
  plus screenshots cannot appear complete when the source post/video is missing.
  When DealDash has both profile URLs and post/video URLs for a platform, the
  extension opens the direct post/video URL in the proof row. Saved view-log
  `sourceUrl` values keep that source post/video URL; screenshot proof links
  stay in structured `screenshotUrls` metadata.

## Validation

* screenshot capture works on supported pages
* OCR behavior is deterministic and does not leak data
* generated links resolve correctly through `/r/*`
* permission scope is justified and reviewed
* `/screenshots` tabs show owned and authorized team-shared records only
* owned view logs and team-shared logs managed by the current team owner/admin can be corrected on the website
* ordinary team-shared view logs are read-only and redact unauthorized screenshot attachments
* the extension does not save incomplete LinkShot proof when views or
  screenshots are missing for a platform row
* the extension does not save LinkShot proof rows that have views or screenshot
  proof but no source URL
* the extension does not label saved proof complete while the source URL is
  missing
* saved LinkShot view logs keep the source post/video URL separate from
  screenshot proof URLs
