# Project export: Argus

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 12.0
- Tagline: Argus combines AI, computer vision, and real-time streaming to deliver intelligent, low-latency surveillance with instant threat detection, reporting, and search across all your video networks.
- Devpost: https://devpost.com/software/argus-w6i0pv
- GitHub: https://github.com/GodPuffin/argus
- Video: https://www.youtube.com/embed/enZRqW1eOOM?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Result: winner (Conway: Most Data-Intensive Application; A37: Best Use of A37)
- Team: 4 GitHub contributor(s) — Carson (48 commits), Marcus (43 commits), Claude (1 commits), claude[bot] (1 commits)

## Devpost submission (written by the team)

### Overview

The name itself Argus comes from Argus or Argos Panoptes, a many-eyed giant in Greek mythology who's known for his perpetual vigilance, he served the goddess Hera as a watchman. Felt fitting and was a cool thing to build around! 👀 What does Argus do? Argus is the multi-tool for all your enterprise surveillance needs. 🛰️ Surveillance Input Pipeline: MUX Realtime Live streaming & VOD asset generation using RTMP streaming Supabase Edge Functions sync the MUX data stream Gemini 2.5 Pro Vision Analysis for Event & Anomaly detection off generated VOD assets Roboflow 3.0 Object Detection Computer Vision for generating bounding boxes and tracking entities within streams 🧩 Event Pipeline: Gemini & Roboflow jobs sync with MUX VOD assets creating a event timeline within the viewer & detection display Elasticsearch accessses the Supabase DB through real-time sync and populates the index to allow for semantic searching of events/anomalies Stats are populated based off of Supabase through realtime & the Elasticsearch knowledge base 💬 Interface Pipeline: The AI Chat page accesses all of the available data and allows for direct interaction through various models (Letta Stateful Agent, Kimi K2 Instruct through Groq, Claude 4.5 Sonnet, Claude 4.5 Haiku) Through the Chat interactions, you are able to generate Incident Reports of events & anomalies which are editable through a Tiptap Rich Markdown editor 🧑‍💻

### How we built it

By coding :) 🤓 ⚔️

### Challenges we ran into

Since Argus has so many services, you need to be running at least 4 terminals to host it locally: ngrok server to point MUX webhooks Next.js application Node worker running the workflow services & agents (Gemini, Roboflow, Elasticsearch) Containerized Docker Supabase instance with supabase edge functions ngrok server to point MUX webhooks Next.js application Node worker running the workflow services & agents (Gemini, Roboflow, Elasticsearch) Containerized Docker Supabase instance with supabase edge functions Alongside the terminal suffering, we had to deal with merge conflict misery a few times.... 😭 🏆

### Accomplishments we're proud of

All in all, Argus is the most fleshed out hackathon project we've made so far, it was really satisfying putting it all together and seeing it all work! As someone who's worked in Government IT & Cybersecurity (Carson), it was really cool to create something that has genuine real-world use cases and with some more overall polish could even be shipped as a full tool integrated into security workflows! 🤯

### What we learned

We learnt a lot about many of the tools provided by CalHacks' sponsors! We had a lot of fun tinkering around with each interface and understanding the capabilities, very cool tools and we are looking forward to spending more time working with them in the future! 👁️👁️👁️

### What's next

Hardware integration (into security cameras for example) Enterprise level security Entity tracking across video streams (did Person A walk from Camera 1 to Camera 3?) More automated workflows & agentic pipelines

## README (from the GitHub repository)

# 👁️ Argus

**AI-Powered Real-Time Video Surveillance & Analysis Platform**

> Named after Argos Panoptes, the all-seeing giant from Greek mythology known for his perpetual vigilance.

[![Built at Cal Hacks 12.0](https://img.shields.io/badge/Built%20at-Cal%20Hacks%2012.0-orange)](https://cal-hacks-12-0.devpost.com/)
[![Devpost](https://img.shields.io/badge/Devpost-Project-blue)](https://devpost.com/software/argus-w6i0pv)

---

## 🏆 Awards

**Cal Hacks 12.0 Winner:**
- 🥇 Conway: Most Data-Intensive Application
- 🥇 A37: Best Use of A37

---

## What is Argus?

Argus is a comprehensive surveillance platform that combines AI, computer vision, and real-time streaming to deliver intelligent video monitoring with instant threat detection, automated reporting, and semantic search across all your video networks.

Think of it as the multi-tool for enterprise surveillance needs: from live streaming and object detection to AI-powered incident reports.

---

## ✨ Key Features

### 📹 Real-Time Surveillance
- RTMP-based live video streaming with MUX integration
- Automatic Video-on-Demand (VOD) asset generation
- Multi-camera management and monitoring

### 🤖 AI-Powered Analysis
- **Gemini 2.5 Pro Vision** for event and anomaly detection
- **Roboflow 3.0** for real-time object detection and entity tracking
- **Multi-Model AI Chat** to interface with your surveillance data

### 📊 Smart Data Management
- **Elasticsearch** integration for semantic search across events
- Real-time data sync with Supabase edge functions
- Comprehensive event timeline with detection visualization

### 📝 Automated Reporting
- AI-generated incident reports based on detected events
- Rich markdown editor (Tiptap) for report customization
- Export and share capabilities

---

## 🛠️ Built With

**Core Stack:**
- Next.js, TypeScript, Tailwind CSS
- Supabase (Database, Auth, Edge Functions)
- MUX (Video streaming)
- Elasticsearch

**AI & Computer Vision:**
- Google Gemini 2.5 Pro
- Roboflow 3.0
- Claude 4.5 (Sonnet & Haiku)
- Letta
- Groq (Kimi K2)

**Streaming:**
- RTMP, WebRTC

---

## 👥 Team

- **[Marcus Lee](https://www.marcus-lee.net/)** - Fullstack with focus on backend logic, video processing, and AI capabilities
- **[Carson Spriggs-Audet](https://carsonspriggs.me/)** - Fullstack with focus on frontend and pipelines (Roboflow, stats, entity processing)

---

## 🙏 Acknowledgments

Built at Cal Hacks 12.0 with amazing tools from MUX, Supabase, Google, Anthropic, Roboflow, Elasticsearch, Letta, and Groq.


## Detected evidence (automated analysis)

Indexed codebase: 294 recognized source files, 1554 KB.
- Anthropic (technology) — detected in the code
- CSS (language) — detected in the code
- Google Gemini (technology) — detected in the code
- JavaScript (language) — detected in the code
- Next.js (technology) — detected in the code
- React (technology) — detected in the code
- SQL (language) — detected in the code
- Supabase (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- Vercel AI SDK (technology) — detected in the code
- AI coding agent: Claude Code — evidence: commit authorship or trailers
- AI coding agent: Cursor — evidence: config files committed to the repository
- AI coding agent: GitHub Copilot — evidence: commit authorship or trailers

## Codebase structure (from repository index)

### Files (120 of 317)

```
.cursor/mcp.json
.github/workflows/claude-code-review.yml
.github/workflows/claude.yml
.github/workflows/scour.yml
.gitignore
.npmrc
app/(dashboard)/ai-chat/[id]/chat-client.tsx
app/(dashboard)/ai-chat/[id]/page.tsx
app/(dashboard)/ai-chat/page.tsx
app/(dashboard)/database/page.tsx
app/(dashboard)/debug/page.tsx
app/(dashboard)/jobs/page.tsx
app/(dashboard)/layout.tsx
app/(dashboard)/reports/[id]/page.tsx
app/(dashboard)/reports/page.tsx
app/(dashboard)/search/page.tsx
app/(dashboard)/stats/page.tsx
app/(dashboard)/stream/page.tsx
app/(dashboard)/watch/[id]/not-found.tsx
app/(dashboard)/watch/[id]/page.tsx
app/(dashboard)/watch/page.tsx
app/api/ai-analysis/events/[assetId]/route.ts
app/api/ai-analysis/events/critical/route.ts
app/api/ai-analysis/results/[sourceId]/route.ts
app/api/ai-analysis/search/route.ts
app/api/ai-analysis/stats/route.ts
app/api/assets/[id]/route.ts
app/api/cameras/[id]/route.ts
app/api/cameras/route.ts
app/api/chat/new/route.ts
app/api/chat/route.ts
app/api/detections/route.ts
app/api/live-streams/route.ts
app/api/mux/upload/route.ts
app/api/reports/[id]/route.ts
app/api/reports/route.ts
app/api/search/route.ts
app/api/search/sync/route.ts
app/api/stats/route.ts
app/api/stream/create/route.ts
app/api/stream/delete/route.ts
app/globals.css
app/layout.tsx
app/not-found.tsx
app/onboarding/layout.tsx
app/onboarding/page.tsx
app/page.tsx
biome.json
components.json
components/ai-elements/actions.tsx
components/ai-elements/artifact.tsx
components/ai-elements/asset.tsx
components/ai-elements/branch.tsx
components/ai-elements/canvas.tsx
components/ai-elements/chain-of-thought.tsx
components/ai-elements/connection.tsx
components/ai-elements/context.tsx
components/ai-elements/controls.tsx
components/ai-elements/conversation.tsx
components/ai-elements/edge.tsx
components/ai-elements/event-card.tsx
components/ai-elements/image.tsx
components/ai-elements/inline-citation.tsx
components/ai-elements/loader.tsx
components/ai-elements/message.tsx
components/ai-elements/node.tsx
components/ai-elements/open-in-chat.tsx
components/ai-elements/panel.tsx
components/ai-elements/plan.tsx
components/ai-elements/prompt-input.tsx
components/ai-elements/queue.tsx
components/ai-elements/reasoning.tsx
components/ai-elements/report.tsx
components/ai-elements/response.tsx
components/ai-elements/shimmer.tsx
components/ai-elements/sources.tsx
components/ai-elements/suggestion.tsx
components/ai-elements/task.tsx
components/ai-elements/tool.tsx
components/ai-elements/toolbar.tsx
components/ai-elements/web-preview.tsx
components/app-sidebar.tsx
components/ascii-eye-art.tsx
components/ascii-eye.tsx
components/braille-loader.tsx
components/browser-component.tsx
components/chat-history-dropdown.tsx
components/command-menu.tsx
components/critical-events-monitor.tsx
components/cta-link.tsx
components/database/columns.tsx
components/database/data-table.tsx
components/database/stat-tile.tsx
components/demo/demo-disabled-notice.tsx
components/dither.tsx
components/jobs/columns.tsx
components/landing/braille-bg.tsx
components/landing/feature-shot.tsx
components/landing/pricing-section.tsx
components/landing/section.tsx
components/landing/style-manifest.tsx
components/landing/workflow-pipeline.tsx
components/landing/workflows.tsx
components/mode-toggle.tsx
components/nav-main.tsx
components/onboarding/apply-tool-event.ts
components/onboarding/assembly-sequence.tsx
components/onboarding/collapsible-copilot-panel.tsx
components/onboarding/completion.ts
components/onboarding/composer.tsx
components/onboarding/confirm-launch.tsx
components/onboarding/constants.ts
components/onboarding/copilot-panel.tsx
components/onboarding/editable-list.tsx
components/onboarding/onboarding-hero.tsx
components/onboarding/onboarding-sections.tsx
components/onboarding/onboarding-theme-scope.tsx
components/onboarding/onboarding-types.ts
components/onboarding/onboarding-wizard.tsx
components/onboarding/review-canvas.tsx
[197 more files omitted for size]
```

### Dependencies

- package.json: @ai-sdk/anthropic@^2.0.37, @ai-sdk/groq@^2.0.24, @ai-sdk/mcp@^0.0.1, @ai-sdk/openai-compatible@^1.0.23, @ai-sdk/react@^2.0.79, @base-ui/react@^1.6.0, @biomejs/biome@2.2.0, @dnd-kit/core@^6.3.1, @dnd-kit/modifiers@^9.0.0, @dnd-kit/sortable@^10.0.0, @dnd-kit/utilities@^3.2.2, @elastic/elasticsearch@^9.1.1, @floating-ui/react@^0.27.16, @icons-pack/react-simple-icons@^13.8.0, @letta-ai/vercel-ai-sdk-provider@^1.3.0, @mux/blurup@^1.0.2, @mux/mux-player-react@^3.6.1, @mux/upchunk@^3.5.0, @radix-ui/react-alert-dialog@^1.1.15, @radix-ui/react-avatar@^1.1.10, @radix-ui/react-checkbox@^1.3.3, @radix-ui/react-collapsible@^1.1.12, @radix-ui/react-dialog@^1.1.15, @radix-ui/react-dropdown-menu@^2.1.16, @radix-ui/react-hover-card@^1.1.15, @radix-ui/react-label@^2.1.7, @radix-ui/react-navigation-menu@^1.2.14, @radix-ui/react-popover@^1.1.15, @radix-ui/react-progress@^1.1.7, @radix-ui/react-scroll-area@^1.2.10, @radix-ui/react-select@^2.2.6, @radix-ui/react-separator@^1.1.7, @radix-ui/react-slider@^1.3.6, @radix-ui/react-slot@^1.2.3, @radix-ui/react-switch@^1.1.14, @radix-ui/react-tabs@^1.1.13, @radix-ui/react-toggle@^1.1.10, @radix-ui/react-toggle-group@^1.1.11, @radix-ui/react-tooltip@^1.2.8, @radix-ui/react-use-controllable-state@^1.2.2, @react-three/fiber@^9.4.0, @react-three/postprocessing@^3.0.4, @supabase/supabase-js@^2.75.1, @tabler/icons-react@^3.35.0, @tailwindcss/postcss@^4, @tanstack/react-table@^8.21.3, @tiptap/extension-collaboration@^3.8.0, @tiptap/extension-collaboration-cursor@^2.26.2, @tiptap/extension-highlight@^3.8.0, @tiptap/extension-horizontal-rule@^3.8.0, @tiptap/extension-image@^3.8.0, @tiptap/extension-link@^3.8.0, @tiptap/extension-list@^3.8.0, @tiptap/extension-list-item@^3.8.0, @tiptap/extension-subscript@^3.8.0, @tiptap/extension-superscript@^3.8.0, @tiptap/extension-task-item@^3.8.0, @tiptap/extension-task-list@^3.8.0, @tiptap/extension-text-align@^3.8.0, @tiptap/extension-typography@^3.8.0, @tiptap/extension-underline@^3.8.0, @tiptap/extensions@^3.8.0, @tiptap/html@^3.8.0, @tiptap/pm@^3.8.0, @tiptap/react@^3.8.0, @tiptap/starter-kit@^3.8.0, @types/d3-color@^3.1.3, @types/d3-scale@^4.0.9, @types/d3-scale-chromatic@^3.1.0, @types/lodash.throttle@^4.1.9, @types/node@^20, @types/react@^19, @types/react-dom@^19, @types/react-syntax-highlighter@^15.5.13, @types/ws@^8.18.1, @xyflow/react@^12.9.0, ai@^5.0.79, class-variance-authority@^0.7.1, clsx@^2.1.1, cmdk@^1.1.1, cross-env@^7.0.3, d3-color@^3.1.0, d3-interpolate@^3.0.1, d3-scale@^4.0.2, d3-scale-chromatic@^3.1.0, date-fns@^4.1.0, dotenv-cli@^8.0.0, embla-carousel-react@^8.6.0, framer-motion@^12.23.24, gsap@^3.13.0, lodash.throttle@^4.1.1, lucide-react@^0.546.0, marked@^16.4.1, mini-svg-data-uri@^1.4.4, motion@^12.23.24, nanoid@^5.1.6, next@15.5.5, next-themes@^0.4.6, nodemon@^3.1.10, postprocessing@^6.37.8, react@19.1.0, react-day-picker@^9.11.1, react-dom@19.1.0, react-hotkeys-hook@^5.2.1, react-syntax-highlighter@^16.0.0, recharts@2.15.4, refractor@^5.0.0, sass@^1.93.2, shiki@^3.13.0, sonner@^2.0.7, streamdown@^1.4.0, tailwind-merge@^3.3.1, tailwind-variants@^3.1.1, tailwindcss@^4, three@^0.180.0, tokenlens@^1.3.1, tw-animate-css@^1.4.0, typescript@^5, use-stick-to-bottom@^1.1.1, vaul@^1.1.2, ws@^8.18.3, zod@^4.1.12
- worker/package.json: @ai-sdk/google@^2.0.23, @google/genai@^1.25.0, @supabase/supabase-js@^2.75.1, @types/fluent-ffmpeg@^2.1.27, @types/node@^20, ai@^5.0.76, axios@^1.6.0, dotenv@^16.4.5, dotenv-cli@^8.0.0, fluent-ffmpeg@^2.1.3, tsx@^4.7.0, typescript@^5, zod@^4.1.12

### Recent commits (newest first)

- Merge pull request #15 from GodPuffin/demo-site
- refactor: update scour workflow to fail on error; enhance type definitions and improve report ID generation
- refactor: clean up imports and improve useEffect dependencies; add new animations
- chore(demo-site): WIP quality pass — chart shell + data/onboarding/landing cleanup
- feat(ui): polish ui and format
- Enhance chart components and hooks: add animation support and demo mode handling
- Refactor dashboard components: replace Card with Surface and enhance layout with PageContainer and PageHeader
- Remove obsolete log and state files from .omx directory
- Refactor PricingSection component: update pricing tiers with new structure, add yearly/monthly toggle, and enhance layout
- Add ButtonBrailleBg component to PricingSection: implement fluid noise animation for button background
- Enhance Home and PricingSection components: add ModeToggle to navigation, improve layout, and refine button animations
- Refactor MiniBrailleBg component: enhance density character generation, update grid dimensions, and improve visual variants in PricingSection
- Refactor PricingSection component: update tier names, enhance button styles, and remove loading animations from Home component
- Refactor PricingSection component: update header text, enhance tier styling, and improve button appearance
- Add PricingSection component and integrate it into StyleManifest
- Refactor layout and components: enhance DashboardLayout, add BrailleLoader, and improve SiteHeader styling
- Refactor Home and StyleManifest components: streamline loading animations, enhance layout, and update contributor information
- Enhance layout and styling: add new fonts, refactor BrowserComponent, and update StyleManifest with alternating features; include background images
- Refactor Home component: replace ModelsSection and FeaturesAlternating with StyleManifest; remove unused components
- Update .gitignore and refactor Home component layout in page.tsx

## Key source files (fetched from GitHub, selected and truncated for size)

### package.json

```
{
  "name": "argus",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "nodemon server.js",
    "build": "next build",
    "vercel-build": "next build",
    "start": "dotenv -e .env.prod -- cross-env NODE_ENV=production node server.js",
    "lint": "biome check --write",
    "format": "biome format --write"
  },
  "nodemonConfig": {
    "watch": [
      "server.js"
    ],
    "ignore": [
      "app/**/*",
      ".next/**/*",
      "node_modules/**/*",
      "videos/**/*"
    ],
    "ext": "js"
  },
  "dependencies": {
    "@ai-sdk/anthropic": "^2.0.37",
    "@ai-sdk/groq": "^2.0.24",
    "@ai-sdk/mcp": "^0.0.1",
    "@ai-sdk/openai-compatible": "^1.0.23",
    "@ai-sdk/react": "^2.0.79",
    "@base-ui/react": "^1.6.0",
    "@dnd-kit/core": "^6.3.1",
    "@dnd-kit/modifiers": "^9.0.0",
    "@dnd-kit/sortable": "^10.0.0",
    "@dnd-kit/utilities": "^3.2.2",
    "@elastic/elasticsearch": "^9.1.1",
    "@floating-ui/react": "^0.27.16",
    "@icons-pack/react-simple-icons": "^13.8.0",
    "@letta-ai/vercel-ai-sdk-provider": "^1.3.0",
    "@mux/blurup": "^1.0.2",
    "@mux/mux-player-react": "^3.6.1",
    "@mux/upchunk": "^3.5.0",
    "@radix-ui/react-alert-dialog": "^1.1.15",
    "@radix-ui/react-avatar": "^1.1.10",
    "@radix-ui/react-checkbox": "^1.3.3",
    "@radix-ui/react-collapsible": "^1.1.12",
    "@radix-ui/react-dialog": "^1.1.15",
    "@radix-ui/react-dropdown-menu": "^2.1.16",
    "@radix-ui/react-hover-card": "^1.1.15",
    "@radix-ui/react-label": "^2.1.7",
    "@radix-ui/react-navigation-menu": "^1.2.14",
    "@radix-ui/react-popover": "^1.1.15",
    "@radix-ui/react-progress": "^1.1.7",
    "@radix-ui/react-scroll-area": "^1.2.10",
    "@radix-ui/react-select": "^2.2.6",
    "@radix-ui/react-separator": "^1.1.7",
    "@radix-ui/react-slider": "^1.3.6",
    "@radix-ui/react-slot": "^1.2.3",
    "@radix-ui/react-switch": "^1.1.14",
    "@radix-ui/react-tabs": "^1.1.13",
    "@radix-ui/react-toggle": "^1.1.10",
    "@radix-ui/react-toggle-group": "^1.1.11",
    "@radix-ui/react-tooltip": "^1.2.8",
    "@radix-ui/react-use-controllable-state": "^1.2.2",
    "@react-three/fiber": "^9.4.0",
    "@react-three/postprocessing": "^3.0.4",
    "@supabase/supabase-js": "^2.75.1",
    "@tabler/icons-react": "^3.35.0",
    "@tanstack/react-table": "^8.21.3",
    "@tiptap/extension-collaboration": "^3.8.0",
    "@tiptap/extension-collaboration-cursor": "^2.26.2",
    "@tiptap/extension-highlight": "^3.8.0",
    "@tiptap/extension-horizontal-rule": "^3.8.0",
    "@tiptap/extension-image": "^3.8.0",
    "@tiptap/extension-link": "^3.8.0",
    "@tiptap/extension-list": "^3.8.0",
    "@tiptap/extension-list-item": "^3.8.0",
    "@tiptap/extension-subscript": "^3.8.0",
    "@tiptap/extension-superscript": "^3.8.0",
    "@tiptap/extension-task-item": "^3.8.0",
    "@tiptap/extension-task-list": "^3.8.0",
    "@tiptap/extension-text-align": "^3.8.0",
    "@tiptap/extension-typography": "^3.8.0",
    "@tiptap/extension-underline": "^3.8.0",
    "@tiptap/extensions": "^3.8.0",
    "@tiptap/html": "^3.8.0",
    "@tiptap/pm": "^3.8.0",
    "@tiptap/react": "^3.8.0",
    "@tiptap/starter-kit": "^3.8.0",
    "@types/d3-color": "^3.1.3",
    "@types/d3-scale": "^4.0.9",
    "@types/d3-scale-chromatic": "^3.1.0",
    "@xyflow/react": "^12.9.0",
    "ai": "^5.0.79",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "cmdk": "^1.1.1",
    "d3-color": "^3.1.0",
    "d3-interpolate": "^3.0.1",
    "d3-scale": "^4.0.2",
    "d3-scale-chromatic": "^3.1.0",
    "date-fns": "^4.1.0",
    "embla-carousel-react": "^8.6.0",
    "framer-motion": "^12.23.24",
    "gsap": "^3.13.0",
    "lodash.throttle": "^4.1.1",
    "lucide-react": "^0.546.0",
    "marked": "^16.4.1",
    "mini-svg-data-uri": "^1.4.4",
    "motion": "^12.23.24",
    "nanoid": "^5.1.6",
    "next": "15.5.5",
    "next-themes": "^0.4.6",
    "postprocessing": "^6.37.8",
    "react": "19.1.0",
    "react-day-picker": "^9.11.1",
    "react-dom": "19.1.0",
    "react-hotkeys-hook": "^5.2.1",
    "react-syntax-highlighter": "^16.0.0",
    "recharts": "2.15.4",
    "refractor": "^5.0.0",
    "shiki": "^3.13.0",
    "sonner": "^2.0.7",
    "streamdown": "^1.4.0",
    "tailwind-merge": "^3.3.1",
    "tailwind-variants": "^3.1.1",
    "three": "^0.180.0",
    "tokenlens": "^1.3.1",
    "use-stick-to-bottom": "^1.1.1",
    "vaul": "^1.1.2",
    "ws": "^8.18.3",
    "zod": "^4.1.12"
  },
  "devDependencies": {
    "@biomejs/biome": "2.2.0",
    "@tailwindcss/postcss": "^4",
    "@types/lodash.throttle": "^4.1.9",
    "@types/node": "^20",
    "@types/react": "^19",
    "@types/react-dom": "^19",
    "@types/react-syntax-highlighter": "^15.5.13",
    "@types/ws": "^8.18.1",
    "cross-env": "^7.0.3",
    "dotenv-cli": "^8.0.0",
    "nodemon": "^3.1.10",
    "sass": "^1.93.2",
    "tailwindcss": "^4",
    "tw-animate-css": "^1.4.0",
    "typescript": "^5"
  },
  "packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977"
}

```

### worker/Dockerfile

```
FROM node:20-slim

# Install ffmpeg
RUN apt-get update && \
    apt-get install -y ffmpeg && \
    rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Copy package files
COPY worker/package*.json ./worker/
COPY package*.json ./

# Install dependencies
WORKDIR /app/worker
RUN npm ci --production

# Copy application code
WORKDIR /app
COPY worker ./worker

# Ensure models directory exists and has the ONNX model
RUN mkdir -p ./worker/models

# Run worker
WORKDIR /app/worker
CMD ["npm", "start"]


```

### worker/package.json

```
{
  "name": "ai-analysis-worker",
  "version": "1.0.0",
  "description": "AI Analysis Worker for minute-by-minute video analysis",
  "type": "module",
  "main": "analysis-worker.ts",
  "scripts": {
    "start": "dotenv -e ../.env.prod -- tsx analysis-worker.ts",
    "dev": "tsx watch analysis-worker.ts",
    "monitor": "tsx monitor-queue.ts"
  },
  "dependencies": {
    "@ai-sdk/google": "^2.0.23",
    "@google/genai": "^1.25.0",
    "@supabase/supabase-js": "^2.75.1",
    "ai": "^5.0.76",
    "axios": "^1.6.0",
    "dotenv": "^16.4.5",
    "fluent-ffmpeg": "^2.1.3",
    "zod": "^4.1.12"
  },
  "devDependencies": {
    "@types/fluent-ffmpeg": "^2.1.27",
    "@types/node": "^20",
    "dotenv-cli": "^8.0.0",
    "tsx": "^4.7.0",
    "typescript": "^5"
  }
}

```

### server.js

```javascript
const http = require("http");
const https = require("https");
const { parse } = require("url");
const next = require("next");
const { Server: WebSocketServer } = require("ws");
const child_process = require("child_process");
const url = require("url");
const fs = require("fs");

const port = parseInt(process.env.PORT || "3000", 10);
const hostname = "localhost";
const dev = process.env.NODE_ENV !== "production";

// Initialize Next.js - simpler initialization per Next.js docs
const app = next({ dev });
const handle = app.getRequestHandler();

// HTTPS configuration (optional)
const cert = process.env.CERT_FILE
  ? fs.readFileSync(process.env.CERT_FILE)
  : undefined;
const key = process.env.KEY_FILE
  ? fs.readFileSync(process.env.KEY_FILE)
  : undefined;
const transcode = process.env.SMART_TRANSCODE !== "false";
const httpsOptions = cert && key ? { cert, key } : null;

app.prepare().then(() => {
  // Create HTTP or HTTPS server
  const server = httpsOptions
    ? https.createServer(httpsOptions, (req, res) => {
        const parsedUrl = parse(req.url, true);
        handle(req, res, parsedUrl);
      })
    : http.createServer((req, res) => {
        const parsedUrl = parse(req.url, true);
        handle(req, res, parsedUrl);
      });

  // Start server
  server.listen(port, hostname, (err) => {
    if (err) throw err;
    console.log(
      `> Server listening at http${httpsOptions ? "s" : ""}://${hostname}:${port} as ${
        dev ? "development" : process.env.NODE_ENV
      }`,
    );
  });

  const wss = new WebSocketServer({
    noServer: true,
  });

  // Track active connections
  let connectionCount = 0;
  const activeConnections = new Map();

  // WebSocket send queue configuration
  const WS_BUFFER_THRESHOLD = 1024 * 1024; // 1MB - pause if buffer exceeds this

  // Handle WebSocket upgrade requests
  server.on("upgrade", (request, socket, head) => {
    const pathname = url.parse(request.url).pathname;

    // Only handle our custom streaming WebSocket at /rtmp
    // Let Next.js handle all other WebSocket connections (including HMR)
    if (pathname === "/rtmp") {
      wss.handleUpgrade(request, socket, head, (ws) => {
        wss.emit("connection", ws, request);
      });
    }
    // Don't destroy the socket - let Next.js handle other paths
  });

  wss.on("connection", (ws, req) => {
    const connectionId = ++connectionCount;
    console.log(`\n[Stream #${connectionId}] New connection established`);
    console.log(
      `[Stream #${connectionId}] Total active streams: ${activeConnections.size + 1}`,
    );

    ws.send(JSON.stringify({ type: "connected", connectionId }));

    const queryString = url.parse(req.url).search;
    const params = new URLSearchParams(queryString);
    const baseUrl = params.get("url") ?? "rtmps://global-live.mux.com:443/app";
    const key = params.get("key");
    const format = params.get("format") ?? "webm"; // mp4 or webm
    const video = params.get("video");
    const audio = params.get("audio");

    console.log(
      `[Stream #${connectionId}] Config: format=${format}, video=${video}, audio=${audio}`,
    );
    console.log(
      `[Stream #${connectionId}] Stream key: ${key?.substring(0, 8)}...`,
    );

    const rtmpUrl = `${baseUrl}/${key}`;

    const videoCodec =
      video === "h264" && transcode
        ? ["-c:v", "copy"]
        : // video codec config: low latency, adaptive bitrate
          [
            "-c:v",
            "libx264",
            "-preset",
            "ultrafast",
            "-tune",
            "zerolatency",
            "-threads",
            "0",
          ];

    // Always transcode audio to AAC for RTMP/FLV compatibility
    // Chrome's MP4 MediaRecorder sends Opus (not AAC), Firefox sends Opus
    // RTMP/FLV only supports AAC, MP3, Speex
    const audioCodec = ["-c:a", "aac", "-ar", "44100", "-b:a", "64k"];

    // Build FFmpeg arguments based on format
    const inputFormat = format === "mp4" ? "mp4" : "webm";

    const ffmpegArgs = [
      // Verbose mode for debugging
      "-loglevel",
      "info",

      // Force input format
      "-f",
      inputFormat,

      // Re-timestamp and sync - input flags
      // +genpts: Generate presentation timestamps
      // +igndts: Ignore DTS (decode timestamps) - regenerate them
      // +ignidx: Ignore index (for broken/streaming files)
      // +discardcorrupt: Keep processing even with corrupt frames
      "-fflags",
      "+genpts+igndts+ignidx+discardcorrupt",
      "-avoid_negative_ts",
      "make_zero",

      // Input from stdin
      "-i",
      "pipe:0",

      // force to overwrite
      "-y",

      // Audio sync
      "-async",
      "1",

      ...videoCodec,
      ...audioCodec,

      // RTMP specific flags for stable streaming
      // Increased buffer size from 3000k to 6000k for better stability
      "-bufsize",
      "6000k",
      "-maxrate",
      "3000k",
      "-g",
      "60", // keyframe every 2 seconds at 30fps
      "-sc_threshold",
      "0",

      // Additional buffering for input stability
      "-probesize",
      "10M",
      "-analyzeduration",
      "5M",

      "-f",
      "flv",
      "-flvflags",
      "no_duration_filesize",

      rtmpUrl,
    ];

    console.log(`[Stream #${connectionId}] Starting FFmpeg...`);
    const ffmpeg = child_process.spawn("ffmpeg", ffmpegArgs, {
      // Set high water mark for stdin pipe to buffer more data (default is 16KB)
      // This helps prevent data loss during brief network hiccups
      stdio: ["pipe", "pipe", "pipe"],
    });

    // Increase stdin buffer size to handle bursty data better
    if (ffmpeg.stdin && ffmpeg.stdin.setDefaultEncoding) {
      ffmpeg.stdin.setMaxListeners(0);
    }

    let ffmpegReady = false;
    let bytesReceived = 0;

    // Store connection info
    activeConnections.set(connectionId, {
      ws,
      ffmpeg,
      key,
      startTime: Date.now(),
      bytesReceived: 0,
    });

    // Kill the WebSocket connection if ffmpeg dies.
 
[truncated — 7001 more characters]
```

### app/layout.tsx

```typescript
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { CriticalEventsMonitor } from "@/components/critical-events-monitor";
import { ThemeProvider } from "@/components/theme-provider";
import { Toaster } from "@/components/ui/sonner";

const inter = Inter({
  variable: "--font-inter",
  subsets: ["latin"],
});

export const metadata: Metadata = {
  title: "Argus",
  description:
    "Computer-vision analytics for live and recorded video, with an AI assistant for search and insights.",
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body className={`${inter.variable} antialiased`}>
        <ThemeProvider
          attribute="class"
          defaultTheme="light"
          enableSystem
          disableTransitionOnChange
        >
          {children}
          <Toaster />
          <CriticalEventsMonitor />
        </ThemeProvider>
      </body>
    </html>
  );
}

```

### app/page.tsx

```typescript
"use client";

import Link from "next/link";
import { AsciiEye } from "@/components/ascii-eye";
import { FeatureShot } from "@/components/landing/feature-shot";
import {
  type FeatureItem,
  LandingSections,
} from "@/components/landing/style-manifest";
import { ModeToggle } from "@/components/mode-toggle";
import { Button } from "@/components/ui/button";

const features: Array<{
  title: string;
  description: string;
  url: string;
  src: string;
  alt: string;
}> = [
  {
    title: "Live Dashboard",
    description:
      "Dashboard showcasing all current RTMP streams with automated video asset creation.",
    url: "argus.io/dashboard",
    src: "/assets/argusdash.webp",
    alt: "Argus Dashboard",
  },
  {
    title: "Entity & Event Detection",
    description: "Entity and event detection with AI-powered analysis.",
    url: "argus.io/watch/{asset_id}",
    src: "/assets/argusdetection.webp",
    alt: "Argus Detection",
  },
  {
    title: "Analytics & Statistics",
    description: "Comprehensive stats from all events and anomalies detected.",
    url: "argus.io/stats",
    src: "/assets/argusstats.webp",
    alt: "Argus Statistics",
  },
  {
    title: "Automated Reports",
    description:
      "Auto-generated editable rich incident reports based on detected events.",
    url: "argus.io/reports",
    src: "/assets/argusreports.webp",
    alt: "Argus Reports",
  },
  {
    title: "Elasticsearch Agent",
    description:
      "Search through all detected anomalies and events with powerful Elasticsearch Agent integration.",
    url: "argus.io/search",
    src: "/assets/argussearch.webp",
    alt: "Argus Search",
  },
  {
    title: "AI Assistant",
    description:
      "Search for specific event types, ask questions, generate reports, and more.",
    url: "argus.io/chat",
    src: "/assets/arguschat.webp",
    alt: "Argus Chat",
  },
];

const featuresContent: FeatureItem[] = features.map((feature, i) => ({
  title: feature.title,
  description: feature.description,
  content: (
    <FeatureShot
      url={feature.url}
      src={feature.src}
      alt={feature.alt}
      priority={i === 1}
    />
  ),
}));

export default function Home() {
  return (
    <>
      <div className="fixed top-4 right-4 z-20">
        <ModeToggle />
      </div>

      <main
        id="overview"
        className="w-full bg-background text-foreground scroll-mt-24"
      >
        <div className="min-h-dvh flex flex-col justify-center">
          <div className="max-w-[1500px] mx-auto px-6 sm:px-10 lg:px-12 pt-24 pb-16">
            <div className="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-16 lg:items-center">
              <div className="flex flex-col gap-8">
                <div className="flex flex-col gap-5">
                  <span className="inline-flex w-fit items-center gap-2 border border-border py-1.5 pr-3 pl-1.5 text-[10px] uppercase tracking-widest text-muted-foreground">
                    <span className="relative flex size-1.5 items-center justify-center">
                      <span
                        className="absolute inline-flex size-full rounded-full animate-ping motion-reduce:hidden"
                        style={{ backgroundColor: "var(--linear-success)" }}
                      />
                      <span
                        className="relative size-1.5 rounded-full"
                        style={{ backgroundColor: "var(--linear-success)" }}
                      />
                    </span>
                    Live · real-time surveillance intelligence
                  </span>
                  <h1 className="font-semibold text-5xl sm:text-6xl lg:text-7xl tracking-tight text-balance max-w-[14ch]">
                    The watcher, catalogued.
                  </h1>
                </div>
                <p className="text-lg text-muted-foreground text-pretty max-w-[44ch]">
                  Computer vision, analytics, and an AI assistant — watching
                  your streams so you don&apos;t have to.
                </p>
                <div className="flex flex-wrap items-center gap-3">
                  <Button
                    asChild
                    className="h-auto px-6 py-3 text-white hover:bg-[var(--linear-primary-hover)] transition-colors"
                  >
                    <Link href="/onboarding">
                      Get Started <span aria-hidden>→</span>
                    </Link>
                  </Button>
                  <Button
                    asChild
                    variant="outline"
                    className="h-auto px-6 py-3 transition-colors"
                  >
                    <Link href="/watch">Skip to Dashboard</Link>
                  </Button>
                </div>
              </div>

              <div className="relative aspect-square w-full max-w-[560px] lg:ml-auto">
                <div className="absolute inset-0 border border-border" />

                {/* Targeting brackets */}
                <span
                  aria-hidden
                  className="absolute -top-px -left-px size-4 border-t-2 border-l-2 border-foreground/40"
                />
                <span
                  aria-hidden
                  className="absolute -top-px -right-px size-4 border-t-2 border-r-2 border-foreground/40"
                />
                <span
                  aria-hidden
                  className="absolute -bottom-px -left-px size-4 border-b-2 border-l-2 border-foreground/40"
                />
                <span
                  aria-hidden
                  className="absolute -bottom-px -right-px size-4 border-b-2 border-r-2 border-foreground/40"
                />

                {/* Viewfinder scanline */}
                <div
                  aria-hidden
                  className="pointer-events-none absolute inset-0 overflow-hidden"
                >
                  <div className="absolute inset-x-0 top-0 h-px bg-primary/50 animate-scanline motion-reduce:hi
[truncated — 1061 more characters]
```

### app/onboarding/page.tsx

```typescript
import { OnboardingWizard } from "@/components/onboarding/onboarding-wizard";

export default function OnboardingPage() {
  return <OnboardingWizard />;
}

```

### app/onboarding/layout.tsx

```typescript
import type { Metadata } from "next";
import type { ReactNode } from "react";
import { OnboardingThemeScope } from "@/components/onboarding/onboarding-theme-scope";

export const metadata: Metadata = {
  title: "Set up Argus",
  description:
    "Configure your AI surveillance workspace with the setup copilot.",
};

export default function OnboardingLayout({
  children,
}: {
  children: ReactNode;
}) {
  return (
    <div className="min-h-dvh bg-background text-foreground antialiased">
      <OnboardingThemeScope>{children}</OnboardingThemeScope>
    </div>
  );
}

```

### app/(dashboard)/layout.tsx

```typescript
import { AppSidebar } from "@/components/app-sidebar";
import { CommandMenu } from "@/components/command-menu";
import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";

export default function DashboardLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <SidebarProvider
      className="h-full"
      style={
        {
          "--sidebar-width": "calc(var(--spacing) * 72)",
        } as React.CSSProperties
      }
    >
      <AppSidebar variant="inset" />
      <SidebarInset className="flex min-h-0 flex-1 overflow-hidden">
        {children}
      </SidebarInset>
      <CommandMenu />
    </SidebarProvider>
  );
}

```

### components/tiptap-ui-primitive/button/index.tsx

```typescript
export * from "./button";

```

[284 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]