{"id":26458292,"url":"https://github.com/freshOS/Router","last_synced_at":"2025-03-19T00:01:45.053Z","repository":{"id":63910204,"uuid":"83279151","full_name":"freshOS/Router-deprecated","owner":"freshOS","description":"🛣 Simple Navigation for iOS - ⚠️ Deprecated","archived":false,"fork":false,"pushed_at":"2021-10-21T06:56:49.000Z","size":2971,"stargazers_count":447,"open_issues_count":0,"forks_count":26,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-03-15T19:36:48.246Z","etag":null,"topics":["freshos","microframework","navigation","router","routing","swift","viewcontroller"],"latest_commit_sha":null,"homepage":"","language":"Swift","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/freshOS.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-02-27T07:04:22.000Z","updated_at":"2024-12-06T07:41:15.000Z","dependencies_parsed_at":"2022-11-29T07:11:32.491Z","dependency_job_id":null,"html_url":"https://github.com/freshOS/Router-deprecated","commit_stats":null,"previous_names":["freshos/router"],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freshOS%2FRouter-deprecated","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freshOS%2FRouter-deprecated/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freshOS%2FRouter-deprecated/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/freshOS%2FRouter-deprecated/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/freshOS","download_url":"https://codeload.github.com/freshOS/Router-deprecated/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244326199,"owners_count":20435122,"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":["freshos","microframework","navigation","router","routing","swift","viewcontroller"],"created_at":"2025-03-19T00:01:27.077Z","updated_at":"2025-03-19T00:01:45.037Z","avatar_url":"https://github.com/freshOS.png","language":"Swift","readme":"![Router](https://raw.githubusercontent.com/freshOS/Router/master/banner.png)\n\n⚠️ Deprecated and no longer supported. Use at your own risks.  \nThis has been used extensively and after weighing up pros and cons, we now favour the use of native Flow Controllers or Coordinators as explained [here](https://www.hackingwithswift.com/articles/71/how-to-use-the-coordinator-pattern-in-ios-apps).  \nThe native route (pun intended) should always be favoured and we believe less dependencies is something we should always strive for.\n\n# Router\n[![Language: Swift](https://img.shields.io/badge/language-swift-f48041.svg?style=flat)](https://developer.apple.com/swift)\n![Platform: iOS 8+](https://img.shields.io/badge/platform-iOS%208%2B-blue.svg?style=flat)\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![Build Status](https://app.bitrise.io/app/11b4cd282c1d70b3/status.svg?token=TFKzkSx6pehcZOj5ouWrFg\u0026branch=master)](https://app.bitrise.io/app/11b4cd282c1d70b3)\n[![License: MIT](http://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat)](https://github.com/freshOS/then/blob/master/LICENSE)\n![Release version](https://img.shields.io/github/release/freshos/router.svg)\n\n[Reason](#why) - [Get Started](#get-started) - [Installation](#installation)\n\n![Router](https://raw.githubusercontent.com/freshOS/Router/master/Infographics.png)\n\n## Why\nBecause **classic App Navigation** introduces **tight coupling** between ViewControllers.\nComplex Apps navigation can look like a **gigantic spider web**.\n\nBesides the fact that **Navigation responsibility is split** among ViewControllers, modifying a ViewController can cascade recompiles and produce **slow compile times.**\n\n## How\nBy using a Navigation `enum` to navigate we decouple ViewControllers between them. Aka they don't know each other anymore. So modifying `VCA` won't trigger `VCB` to recompile anymore \\o/\n\n```swift\n// navigationController?.pushViewController(AboutViewController(), animated: true)\nnavigate(.about)\n```\n\nNavigation code is now encapsulated in a `AppNavigation` object.\n\n## Benefits\n- [x] Decouples ViewControllers  \n- [x] Makes navigation Testable   \n- [x] Faster compile times\n\n## Get started\n\n### 1 - Declare your Navigation enum\n```swift\nenum MyNavigation: Navigation {\n    case about\n    case profile(Person)\n}\n```\nSwift enum can take params!\nAwesome for us because that's how we will pass data between ViewControllers :)\n\n### 2 - Declare your App Navigation\n\n```swift\nstruct MyAppNavigation: AppNavigation {\n\n    func viewcontrollerForNavigation(navigation: Navigation) -\u003e UIViewController {\n        if let navigation = navigation as? MyNavigation {\n            switch navigation {\n            case .about:\n                return AboutViewController()\n            case .profile(let p):\n                return ProfileViewController(person: p)\n            }\n        }\n        return UIViewController()\n    }\n\n    func navigate(_ navigation: Navigation, from: UIViewController, to: UIViewController) {\n      from.navigationController?.pushViewController(to, animated: true)\n    }\n}\n```\n\nA cool thing is that the swift compiler will produce an error if a navigation\ncase is not handled ! Which would'nt be the case with string URLs by the way ;)\n\n\n### 3 - Register your navigation on App Launch\n\nIn `AppDelegate.swift`, before everything :\n```swift\nRouter.default.setupAppNavigation(appNavigation: MyAppNavigation())\n```\n\n### 4 - Replace navigations in your View Controllers\n\nYou can now call nagivations from you view controllers :\n\n```swift\nnavigate(MyNavigation.about)\n```\n\nBridge `Navigation` with your own enum type, here `MyNavigation` so that we don't have to type our own.\n```swift\nextension UIViewController {\n\n    func navigate(_ navigation: MyNavigation) {\n        navigate(navigation as Navigation)\n    }\n}\n```\nYou can now write :\n```swift\nnavigate(.about)\n```\n\n\n### Bonus - Tracking\nAnother cool thing about decoupling navigation is that you can now extract traking code from view Controllers as well. You can be notified by the router whenever a navigation happened.\n\n```swift\nRouter.default.didNavigate { navigation in\n    // Plug Analytics for instance\n    GoogleAnalitcs.trackPage(navigation)\n}\n\n```\n\n## Shave off compilation times\n\nThere is a nasty bug in Swift 3 compiler where the compiler rebuilds files even though they haven't changed.\nThis is documented here : https://forums.developer.apple.com/thread/62737?tstart=0\n\nDue to this bug, the compilation can go like this :\n\nChange `ViewController1` -\u003e `Build`  \n-\u003e Compiles `ViewController1`, referenced in `MyAppNavigation` so   \n`MyAppNavigation` gets recompiled.  `MyAppNavigation` is referenced in `AppDelegate` which gets recompiled which references ...\n`App` -\u003e `ViewController2` -\u003e `ViewController3` -\u003e `ViewControllerX` you get the point.\nBefore you know it the entire App gets rebuilt :/\n\nA good this is that most of the app coupling usually comes from navigation. which Router decouples.\n\nWe can stop this nonsense until this gets fixed in a future release of Xcode.\nRouter can help us manage this issue by injecting our AppNavigation implementation at runtime.\n\n\nIn your `AppDelegate.swift`\n\n```swift\n// Inject  your AppNavigation  at runtime to avoid recompilation of AppDelegate :)\nRouter.default.setupAppNavigation(appNavigation: appNavigationFromString(\"YourAppName.MyAppNavigation\"))\n```\n\nAnd make sure your `AppNavigation` implementation is now a `class` that is `RuntimeInjectable`\n```swift\nclass MyAppNavigation: RuntimeInjectable, AppNavigation {\n```\n\n## Installation\n\n#### Carthage\n```\ngithub \"freshOS/Router\"\n```\n#### Manually\nSimply Copy and Paste `Router.swift` files in your Xcode Project :)\n\n#### As A Framework\nGrab this repository and build the Framework target on the example project. Then Link against this framework.\n\n\n### Backers\nLike the project? Offer coffee or support us with a monthly donation and help us continue our activities :)\n\n\u003ca href=\"https://opencollective.com/freshos/backer/0/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/0/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/1/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/1/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/2/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/2/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/3/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/3/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/4/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/4/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/5/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/5/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/6/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/6/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/7/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/7/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/8/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/8/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/9/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/9/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/10/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/10/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/11/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/11/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/12/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/12/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/13/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/13/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/14/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/14/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/15/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/15/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/16/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/16/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/17/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/17/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/18/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/18/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/19/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/19/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/20/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/20/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/21/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/21/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/22/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/22/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/23/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/23/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/24/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/24/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/25/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/25/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/26/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/26/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/27/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/27/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/28/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/28/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/backer/29/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/backer/29/avatar.svg\"\u003e\u003c/a\u003e\n\n### Sponsors\nBecome a sponsor and get your logo on our README on Github with a link to your site :)\n\n\u003ca href=\"https://opencollective.com/freshos/sponsor/0/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/0/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/1/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/1/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/2/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/2/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/3/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/3/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/4/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/4/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/5/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/5/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/6/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/6/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/7/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/7/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/8/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/8/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/9/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/9/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/10/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/10/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/11/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/11/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/12/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/12/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/13/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/13/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/14/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/14/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/15/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/15/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/16/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/16/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/17/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/17/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/18/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/18/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/19/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/19/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/20/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/20/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/21/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/21/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/22/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/22/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/23/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/23/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/24/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/24/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/25/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/25/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/26/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/26/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/27/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/27/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/28/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/28/avatar.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://opencollective.com/freshos/sponsor/29/website\" target=\"_blank\"\u003e\u003cimg src=\"https://opencollective.com/freshos/sponsor/29/avatar.svg\"\u003e\u003c/a\u003e\n","funding_links":["https://opencollective.com/freshos/backer/0/website","https://opencollective.com/freshos/backer/1/website","https://opencollective.com/freshos/backer/2/website","https://opencollective.com/freshos/backer/3/website","https://opencollective.com/freshos/backer/4/website","https://opencollective.com/freshos/backer/5/website","https://opencollective.com/freshos/backer/6/website","https://opencollective.com/freshos/backer/7/website","https://opencollective.com/freshos/backer/8/website","https://opencollective.com/freshos/backer/9/website","https://opencollective.com/freshos/backer/10/website","https://opencollective.com/freshos/backer/11/website","https://opencollective.com/freshos/backer/12/website","https://opencollective.com/freshos/backer/13/website","https://opencollective.com/freshos/backer/14/website","https://opencollective.com/freshos/backer/15/website","https://opencollective.com/freshos/backer/16/website","https://opencollective.com/freshos/backer/17/website","https://opencollective.com/freshos/backer/18/website","https://opencollective.com/freshos/backer/19/website","https://opencollective.com/freshos/backer/20/website","https://opencollective.com/freshos/backer/21/website","https://opencollective.com/freshos/backer/22/website","https://opencollective.com/freshos/backer/23/website","https://opencollective.com/freshos/backer/24/website","https://opencollective.com/freshos/backer/25/website","https://opencollective.com/freshos/backer/26/website","https://opencollective.com/freshos/backer/27/website","https://opencollective.com/freshos/backer/28/website","https://opencollective.com/freshos/backer/29/website","https://opencollective.com/freshos"],"categories":["App Routing"],"sub_categories":["Other free courses","Getting Started"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FfreshOS%2FRouter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FfreshOS%2FRouter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FfreshOS%2FRouter/lists"}