npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

orgo-vnc

v0.3.0

Published

Embed Orgo cloud computers in your React app

Readme

orgo-vnc

Embed an Orgo cloud computer in your React app.

npm install orgo-vnc
import { ComputerDisplay } from 'orgo-vnc';

<ComputerDisplay
  instanceId={instanceId}
  password={password}
  onError={(message) => console.error(message)}
  style={{ width: 1280, height: 720 }}
/>

Getting the two values

instanceId is the computer's instance id, not its UUID. POST /computers returns it as instance_id. GET /computers/{id} returns the same value under the older name fly_instance_id.

password comes from GET /computers/{id}/vnc-password. It rotates whenever the computer restarts, so fetch it fresh rather than hardcoding it.

Fetch it on your server, never in the browser:

// app/api/desktop/route.ts
export async function GET() {
  const res = await fetch(
    `https://www.orgo.ai/api/computers/${process.env.ORGO_COMPUTER_ID}/vnc-password`,
    { headers: { Authorization: `Bearer ${process.env.ORGO_API_KEY}` } },
  );
  const { password } = await res.json();
  // Only the per-computer password crosses to the browser. Never the API key.
  return Response.json({ instanceId: process.env.ORGO_INSTANCE_ID, password });
}

The VNC password is root on that computer. The same value opens a terminal and the command API, not just the screen. Anyone who can read it from your page can run commands on the machine. Point embeds at disposable computers.

An account API key (sk_...) is rejected when it arrives from a browser. Use the per-computer password.

Embedding from your own domain

There is no origin allowlist on this path and nothing to register. The per-computer password is the credential, and it is what decides whether a connection is allowed.

Always handle onError

A rejected connection is otherwise invisible. The proxy accepts the WebSocket upgrade and then closes it, so noVNC raises nothing and the component renders black. onError receives a decoded reason for every close the proxy sends.

<ComputerDisplay
  instanceId={instanceId}
  password={password}
  onError={(message) => console.error(message)}
  onClose={(code, info) => {
    if (info?.retryable) scheduleReconnect();
  }}
/>

| Close | Meaning | What to do | | --- | --- | --- | | 4001 | Authentication rejected | Use the per-computer password, not an sk_ key. It may have rotated. | | 4003 | Computer is not running | Start it, reconnect when its status is running. | | 4004 | No such computer | Check instanceId. It is instance_id, not the UUID. | | 4006 | Credential scoped to another workspace | Use a key for this computer's workspace. | | 4008 | Idle for 30 minutes | Expected. Reconnect on user activity. | | 4500 | Proxy error | Retry. | | 4502 | Proxy could not reach the computer | Usually transient while starting or moving hosts. |

describeCloseCode(code) and closeCodeMessage(code) are exported if you want to render these yourself.

Props

| Prop | Type | Default | Notes | | --- | --- | --- | --- | | instanceId | string | required | The computer's instance_id. | | password | string | required | From GET /computers/{id}/vnc-password. | | host | string | www.orgo.ai | Only for self-hosted or staging. | | readOnly | boolean | false | Render the screen without sending input. | | scaleViewport | boolean | true | Scale the remote screen to fit. | | clipViewport | boolean | true | Clip rather than letterbox. | | resizeSession | boolean | true | Ask the computer to match the container size. | | cursorVisible | boolean | true | Set false to hide the OS cursor while an agent drives. | | showDotCursor | boolean | true | Draw a dot when the remote cursor is hidden. | | compressionLevel | number | 2 | 0 to 9. | | qualityLevel | number | 6 | 0 to 9. | | background | string | #000 | Fill behind the screen. | | onConnect | () => void | | Connected and painting. | | onDisconnect | (clean: boolean) => void | | Session ended. | | onError | (message: string) => void | | Decoded failure reason. Handle this. | | onClose | (code: number, info) => void | | Raw close code plus its decoded meaning. | | onClipboard | (text: string) => void | | The computer copied something. | | onReady | (handle) => void | | Imperative handle, see below. |

Imperative handle

const [handle, setHandle] = useState<ComputerDisplayHandle | null>(null);

<ComputerDisplay instanceId={instanceId} password={password} onReady={setHandle} />;

handle?.sendClipboard('text to paste into the computer');
await handle?.pasteFromClipboard();
handle?.disconnect();

Without React

The component is a convenience wrapper. Any websockify-compatible client works against the same URL:

import RFB from '@novnc/novnc'; // noVNC 1.7+

const rfb = new RFB(
  container,
  `wss://www.orgo.ai/desktops/${instanceId}/ws/websockify?token=${encodeURIComponent(password)}`,
  { credentials: { password } },
);
rfb.addEventListener('credentialsrequired', () => rfb.sendCredentials({ password }));

buildWsUrl(host, instanceId, password) is exported if you want the URL without building it by hand.

Upgrading from 0.2.x

0.2.x connected to wss://{hostname}/websockify, from when every computer had its own hostname. That is no longer how Orgo works, so 0.2.x cannot connect to any current computer.

Replace the hostname prop with instanceId:

- <ComputerDisplay hostname={hostname} password={password} />
+ <ComputerDisplay instanceId={instanceId} password={password} onError={console.error} />

hostname is now ignored and logs a warning. Add onError while you are there: its absence is why the 0.2.x breakage was invisible.

License

MIT