{"id":20455108,"url":"https://github.com/atomic-router/atomic-router","last_synced_at":"2025-05-16T00:09:03.423Z","repository":{"id":43171456,"uuid":"421223374","full_name":"atomic-router/atomic-router","owner":"atomic-router","description":"Platform-agnostic router that does not break your architecture","archived":false,"fork":false,"pushed_at":"2025-05-07T18:14:47.000Z","size":1694,"stargazers_count":157,"open_issues_count":32,"forks_count":20,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-13T04:01:40.661Z","etag":null,"topics":["atomic-router","effector","forest","javascript","js","router","routing","solid","solidjs","ts","typescript"],"latest_commit_sha":null,"homepage":"https://atomic-router.github.io","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/atomic-router.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["atomic-router"]}},"created_at":"2021-10-26T00:11:40.000Z","updated_at":"2025-05-12T12:39:29.000Z","dependencies_parsed_at":"2023-11-29T09:25:53.230Z","dependency_job_id":"d82c8f96-4fcb-4929-8fc8-9b6a89fea0e0","html_url":"https://github.com/atomic-router/atomic-router","commit_stats":{"total_commits":235,"total_committers":13,"mean_commits":"18.076923076923077","dds":0.4085106382978724,"last_synced_commit":"3c1d038d162b567bc29c44a3766d600eb797d010"},"previous_names":["kelin2025/atomic-router"],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomic-router%2Fatomic-router","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomic-router%2Fatomic-router/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomic-router%2Fatomic-router/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atomic-router%2Fatomic-router/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atomic-router","download_url":"https://codeload.github.com/atomic-router/atomic-router/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253870865,"owners_count":21976613,"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":["atomic-router","effector","forest","javascript","js","router","routing","solid","solidjs","ts","typescript"],"created_at":"2024-11-15T11:17:56.507Z","updated_at":"2025-05-16T00:08:58.349Z","avatar_url":"https://github.com/atomic-router.png","language":"TypeScript","funding_links":["https://github.com/sponsors/atomic-router"],"categories":[],"sub_categories":[],"readme":"# Atomic Router\n\nSimple routing implementation that provides abstraction layer instead of inline URL's and does not break your architecture\n\n- Type-safe\n- No inline URL's\n- Atomic routes\n- Does not break architecture\n- Framework-agnostic\n- Isomorphic (pass your own `history` instance and it works everywhere)\n\n### Read the docs: [atomic-router.github.io](https://atomic-router.github.io)\n\n\u003e ❗️ **Attention**: At the moment atomic-router team collecting issues and feature requests to improve current design. Upgrade atomic-router version with caution. We are going to write migration guide when/if the release will contain breaking changes. Thank you for reporting issues 🧡\n\n### Get view-library bindings\n\n- ⚛️ [**React**](https://github.com/atomic-router/react)\n- 🍃 [**Forest**](https://github.com/atomic-router/forest)\n- [**Solid**](https://github.com/atomic-router/solid)\n\n## Installation\n\n```bash\n$ npm install effector atomic-router\n```\n\n## Initialization\n\nCreate your routes wherever you want:\n\n```ts\n// pages/home\nimport { createRoute } from 'atomic-router';\nexport const homeRoute = createRoute();\n\n// pages/posts\nimport { createRoute } from 'atomic-router';\nexport const postsRoute = createRoute\u003c{ postId: string }\u003e();\n```\n\nAnd then create a router\n\n```ts\n// app/routing\nimport { createHistoryRouter } from 'atomic-router';\nimport { createBrowserHistory, createMemoryHistory } from 'history';\nimport { homeRoute } from '@/pages/home';\nimport { postsRoute } from '@/pages/posts';\n\nconst routes = [\n  { path: '/', route: homeRoute },\n  { path: '/posts', route: postsRoute },\n];\n\nconst router = createHistoryRouter({\n  routes: routes,\n});\n\n// Attach history\nconst history = isSsr ? createMemoryHistory() : createBrowserHistory();\nrouter.setHistory(history);\n```\n\n## Why atomic routes?\n\nThere are 3 purposes for using atomic routes:\n\n- To abstract the application from hard-coded paths\n- To provide you a declarative API for a comfortable work\n- To avoid extra responsibility in app features\n\n## Examples\n\n\u003cdetails\u003e\n  \u003csummary\u003eFetch post on page open\u003c/summary\u003e\n\n1. In your model, create effect and store which you'd like to trigger:\n\n```tsx\nexport const getPostFx = createEffect\u003c{ postId: string }, Post\u003e(\n  ({ postId }) =\u003e {\n    return api.get(`/posts/${postId}`);\n  }\n);\n\nexport const $post = restore(getPostFx.doneData, null);\n```\n\n2. And just trigger it when `postPage.$params` change:\n\n```tsx\n//route.ts\nimport { createRoute } from 'atomic-router';\nimport { getPostFx } from './model';\n\nconst postPage = createRoute\u003c{ postId: string }\u003e();\n\nsample({\n  source: postPage.$params,\n  filter: postPage.$isOpened,\n  target: getPostFx,\n});\n```\n\n\u003c/details\u003e\n\u003cdetails\u003e\n  \u003csummary\u003eAvoid breaking architecture\u003c/summary\u003e\n\nImagine that we have a good architecture, where our code can be presented as a dependency tree.  \n So, we don't make neither circular imports, nor they go backwards.  \n For example, we have `Card -\u003e PostCard -\u003e PostsList -\u003e PostsPage` flow, where `PostsList` doesn't know about `PostsPage`, `PostCard` doesn't know about `PostsList` etc.\n\nBut now we need our `PostCard` to open `PostsPage` route.  \n And usually, we add extra responisbility by letting it know what the route is\n\n```tsx\nconst PostCard = ({ id }) =\u003e {\n  const post = usePost(id);\n\n  return (\n    \u003cCard\u003e\n      \u003cCard.Title\u003e{post.title}\u003c/Card.Title\u003e\n      \u003cCard.Description\u003e{post.title}\u003c/Card.Description\u003e\n      {/* NOOOO! */}\n      \u003cLink to={postsPageRoute} params={{ postId: id }}\u003e\n        Read More\n      \u003c/Link\u003e\n    \u003c/Card\u003e\n  );\n};\n```\n\nWith `atomic-router`, you can create a \"personal\" route for this card:\n\n```tsx\nconst readMoreRoute = createRoute\u003c{ postId: id }\u003e();\n```\n\nAnd then you can just give it the same path as your `PostsPage` has:\n\n```tsx\nconst routes = [\n  { path: '/posts/:postId', route: readMoreRoute },\n  { path: '/posts/:postId', route: postsPageRoute },\n];\n```\n\nBoth will work perfectly fine as they are completely independent\n\n\u003c/details\u003e\n\n## API Reference\n\n```tsx\n// Params is an object-type describing query params for your route\nconst route = createRoute\u003cParams\u003e();\n\n// Stores\nroute.$isOpened; // Store\u003cboolean\u003e\nroute.$params; // Store\u003c{ [key]: string }\u003e\nroute.$query; // Store\u003c{ [key]: string }\u003e\n\n// Events (only watch 'em)\nroute.opened; // Event\u003c{ params: RouteParams, query: RouteQuery }\u003e\nroute.updated; // Event\u003c{ params: RouteParams, query: RouteQuery }\u003e\nroute.closed; // Event\u003c{ params: RouteParams, query: RouteQuery }\u003e\n\n// Effects\nroute.open; // Effect\u003cRouteParams\u003e\nroute.navigate; // Effect\u003c{ params: RouteParams, query: RouteQuery }\u003e\n\n// Note: Store, Event and Effect is imported from 'effector' package\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatomic-router%2Fatomic-router","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatomic-router%2Fatomic-router","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatomic-router%2Fatomic-router/lists"}