{"id":9970,"date":"2026-06-04T11:13:18","date_gmt":"2026-06-04T16:13:18","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=9970"},"modified":"2026-06-04T11:13:48","modified_gmt":"2026-06-04T16:13:48","slug":"navigation-api-baseline","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/navigation-api-baseline\/","title":{"rendered":"Navigation API Baseline"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">If you&#8217;ve ever built your own client-side navigation that properly respects updating URLs, you&#8217;ve probably used <code>history.pushState()<\/code> a bunch, and it&#8217;s a bunch of work getting it robust and right. I think Jay Rungta does a good job of <a href=\"https:\/\/web.dev\/blog\/baseline-navigation-api?hl=en\">showcasing the newly-baseline Navigation API<\/a> and why it&#8217;s better.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sorry for the huge blockquote, but it&#8217;s worth it:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">Building a router with the History API felt like assembling a puzzle, since you had to:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Listen for clicks on&nbsp;<code>&lt;a&gt;<\/code>&nbsp;tags globally.<\/li>\n\n\n\n<li>Call&nbsp;<code>preventDefault()<\/code>&nbsp;on them.<\/li>\n\n\n\n<li>Manually call&nbsp;<code>history.pushState()<\/code>.<\/li>\n\n\n\n<li>Manually update your DOM.<\/li>\n\n\n\n<li><em>Separately<\/em>&nbsp;listen for the&nbsp;<code>popstate<\/code>&nbsp;event to handle the back\/forward buttons.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">If you forgot to handle one edge case, users might accidentally end up at the wrong view, highlighting its fragility.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The Navigation API radically simplifies this. It gives you a single, centralized&nbsp;<a href=\"https:\/\/developer.mozilla.org\/docs\/Web\/API\/NavigateEvent\">NavigateEvent<\/a>&nbsp;for every navigation\u2014whether it&#8217;s a user clicking a link, submitting a form, hitting the back button, or your code calling&nbsp;<code>navigation.navigate()<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The&nbsp;<code>event.intercept()<\/code>&nbsp;function does a lot of the heavy lifting for you:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Automatic URL updates:<\/strong>&nbsp;Handles updating the address bar and the history stack, without the need to call&nbsp;<code>pushState<\/code>.<\/li>\n\n\n\n<li><strong>Automatic accessibility:<\/strong>&nbsp;Handles accessibility primitives like focus management (restoring focus after navigation) automatically.<\/li>\n\n\n\n<li><strong>Centralized logic:<\/strong>&nbsp;Handles the back button and click events in the exact same function.<\/li>\n<\/ul>\n<\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>If you&#8217;ve ever built your own client-side navigation that properly respects updating URLs, you&#8217;ve probably used history.pushState() a bunch, and it&#8217;s a bunch of work getting it robust and right. I think Jay Rungta does a good job of showcasing the newly-baseline Navigation API and why it&#8217;s better. Sorry for the huge blockquote, but it&#8217;s [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":9971,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[29],"tags":[3,494,241],"class_list":["post-9970","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-the-beat","tag-javascript","tag-navigation-api","tag-router"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/06\/pexels-photo-4373997.jpeg?fit=1880%2C1253&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/9970","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/comments?post=9970"}],"version-history":[{"count":2,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/9970\/revisions"}],"predecessor-version":[{"id":9973,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/9970\/revisions\/9973"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/9971"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=9970"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=9970"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=9970"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}