YAML Metadata Warning:empty or missing yaml metadata in repo card

Check out the documentation for more information.

PixelStream πŸ–₯️➑️🌐

A mini "TeamViewer for a browser". You open a web UI, hit Start Browser, and a headless Chromium running inside a Docker container streams its screen back to your browser in real time. You can click, scroll, type, and navigate β€” and it all happens inside that remote headless browser...........


How it works

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   click / scroll / type (WebSocket)   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   CDP    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Web UI      β”‚  ───────────────────────────────────► β”‚  Node backend β”‚ ───────► β”‚ Headless Chromium β”‚
β”‚ (Next.js)    β”‚                                        β”‚  (ws + CDP)   β”‚          β”‚   (Puppeteer)     β”‚
β”‚  <canvas>    β”‚  ◄─────────────────────────────────── β”‚               β”‚ ◄─────── β”‚                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜     live JPEG frames (WebSocket)       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ screencast β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  • Frontend (/frontend) β€” Next.js app. A <canvas> paints the live frames; mouse/keyboard/scroll events are captured, converted to real browser coordinates, and sent over a WebSocket.
  • Backend (/backend) β€” Node.js + ws + Puppeteer. Launches Chromium, uses the Chrome DevTools Protocol (CDP) Page.startScreencast to get a continuous stream of JPEG frames, and injects input via Input.dispatchMouseEvent / Input.dispatchKeyEvent.
  • Docker β€” both services run in containers via docker compose. The backend uses the official Puppeteer image (Chromium + system deps preinstalled).

Why CDP screencast (not a screenshot loop)?

Page.startScreencast only emits a frame when the page actually changes, and it's much smoother and lower-latency than taking page.screenshot() on a timer.


Run it

Option A β€” Docker (recommended)

docker compose up --build

Then open http://localhost:3000 and click Start Browser.

Option B β€” Local (no Docker, for fast iteration)

# terminal 1
cd backend && npm install && npm start      # ws server on :8080

# terminal 2
cd frontend && npm install && npm run dev    # UI on :3000

Deploy (Frontend β†’ Vercel, Backend β†’ Render)

⚠️ The browser page is served over HTTPS (Vercel), so it can only open a secure WebSocket (wss://). Render gives you an https://…onrender.com URL, whose WebSocket endpoint is wss://…onrender.com. Plain ws:// will be blocked as mixed content.

1. Backend on Render

  • New Web Service β†’ connect this repo.
  • Runtime: Docker, Dockerfile path: backend/Dockerfile, context: backend (or just use the included render.yaml Blueprint).
  • Deploy. Note the URL, e.g. https://pixelstream-backend.onrender.com.
  • Render injects PORT automatically β€” the server already reads it.

2. Frontend on Vercel

  • New Project β†’ import this repo β†’ set Root Directory = frontend.

  • Add an environment variable:

    Key Value
    NEXT_PUBLIC_WS_URL wss://pixelstream-backend.onrender.com
  • Deploy. Open the Vercel URL β†’ Start Browser.


What works βœ…

  • Start a headless Chromium in a Docker container from the web UI
  • Live screen streaming via CDP screencast (JPEG frames over WebSocket)
  • Mouse: move, left/right click, scroll
  • Keyboard: printable characters + common special keys (Enter, Backspace, Tab, arrows, Esc, Delete…)
  • URL bar to navigate the remote browser
  • Accurate click mapping (canvas coords β†’ real viewport coords)

Known limitations / where it gets hard ⚠️

  • Keyboard coverage β€” only common special keys are mapped; modifier combos (Ctrl+C, Shift+selection) aren't fully wired yet.
  • Single session β€” one browser per server; no multi-user / multi-tab.
  • Streaming β€” JPEG-over-WebSocket is simple but bandwidth-heavy; WebRTC or VP8/H.264 encoding would be smoother at scale.
  • Chromium-in-Docker β€” needs --no-sandbox, --disable-dev-shm-usage, and shm_size: 1gb or Chromium crashes. (These are already set.)

Next steps πŸš€

  1. Full keyboard model with modifiers + IME/composition events
  2. Multiple isolated sessions (one container per user, spawned on demand)
  3. WebRTC streaming for lower latency / adaptive quality
  4. Reconnect handling + session timeouts + resource cleanup

Project structure

Pixel/
β”œβ”€β”€ docker-compose.yml
β”œβ”€β”€ backend/
β”‚   β”œβ”€β”€ Dockerfile
β”‚   β”œβ”€β”€ package.json
β”‚   └── server.js          # ws server + Puppeteer + CDP screencast/input
└── frontend/
    β”œβ”€β”€ Dockerfile
    β”œβ”€β”€ package.json
    β”œβ”€β”€ next.config.js
    └── app/
        β”œβ”€β”€ layout.js
        └── page.js        # UI + canvas + input capture
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support