{"id":1972,"date":"2021-11-04T12:27:11","date_gmt":"2021-11-04T19:27:11","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/surface-duo\/?p=1972"},"modified":"2022-06-09T10:06:31","modified_gmt":"2022-06-09T17:06:31","slug":"jetpack-compose-navigation-rail","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/surface-duo\/jetpack-compose-navigation-rail\/","title":{"rendered":"Jetpack Compose Navigation Rail"},"content":{"rendered":"<p>Hello Jetpack Compose developers!<\/p>\n<p>This week, we released a <a href=\"https:\/\/github.com\/microsoft\/surface-duo-compose-samples\/tree\/main\/NavigationRail\">new sample<\/a> that demonstrates how to use the <strong>NavigationRail<\/strong> component with large screen and foldable devices. These guidelines were also introduced recently in the Microsoft <a href=\"https:\/\/aka.ms\/SurfaceDuoDesign\">Surface Duo Design Kit 2.1<\/a>.<\/p>\n<h2>Create a NavigationRail with Compose<\/h2>\n<p>We first blogged about <strong>NavigationRail<\/strong> in <a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/dual-screen-navigation-rail\/\">August<\/a>, when we described how to use it in a dual-screen sample with XML layouts. As a reminder, the <a href=\"https:\/\/material.io\/components\/navigation-rail\">NavigationRail<\/a> component is used for navigation on large screens and can hold 3-7 app destinations, plus a logo or floating action button.<\/p>\n<p>To add a <strong>NavigationRail<\/strong> to your Compose application, follow these steps:<\/p>\n<ol>\n<li>Add the following dependencies to your <code>build.gradle<\/code> file:\n<pre>ext {\r\n   composeVersion = \"1.1.0-alpha06\"\r\n   navVersion = \"2.4.0-alpha10\"\r\n}\r\nimplementation \"androidx.compose.material:material:$composeVersion\"\r\nimplementation \"androidx.navigation:navigation-compose:$navVersion\"<\/pre>\n<p>The component is still in alpha, so make sure to update <code>composeVersion<\/code> and <code>navVersion<\/code> with the most recent releases, which can be found at the <a href=\"https:\/\/developer.android.com\/jetpack\/androidx\/releases\/compose-material\">Compose Material<\/a> and <a href=\"https:\/\/developer.android.com\/jetpack\/androidx\/releases\/navigation\">Navigation<\/a> pages. You will also have to add the <code>@ExperimentalMaterialApi<\/code> tag to any Composable functions that use <strong>NavigationRail<\/strong> or <strong>NavigationRailItem<\/strong>.<\/li>\n<li>Create a composable with a <strong>NavigationRail<\/strong> that contains <strong>NavigationRailItem<\/strong> components. The code snippet below is based on an example from the <a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/material\/package-summary#NavigationRail(androidx.compose.ui.Modifier,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.unit.Dp,kotlin.Function1,kotlin.Function1)\">NavigationRail API reference<\/a>, but similar code can be found in our sample in <a href=\"https:\/\/github.com\/microsoft\/surface-duo-compose-samples\/blob\/main\/NavigationRail\/src\/main\/java\/com\/microsoft\/device\/display\/samples\/navigationrail\/ui\/components\/GalleryNavWithSelector.kt\">GalleryNavWithSelector.kt<\/a>.\n<pre>@ExperimentalMaterialApi\r\n@Composable\r\nfun ExampleNavRail(navController: NavHostController, items: List) {\r\n   val icons = listOf(Icons.Filled.Home, Icons.Filled.Search, Icons.Filled.Settings)\r\n\r\n   NavigationRail {\r\n       items.forEachIndexed { index, item -&gt;\r\n           val currentDestination = navController.currentBackStackEntryAsState().value?.destination\r\n           NavigationRailItem(\r\n               icon = { Icon(icons[index], contentDescription = item) },\r\n               label = { Text(item) },\r\n               selected = currentDestination?.route?.let { it == item } ?: false,\r\n               onClick = { navController.navigate(item) }\r\n           )\r\n       }\r\n   }\r\n}<\/pre>\n<\/li>\n<li>Add your <strong>NavigationRail<\/strong> composable next to your <strong>NavHost <\/strong>by placing them together in a <strong>Row<\/strong>.\n<pre>val navController = rememberNavController()\r\nval items = listOf(\"Home\", \"Search\", \"Settings\")\r\n\r\nScaffold(topBar = { TopAppBar(title = { Text(\"Example Nav Rail App\") }) }) {\r\n   Row {\r\n       ExampleNavRail(navController, items)\r\n       NavHost(navController = navController, startDestination = items.first()) {\r\n           items.forEach { item -&gt;\r\n               composable(route = item) { Text(text = item) }\r\n           }\r\n       }\r\n   }\r\n}<\/pre>\n<\/li>\n<\/ol>\n<h2>Design guidelines for large screen and foldable devices UX<\/h2>\n<p>When adding navigation to apps for large screen and foldable devices, we recommend using a combination of <strong>NavigationRail<\/strong> and <strong>BottomNavigation<\/strong>. In the case of Surface Duo, this means using a navigation rail when the app is spanned and switching to a bottom navigation bar when the app is unspanned.<\/p>\n<p><img decoding=\"async\" width=\"1011\" height=\"918\" class=\"wp-image-1973\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/resource-from-surface-duo-design-kit-2-1-that-show.png\" alt=\"Resource from Surface Duo Design Kit 2.1 that shows options for NavigationRail and BottomNavigation\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/resource-from-surface-duo-design-kit-2-1-that-show.png 1011w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/resource-from-surface-duo-design-kit-2-1-that-show-300x272.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/resource-from-surface-duo-design-kit-2-1-that-show-768x697.png 768w\" sizes=\"(max-width: 1011px) 100vw, 1011px\" \/><\/p>\n<p><em>Figure 1: Navigation rail guidelines from the <\/em><a href=\"https:\/\/www.figma.com\/community\/file\/925222050648034066\"><em>Surface Duo Design Kit 2.1<\/em><\/a><em>.<\/em><\/p>\n<p>To dynamically switch between navigation components based on screen size, use a combination of the <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/jetpack\/compose\/jetpack-window-manager\">Jetpack Window Manager library<\/a> and other device properties available via <code>LocalConfiguration.current<\/code>. On Surface Duo and other foldables, you can use Window Manager to check if a hinge is present in the form of a <strong>FoldingFeature<\/strong>, while <code>LocalConfiguration.current<\/code> is useful for checking the size of a device\u2019s screen. To see how we used these two resources in the sample app, check out the <strong>SetupUI<\/strong> function in <a href=\"https:\/\/github.com\/microsoft\/surface-duo-compose-samples\/blob\/main\/NavigationRail\/src\/main\/java\/com\/microsoft\/device\/display\/samples\/navigationrail\/ui\/view\/HomePage.kt\">HomePage.kt<\/a>.<\/p>\n<h2>Sample highlights and challenges<\/h2>\n<p>Our <strong>NavigationRail<\/strong> sample is a nature information catalog with five categories: plants, birds, animals, lakes, and rocks. Each category has multiple items, and each item has a picture and a scientific description. The app uses our custom control <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/jetpack\/compose\/two-pane-layout\">TwoPaneLayout<\/a> and follows the <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/design\/list-detail\">List Detail design pattern<\/a>, with the \u201clist\u201d being the gallery for the current category and the \u201cdetail\u201d being the picture and description of the selected item.<\/p>\n<h3>Navigation hierarchy<\/h3>\n<p>In our plans for the sample, we decided on the layout designs shown in Figure 2. When it came time to implement the behavior, setting up the navigation was a bit complicated!<\/p>\n<p><img decoding=\"async\" width=\"1339\" height=\"1190\" class=\"wp-image-1974\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/layout-view-design-diagram-showing-the-placement.png\" alt=\"Layout view design diagram, showing the placement for the NavigationRail \/ BottomNavigation, detail view for selected item, and list view for selected gallery;Dual portrait mode: navigation rail on left, list view on left, detail view on right;Dual landscape mode: navigation rail on left, list view or detail view on top and bottom (can navigate between); Single portrait\/landscape modes: bottom navigation on bottom, list view or detail view in the rest of the screen (can navigate between)\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/layout-view-design-diagram-showing-the-placement.png 1339w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/layout-view-design-diagram-showing-the-placement-300x267.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/layout-view-design-diagram-showing-the-placement-1024x910.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/layout-view-design-diagram-showing-the-placement-768x683.png 768w\" sizes=\"(max-width: 1339px) 100vw, 1339px\" \/>\n<em>Figure 2: Layout designs for each Surface Duo orientation.<\/em><\/p>\n<p>After some thought, we realized that the <strong>BottomNavigation<\/strong>\/<strong>NavigationRail<\/strong> would always be shown in pane 1, and the associated <strong>NavHost<\/strong> would only be used to display the different galleries. Even though we would sometimes need to switch between the gallery and item views, it wouldn\u2019t make sense to add the item view to the <strong>NavHost<\/strong> as a top-level app destination.<\/p>\n<p>So, the final navigation graph we settled on has two main parts. The first part, as shown in Figure 3, uses the navigation support provided by <strong>TwoPaneLayout<\/strong> to switch between the gallery and item views when only one pane is being displayed.<\/p>\n<p><img decoding=\"async\" width=\"2147\" height=\"897\" class=\"wp-image-1975\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/twopanelayout-navigation-diagram-pane-1-holds-nav.png\" alt=\"TwoPaneLayout navigation diagram; Pane 1 holds navigation rail\/bottom navigation and NavHost, Pane 2 holds ItemDetailView, can use navigateToPane2 and navigateToPane1 methods to switch between; Logic flow: if dual portrait, show 2 panes; if not, check if item is selected. If item is selected, show ItemDetailView via navigateToPane2; if not, show NavHost\/GalleryView via navigateToPane1\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/twopanelayout-navigation-diagram-pane-1-holds-nav.png 2147w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/twopanelayout-navigation-diagram-pane-1-holds-nav-300x125.png 300w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/twopanelayout-navigation-diagram-pane-1-holds-nav-1024x428.png 1024w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/twopanelayout-navigation-diagram-pane-1-holds-nav-768x321.png 768w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/twopanelayout-navigation-diagram-pane-1-holds-nav-1536x642.png 1536w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/twopanelayout-navigation-diagram-pane-1-holds-nav-2048x856.png 2048w\" sizes=\"(max-width: 2147px) 100vw, 2147px\" \/>\n<em>Figure 3: Navigation logic within TwoPaneLayout.<\/em><\/p>\n<p>The second part, seen in Figure 4, exists only within pane 1, where a <strong>NavHost<\/strong> is connected to the current navigation component to enable switching between the five different gallery categories. One important note is that because the <strong>NavHost<\/strong> only exists at the pane 1 level in the layout hierarchy, the app technically had two <strong>NavHost<\/strong> instance; one for the single pane container and another for the two pane container. To ensure that both instances were synced, we created a <code>currentRoute<\/code> variable at the highest level of the hierarchy and checked it when recomposing pane 1.<\/p>\n<p><img decoding=\"async\" width=\"812\" height=\"1009\" class=\"wp-image-1976\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/navhost-navigation-logic-diagram-inside-pane-1-w.png\" alt=\"NavHost navigation logic diagram; Inside Pane 1, with either navigation rail or bottom navigation, then NavHost\/GalleryView in the rest of the pane; NavHost\/GalleryView has 5 different appearance options for the 5 different categories: plants, birds, animals, lakes, and rocks\" srcset=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/navhost-navigation-logic-diagram-inside-pane-1-w.png 812w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/navhost-navigation-logic-diagram-inside-pane-1-w-241x300.png 241w, https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/navhost-navigation-logic-diagram-inside-pane-1-w-768x954.png 768w\" sizes=\"(max-width: 812px) 100vw, 812px\" \/>\n<em>Figure 4: Navigation logic within pane 1 with a NavHost.<\/em><\/p>\n<h3>Custom components<\/h3>\n<p>Another challenge was creating custom components to match the designs for the sample. We found that the <a href=\"https:\/\/github.com\/android\/compose-samples\/tree\/main\/Jetsnack\">Jetsnack<\/a> sample from the official Compose repository was a great reference for both setting up navigation and adding custom UI components.<\/p>\n<p>The first customization we made was adding a selector to the <strong>NavigationRailItem<\/strong> and <strong>BottomNavigationItem<\/strong> components. This selector appears behind the icon of the current destination and includes visibility animations (see Figure 5). If you\u2019re interested in the implementation, check out <a href=\"https:\/\/github.com\/microsoft\/surface-duo-compose-samples\/blob\/main\/NavigationRail\/src\/main\/java\/com\/microsoft\/device\/display\/samples\/navigationrail\/ui\/components\/NavRailItemWithSelector.kt\">NavRailItemWithSelector.kt<\/a> and <a href=\"https:\/\/github.com\/microsoft\/surface-duo-compose-samples\/blob\/main\/NavigationRail\/src\/main\/java\/com\/microsoft\/device\/display\/samples\/navigationrail\/ui\/components\/BottomNavItemWithSelector.kt\">BottomNavItemWithSelector.kt<\/a>.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/ComposeNavRail-animation-1b.gif\"><img decoding=\"async\" class=\"alignnone size-full wp-image-1995\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/ComposeNavRail-animation-1b.gif\" alt=\"Animation of Jetpack Componse Navigation Rail on Surface Duo 2\" width=\"640\" height=\"500\" \/><\/a>\n<em>Figure 5: Example of how the selector highlights the current destination in the NavigationRail.<\/em><\/p>\n<p>We also created a custom <strong>ContentDrawer<\/strong> component that behaves similarly to a <a href=\"https:\/\/developer.android.com\/reference\/kotlin\/androidx\/compose\/material\/package-summary#BottomSheetScaffold(kotlin.Function1,androidx.compose.ui.Modifier,androidx.compose.material.BottomSheetScaffoldState,kotlin.Function0,kotlin.Function1,kotlin.Function0,androidx.compose.material.FabPosition,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.ui.unit.Dp,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.unit.Dp,kotlin.Function1,kotlin.Boolean,androidx.compose.ui.graphics.Shape,androidx.compose.ui.unit.Dp,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,kotlin.Function1)\">BottomSheetScaffold<\/a>, except with an enhancement that prevents content from rendering under the hinge.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/ComposeNavRail-animation-2b.gif\"><img decoding=\"async\" class=\"alignnone size-full wp-image-1996\" src=\"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-content\/uploads\/sites\/53\/2021\/11\/ComposeNavRail-animation-2b.gif\" alt=\"Animation of ContentDrawer on Surface Duo 2\" width=\"430\" height=\"550\" \/><\/a>\n<em>Figure 6: Demonstration of hinge aware ContentDrawer component.<\/em><\/p>\n<p>This was achieved by creating a swipeable <strong>BoxWithConstraints<\/strong> and adding a <strong>Spacer<\/strong> with dynamic height based on swipe progress. The code snippet below was taken from <a href=\"https:\/\/github.com\/microsoft\/surface-duo-compose-samples\/blob\/main\/NavigationRail\/src\/main\/java\/com\/microsoft\/device\/display\/samples\/navigationrail\/ui\/components\/ContentDrawer.kt\">ContentDrawer.kt<\/a>, and it shows how height was calculated using hinge properties and information from the swipeable modifier.<\/p>\n<pre>\/\/ Check if a spacer needs to be included to render content around an occluding hinge\r\nval spacerHeight = if (hingeOccludes) {\r\n   val isExpanding = swipeableState.progress.to == DrawerState.Expanded\r\n   val progressHeight = (hingeSize.value * swipeableState.progress.fraction).dp\r\n   if (isExpanding)\r\n       progressHeight\r\n   else\r\n       hingeSize - progressHeight\r\n} else {\r\n   0.dp\r\n}<\/pre>\n<h2>Resources and feedback<\/h2>\n<p>For coding tips, visit the <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/\">Surface Duo developer documentation<\/a> , <a href=\"https:\/\/docs.microsoft.com\/dual-screen\/android\/jetpack\/window-manager\/samples\">our samples<\/a>, and Google\u2019s <a href=\"https:\/\/developer.android.com\/large-screens\">Android large screen development guidance<\/a>.<\/p>\n<p>If you have any questions, or would like to tell us about your dual-screen apps, use the\u00a0<a href=\"http:\/\/aka.ms\/SurfaceDuoSDK-Feedback\">feedback forum<\/a>\u00a0or message us on Twitter\u00a0<a href=\"https:\/\/twitter.com\/surfaceduodev\">@surfaceduodev<\/a>.<\/p>\n<p>Finally, please join us for our <a href=\"https:\/\/twitch.tv\/surfaceduodev\">dual screen developer livestream<\/a> at 11am (Pacific time) each Friday \u2013 mark it in your calendar and check out the <a href=\"https:\/\/www.youtube.com\/channel\/UClGu9QLtPNz8OdddBfhZXPA\">archives on YouTube<\/a>.<\/p>\n<h2>Attribution<\/h2>\n<p>The images used in the Navigation rail sample are licensed under [\u00a9 eakarat], [\u00a9 nerudol], [\u00a9 DedMityay], [\u00a9 tibor13], [\u00a9 Harry Collins], [\u00a9 Tony Baggett], [\u00a9 WildMedia], [\u00a9 Vlasto Opatovsky], [\u00a9 Lakeview Images], [\u00a9 viktoriya89], [\u00a9 dudlajzov], [\u00a9 zkbld], [\u00a9 muraviov], [\u00a9 phototrip.cz], [\u00a9 gpisano71], [\u00a9 Mike Mareen], [\u00a9 Fokke], [\u00a9 ronnybas], [\u00a9 Piotr Krzeslak], [\u00a9 shaiith], [\u00a9 aiisha], [\u00a9 Andrew Mayovskyy], [\u00a9 Andrey Armyagov], [\u00a9 \u041d\u0430\u0442\u0430\u043b\u044c\u044f \u0411\u043e\u0441\u044f\u043a] \/ <a href=\"https:\/\/stock.adobe.com\/\">stock.adobe.com<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello Jetpack Compose developers! This week, we released a new sample that demonstrates how to use the NavigationRail component with large screen and foldable devices. These guidelines were also introduced recently in the Microsoft Surface Duo Design Kit 2.1. Create a NavigationRail with Compose We first blogged about NavigationRail in August, when we described how [&hellip;]<\/p>\n","protected":false},"author":72597,"featured_media":1998,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[692,473,46],"class_list":["post-1972","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-surface-duo-sdk","tag-jetpack-compose","tag-kotlin","tag-surface-duo"],"acf":[],"blog_post_summary":"<p>Hello Jetpack Compose developers! This week, we released a new sample that demonstrates how to use the NavigationRail component with large screen and foldable devices. These guidelines were also introduced recently in the Microsoft Surface Duo Design Kit 2.1. Create a NavigationRail with Compose We first blogged about NavigationRail in August, when we described how [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/1972","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/users\/72597"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/comments?post=1972"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/posts\/1972\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media\/1998"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/media?parent=1972"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/categories?post=1972"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/surface-duo\/wp-json\/wp\/v2\/tags?post=1972"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}