A JavaScript routing library with easy navigation control and monitoring.
trike is a browser history wrapper that solves common problems with the standard History API:
- Detecting navigation direction (back/forward) on popstate events
- Preventing users from leaving the site via the back button (
canLeaveBackoption) - Persisting and restoring navigation history on page refresh/tab restore
- Full compatibility with
react-routervia thehistorypackage interface
# Using pnpm
pnpm add @trike/history
# Using npm
npm install @trike/history
# Using yarn
yarn add @trike/history- @trike/history - Core library with history and history controllers
import {
createTrikeHistory,
createTrikeLocationController
} from '@trike/history';
// Create controller (manages navigation entries in memory)
const controller = createTrikeLocationController({
canLeaveBack: false, // prevent leaving site via back button
});
// Create history instance
const history = createTrikeHistory(controller);
// Use like standard history
history.push('/dashboard');
history.replace('/settings');
history.back();
// Listen to navigation events with direction info
history.listenNavigation((event) => {
console.log(event.direction); // 'forward' | 'back' | 'replace'
console.log(event.source); // 'programmatic' | 'browser'
console.log(event.from.location, event.to.location);
});Browser's popstate event doesn't indicate navigation direction. When user clicks back or forward button, you only get
a POP action without knowing which way they went.
Trike maintains a virtual stack of 1-3 entries in browser history with indices { index: 1 | 2 | 3 }. By tracking the
current index, it determines navigation direction. The actual navigation history is stored in TrikeLocationController
in memory and persisted to browser state.
- TrikeHistory — wrapper over
window.history, implementsHistoryinterface from thehistorypackage - TrikeLocationController — stores the full navigation stack in memory, handles back/forward logic
import {createTrikeHistory, createTrikeLocationController} from '@trike/history';
import {Router} from 'react-router-dom';
const controller = createTrikeLocationController({canLeaveBack: false});
const history = createTrikeHistory(controller);
function App() {
return (
<Router history = {history} >
{/* your routes */}
< /Router>
);
}history.listenNavigation((event) => {
if (event.direction === 'back' && event.source === 'browser') {
// User clicked browser's back button
analytics.track('browser_back_navigation');
}
});// Block navigation with confirmation prompt
const unblock = history.blockV4('You have unsaved changes. Leave anyway?');
// Later, remove the block
unblock();Creates a controller that manages navigation history in memory.
| Option | Type | Default | Description |
|---|---|---|---|
canLeaveBack |
boolean |
false |
If false, prevents leaving the site via back button |
Creates a history instance. Returns ITrikeHistory which extends the standard History interface.
Navigation Methods:
push(path, state?)— navigate to a new locationreplace(path, state?)— replace current locationback()/goBack()— go back (returnsbooleanindicating success)forward()/goForward()— go forward (returnsboolean)go(n)— go n steps (returnsboolean)
Listeners:
listen(listener)— standard history listenerlistenNavigation(listener)— rich event listener with direction/source info
Other:
blockV4(prompt?)— block navigation with optional confirmation messagecreateHref(location)— create URL string from locationdestroy()— cleanup listeners
trike is built with TypeScript and provides full type safety
Trike includes comprehensive tests using Vitest:
# Run all tests
pnpm test
# Run tests for specific package
pnpm --filter @trike/history test
# Watch mode
pnpm test:watchtrike/
├── packages/
│ └── history/ # History library
├── apps/
│ └── dev-app/ # Demo application (Preact)
├── configs/ # Shared configurations
└── .changeset/ # Changesets for versioning
# Install dependencies
pnpm install
# Build all packages
pnpm build
# Build specific package
pnpm --filter @trike/history build
# Run demo app
pnpm --filter dev-app dev
# Run linter
pnpm lint
# Type check
pnpm typecheck
# Format code
pnpm format- Fork the repository
- Create a feature branch
- Make your changes
- Run tests and linters:
pnpm test && pnpm lint && pnpm typecheck - Create a changeset:
pnpm changeset - Submit a pull request
- Node.js: >= 18
- TypeScript: >= 5.0
- Module format: ESM only
- Target: ES5 (transpiled output)
Trike works in all modern browsers.
MIT License - see LICENSE file for details.
Developed by Vladimir Sannikov
Built with ❤️ using TypeScript