{"id":23128231,"url":"https://github.com/victorqueiroz/halter","last_synced_at":"2026-05-02T19:33:18.459Z","repository":{"id":32501846,"uuid":"109846398","full_name":"VictorQueiroz/halter","owner":"VictorQueiroz","description":"Simple JS router with support for HTML5 history","archived":false,"fork":false,"pushed_at":"2023-01-03T18:23:27.000Z","size":394,"stargazers_count":1,"open_issues_count":7,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-03T09:49:22.882Z","etag":null,"topics":["convenience","halter","html5-history","js-router","labeled-routes","react"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/VictorQueiroz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-11-07T14:28:43.000Z","updated_at":"2020-06-13T01:31:00.000Z","dependencies_parsed_at":"2023-01-14T21:25:48.755Z","dependency_job_id":null,"html_url":"https://github.com/VictorQueiroz/halter","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VictorQueiroz%2Fhalter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VictorQueiroz%2Fhalter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VictorQueiroz%2Fhalter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/VictorQueiroz%2Fhalter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/VictorQueiroz","download_url":"https://codeload.github.com/VictorQueiroz/halter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247128738,"owners_count":20888234,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["convenience","halter","html5-history","js-router","labeled-routes","react"],"created_at":"2024-12-17T09:17:48.849Z","updated_at":"2026-05-02T19:33:17.102Z","avatar_url":"https://github.com/VictorQueiroz.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# halter ![Travis CI build](https://travis-ci.org/VictorQueiroz/halter.svg?branch=master)\n\nSimple independent JS router\n\n### Usage\n\nFirst remember to install `history` NPM module of your choice:\n\n```\nnpm install history\n```\n\nThen set up your routes:\n\n```ts\nimport { createMemoryHistory } from 'history';\nimport { Router } from 'halter';\n\nasync function bootstrap() {\n    const router = new Router(createMemoryHistory()).addRoute({\n        path: '/',\n        callback() {\n            // it will be triggered when the browser history match \"/\"\n        }\n    });\n\n    // very important to listen to changes on history\n    await router.init();\n\n    // Stop listening to changes on history\n    router.destroy();\n}\n```\n\n### Labeled routes\n\nFollowing an similar approach of Angular UI for Angular 1.x we decided to create labeled routes for convenience, so we can build our app based on labeled routes and not on routes paths it self. For example when you create your `\u003cLink/\u003e` in your React app instead of putting the path to go when the user click the component, you put a convenient label which will match to be the path you need, check the following example:\n\n```ts\nimport { createBrowserHistory } from 'history';\nimport { Router } from 'halter';\nimport PostDetail from './components/PostDetail';\nimport PostsList from './components/PostsList';\nimport Link from './components/Link';\n\nconst router = new Router(createBrowserHistory()).addRoute({\n    name: 'post.detail'\n    path: '/posts/{id:[0-9]+}',\n    callback: ({ params }) =\u003e {\n        ReactDOM.render(\n            \u003cPostDetail postId={params.get('id')} /\u003e,\n            document.getElementById('app'));\n    }\n}).addRoute({\n    name: 'post.list',\n    path: '/posts/list',\n    callback: () =\u003e {\n        ReactDOM.render(\u003cdiv\u003e\n            \u003cPostsList getContents={posts =\u003e posts.map(post =\u003e (\n                \u003cLink key={post.id} to=\"post.detail\" params={new Map().set('id', 'post.id')}\u003e\n                    {post.title}\n                \u003c/Link\u003e\n            ))}\n        \u003c/div\u003e, document.getElementById('app'));\n    }\n});\n\nrouter.pushState('post.detail', new Map().set('id', '1040'));\n```\n\nThe advantages I see on this approach is that you don't need to keep track of paths itself but the route labels instead. So if you need to change a route path you'll be able to do this without worrying about looking all over through your code searching for that path.\n\nRemember that whenever you don't name your route definitions, it'll be the route path (i.e. if you have /posts/{id:[0-9]+} with no name, the name will automatically be /posts/{id:[0-9]+}).\n\n### Listening to changes\n\nListening to changes on history API it's pretty simple.\n\n```js\nconst router = new Router();\n\nrouter.listen((name, params, query) =\u003e (\n    console.log('New path is %s, params are %o and query is %o', name, params, query);\n));\n```\n\n### Integration with React\n\nIntegration with React it's pretty straightforward. You use `\u003cRouterView routes={x} router={y} /\u003e` from `react-halter` NPM module and it'll automatically create necessary routes according to the nested structure provided through `routes` property. See the steps below:\n\n1. Install `react-halter` module:\n\n```\nnpm install --save react-halter\n```\n\n2. Set up routes:\n\n```ts\nconst routes = [{\n    path: '/',\n    name: 'app',\n    component: HomeWrapper,\n    childRoutes: [{\n        name: 'post',\n        path: 'posts/{id:[A-z0-9]+}',\n        component: Post\n    }, {\n        path: 'login',\n        name: 'login',\n        component: Login\n    }]\n}, {\n    name: 'dashboard',\n    path: '/dashboard',\n    component: Dashboard,\n    onBefore: rules.isGuest\n}];\nReactDOM.render(\n    \u003cRouterView\n        router={router}\n        routes={router} /\u003e,\n    document.getElementById('app')\n);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvictorqueiroz%2Fhalter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvictorqueiroz%2Fhalter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvictorqueiroz%2Fhalter/lists"}