Skip to main content
One of the most common overlay patterns is a window the player summons on demand: press a key to open your HUD, hold a key to peek at a scoreboard. This guide walks through wiring a keybind to a window’s visibility, end to end.
This guide covers the show/hide workflow specifically. For the full keybinds API reference, see Setup Keybinds.

How Keybinds Work

Before writing any code, it helps to know three things about how Overlayed handles keybinds:
  1. Keybinds are defined at setup time. You declare every keybind (with a default key combination) in your overlayed() config. You can change a keybind’s keys and mode at runtime, but you cannot add brand new keybind names after setup.
  2. Key presses are captured by Overlayed’s native keyboard hook. Keybinds fire while the game is focused and fullscreen - you don’t need Electron’s globalShortcut, and there’s nothing to register with the OS.
  3. User changes persist automatically. The config you pass in is only the default. When your code calls updateKeybind (typically from your keybind settings UI), the new binding is saved to disk and used from then on.

Wiring a Keybind to a Window

1

Define the keybind

Add a keybind to your overlayed() setup. The name (toggleHud here) is yours to choose - you’ll use it to listen for the keybind later.
main.ts
export const overlay = overlayed({
	keybinds: {
		toggleHud: {
			keys: ["AltLeft", "KeyO"],
			mode: "toggle",
		},
	},
});
  • keys is an array of KeyboardEvent#code values - "KeyO", not "o". Every entry must be held at once, so ["AltLeft", "KeyO"] means Alt + O. Use keycode.info to look up codes.
  • mode is "toggle" (press once to fire) or "hold" (fires on press and release).
Key codes are case-sensitive, and left/right modifiers are distinct codes. There is no generic "Ctrl" - use "ControlLeft" or "ControlRight". Binding to "AltLeft" will not trigger when the user presses the right Alt key.
2

Create the window

Create the window you want to control. For a window rendered inside the game, use createInGameWindow:
const hudWindow = overlay.windows.createInGameWindow({
	width: 400,
	height: 300,
	show: false, // start hidden, let the keybind reveal it
});
See Creating Windows for the difference between in-game and out-of-game windows.
3

Listen and toggle visibility

Attach a listener to the keybind and flip the window’s visibility:
overlay.keybinds.toggleHud.on("toggle", () => {
	hudWindow.toggleVisibility();
});
That’s it - pressing Alt + O in-game now shows the window, and pressing it again hides it.

Toggle vs. Hold

Which mode you pick changes which events you should listen to. A toggled HUD listens to toggle; a hold-to-peek scoreboard listens to down and up.
The toggle event fires once per full key press. The user must release the keys before the keybind can fire again - holding the combination down does not re-trigger it.
export const overlay = overlayed({
	keybinds: {
		toggleHud: {
			keys: ["AltLeft", "KeyO"],
			mode: "toggle",
		},
	},
});

overlay.keybinds.toggleHud.on("toggle", () => {
	hudWindow.toggleVisibility();
});
If you let users change a keybind’s mode in your settings UI, register listeners for all three events (toggle, down, and up) so the keybind keeps working in either mode.

Conditionally Blocking the Keybind

Sometimes showing the window doesn’t make sense - for example, a scoreboard when the user isn’t in a match. Return a string (the rejection reason) from a toggle or down listener to block it:
overlay.keybinds.showScoreboard.on("down", () => {
	if (!siegeState.match) {
		return "Not in a match";
	}

	scoreboardWindow.show();
});
Returning a string marks the press as rejected - Overlayed logs the reason, and for hold keybinds the matching up event won’t fire.

Letting Users Rebind Keys

The keys you configure are just defaults. To support user customization, build a settings UI on top of these methods:
// Read the current (possibly user-modified) bindings to display in your UI
const config = overlay.keybinds.getConfig();

// Persist a new binding - saved to disk automatically
overlay.keybinds.updateKeybind("toggleHud", {
	keys: ["ControlLeft", "KeyH"],
	mode: "toggle",
});
While the user is recording a new key combination, call overlay.keybinds.pauseKeybindListening() first and overlay.keybinds.resumeKeybindListening() after. Otherwise, pressing keys during recording can trigger existing keybinds - like hiding the very settings window they’re typing into.
overlay.keybinds.pauseKeybindListening();
const newKeys = await recordKeysFromUser();
overlay.keybinds.resumeKeybindListening();

overlay.keybinds.updateKeybind("toggleHud", { keys: newKeys, mode: "toggle" });

FAQ

Yes. Keybinds are captured through Overlayed’s native keyboard hook in the game, so they fire while the game has focus - including exclusive fullscreen. The overlay window itself doesn’t need focus, and it doesn’t matter whether the window is currently hidden.
Overlayed observes key presses; it doesn’t stop the game from also acting on them. Pick defaults that rarely clash with common game binds (e.g. Alt-modified combinations rather than bare letters), and give users a way to rebind. When users update keybinds, validate that two of your own keybinds don’t end up with the same combination.
Matching runs on every key press against the full set of currently held keys. A keybind whose keys exactly match that set wins; if nothing matches exactly, any keybind whose keys are all held fires - so ["AltLeft", "KeyX"] triggers even if an unrelated key is also down. Be careful defining one keybind as a subset of another (like ["AltLeft", "KeyX"] and ["AltLeft", "ShiftLeft", "KeyX"]): because keys arrive one at a time, pressing Alt, then X, then Shift exactly matches the two-key bind mid-sequence and fires it before the three-key bind.
Yes. on supports multiple listeners per keybind, so several windows can react to the same press. The reverse also works: nothing stops two keybind names from pointing at the same window.
In a keybinds.json file in your app’s data directory. Overlayed manages it entirely - updateKeybind and updateKeybinds write to it, and getConfig() reads from it. You never need to touch the file yourself.
No. Keybind listening is torn down automatically when the app quits. Since keybinds aren’t OS-level global shortcuts, there’s nothing left registered with the system after a crash either.
No - keybind names are fixed at setup. You can update an existing keybind’s keys and mode at runtime, but new keybinds require declaring them in the overlayed() config. Also note there is currently no migration path for renaming a keybind, so choose names you can live with.
Check these in order:
  1. Key codes: make sure you’re using KeyboardEvent#code values ("KeyX", "Digit1", "Backquote"), not characters. Unknown keys are logged as errors.
  2. Left/right modifiers: "AltLeft" and "AltRight" are different keys.
  3. Logs: every trigger is logged as accepted or rejected (with your rejection reason), which tells you whether the keybind fired but the listener blocked it. See Logging.
  4. Paused listening: verify you didn’t call pauseKeybindListening() without a matching resume.

Next Steps

Keybinds Reference

The full keybinds API: events, updating, pausing, and rejection.

Creating Windows

In-game vs. out-of-game windows and how to create them.

Render Windows

Layers, input, and the extra methods on in-game windows.

Blocking Game Input

Prevent input from reaching the game while your window is open.