{"id":19228226,"url":"https://github.com/capitec/omni-router","last_synced_at":"2025-04-16T01:09:22.435Z","repository":{"id":65042414,"uuid":"575745935","full_name":"capitec/omni-router","owner":"capitec","description":"Framework agnostic, zero dependency, client-side web component router.","archived":false,"fork":false,"pushed_at":"2025-04-09T14:50:21.000Z","size":908,"stargazers_count":16,"open_issues_count":6,"forks_count":2,"subscribers_count":2,"default_branch":"develop","last_synced_at":"2025-04-16T01:09:03.310Z","etag":null,"topics":["router","single-page-app","spa-router","vanilla-js"],"latest_commit_sha":null,"homepage":"https://capitec.github.io/open-source/docs/omni-router/","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/capitec.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-12-08T07:50:48.000Z","updated_at":"2025-04-09T10:23:20.000Z","dependencies_parsed_at":"2022-12-25T19:21:52.743Z","dependency_job_id":"615355c0-cd99-4b88-87bf-882117ef26e2","html_url":"https://github.com/capitec/omni-router","commit_stats":{"total_commits":50,"total_committers":7,"mean_commits":7.142857142857143,"dds":"0.45999999999999996","last_synced_commit":"bdeea7cecbcf88eb17433b8a872b9f32610363d0"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capitec%2Fomni-router","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capitec%2Fomni-router/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capitec%2Fomni-router/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capitec%2Fomni-router/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/capitec","download_url":"https://codeload.github.com/capitec/omni-router/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249178212,"owners_count":21225349,"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":["router","single-page-app","spa-router","vanilla-js"],"created_at":"2024-11-09T15:27:13.741Z","updated_at":"2025-04-16T01:09:22.425Z","avatar_url":"https://github.com/capitec.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cbr\u003e\n\n\u003cp align=\"center\"\u003e\u003cimg src=\"./docs/logos/omni.png\" width=\"128\" height=\"128\"/\u003e\u003c/p\u003e\n\n\u003ch3 align=\"center\"\u003eOmni Router\u003c/h3\u003e\n\u003cp align=\"center\"\u003e\u003cstrong\u003e\u003ccode\u003e@capitec/omni-router\u003c/code\u003e\u003c/strong\u003e\u003c/p\u003e\n\u003cp align=\"center\"\u003eFramework agnostic, zero dependency, client-side web component router\u003c/p\u003e\n\n\u003cbr /\u003e\n\n\u003cp align=\"center\"\u003e\n\t\u003ca href=\"https://npmcharts.com/compare/@capitec/omni-router?minimal=true\"\u003e\u003cimg alt=\"Downloads per week\" src=\"https://img.shields.io/npm/dw/@capitec/omni-router.svg\" height=\"20\"/\u003e\u003c/a\u003e\n\t\u003ca href=\"https://www.npmjs.com/package/@capitec/omni-router\"\u003e\u003cimg alt=\"NPM Version\" src=\"https://img.shields.io/npm/v/@capitec/omni-router.svg\" height=\"20\"/\u003e\u003c/a\u003e\n\t\u003ca href=\"https://github.com/capitec/omni-router/actions/workflows/build.yml\"\u003e\u003cimg alt=\"GitHub Build\" src=\"https://github.com/capitec/omni-router/actions/workflows/build.yml/badge.svg\" height=\"20\"/\u003e\u003c/a\u003e\n\t\u003ca href=\"https://github.com/capitec/omni-router/blob/develop/LICENSE\"\u003e\u003cimg alt=\"MIT License\" src=\"https://img.shields.io/github/license/capitec/omni-router\" height=\"20\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n\t\u003ca href=\"https://capitec.github.io/open-source/?repo=Omni-Router\"\u003e\u003cimg alt=\"Docs\" src=\"https://img.shields.io/static/v1?label=docs\u0026message=capitec.github.io/open-source\u0026color=blue\u0026style=flat-square\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cbr/\u003e\n\n\u003cp align=\"center\"\u003e\n\t[\u003ca href=\"#introduction\"\u003eIntroduction\u003c/a\u003e]\n\t[\u003ca href=\"#usage\"\u003eUsage\u003c/a\u003e]\n\t[\u003ca href=\"#api-reference\"\u003eAPI Reference\u003c/a\u003e]\n\t[\u003ca href=\"#contributors\"\u003eContributors\u003c/a\u003e]\n\t[\u003ca href=\"#license\"\u003eLicense\u003c/a\u003e]\n\u003c/p\u003e\n\n\u003cbr/\u003e\n\n---\n\n\u003cbr /\u003e\n\n## Introduction\n\nOmni Router is a simple client-side page router for single page application (SPA) web component projects that enable you to add animated URL based page navigation to your web app.\n\nCore features of the library include:\n- **Framework Agnostic** - The router is provided as a standard HTML [web components](https://developer.mozilla.org/en-US/docs/Web/Web_Components), that can be used in VanillaJS or within any framework, e.g. Lit, React, Vue, Angular, etc.\n- **Web Components** - The router has been specifically built to route pages built using web components.\n- **Lazy Loading** - Web component pages can be lazy loaded using `import('...')`.\n- **Route Guards** - Routes can be protected using guard functions that prevent routing based on your app logic, e.g. check if the user is logged in.\n- **Animations** - Pages can be animated in and out of view when routing, e.g. fade, slide, pop, etc.\n- **Browser History** - Integrates with the browser history API to push, pop, and replace paths.\n- **Mobile Friendly** - Navigating back reverses the route load animation, allowing mobile-like user experiences e.g. sliding routes in and out.\n- **Lightweight** - The library is small and comes with zero dependencies, minimizing bloat to your project.\n\n\u003cbr /\u003e\n\n## Usage\n\n1️⃣ \u0026nbsp; Install the library in your project.\n\n```bash\nnpm install @capitec/omni-router\n```\n\n2️⃣ \u0026nbsp; Specify a base href location in your `index.html` to use as root for page navigation.\n\n```html\n\u003cbase href=\"/\"\u003e\n```\n\n3️⃣ \u0026nbsp; Import the ```Router``` package.\n\n```js\n// JS import\nimport '@capitec/omni-router';\n\n// or HTML import\n\u003cscript type=\"module\" src=\"/node_modules/omni-router/dist/index.js\"\u003e\u003c/script\u003e\n```\n\n4️⃣ \u0026nbsp; Place the `\u003comni-router\u003e` tag in your web page, all routes will be rendered in this container.\n```html\n\u003comni-router\u003e\u003c/omni-router\u003e\n```\n\n5️⃣ \u0026nbsp; Define the pages you will route to.\n\n```js\n// Register the app routes.\nRouter.addRoute({\n    name: 'view-fade',\n    title: 'Fade',\n    path: '/fade',\n    animation: 'fade',\n    load: () =\u003e import('./views/ViewFade'),\n    isDefault: true\n});\n\n// Load the route matching the current browser path.\nRouter.load();\n```\n\n\u003cbr\u003e\n\n### 💡 Example\n\nThis example sets up a simple web page containing the Omni Router. Routes are registered on page load to navigate to individual web component pages using fade, slide, and pop animations.\n\n```html\n\u003c!DOCTYPE html\u003e\n\n\u003chtml lang=\"en\"\u003e\n    \u003chead\u003e\n        \u003cmeta charset=\"utf-8\"\u003e\n\n        \u003ctitle\u003eOmni Router Demo\u003c/title\u003e\n\n        \u003cbase href=\"/\"\u003e\n\n        \u003cscript type=\"module\"\u003e\n            import { Router } from '@capitec/omni-router';\n\n            // Register the app routes.\n            Router.addRoute({\n                name: 'view-fade',\n                title: 'Fade',\n                path: '/fade',\n                animation: 'fade',\n                load: () =\u003e import('./views/ViewFade'),\n                isDefault: true\n            });\n\n            Router.addRoute({\n                name: 'view-slide',\n                title: 'Slide',\n                path: '/slide',\n                animation: 'slide',\n                load: () =\u003e import('./views/ViewSlide')\n            });\n\n            Router.addRoute({\n                name: 'view-pop',\n                title: 'Pop',\n                path: '/pop',\n                animation: 'pop',\n                load: () =\u003e import('./views/ViewPop')\n            });\n\n            Router.addRoute({\n                name: 'view-guarded',\n                title: 'Guarded Route',\n                path: '/guarded',\n                load: () =\u003e import('./views/ViewGuarded'),\n                guard: () =\u003e !this._isUserLoggedIn()\n            });\n\n            Router.addRoute({\n                name: 'view-fallback',\n                title: 'Fallback Route',\n                path: '/error404',\n                load: () =\u003e import('./views/ViewFallback'),\n                isFallback: true\n            });\n\n            // Load the route matching the current browser path.\n            Router.load();\n        \u003c/script\u003e\n\n        \u003cscript type=\"module\" src=\"./AppShell.js\"\u003e\u003c/script\u003e\n    \u003c/head\u003e\n\n    \u003cbody\u003e\n        \u003comni-router\u003e\u003c/omni-router\u003e\n    \u003c/body\u003e\n\u003c/html\u003e\n```\n\n```js\n// view/ViewFade.js\n\nimport { Router } from '@capitec/omni-router';\n\nclass ViewFade extends HTMLElement {\n\n    constructor() {\n\n        super();\n\n        // Create the DOM content template.\n        const template = document.createElement('template');\n        template.innerHTML = `\n            \u003cstyle\u003e\n                :host {\n                    .background-color: white;\n                }\n            \u003c/style\u003e\n\n            \u003ch1\u003eHello World\u003c/h1\u003e\n\n            \u003cbutton id=\"back\"\u003e⬅ Go Back\u003c/button\u003e\n        `;\n\n        // Create a shadow root for the content.\n        this.attachShadow({ mode: 'open' });\n\n        // Add the template content to the shadow root.\n        this.shadowRoot.appendChild(template.content.cloneNode(true));\n\n        // Register element event listeners.\n        this.shadowRoot.querySelector('#back').addEventListener('click', () =\u003e Router.pop());\n    }\n}\n\ncustomElements.define('view-fade', ViewFade);\n```\n\n\u003cbr\u003e\n\n### 🚩 Framework Starter Projects\n\nStarter projects are available in the [examples directory](./examples) for the following frameworks:\n\n\u003cdiv align=\"center\"\u003e\n\t\u003ctable\u003e\n\t\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\u003ctd align=\"center\"\u003e\n\t\t\t\t\t\u003ca href=\"./examples/vanilla\"\u003e\n\t\t\t\t\t\t\u003cimg src=\"./docs/logos/javascript.png\" width=\"128\" height=\"128\" alt=\"Vanilla JS\" /\u003e\n\t\t\t\t\t\t\u003cbr /\u003e\n\t\t\t\t\t\t\u003cp\u003e\u003cb\u003eVanilla JS\u003c/b\u003e\u003cbr\u003e\u003csub\u003e\u003c/sub\u003c/p\u003e\n\t\t\t\t\t\u003c/a\u003e\n\t\t\t\t\u003c/td\u003e\n\t\t\t\t\u003ctd align=\"center\"\u003e\n\t\t\t\t\t\u003ca href=\"./examples/lit\"\u003e\n\t\t\t\t\t\t\u003cimg src=\"./docs/logos/lit.png\" width=\"128\" height=\"128\" alt=\"Lit\" /\u003e\n\t\t\t\t\t\t\u003cbr /\u003e\n\t\t\t\t\t\t\u003cp\u003e\u003cb\u003eLit\u003c/b\u003e\u003cbr\u003e\u003csub\u003e\u003c/sub\u003c/p\u003e\n\t\t\t\t\t\u003c/a\u003e\n\t\t\t\t\u003c/td\u003e\n\t\t\t\t\u003ctd align=\"center\"\u003e\n\t\t\t\t\t\u003ca href=\"./examples/angular\"\u003e\n\t\t\t\t\t\t\u003cimg src=\"./docs/logos/angular.png\" width=\"128\" height=\"128\" alt=\"Lit\" /\u003e\n\t\t\t\t\t\t\u003cbr /\u003e\n\t\t\t\t\t\t\u003cp\u003e\u003cb\u003eAngular\u003c/b\u003e\u003cbr\u003e\u003csub\u003e(coming soon)\u003c/sub\u003c/p\u003e\n\t\t\t\t\t\u003c/a\u003e\n\t\t\t\t\u003c/td\u003e\n\t\t\t\t\u003ctd align=\"center\"\u003e\n\t\t\t\t\t\u003ca href=\"./examples/vue\"\u003e\n\t\t\t\t\t\t\u003cimg src=\"./docs/logos/vue.png\" width=\"128\" height=\"128\" alt=\"Lit\" /\u003e\n\t\t\t\t\t\t\u003cbr /\u003e\n\t\t\t\t\t\t\u003cp\u003e\u003cb\u003eVue\u003c/b\u003e\u003cbr\u003e\u003csub\u003e(coming soon)\u003c/sub\u003c/p\u003e\n\t\t\t\t\t\u003c/a\u003e\n\t\t\t\t\u003c/td\u003e\n\t\t\t\t\u003ctd align=\"center\"\u003e\n\t\t\t\t\t\u003ca href=\"./examples/react\"\u003e\n\t\t\t\t\t\t\u003cimg src=\"./docs/logos/react.png\" width=\"128\" height=\"128\" alt=\"Lit\" /\u003e\n\t\t\t\t\t\t\u003cbr /\u003e\n\t\t\t\t\t\t\u003cp\u003e\u003cb\u003eReact\u003c/b\u003e\u003cbr\u003e\u003csub\u003e(coming soon)\u003c/sub\u003c/p\u003e\n\t\t\t\t\t\u003c/a\u003e\n\t\t\t\t\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\u003c/tbody\u003e\n\t\u003c/table\u003e\n\u003c/div\u003e\n\n\u003cbr\u003e\n\n## API Reference\n\n### Route Object\n\nThe ```Route``` object contains the following properties:\n\n| Property | Type | Description |\n| -------- | ---- | ----------- |\n| **name** | string | The unique identifier for the route, must be the tag name of the web component if tag is not set. |\n| **tag** | string | Optional, the registered custom-element tag name for your page web component, e.g. ```'view-login'``` |\n| **path** | string | The relative URL path for the route to set in the browser navigation bar, e.g. ```'/login'``` |\n| **title** | string | The window title to show when the route is loaded, e.g. ```'Login'``` |\n| **animation** | string | Optional, animation to apply when loading the route. Can be one of ```fade```, ```slide```, ```pop``` |\n| **theme** | string | Optional, CSS class name to attach to the route page when loading, useful to apply page level theme variables. Note the `dom=\"light\"` attribute has to be set for this option to take effect. |\n| **metadata** | object | Optional, metadata to store on the route. |\n| **cache** | boolean | Optional, indicator if the route template should be cached and reused, or recreated every time the route is navigated to. |\n| **load** | function | Optional, function to execute before navigating to the route. Typically used to lazy load the page web component, e.g. \u003cbr\u003e```() =\u003e import('./views/ViewLogin')``` |\n| **guard** | function | Optional, function to execute to check if a route may be navigated to. Typically used to limit access to routes., e.g. \u003cbr\u003e```() =\u003e !this._isUserLoggedIn()``` |\n| **isDefault** | boolean | Optional, flag to set this route as the default route to load when the browser URL path is empty or default, e.g. ```/```. Note: can only be applied to 1 route. |\n| **isFallback** | boolean | Optional, flag to set this route as the fallback route to load when the user attempts to navigate to a route that does not exist, e.g. a 404 page. Note: can only be applied to 1 route. |\n\n\u003cbr\u003e\n\n### Path Patterns\n\nThe router supports URL paths for the following patterns:\n\n| Pattern | Example | Matches | Description |\n| ------- | ------- | ------- | ----------- |\n| **/part** | /hello/world | /hello/world | A static path part, will be matched exactly. |\n| **/:param** | /hello/:place | /hello/world | A required path parameter. |\n| **/:param?** | /hello/:place? | /hello\u003cbr\u003e/hello/world | An optional path parameter |\n\n\u003e Note: Path part parameters must be valid URL characters including: Period (.), Dash (-), Characters (a-Z), Numbers (0-9).\n\n\u003cbr\u003e\n\n### Styling\n\nThe router styling can be customized using the following CSS Custom Properties:\n\n| CSS Variable | Default Value | Description |\n| ------------ | ------------- | ----------- |\n| ```--omni-router-animation-duration``` | ```300ms``` | The duration it takes for route pages to be animated into view. |\n| ```--omni-router-animation-z-index``` | ```1000000``` | The z-index to apply to the page being routed to. Set to a value higher than your app's highest z-index value to prevent elements from appearing above the page while routing. |\n\n\u003cbr\u003e\n\n### Router Tag\n\nThe ```\u003comni-router\u003e``` tag exposes the following attributes:\n\n| Function | Description |\n| -------- | ----------- |\n| ```dom=\"shadow\"``` | Attached as shadow DOM to the router, preventing page level CSS from inheriting into the loaded route pages. This is the default. |\n| ```dom=\"light\"``` | Render the router in the parent element DOM, allowing for CSS values to inherit into the loaded route pages. |\n\nThe ```\u003comni-router\u003e``` tag dispatches the following events, that may be useful to subscribe to when wanting to apply changes to a page while a route is lazy loading, e.g. show a loading indicator.\n\n| Event | Description |\n| ----- | ----------- |\n| navigation-started | Fired before the route starts navigating, e.g. after ```guard``` is successful, but before ```load``` is called. |\n| navigation-started | Fired after the route page has completely rendered on screen, e.g. after it was fully animated in. |\n\nThe ```\u003comni-router\u003e``` tag provides the following functions:\n\n| Function | Description |\n| -------- | ----------- |\n| ```clearCache(): void``` | Clear the cache of route components. |\n\n\u003cbr\u003e\n\n### Router Class\n\nFull API documentation [available here](https://capitec.github.io/open-source/?repo=Omni-Router).\n\nThe ```Router``` class provides the following properties and functions:\n\n| Property | Description |\n| -------- | ----------- |\n| ```get currentLocation(): RoutedLocation \\| undefined``` | Get the currently location routed to. |\n| ```get previousLocation(): RoutedLocation \\| undefined``` | Get the previous location routed to. |\n| ```get defaultRoute(): Route \\| undefined ``` | Get the route that should be rendered when navigating to the app base URL. |\n| ```get fallbackRoute(): Route \\| undefined``` | Get the route that should be rendered when navigating to a route that does not exist. |\n\n| Function | Description |\n| -------- | ----------- |\n| ```addEventListener(eventName: RouterEventType, callback: () =\u003e void): void``` | Registers a callback function to be invoked when the router dispatches an event. |\n| ```removeEventListener(eventName: RouterEventType, callback: () =\u003e void): void``` | Removes a callback function from the list of functions to be invoked when the router dispatches an event. |\n| ```addRoute(route: Route): void``` | Add a route from the list of navigable routes. |\n| ```remove(name: string): void``` | Remove a route from the list of navigable routes. |\n| ```getRouteForPath(pathOrUrl: string): Route \\| null``` | Get the registered route for the given path. |\n| ```setDefault(name: string): boolean``` | Set the route that should be rendered when navigating to the app base URL. |\n| ```setFallback(name: string): boolean``` | Set the route that should be rendered when navigating to a route that does not exist. |\n| ```load(): Promise\u003cboolean\u003e``` | Navigate to the current browser URL path. |\n| ```push(path: string, state = {}, animateOut = false): Promise\u003cboolean\u003e``` | Push a new path onto the browser history stack and render it's registered route. |\n| ```replace(path: string, state = {}, animateOut = false): Promise\u003cboolean\u003e``` | Update the current path in the browser history stack with a new path and render it's registered route. |\n| ```pop(delta?: number): Promise\u003cboolean\u003e``` | Pops the current path in the browser history stack and navigate the previous path, or specified number pages back. |\n| ```popToPath(path: string, before = false): Promise\u003cboolean\u003e``` | Pops back in history to a previous path, removing all paths after this point from the stack. |\n\n\u003cbr\u003e\n\n## Contributors\n\nMade possible by these fantastic people. 💖\n\nSee the [`CONTRIBUTING.md`](./CONTRIBUTING.md) guide to get involved.\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/jn42lm1\"\u003e\u003cimg src=\"https://avatars2.githubusercontent.com/u/54233338?v=4?s=100\" width=\"100px;\" alt=\"jn42lm1\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003ejn42lm1\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/capitec/omni-router/commits?author=jn42lm1\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/capitec/omni-router/commits?author=jn42lm1\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/BOTLANNER\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/16349308?v=4?s=100\" width=\"100px;\" alt=\"BOTLANNER\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eBOTLANNER\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/capitec/omni-router/commits?author=BOTLANNER\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#tool-BOTLANNER\" title=\"Tools\"\u003e🔧\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\n\u003cbr\u003e\n\n## License\n\nLicensed under [MIT](LICENSE)\n\n\u003cbr\u003e\n\u003cbr\u003e\n\u003chr\u003e\n\u003cbr\u003e\n\u003cbr\u003e\n\u003cbr\u003e\n\u003cp align=\"center\"\u003e\n    \u003cpicture\u003e\n        \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"./docs/logos/capitec-logo-white.svg\"\u003e\n        \u003cimg alt=\"Capitec Logo\" src=\"./docs/logos/capitec-logo-color.svg\" height=\"28\"\u003e\n    \u003c/picture\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003eWe are hiring 🤝 Join us! 🇿🇦\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://www.capitecbank.co.za/about-us/careers\"\u003ehttps://www.capitecbank.co.za/about-us/careers\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cbr\u003e\n\u003cbr\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcapitec%2Fomni-router","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcapitec%2Fomni-router","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcapitec%2Fomni-router/lists"}