Documentation

Everything you need to know about BrowserView — from first launch to advanced automation via CLI and Runtime API.

🚀 Getting Started

Installation

BrowserView is currently available by request. To get access:

  1. Submit a request on the main page via the "Request Access" button
  2. Wait for a response with connection details and access terms
  3. Receive setup and launch instructions
  4. Install the application and open BrowserView on your Mac
💡 Tip: BrowserView requires macOS. The application runs natively and uses system rendering engines for maximum accuracy.

First Launch

On first launch, you'll see the main canvas — this is your workspace. The app may load the last used device configuration, or you'll see a blank canvas.

Main UI elements:

  • Canvas — the central area where devices are placed
  • Address Bar — at the top, for entering the website URL
  • Device Panel — for adding and managing devices
  • Toolbar — zoom, synchronized scrolling, and other options

Quick Start in 30 Seconds

  1. Add several devices (e.g., iPhone, Galaxy, Desktop)
  2. Enter your website URL in the address bar
  3. Press Enter — the site loads on all devices simultaneously
  4. Done! You can see how your site looks on different screens

🖼️ Workspace

The canvas is an infinite workspace where all your devices are placed. You can freely pan around and zoom in or out.

Canvas Navigation

  • Panning — click and drag an empty area of the canvas to move around the workspace
  • Zooming — use scroll with the Ctrl key held or a pinch gesture on the trackpad to zoom in and out
  • Zoom Level — the default maximum zoom is 0.5, but it can be changed

Device Layout

Devices are automatically placed on the canvas when added. BrowserView uses an intelligent layout algorithm that optimally arranges devices so they are all visible on screen.

💡 Tip: You can detach any device into a separate floating window for convenient work on a second monitor.

📱 Devices

BrowserView includes over 67 built-in device profiles covering all popular phone, tablet, and desktop models.

Adding Devices

To add a device to the canvas, select it from the list of available devices. The device will appear on the canvas and immediately load the current URL.

Available Devices

  • iPhone — from iPhone 7 to iPhone 16 Pro Max, all SE models
  • Android — Samsung Galaxy S20–S24, Google Pixel 6–9
  • Desktop — popular resolutions from 1280×1024 to 5120×2880 (iMac 5K)

Device Rotation

Any mobile device can be rotated to landscape (horizontal) orientation. This is useful for checking site responsiveness when the phone is turned.

Detach into Separate Window

You can detach a device from the canvas and work with it in a separate floating window. This is especially handy with multiple monitors — place the phone on one screen and the desktop on another.

Custom Sizes

In addition to built-in profiles, you can set a custom resolution in the "Desktop WidthxHeight" format (e.g., "Desktop 1920x1080").

🔄 Synchronized Scrolling

Synchronized scrolling is one of BrowserView's key features. When enabled, scrolling on one device automatically scrolls all other devices to the same position.

How to Enable

Click the synchronized scrolling button on the toolbar or use the hotkey. When active, the indicator will light up.

How It Works

When you scroll a page on any device, all other devices scroll to the same relative position. This lets you instantly check how a specific content block looks on all screens.

💡 Tip: Synchronized scrolling works proportionally — on a small iPhone and a large desktop, content will be in the same viewing zone.

Two Rendering Engines

BrowserView is the only tool that uses two browser engines at once: WebKit and Chromium. This gives you an accurate picture of how your site looks across different browsers.

WebKit

This is the Safari engine — the browser installed on every iPhone and iPad. When you view a site on a virtual iPhone in BrowserView, it renders exactly as real Safari users will see it. It's the native macOS engine, so it runs as fast and accurately as possible.

Chromium (CEF)

This is the engine behind Chrome, Edge, Opera, and most Android browsers. BrowserView uses Chromium Embedded Framework to render Android and desktop devices. You see exactly what Chrome users will see.

Why Two Engines?

WebKit and Chromium handle CSS, fonts, and JavaScript differently. A bug absent in Chrome may break layout in Safari — and vice versa. With two engines, you catch the issue before your users do.

🛠️ DevTools

BrowserView provides developer tools for each device. Depending on the engine, you get the corresponding DevTools.

Safari Web Inspector (WebKit)

For WebKit devices (iPhone, iPad), Safari Web Inspector opens — a powerful tool for inspecting DOM, CSS, network requests, and performance. It launches as a separate system Web Inspector window.

Chrome DevTools (Chromium)

For Chromium devices (Android, Desktop), Chrome DevTools open — the developer tools familiar to every web developer with Elements, Console, Network tabs, and more.

How to Open

Select a device and use the context menu or hotkey to open DevTools. The tools open for the specific selected device — you can debug the exact viewport you're interested in.

💾 Presets

Presets let you save and load device configurations. This is convenient if you regularly work with a specific set of devices.

Saving a Preset

Set up the canvas with the devices, URL, and settings you need. Save the configuration as a JSON preset file that you can load later.

Loading a Preset

Load a previously saved preset, and all devices, URLs, and settings will be restored automatically. This is especially handy for switching between projects.

Usage Examples

  • "Mobile" — iPhone 16 Pro, Galaxy S24, Pixel 9 for mobile testing
  • "Full Set" — several mobile + tablet + desktop for full coverage
  • "Client X" — specific devices used by the client

📸 Screenshots

BrowserView allows you to take screenshots of individual devices. This is useful for documentation, client presentations, or visual regression testing.

How to Take a Screenshot

You can capture a screenshot of a specific device — WebKit or Chromium. The screenshot is saved as a PNG file to a location you specify. For automation, use command-line arguments (described in the "For Developers" section).

💡 Tip: CLI screenshots are ideal for automated visual testing in CI/CD pipelines.

⌨️ Hotkeys

Hotkeys speed up your workflow. Here are the main shortcuts:

ShortcutAction
⌘ + RReload all devices
⌘ + LFocus address bar
⌘ + +Zoom in
⌘ + −Zoom out
⌘ + 0Reset zoom
⌘ + ,Open settings

💳 Subscription

Trial Period

Trial access and onboarding terms are discussed when reviewing your request. We'll include available options and next steps for activation in our response.

Subscribing

Access to the application is currently provided by request. After approval, you'll receive instructions for setup and activation.

Managing Your Subscription

💡 Tip: If you need help with installation or activation, describe your use case in the request — this helps us prepare a working configuration faster.

Command-Line Arguments

Launch BrowserView with arguments to configure devices, URLs, and behavior. All arguments can be combined.

Device Management

# Launch with empty canvas (ignore saved state)
--empty

# Add devices to the main canvas
--device="iPhone 16 Pro"
--device="Galaxy S24"
--device="Desktop 1920x1080"

# Open device in a separate window
--detach="iPhone 15"

# Rotate device to landscape orientation
--rotate="iPhone 16 Pro"

# Multiple devices at once
--device="iPhone 16" --device="Pixel 9" --device="Galaxy S24"

Navigation

# Load URL (https:// added automatically if no scheme)
--url=https://example.com
--url=example.com
--url=http://localhost:3000
--url=file:///path/to/index.html

Display Options

# Set maximum zoom level (0.1 to 2.0, default: 0.5)
--zoom=0.8

# Enable synchronized scrolling for all devices
--scroll-sync

# Watch directory and auto-reload on changes
--watch-dir=/path/to/your/project

Presets

# Load a saved preset configuration
--preset=/path/to/my-preset.json

Screenshots and Testing

# Capture screenshot of a WebKit device
--webkit-view-screenshot-path=/path/to/output.png

# Capture screenshot of a CEF (Chromium) device
--cef-screenshot-path=/path/to/output.png

# Run test scroll on a device
--test-touch-scroll="iPhone 16 Pro"

# Log processed arguments to a file
--args-log-path=/path/to/args.log

# Write JSON layout metrics on each pass
--layout-log-path=/path/to/layout.json

Full Example

# Launch with 3 devices, URL, synchronized scrolling, and file watching
BrowserView --empty \
  --device="iPhone 16 Pro" \
  --device="Galaxy S24" \
  --device="Desktop 1920x1080" \
  --url=http://localhost:3000 \
  --watch-dir=./src \
  --scroll-sync

Runtime API (Distributed Notifications)

Control BrowserView at runtime via macOS Distributed Notifications. This lets external scripts and AI agents manipulate the application in real time.

Available Notifications

Notification Name Object (payload) Description
com.viewportstudio.addDevice Device name Add a device to the canvas
com.viewportstudio.detachDevice Device name Detach a device into a floating window
com.viewportstudio.navigateURL URL string Navigate to URL on all devices
com.viewportstudio.openDevTools Device name Open DevTools for a device
com.viewportstudio.highlightElement deviceName|cssSelector Highlight a DOM element in a device
com.viewportstudio.lowerDetachedWindows (any) Lower floating windows to normal level

Sending from Swift

import Foundation

DistributedNotificationCenter.default().post(
    name: NSNotification.Name("com.viewportstudio.addDevice"),
    object: "iPhone 16 Pro"
)

Sending from Shell

# Add a device
swift -e 'import Foundation; DistributedNotificationCenter.default().post(name: NSNotification.Name("com.viewportstudio.addDevice"), object: "iPhone 16 Pro"); RunLoop.current.run(until: Date(timeIntervalSinceNow: 0.1))'

# Navigate to URL
swift -e 'import Foundation; DistributedNotificationCenter.default().post(name: NSNotification.Name("com.viewportstudio.navigateURL"), object: "https://example.com"); RunLoop.current.run(until: Date(timeIntervalSinceNow: 0.1))'

# Open DevTools
swift -e 'import Foundation; DistributedNotificationCenter.default().post(name: NSNotification.Name("com.viewportstudio.openDevTools"), object: "Galaxy S24"); RunLoop.current.run(until: Date(timeIntervalSinceNow: 0.1))'

Sending from Python

import subprocess

def send_notification(name, value):
    script = f'''
    import Foundation
    DistributedNotificationCenter.default().post(
        name: NSNotification.Name("{name}"),
        object: "{value}"
    )
    RunLoop.current.run(until: Date(timeIntervalSinceNow: 0.1))
    '''
    subprocess.run(['swift', '-e', script])

# Usage
send_notification('com.viewportstudio.addDevice', 'iPhone 16 Pro')
send_notification('com.viewportstudio.navigateURL', 'https://example.com')

Sending from Node.js

const { execSync } = require('child_process');

function sendNotification(name, value) {
  const script = `
    import Foundation
    DistributedNotificationCenter.default().post(
        name: NSNotification.Name("${name}"),
        object: "${value}"
    )
    RunLoop.current.run(until: Date(timeIntervalSinceNow: 0.1))
  `;
  execSync(`swift -e '${script}'`);
}

// Usage
sendNotification('com.viewportstudio.addDevice', 'iPhone 16 Pro');
sendNotification('com.viewportstudio.navigateURL', 'https://example.com');

Automation Examples

Screenshot Automation

#!/bin/bash
# Capture screenshots of a site on multiple devices

APP="/Applications/BrowserView.app/Contents/MacOS/BrowserView"

"$APP" --empty \
  --device="iPhone 16 Pro" \
  --device="Galaxy S24" \
  --device="Desktop 1920x1080" \
  --url="https://your-site.com" \
  --webkit-view-screenshot-path="./iphone.png" \
  --cef-screenshot-path="./android.png"

Recording an Interactive Demo

#!/bin/bash
# Automated demo: adding devices one by one with delays

BrowserView --empty --url="https://your-site.com" &
sleep 3

# Sequential device addition
for device in "iPhone 16 Pro" "Galaxy S24" "Desktop 1920x1080"; do
  swift -e "import Foundation; DistributedNotificationCenter.default().post(name: NSNotification.Name(\"com.viewportstudio.addDevice\"), object: \"$device\"); RunLoop.current.run(until: Date(timeIntervalSinceNow: 0.1))"
  sleep 2
done

# Opening DevTools for one device
swift -e 'import Foundation; DistributedNotificationCenter.default().post(name: NSNotification.Name("com.viewportstudio.openDevTools"), object: "Galaxy S24"); RunLoop.current.run(until: Date(timeIntervalSinceNow: 0.1))'

For AI Agents

BrowserView is designed for full control by AI coding agents such as Claude, GPT, and others. Here's how agents can interact with the application:

Capabilities

  • Launch with configuration — Start the app with specific devices, URLs, and settings via CLI
  • Runtime control — Add/remove devices, navigate, open DevTools while the app is running
  • Screenshot capture — Capture device screenshots for visual verification
  • Layout metrics — Get JSON output of layout calculations for verification
  • File watching — Auto-reload on code changes

Agent Integration Pattern

# 1. Launch BrowserView with initial configuration
BrowserView --empty \
  --device="iPhone 16 Pro" \
  --url="http://localhost:3000" \
  --watch-dir=./src

# 2. Agent makes code changes...
# (App auto-reloads via watch-dir)

# 3. Agent adds more devices for testing
swift -e 'import Foundation; DistributedNotificationCenter.default().post(name: NSNotification.Name("com.viewportstudio.addDevice"), object: "Galaxy S24")'

# 4. Agent captures a screenshot for verification
# (Use CLI screenshot arguments or screen capture tools)

# 5. Agent opens DevTools for debugging
swift -e 'import Foundation; DistributedNotificationCenter.default().post(name: NSNotification.Name("com.viewportstudio.openDevTools"), object: "iPhone 16 Pro")'

Supported Devices

Device names are case-insensitive. Available devices include:

  • iPhone — iPhone 7 through iPhone 16 Pro Max, SE models
  • Android — Galaxy S20-S24 series, Pixel 6-9 series
  • Desktop — Common resolutions from 1280x1024 to 5120x2880

CI/CD Integration

BrowserView can be integrated into continuous integration workflows for automated visual testing.

GitHub Actions

# .github/workflows/visual-test.yml
name: Visual Regression Test
on: [push, pull_request]

jobs:
  visual-test:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install dependencies
        run: npm ci

      - name: Start dev server
        run: npm run dev &

      - name: Wait for server
        run: sleep 5

      - name: Run BrowserView
        run: |
          "/Applications/BrowserView.app/Contents/MacOS/BrowserView" \
            --empty \
            --device="iPhone 16 Pro" \
            --device="Desktop 1920x1080" \
            --url="http://localhost:3000" \
            --webkit-view-screenshot-path="./screenshots/iphone.png" \
            --cef-screenshot-path="./screenshots/desktop.png" \
            --layout-log-path="./layout.json"

      - name: Upload screenshots
        uses: actions/upload-artifact@v4
        with:
          name: screenshots
          path: screenshots/

Shell Script for CI

#!/bin/bash
# visual-regression.sh — visual regression testing

set -e
APP="/Applications/BrowserView.app/Contents/MacOS/BrowserView"
SCREENSHOTS_DIR="./screenshots"
mkdir -p "$SCREENSHOTS_DIR"

# Start dev server
npm run dev &
DEV_PID=$!
sleep 5

# Capture screenshots
"$APP" --empty \
  --device="iPhone 16 Pro" \
  --device="Desktop 1920x1080" \
  --url="http://localhost:3000" \
  --webkit-view-screenshot-path="$SCREENSHOTS_DIR/iphone.png" \
  --cef-screenshot-path="$SCREENSHOTS_DIR/desktop.png" \
  --layout-log-path="$SCREENSHOTS_DIR/layout.json"

# Stop dev server
kill $DEV_PID

echo "✅ Screenshots saved to $SCREENSHOTS_DIR"

Fastlane

# fastlane/Fastfile
lane :visual_test do
  sh("npm run dev &")
  sleep(5)

  viewport_app = "/Applications/BrowserView.app/Contents/MacOS/BrowserView"

  sh("#{viewport_app} --empty " \
     "--device='iPhone 16 Pro' " \
     "--device='Desktop 1920x1080' " \
     "--url='http://localhost:3000' " \
     "--webkit-view-screenshot-path='./screenshots/iphone.png' " \
     "--cef-screenshot-path='./screenshots/desktop.png'")

  sh("pkill -f 'npm run dev' || true")
end

Layout Log

When using the --layout-log-path argument, BrowserView writes a JSON file with layout metrics on each pass. This is useful for automated testing and verification.

File Format

{
  "timestamp": "2025-01-15T10:30:00Z",
  "devices": [
    {
      "name": "iPhone 16 Pro",
      "engine": "webkit",
      "width": 393,
      "height": 852,
      "scale": 3,
      "rotated": false,
      "position": { "x": 0, "y": 0 }
    },
    {
      "name": "Desktop 1920x1080",
      "engine": "cef",
      "width": 1920,
      "height": 1080,
      "scale": 1,
      "rotated": false,
      "position": { "x": 420, "y": 0 }
    }
  ],
  "canvas": {
    "zoom": 0.5,
    "scrollSync": true
  }
}

Usage for Tests

#!/bin/bash
# Verify that all devices loaded correctly

LAYOUT=$(cat layout.json)

# Check device count
DEVICE_COUNT=$(echo "$LAYOUT" | python3 -c "import sys,json; print(len(json.load(sys.stdin)['devices']))")

if [ "$DEVICE_COUNT" -ne 3 ]; then
  echo "❌ Expected 3 devices, got $DEVICE_COUNT"
  exit 1
fi

echo "✅ Layout log: $DEVICE_COUNT devices loaded"
# Python: parse layout log
import json

with open('layout.json') as f:
    layout = json.load(f)

for device in layout['devices']:
    print(f"{device['name']}: {device['width']}x{device['height']} ({device['engine']})")

# Verify all devices are present
expected = {"iPhone 16 Pro", "Galaxy S24", "Desktop 1920x1080"}
actual = {d['name'] for d in layout['devices']}
assert expected == actual, f"Missing devices: {expected - actual}"

Troubleshooting

Application Won't Start

Make sure you're using a supported version of macOS. Check the system requirements in the instructions you received. Try restarting your Mac and launching the app again.

localhost Not Loading

Make sure your dev server is actually running and listening on the specified port. Try opening the same URL in a regular browser. If the server listens on 127.0.0.1, try using localhost and vice versa.

WebKit and Chromium Show Different Results

This is normal and expected! That's the whole point of two engines — you discover cross-browser differences. Check CSS properties that are interpreted differently by engines: -webkit- prefixes, flexbox/grid nuances, font rendering.

Synchronized Scrolling is Inaccurate

Synchronized scrolling works in proportional mode. If pages have different content heights on different devices, the scroll position will be approximate. This is normal behavior.

Screenshots Not Saving

Check that the file path is correct and the directory exists. Make sure the app has write permissions to the specified directory. When using relative paths, they resolve from the current working directory.

CLI Arguments Not Working

# Make sure you're using the full path to the executable:
"/Applications/BrowserView.app/Contents/MacOS/BrowserView" --empty --device="iPhone 16 Pro"

# Or add an alias to ~/.zshrc:
alias viewport='"/Applications/BrowserView.app/Contents/MacOS/BrowserView"'

# For argument debugging, use the log:
BrowserView --args-log-path=/tmp/viewport-args.log --device="iPhone 16 Pro"
cat /tmp/viewport-args.log

Distributed Notifications Not Delivered

# Check that the application is running:
pgrep -f "BrowserView" || echo "Application is not running!"

# Make sure RunLoop has time to send the notification:
swift -e '
import Foundation
DistributedNotificationCenter.default().post(
    name: NSNotification.Name("com.viewportstudio.addDevice"),
    object: "iPhone 16 Pro"
)
RunLoop.current.run(until: Date(timeIntervalSinceNow: 0.5))
'
# Note: a 0.5s delay (instead of 0.1s) may help with unstable delivery