TanStack Hotkeys: type-safe keyboard shortcuts with a framework adapter for each
Type-Safe keyboard shortcuts library with awesome devtools
At a glance
- What is it?
- TanStack Hotkeys is a beta library for keyboard shortcuts in the browser, offering template-string bindings like Mod+Shift+S, a cross-platform Mod key, a singleton manager, Vim-style sequences and a devtools panel, with adapters for React, Vue, Angular, Svelte, Solid, Lit, Preact, Alpine, Ember and Octane. It suits teams that want one shortcut layer across many apps, and its beta status and adapter sprawl are the trade-offs.
- Who is it for?
- TanStack Hotkeys fits a web team that wants shortcut handling in one place, with a Mod key that behaves correctly across platforms and a devtools panel to see what is bound, and it does not fit a project that cannot take a beta dependency into production.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the library promises: typed bindings and a cross-platform Mod
TanStack Hotkeys is described as type-safe keyboard shortcuts for the web, built around template-string bindings, parsed objects, a cross-platform Mod key, a singleton Hotkey Manager, and utilities for cheatsheet UIs, and it is built to stay SSR-friendly.
The type-safe bindings come in two forms. You can write a shortcut as a template string, the readme's examples being Mod+Shift+S and Escape, or you can use a parsed object for full control. The first is what you want in application code, the second is what you reach for when the binding is generated or composed.
The Mod key is the detail that separates this from most shortcut libraries. It maps to Cmd on macOS and Ctrl on Windows and Linux, so a single binding string means the right thing on every platform without a platform check in the binding table.
The batteries-included list in the readme covers validation and matching, sequences in the Vim style, key-state tracking, recorder UI helpers, framework adapters and devtools. The cheatsheet and recorder pieces are worth calling out, because a shortcut system without a way to discover the shortcuts is a shortcut system half of your users will never find.
The project says it is in beta, is being actively developed, and is open to feedback and contributions. That word is doing real work in the risk column, and it is the first thing to weigh.
The options that decide whether a shortcut fires
Beyond the binding itself, the options determine when a shortcut is allowed to run, and the readme lists them as keydown and keyup, preventDefault, stopPropagation, conditional enabled, and requireReset.
The keydown and keyup choice is the foundation. A keydown binding fires when the key goes down, which is what a command palette wants. A keyup binding fires when the key comes back up, which is what a modifier-driven gesture wants, because the action happens once the combination is released rather than on the first key of the pair. Getting this wrong is the classic source of a shortcut that fires twice or fires when you only meant to press one of the keys.
preventDefault and stopPropagation are the escape hatches for when a shortcut has to suppress the browser's own behaviour, such as a built-in find shortcut, or has to stop the event from reaching other handlers. Both are opt-in, which is the right default, since a library that swallows events by default breaks every other library listening on the same key.
The conditional enabled option lets a binding be live or dead depending on application state, which is how you keep a shortcut from firing in a modal or while a text field has focus. requireReset is the option to look at closely: it means the shortcut only triggers after the keys have been released and pressed again, rather than firing as soon as the combination is complete. That is the difference between a shortcut you can hold down and one that fires once per deliberate press.
A singleton manager, and why that matters for a page with many shortcuts
The Hotkey Manager is a singleton, and that single word carries most of the design decisions in the library.
A page with shortcuts has one keyboard. If each component registered its own document-level listener, you would end up with ordering problems, duplicate handlers when a component mounts twice, and a bookkeeping problem on teardown. A singleton manager is the answer to that: one place owns the listeners and the registry of bindings.
The cost of a singleton is that it is global state, and global state has to be reset when the app changes shape. A single-page application that swaps out a whole screen of components has to make sure the old bindings are unregistered, or the shortcut that used to open one dialog now also opens another one that happens to use the same combination. The readme does not document a reset or teardown procedure in the visible text, so if you are integrating this into an app with heavy route-level mounting and unmounting, that is a question to put to the documentation site.
Sequences, key-state tracking and the recorder helpers all sit on top of this manager. Sequences are the Vim-style multi-key form, g then i, and they need the manager to hold state between keystrokes. Key-state tracking is what makes requireReset and keyup bindings work. The recorder UI helpers exist to let a user record a custom combination and store it, which is a common feature in editors and design tools.
Ten framework adapters, and a monorepo that publishes sixteen packages
The readme says you may know TanStack Hotkeys by its adapter names, and it lists them: Alpine Hotkeys, Ember Hotkeys, Octane Hotkeys, React Hotkeys, Preact Hotkeys, Solid Hotkeys, Angular Hotkeys, Vue Hotkeys, Lit Hotkeys and Svelte Hotkeys.
That list is longer than it looks, because each framework tends to have a reactive model, a lifecycle and a component idiom, and an adapter is what translates a binding into that framework's world. The examples directory matches the list, with an examples/ directory for alpine, angular, ember, lit, octane, preact, react, solid, svelte and vue, plus a vanilla one, which is the no-framework case.
The build script in the repository's package.json shows the package set being published, and it is sixteen packages: hotkeys, hotkeys-devtools, and for angular, react, preact, solid, vue, lit, svelte, alpine, ember and octane, a library package and a devtools package for react, preact, solid and vue. The core package is built on its own with a dedicated build:core target.
That is a lot of surface for a beta library, and it cuts both ways. It means an existing app of any of these frameworks gets a first-class path rather than a hand-rolled wrapper, and it means every adapter has to be kept in step with the core as the API moves. The readme notes the library may be known by adapter name, which is a fair warning that a search for the tooling by the name you know may not lead to the core package.
Devtools, and the workspace that builds all of it
The repository description calls out awesome devtools as a defining feature, and there are separate devtools packages for React, Preact, Solid and Vue.
For a keyboard shortcut library, devtools are not decoration. The question you always need answered is which shortcuts are currently registered, which one is focused, what the key state is, and whether the last keystroke matched anything. Debugging that by adding console output to your own handlers is miserable, so a panel that shows the live registry is a real working tool rather than a novelty.
The build system is a pnpm workspace driven by nx. The package manager is pinned to [email protected], the package type is module, and the engines field in the root package.json reads:
"engines": {
"pnpm": ">=12.6.0",
"node": "^22.22.3 || ^24.15.0 || >=26.0.0"
},The build script runs nx affected, skipping the cache and excluding the examples, and then runs size-limit, so bundle size is a gate in the build rather than an afterthought. There is a separate build:all target that runs every project.
The rest of the toolchain is standard TanStack practice. Changesets handle versioning and publishing, vitest.workspace.ts drives the test projects, there is an e2e directory, knip.json checks for unused code, typedoc.json generates the API documentation, and prettier and eslint handle formatting and linting. The top-level entries also include AGENTS.md, an .intent directory, a .cursorignore and a .coderabbit.yaml, which is a sign of a repository that has been set up for automated tooling workflows.
Where to get it, and what the documentation has to carry
The readme does not include an installation command, and it points to the documentation site instead, with a Read the docs link to tanstack.com/hotkeys. The package is published on npm as @tanstack/hotkeys, and the per-framework packages follow the same scope.
That is a deliberate choice by the project, and it has a consequence for anyone evaluating it. The library is in beta, the API is expected to move, and the readme is a summary rather than a reference. The details that matter for a decision, such as the exact shape of the parsed object binding form, the signature of the manager's registration call, and the semantics of requireReset at the edges, live in the documentation site and in the typedoc-generated API reference rather than in the repository readme.
The repository does contain the source, the typedoc configuration, the examples for every supported framework and the e2e suite, so the truth is inspectable even where the prose is thin. For a library in beta, that is the right place to look before you commit.
The MIT licence applies, and the repository is not archived with the last push on 2026-10-19, which is the same day as the recent releases: @tanstack/vue-hotkeys at 0.16.0 and 0.15.1, and @tanstack/vue-hotkeys-devtools at 0.11.0.
Editorial conclusion
TanStack Hotkeys fits a web team that wants shortcut handling in one place, with a Mod key that behaves correctly across platforms and a devtools panel to see what is bound, and it does not fit a project that cannot take a beta dependency into production. Before adopting it, read the framework adapter docs for the framework you use, check the requireReset and enabled options against your own needs for held keys, and confirm your Node and pnpm versions satisfy the ranges the repository's package.json requires.
Frequently asked questions
What is TanStack Hotkeys and what does it do?
It is a type-safe keyboard shortcut library for the web, with template string bindings like Mod+Shift+S or parsed objects, options for keydown and keyup, preventDefault, stopPropagation, conditional enabled and requireReset, plus sequences, key-state tracking, recorder helpers, framework adapters and devtools.
How does the Mod key work in TanStack Hotkeys?
Mod is a cross-platform modifier that maps to Cmd on macOS and Ctrl on Windows and Linux, so a single binding string behaves correctly on every platform without platform checks in the binding table.
Which frameworks does TanStack Hotkeys support?
Adapters exist for Alpine, Ember, Octane, React, Preact, Solid, Angular, Vue, Lit and Svelte, and the repository carries an examples directory for each of them plus a vanilla example. Separate devtools packages are published for React, Preact, Solid and Vue.
What does requireReset do in a TanStack Hotkeys binding?
It makes the shortcut trigger only after the keys are released and pressed again, rather than firing as soon as the combination is completed. It is one of the documented binding options alongside keydown and keyup, preventDefault, stopPropagation and conditional enabled.
Is TanStack Hotkeys ready for production use?
The readme states that TanStack Hotkeys is in beta, that the project is actively developing it, and that it is open to feedback and contributions. The build is a pnpm workspace driven by nx with size-limit and vitest, and the engines field requires pnpm 12.6.0 or above and Node 22.22.3, 24.15.0 or 26 and above.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/tanstack-hotkeys)Was this useful?