Point any camera. Describe what to watch for in plain English. Get a webhook when it happens.
$ sightline monitor --watcher front-door
Initializing camera feed...
Agent online. Watching for: "package at door"
[00:00:03] Frame captured. Analyzing... No detection (0.12)
[00:00:18] Frame captured. Analyzing... No detection (0.08)
[00:00:33] Frame captured. Analyzing...
[00:00:33] DETECTED: Package visible at door (0.94)
[00:00:33] Triggering alert → Zapier webhook
[00:00:33] Action sent successfully
- Truly bring-your-own-key. Users paste their OpenAI key once; it lives in
localStorageand is forwarded as anx-openai-keyheader on each scan. The server never stores, logs, hashes, or fingerprints it — and runs with no fallback key, so the privacy guarantee is enforced by absence, not policy. - Browser-first agent loop. Instead of a server-side scheduler with uploaded media streams, the loop lives in the browser:
getUserMedia+setInterval+ a passthrough endpoint. Removes an entire class of infrastructure (queues, workers, blob storage) without sacrificing UX. - Type-safe vision output. The detection schema is a Zod object passed to AI SDK's
Output.object(), so the model returns a typed{ detected, confidence, reason, objects_found, suggested_action }— no string parsing, no JSON repair. - A real multi-device UX. Since keys don't sync, a returning user on a new browser would see "Add your key" — same as a brand-new signup. One server-side boolean (
byok_initialized) switches between "Welcome" and "Welcome back" copy. One bit on disk, zero key material leaked. - Single AI chokepoint. Every model call goes through
app/api/analyzewith a typed error taxonomy (invalid_key,quota_exceeded,rate_limited, …). Swapping providers or adding caching is a one-file change.
flowchart LR
A[Camera frame] --> B[GPT-4o vision]
B --> C{Condition met?}
C -- yes, above threshold --> D[Webhook fires]
C -- no --> A
D --> A
Every N seconds, Sightline captures a frame, asks a vision model whether your condition is met, and — if it is — fires a Zapier webhook. SMS, Slack, WhatsApp, any of 6,000+ apps.
| Home | Office | Anywhere |
|---|---|---|
| Package delivered at the door | Whiteboard has new content | Parking spot becomes empty |
| Baby wakes up in the crib | Person in a restricted area | Plant needs watering |
| Car arrives in the driveway | Meeting room is empty | Pet near the food bowl |
If you can describe it, Sightline can detect it.
Sightline doesn't pay for inference. You supply your own OpenAI key, and we get out of the way.
The promise: your key lives in this browser's
localStorageand nowhere else. It is sent as a header on each scan, used once, and discarded. We never store it, log it, hash it, or fingerprint it.
sequenceDiagram
autonumber
participant B as Browser
participant S as Sightline server
participant O as OpenAI
Note over B: Key in localStorage
B->>S: POST /api/analyze<br/>(x-openai-key header)
Note over S: Header read once.<br/>Never stored, never logged.
S->>O: Vision request<br/>(Authorization: Bearer)
O-->>S: Detection result
S-->>B: Result
- Storage: browser
localStorageonly. Cleared automatically on sign-out. - Cost: roughly $0.01 per scan with
gpt-4o-mini. OpenAI bills you directly — we never see the charge. - Per-device: add the key once on each browser or device you use Sightline from. We don't sync.
- Validation: every saved key is verified against OpenAI before it lands in storage.
The only server-side signal we keep is a one-way byok_initialized boolean per user — used solely to choose between "first-time" and "welcome back" onboarding copy. No key material, no fingerprint, no device info.
npm install
npm run devRequired environment variables (Supabase only):
NEXT_PUBLIC_SUPABASE_URL=...
NEXT_PUBLIC_SUPABASE_ANON_KEY=...Then run the SQL files in scripts/ against your Supabase project, in order:
scripts/001_create_schema.sql Core tables (watchers, snapshots, ...)
scripts/002_add_webhook_url.sql Zapier webhook column
scripts/003_create_user_settings.sql BYOK onboarding flag
Open http://localhost:3000, sign up, paste your OpenAI key in Settings, and deploy your first agent.
Note: No
OPENAI_API_KEYis needed server-side. Users supply their own at runtime. If you previously set one, remove it — it's no longer read, and its absence is part of the privacy guarantee.
┌─────────────────────────────────────────────────────────────────┐
│ Browser │
│ │
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────────┐ │
│ │ Camera │───▶│ Monitor │───▶│ localStorage: │ │
│ │ (getUM) │ │ loop │ │ sightline. │ │
│ └─────────────┘ │ (setIntv) │ │ openai_key.v1 │ │
│ └──────┬───────┘ └────────┬─────────┘ │
└─────────────────────────────┼─────────────────────┼─────────────┘
│ │
POST /api/analyze (x-openai-key header)
│ │
┌─────────────────────────────▼─────────────────────▼─────────────┐
│ Next.js API routes │
│ │
│ /api/analyze /api/validate-key /api/byok/initialized │
└──────────┬───────────────────┬──────────────────┬───────────────┘
│ │ │
▼ ▼ ▼
OpenAI API OpenAI API Supabase
(vision) (key check) (RLS-scoped)
| Layer | Tools |
|---|---|
| Framework | Next.js 16 · React 19 · TypeScript (strict) |
| Styling | Tailwind CSS 4 · Radix UI · lucide-react |
| Backend | Supabase (auth, Postgres, RLS) |
| AI | AI SDK 6 · @ai-sdk/openai · GPT-4o-mini vision |
| Deploy | Vercel |
app/
(dashboard)/
dashboard/ Command Center
monitor/[id]/ Live camera + agent loop
watchers/ CRUD for detection rules
alerts/ Triggered detections
settings/ BYOK management
api/
analyze/ Scan endpoint (consumes the user's key)
validate-key/ Pre-save key validator
byok/initialized/ Flips the onboarding flag
components/
byok-*.tsx BYOK UI surfaces (provider, settings, banner, chip)
monitor-client.tsx The agent loop component
watcher-*.tsx Watcher CRUD
lib/
byok.ts Key storage + per-device meta
use-byok.ts React hook (useSyncExternalStore)
supabase/ Server + browser clients
scripts/ SQL migrations (run in order)
- OpenAI key: browser-local only. Never in the database, logs, or analytics.
- Row Level Security: every table is RLS-scoped; users can only read or write their own rows.
- Webhooks: user-configured per watcher. We forward the documented payload to your URL and nothing else.
- Transport: HTTPS only, via Vercel.
This repository is linked to a v0 project. Every merge to main deploys automatically.
Built for the v0 + MCP Hackathon