Skip to content

Source code

Remote desktops with noVNC

Use noVNC to display an RFB remote desktop through your application’s authorized WebSocket gateway. Use the separate terminal component for direct SSH sessions.

Start with your first page. Shared ui* providers are registered by createAdmin. Examples belong inside a route template, not the root HTML document. The page and its optional controller load through Atrium’s lazy route registry.

Minimal example

/**
* Integrate remote desktops with novnc into an application-owned route.
*
* @author Laurent Declercq l.declercq@agon-innovation.ch
* @version 20260921
*/
import { vncConsole } from '@agon/atrium/components/vnc';
/**
* Register an application-owned remote desktop session.
*
* @param {object} context - Alpine and consumer service dependencies.
* @returns {void} Registers the desktop provider.
*/
export function register(context) {
context.Alpine.data('serverDesktop',
/**
* Request fresh authorization whenever the user connects.
*
* @returns {object} RFB surface provider.
*/
() => vncConsole({
viewOnly: false,
resizeSession: false,
/**
* Obtain a short-lived, authorized RFB gateway session.
*
* @param {AbortSignal} signal - Component lifetime.
* @returns {Promise<object>} A URL and optional noVNC constructor options.
*/
session: (signal) => context.services.desktop.createSession(signal),
}));
}
<section x-data="serverDesktop">
<h1 tabindex="-1">Remote desktop</h1>
<include src="{{ uiRoot }}/vnc.html"></include>
</section>

Settings and behavior

Option or commandMeaning
session(signal)Resolve { url, options } for a fresh connection. url is normally a wss:// URL.
options in the session resultnoVNC constructor options, such as credentials or wsProtocols.
viewOnlyDisable remote input, default false.
resizeSessionRequest remote resolution changes, default false. Viewport scaling is always enabled.
command('credentials', credentials)Answer a credentialsrequired challenge using an application-owned form.
command('attention')Send Ctrl+Alt+Delete.
command('paste', text)Send plain text to the remote clipboard.
statusidle, loading, connecting, connected, credentials, disconnected, or error.

Use the shared Connect and Disconnect buttons. Reconnecting obtains a new session. Stop and route teardown disconnect the old client. Native instances stay outside Alpine’s reactive proxies. The desktop itself stays left-to-right in RTL layouts, while the toolbar follows the surrounding interface.

Enter fullscreen expands the desktop and its toolbar through the browser Fullscreen API without reconnecting. noVNC scales the existing framebuffer to the available area. Remote resolution changes still follow resizeSession. Exit fullscreen and the browser’s Escape action restore the normal view and update the control state. Route teardown exits only this desktop’s fullscreen session. Unsupported or denied requests show a localized message without interrupting the connection.

Integration notes

The session adapter must honor its AbortSignal and release partially created gateway resources if cancelled. Your backend owns authentication, authorization, ticket expiry, audit trails, and protocol bridging. Configure connect-src for the authorized WebSocket origin. Do not place credentials in preferences or diagnostic output. An authentication form should clear its secret immediately after calling the credentials command. The offline showcase supplies an in-memory RFB 3.8 fixture to the real decoder. It makes no network connection and is not a remote-control server. See the noVNC API.

Working reference

See the production example. Return to the component index.

Author

Laurent Declercq l.declercq@agon-innovation.ch

License

Unless otherwise stated all source code is licensed under LGPL 2.1 and has the following copyright:

© 2026, Agon Partners Innovation AG, All rights reserved.

The design material and the “Agon Ātrium” trademark is the property of their authors. Reuse of them without prior consent of their respective authors is strictly prohibited.

Version

Version: 20260921