# RCWeb screen examples

Version: 1

Published location: https://rcweb.live/mcp/screen-examples.md
Read the operating guide first: https://rcweb.live/mcp/llm-guide.md

These are starting points for a default viewer that the user wants to use for new display content. Inspect the selected client first. Do not cover an active app with these examples unless the user wants its display replaced. Send code only through `execute_javascript` to the exact selected client.

## Shared setup

Prepend this setup to each of the three recipe bodies below, in the SAME tool call. It defines a local helper and intentionally does not reply. The recipe must send the reply. All names starting with `rcweb-assistant` or `__rcwebAssistant` below are owned by these examples, not built-in RCWeb APIs.

```javascript
function prepareAssistantStage() {
    if (typeof window.__rcwebAssistantCleanup === 'function') {
        window.__rcwebAssistantCleanup();
    }
    window.__rcwebAssistantCleanup = null;
    var stage = document.getElementById('rcweb-assistant-stage');
    if (!stage) {
        stage = document.createElement('div');
        stage.id = 'rcweb-assistant-stage';
        document.body.appendChild(stage);
    }
    while (stage.firstChild) stage.removeChild(stage.firstChild);
    stage.style.cssText = 'position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;background:#10253b;color:white;overflow:hidden;';
    return stage;
}
```

This overlay leaves the viewer runtime intact. It may cover its welcome controls. To restore them, run the cleanup function and remove only `rcweb-assistant-stage`. Inspect its dimensions and stacking on the real screen; do not assume that every app has the same layout.

## Display an image

Replace `USER_IMAGE_URL` with the user's approved direct image URL using safe JavaScript string serialization. The URL placeholder is not a real media address. This example fits an image without cropping and reports only after loading. Use an appropriate MCP timeout for the network; after a timeout inspect the image before retrying.

```javascript
var stage = prepareAssistantStage();
var image = document.createElement('img');
image.alt = 'Image selected by the user';
image.style.cssText = 'position:absolute;top:50%;left:50%;max-width:100%;max-height:100%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);';
image.onload = function () {
    reply({loaded: true, width: image.naturalWidth, height: image.naturalHeight});
};
image.onerror = function () { fail('The image could not be loaded. Check the URL and format.'); };
window.__rcwebAssistantCleanup = function () {
    image.onload = image.onerror = null;
    image.removeAttribute('src');
};
stage.appendChild(image);
image.src = 'USER_IMAGE_URL';
```

## Play a video

Replace `USER_VIDEO_URL` with an approved direct video URL, not a sharing webpage. This example requests muted autoplay and keeps controls available. It does not force fullscreen or audio playback. Its reply describes the state when media data arrives; if `playing` is false, inspect again or explain that a click on the display may be needed.

```javascript
var stage = prepareAssistantStage();
var video = document.createElement('video');
video.controls = true;
video.muted = true;
video.autoplay = true;
video.setAttribute('playsinline', '');
video.style.cssText = 'display:block;width:100%;height:100%;background:black;';
video.onloadeddata = function () {
    reply({loaded: true, playing: !video.paused, muted: video.muted, controls: video.controls});
};
video.onerror = function () {
    fail('Video could not be loaded. Media error code: ' + (video.error ? video.error.code : 'unknown'));
};
window.__rcwebAssistantCleanup = function () {
    video.onloadeddata = video.onerror = null;
    video.pause();
    video.removeAttribute('src');
    video.load();
};
stage.appendChild(video);
video.src = 'USER_VIDEO_URL';
```

For a later verification, inspect this stage's video: `readyState`, `paused`, `currentTime`, `videoWidth`, `videoHeight`, and `error`. Two observations with increasing `currentTime` are stronger evidence of playback than the initial load event. Report muted playback accurately.

## Create an analog clock

This example uses a canvas, no images or libraries, and the display browser's local time. Its timer is replaced rather than duplicated on the next recipe. If `getContext` is unavailable, report that limitation instead of claiming a working clock.

```javascript
var stage = prepareAssistantStage();
var canvas = document.createElement('canvas');
canvas.width = canvas.height = 600;
canvas.style.cssText = 'position:absolute;top:50%;left:50%;width:80vmin;height:80vmin;max-width:100%;max-height:100%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);';
canvas.setAttribute('role', 'img');
var context = canvas.getContext && canvas.getContext('2d');
if (!context) { fail('This browser cannot draw a canvas clock.'); return; }
stage.appendChild(canvas);
function drawClock() {
    var now = new Date();
    canvas.setAttribute('aria-label', 'Local time: ' + now.toLocaleTimeString());
    context.clearRect(0, 0, 600, 600);
    context.save();
    context.translate(300, 300);
    context.beginPath();
    context.arc(0, 0, 280, 0, Math.PI * 2);
    context.fillStyle = '#ffffff';
    context.fill();
    context.strokeStyle = '#1769b5';
    var i;
    for (i = 0; i < 60; i++) {
        context.save();
        context.rotate(i * Math.PI / 30);
        context.lineWidth = i % 5 === 0 ? 6 : 2;
        context.beginPath();
        context.moveTo(0, -260);
        context.lineTo(0, i % 5 === 0 ? -235 : -250);
        context.stroke();
        context.restore();
    }
    function hand(angle, length, width, color) {
        context.save();
        context.rotate(angle);
        context.beginPath();
        context.moveTo(0, 12);
        context.lineTo(0, -length);
        context.lineWidth = width;
        context.lineCap = 'round';
        context.strokeStyle = color;
        context.stroke();
        context.restore();
    }
    hand(((now.getHours() % 12) + now.getMinutes() / 60) * Math.PI / 6, 145, 12, '#253b53');
    hand((now.getMinutes() + now.getSeconds() / 60) * Math.PI / 30, 210, 8, '#253b53');
    hand(now.getSeconds() * Math.PI / 30, 225, 3, '#1e87f0');
    context.restore();
}
drawClock();
var clockTimer = window.setInterval(drawClock, 1000);
window.__rcwebAssistantCleanup = function () { window.clearInterval(clockTimer); };
reply({created: true, kind: 'analog clock', time: new Date().toString(), width: canvas.width, height: canvas.height});
```

For subsequent color or size changes, adjust the existing clock implementation and replace its timer cleanly. Verify the stage is visible and the clock continues updating. The initial reply confirms drawing/setup, not observation of an elapsed second.
