Architecture
System Overview
Blincr is a co-browsing platform built on Cloudflare Workers. Users install a Chrome extension that captures browsing trails (navigation, clicks, scrolls, selections, clipboard, overlays) and syncs them to a backend that coordinates real-time sessions and persists data.
Component Map
┌─────────────────────────────────────┐
│ Chrome Extension (MV3) │
│ ├── content.ts event capture │
│ ├── background.ts session relay │
│ ├── popup.ts controls/tabs │
│ ├── sidepanel.ts trail replay │
│ ├── trail-db.ts IndexedDB store │
│ └── plugins/ overlay system │
│ ├── overlay-manager.ts │
│ └── comment.ts │
└────────────┬────────────────────────┘
│ HTTP / WebSocket
┌────────────▼────────────────────────┐
│ Cloudflare Worker (workers/app.ts) │
│ ├── React Router SSR (dashboard) │
│ ├── /api/* REST endpoints │
│ ├── /mcp MCP server (agents) │
│ └── /session/* DO proxy │
└──┬──────────┬──────────┬────────────┘
│ │ │
┌──▼──┐ ┌───▼───┐ ┌───▼────┐
│ D1 │ │ R2 │ │ DO │
│AUDIT│ │TRAILS │ │SESSION │
│ _DB │ │SNAPS │ │COORD. │
└─────┘ └───────┘ └────────┘
Data Flow
- Event capture — Content script intercepts DOM events (click, scroll,
navigation, selection, clipboard) and sends them via
chrome.runtime.sendMessageto the background service worker. - Local storage — Background worker writes events to IndexedDB (
blincr-trailsdatabase) viatrail-db.ts. Trails are available offline. - Session relay — When a live session is active, the background worker
forwards events over a WebSocket to the
SessionCoordinatorDurable Object, which broadcasts to all participants. - Cloud sync — Authenticated users can upload trails to D1 (
cloud_trailstable) with R2 storage for the full event payload. - Dashboard — React Router app served by the same worker renders trails, audit logs, live sessions, and account settings.
Storage
| Binding | Service | Purpose |
|---|---|---|
AUDIT_DB |
D1 | Users, sessions, credentials, audit log |
SESSION_SNAPSHOTS |
R2 | Trail JSON snapshots (trails/{id}.json) |
SESSION_COORDINATOR |
DO | Real-time WebSocket session state (SQLite) |
Blincrs (standing page watchers)
A blincr is a watcher pinned to a page: it periodically re-fetches the page, extracts a value (CSS text, JSON-LD field, or regex), and alerts the owner when the value changes / crosses a threshold / appears / disappears.
blincr-watch-worker(separate deployment,watch-worker/) runs on a*/5 * * * *cron. Each tick selects due blincrs (next_check_at <= now, one hit per domain per run for politeness), honorsrobots.txt, extracts viaHTMLRewriter, compares againstlast_value, and on a crossing writes ablincr_alertsrow + anotificationsrow (kind='blincr_alert', "The trail blinked") with a per-blincr cooldown. Five consecutive failures flag the blincrsight_lostand pause it.- Shared pure logic (extractors, comparators, robots parsing) lives in
src/blincr-engine.ts(unit-tested, no bindings) so both workers reuse it. - The main worker owns CRUD:
src/blincrs.ts+/api/user/blincrs*routes, with per-plan quotas resolved throughsrc/entitlements.ts(ARC). - Separation rationale: MASTER-PLAN §3.2 — scheduled fetch fan-out runs on its own trigger and must not compete with interactive traffic.
Deployment
- Worker:
npm run deploy→wrangler deploy workers/deploy-entry.ts(prebuilt dist entry).wrangler.jsoncmainpoints atworkers/app.ts(virtual RR build) soreact-router devhot-reloads route loaders; the deploy/preview scripts override the entry on the command line. - Watch worker:
wrangler deploy -c watch-worker/wrangler.jsonc - Dev:
wrangler dev(useswrangler.jsonc) - Extension:
cd extension && node build.js(esbuild, outputs toextension/dist/) - Domain:
blincr.com(Cloudflare custom domain)