[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"verticals":3,"search-suggestions":44,"article-screen-wake-lock-api-keep-screen-on":90,"related-screen-wake-lock-api-keep-screen-on":291,"code:html:true:x91cxh":418,"code:js:true:1qnvag3":419,"code:js:true:15p2tlz":420,"code:js:true:lcw8r5":421,"code:js:true:raevws":422,"comments-01a05cb5-e732-76ca-8865-14b97c64f2ba":423},[4,20,32],{"id":5,"slug":6,"name":7,"tagline":8,"description":9,"accentFrom":10,"accentTo":11,"icon":12,"defaultLocale":13,"locales":14,"features":16,"position":19},"019fe637-3d33-714b-b57f-23e163ffca0c","dev","Web Development","Read it. Run it. Prove it.","A post a day on modern web development — most with an editable playground and a quiz that explains every answer. Free, no account needed.","violet-500","cyan-400","◇","en",[13,15],"fa",{"courses":17,"paths":17,"articles":17,"exams":18,"flashcards":18,"packages":17,"community":17,"certificates":17,"teams":17,"commerce":17},true,false,0,{"id":21,"slug":22,"name":23,"tagline":24,"description":25,"accentFrom":26,"accentTo":10,"icon":27,"defaultLocale":13,"locales":28,"features":30,"position":31},"019fe637-3dc2-754c-8657-0f175bfee7c6","lang","Languages","Learn a language the way you learn a codebase.","Grammar explained the way good documentation explains an API — one idea at a time, each with a quiz.","amber-400","⌘",[13,15,29],"es",{"courses":18,"paths":18,"articles":17,"exams":18,"flashcards":17,"packages":18,"community":17,"certificates":17,"teams":18,"commerce":18},2,{"id":33,"slug":34,"name":35,"tagline":36,"description":37,"accentFrom":38,"accentTo":39,"icon":40,"defaultLocale":13,"locales":41,"features":42,"position":43},"7b3c16f2-931d-410e-802e-e1fa4edab7de","soft","Soft Skills","The half of the job nobody wrote documentation for.","Weekly, on the parts of working life that decide more than your code does — first weeks, meetings, interviews, promotions, and the people around you. Written from what actually happens, and recorded as a podcast you can listen to on the walk.","emerald-400","teal-300","◉",[13],{"courses":18,"paths":18,"articles":17,"exams":18,"flashcards":18,"packages":18,"community":17,"certificates":18,"teams":18,"commerce":18},3,[45,49,53,57,61,65,69,72,76,80,83,87],{"slug":46,"name":47,"articles":48},"webdev","Webdev",82,{"slug":50,"name":51,"articles":52},"javascript","Javascript",69,{"slug":54,"name":55,"articles":56},"frontend","Frontend",67,{"slug":58,"name":59,"articles":60},"css","Css",29,{"slug":62,"name":63,"articles":64},"tutorial","Tutorial",17,{"slug":66,"name":67,"articles":68},"performance","Performance",11,{"slug":70,"name":71,"articles":68},"typescript","Typescript",{"slug":73,"name":74,"articles":75},"react","React",9,{"slug":77,"name":78,"articles":79},"browser","Browser",6,{"slug":81,"name":82,"articles":79},"grammar","Grammar",{"slug":84,"name":85,"articles":86},"html","Html",5,{"slug":88,"name":89,"articles":86},"node","Node",{"id":91,"slug":92,"title":93,"subtitle":94,"excerpt":95,"coverUrl":96,"locale":13,"readingMinutes":86,"publishedAt":97,"viewCount":98,"likeCount":19,"commentCount":19,"author":99,"vertical":104,"topic":105,"tags":107,"_count":114,"playground":116,"body":118,"bodyMd":274,"seo":275,"translationGroupId":278,"series":94,"podcastUrl":94,"verticalId":5,"thread":279,"assessments":281,"translations":287,"quiz":289},"01a05cb5-e732-76ca-8865-14b97c64f2ba","screen-wake-lock-api-keep-screen-on","Your Recipe App Is Hiding a Silent Video",null,"Cooking sites, workout timers, and boarding-pass pages used to autoplay an invisible, muted, looping video for one job only: stopping your phone from locking its screen. The Screen Wake Lock API replaces that hack with three lines of JavaScript — and it comes with one gotcha the docs bury.","\u002Fmedia\u002Fcovers\u002Fscreen-wake-lock-api-keep-screen-on.png","2026-09-06T10:37:22.891Z",23,{"id":100,"name":101,"username":102,"avatarUrl":94,"headline":103},"019fe637-3c25-7088-9034-39c9f15dc3c8","Parsa Jiravand","parsa","Frontend engineer · building bestpractic",{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":50,"name":106},"JavaScript",[108,109,110,111],{"slug":50,"name":51,"color":94},{"slug":46,"name":47,"color":94},{"slug":77,"name":78,"color":94},{"slug":112,"name":113,"color":94},"apis","Apis",{"assessments":115},1,{"slug":92,"title":117},"Screen Wake Lock API — interactive playground",{"blocks":119,"version":115},[120,124,127,132,135,138,143,146,149,152,160,163,166,169,172,175,178,181,184,189,192,195,199,202,205,208,211,214,218,221,225,228,232,235,238,241,244,247,250,253,256,259,262,265,268],{"id":121,"html":122,"type":123},"b1","\u003Cp>Open dev tools on almost any recipe site mid-scroll and check the Elements panel. Buried near the bottom, there&#39;s a \u003Ccode>&lt;video&gt;\u003C\u002Fcode> tag. It&#39;s one pixel. It&#39;s muted. It&#39;s on an infinite loop. And if you actually watch what it&#39;s playing — nothing. It&#39;s a single frame of black, looping forever, going nowhere.\u003C\u002Fp>","paragraph",{"id":125,"html":126,"type":123},"b2","\u003Cp>That&#39;s not debug cruft someone forgot to delete. It&#39;s load-bearing. Rip it out and the page&#39;s actual job — keeping your phone&#39;s screen on while your hands are covered in flour — quietly breaks.\u003C\u002Fp>",{"id":128,"html":129,"text":130,"type":131,"level":31},"b3","The problem it&#39;s solving","The problem it's solving","heading",{"id":133,"html":134,"type":123},"b4","\u003Cp>Mobile browsers don&#39;t give a web page a button that says &quot;don&#39;t lock the screen.&quot; There&#39;s no \u003Ccode>document.staySharp()\u003C\u002Fcode>. The OS owns that timer, and for a long time the only way JavaScript could influence it was indirectly — by doing something the OS already treats as a signal that the user is still engaged.\u003C\u002Fp>",{"id":136,"html":137,"type":123},"b5","\u003Cp>Actively playing video is one of those signals. Every mobile OS defers the screen-lock timer while media is playing, because pausing a movie mid-scene to lock the screen would be a terrible experience. So people found the seam: play \u003Cem>something\u003C\u002Fem>, even if that something is deliberately nothing.\u003C\u002Fp>",{"id":139,"code":140,"type":141,"language":84,"highlight":142},"b6","\u003Cvideo id=\"keep-awake\" muted playsinline loop>\n  \u003Csource src=\"silent-1px.mp4\" type=\"video\u002Fmp4\" \u002F>\n\u003C\u002Fvideo>\n\u003Cscript>\n  document.getElementById(\"keep-awake\").play();\n\u003C\u002Fscript>","code",[],{"id":144,"html":145,"type":123},"b7","\u003Cp>\u003Ccode>muted\u003C\u002Fcode> and \u003Ccode>playsinline\u003C\u002Fcode> are load-bearing too — without them, most mobile browsers either block the autoplay outright or hijack the screen with a fullscreen player. Libraries like NoSleep.js packaged exactly this pattern for years, because it worked, and because there wasn&#39;t anything better to reach for.\u003C\u002Fp>",{"id":147,"html":148,"text":148,"type":131,"level":31},"b8","Where it falls apart",{"id":150,"html":151,"type":123},"b9","\u003Cp>It&#39;s a real technique and it did the job — but borrowing &quot;video playback&quot; as a proxy for &quot;keep the screen awake&quot; comes with everything you&#39;d expect from repurposing the wrong primitive:\u003C\u002Fp>",{"id":153,"type":154,"items":155,"ordered":18},"b10","list",[156,157,158,159],"\u003Cstrong>Autoplay policies fight you.\u003C\u002Fstrong> Some mobile browsers still block autoplaying video unless it happens inside a user gesture, so the trick can silently fail on exactly the browser version where you need it most.","\u003Cstrong>It costs a decoder, not a flag.\u003C\u002Fstrong> A one-pixel video is small, but &quot;small&quot; isn&#39;t &quot;free&quot; — you&#39;re spinning up video decoding hardware and a render loop to communicate a boolean.","\u003Cstrong>Nothing tells you it stopped working.\u003C\u002Fstrong> If the tab is backgrounded in a way the browser doesn&#39;t treat as &quot;still playing,&quot; the video pauses and your screen locks — with no error, no event, nothing to catch.","\u003Cstrong>It&#39;s semantically a lie.\u003C\u002Fstrong> Anyone reading that markup six months from now has to reverse-engineer \u003Cem>why\u003C\u002Fem> there&#39;s a phantom video before they can safely touch it.",{"id":161,"html":162,"type":123},"b11","\u003Cp>The workaround earned its keep because the platform had a real gap. In 2019, Chrome closed it.\u003C\u002Fp>",{"id":164,"html":165,"text":165,"type":131,"level":31},"b12","The API that says what it means",{"id":167,"html":168,"type":123},"b13","\u003C!-- playground:start -->",{"id":170,"html":171,"text":171,"type":131,"level":31},"b14","🎮 Try it yourself",{"id":173,"html":174,"type":123},"b15","\u003Cp>\u003Cstrong>\u003Ca href=\"https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fscreen-wake-lock-api-keep-screen-on\u002Fplayground\">▶️ Open the interactive playground →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":176,"html":177,"type":123},"b16","\u003Cp>\u003Cem>Runs right in your browser — poke at it and watch the concept react live.\u003C\u002Fem>\u003C\u002Fp>",{"id":179,"html":180,"type":123},"b17","\u003C!-- playground:end -->",{"id":182,"html":183,"type":123},"b18","\u003Cp>The Screen Wake Lock API does exactly one thing, and its name doesn&#39;t lie about it:\u003C\u002Fp>",{"id":185,"code":186,"type":141,"language":187,"highlight":188},"b19","let wakeLock = null;\n\nasync function requestWakeLock() {\n  try {\n    wakeLock = await navigator.wakeLock.request(\"screen\");\n    console.log(\"Screen will stay on\");\n  } catch (err) {\n    \u002F\u002F Fails if the document isn't visible, isn't a secure context,\n    \u002F\u002F or the platform refuses for its own reasons.\n    console.error(`${err.name}: ${err.message}`);\n  }\n}","js",[],{"id":190,"html":191,"type":123},"b20","\u003Cp>\u003Ccode>navigator.wakeLock.request(&quot;screen&quot;)\u003C\u002Fcode> — \u003Ccode>&quot;screen&quot;\u003C\u002Fcode> is currently the only lock type the spec defines — returns a promise for a \u003Ccode>WakeLockSentinel\u003C\u002Fcode>. While that sentinel is alive, the screen won&#39;t dim or lock on its own. No \u003Ccode>&lt;video&gt;\u003C\u002Fcode>, no decoder, no lying markup. It needs a secure context (HTTPS or localhost) and the document has to actually be visible when you call it, or the promise rejects with a \u003Ccode>NotAllowedError\u003C\u002Fcode>.\u003C\u002Fp>",{"id":193,"html":194,"type":123},"b21","\u003Cp>Releasing it is just as direct:\u003C\u002Fp>",{"id":196,"code":197,"type":141,"language":187,"highlight":198},"b22","async function releaseWakeLock() {\n  await wakeLock?.release();\n  wakeLock = null;\n}",[],{"id":200,"html":201,"type":123},"b23","\u003Cp>That would be the whole post, except the API has one behavior that catches almost everyone the first time.\u003C\u002Fp>",{"id":203,"html":204,"text":204,"type":131,"level":31},"b24","The part the happy path hides",{"id":206,"html":207,"type":123},"b25","\u003Cp>Switch away from the tab holding the lock — another window, another app, the phone&#39;s lock button — and the browser releases the wake lock for you. Silently. No exception. No rejected promise. Your \u003Ccode>wakeLock\u003C\u002Fcode> variable still points at a sentinel object; it&#39;s just that the sentinel&#39;s job is now over, and nothing forces you to notice.\u003C\u002Fp>",{"id":209,"html":210,"type":123},"b26","\u003Cp>Come back to the tab, and the screen goes right back to locking on schedule — because as far as the platform&#39;s concerned, you never asked it not to. If your only test was &quot;click the button once, watch the screen stay on for thirty seconds,&quot; you&#39;ll ship this and find out from a support ticket instead.\u003C\u002Fp>",{"id":212,"html":213,"type":123},"b27","\u003Cp>The sentinel does expose a \u003Ccode>release\u003C\u002Fcode> event, and MDN&#39;s own guide handles the whole thing with a \u003Ccode>visibilitychange\u003C\u002Fcode> listener that re-requests the lock the moment the tab becomes visible again:\u003C\u002Fp>",{"id":215,"code":216,"type":141,"language":187,"highlight":217},"b28","document.addEventListener(\"visibilitychange\", async () => {\n  if (wakeLock !== null && document.visibilityState === \"visible\") {\n    await requestWakeLock();\n  }\n});",[],{"id":219,"html":220,"type":123},"b29","\u003Cp>One wrinkle worth planning for yourself: that condition only checks &quot;did we ever request a lock,&quot; not &quot;does the user still want one.&quot; If you also let people manually turn the feature off, null out \u003Ccode>wakeLock\u003C\u002Fcode> on that path too — otherwise switching tabs and back will quietly turn a lock the user explicitly released back on.\u003C\u002Fp>",{"id":222,"html":223,"text":224,"type":131,"level":31},"b30","Ship it without breaking the browsers that don&#39;t have it","Ship it without breaking the browsers that don't have it",{"id":226,"html":227,"type":123},"b31","\u003Cp>Feature-detect before you touch any of this:\u003C\u002Fp>",{"id":229,"code":230,"type":141,"language":187,"highlight":231},"b32","if (\"wakeLock\" in navigator) {\n  requestWakeLock();\n} else {\n  \u002F\u002F Fall back to whatever you were doing before, or do nothing —\n  \u002F\u002F a screen that locks isn't a crash.\n}",[],{"id":233,"html":234,"type":123},"b33","\u003Cp>Support is solid across Chrome, Edge, and Opera, and Safari added it in 16.4. Firefox has historically lagged on this one — check caniuse.com for the current state before you rely on it, and always keep the feature-detect branch rather than assuming.\u003C\u002Fp>",{"id":236,"html":237,"text":237,"type":131,"level":31},"b34","The one-pixel video, decoded",{"id":239,"html":240,"type":123},"b35","\u003Cp>Next time a cooking site keeps your screen alive while you&#39;re up to your elbows in dough, you&#39;ll know what&#39;s happening under the hood — and whether it&#39;s a phantom \u003Ccode>&lt;video&gt;\u003C\u002Fcode> tag or three lines calling an API built for exactly that job.\u003C\u002Fp>",{"id":242,"html":243,"type":123},"b36","\u003Cp>If you&#39;re still shipping the video trick somewhere, what&#39;s holding you back from swapping it — browser support, or just not knowing the replacement existed?\u003C\u002Fp>",{"id":245,"html":246,"type":123},"b37","\u003C!-- quiz:start -->",{"id":248,"html":249,"text":249,"type":131,"level":31},"b38","🧠 Test yourself",{"id":251,"html":252,"type":123},"b39","\u003Cp>Think it clicked? \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fscreen-wake-lock-api-keep-screen-on\u002Fquiz\">Take the 7-question quiz →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":254,"html":255,"type":123},"b40","\u003Cp>\u003Cem>Instant feedback, a hint on every question, and an explanation for each answer — right or wrong.\u003C\u002Fem>\u003C\u002Fp>",{"id":257,"html":258,"type":123},"b41","\u003C!-- quiz:end -->",{"id":260,"type":261},"b42","divider",{"id":263,"html":264,"type":123},"b43","\u003Cp>🚀 \u003Cstrong>Want more like this?\u003C\u002Fstrong> Every guide, playground, and quiz lives on \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fbestpractic.org\u002F\">bestpractic.org\u003C\u002Fa>\u003C\u002Fstrong> — open it and \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fbestpractic.org\u002F\">sign up free\u003C\u002Fa>\u003C\u002Fstrong> so the next one finds you.\u003C\u002Fp>",{"id":266,"html":267,"type":123},"b44","\u003Cp>\u003Cem>Thanks for reading! Let&#39;s stay connected:\u003C\u002Fem>\u003C\u002Fp>",{"id":269,"type":154,"items":270,"ordered":18},"b45",[271,272,273],"⭐ \u003Cstrong>GitHub\u003C\u002Fstrong> — follow me and star the projects: \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fparsajiravand\">github.com\u002Fparsajiravand\u003C\u002Fa>","💬 \u003Cstrong>Discord\u003C\u002Fstrong> — join the frontend best-practices community: \u003Ca href=\"https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ\">discord.gg\u002Fd9KRhuAwQ\u003C\u002Fa>","📸 \u003Cstrong>Instagram\u003C\u002Fstrong> — frontend best practices, daily: \u003Ca href=\"https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F\">@bestpractice___\u003C\u002Fa>","Open dev tools on almost any recipe site mid-scroll and check the Elements panel. Buried near the bottom, there's a `\u003Cvideo>` tag. It's one pixel. It's muted. It's on an infinite loop. And if you actually watch what it's playing — nothing. It's a single frame of black, looping forever, going nowhere.\n\nThat's not debug cruft someone forgot to delete. It's load-bearing. Rip it out and the page's actual job — keeping your phone's screen on while your hands are covered in flour — quietly breaks.\n\n## The problem it's solving\n\nMobile browsers don't give a web page a button that says \"don't lock the screen.\" There's no `document.staySharp()`. The OS owns that timer, and for a long time the only way JavaScript could influence it was indirectly — by doing something the OS already treats as a signal that the user is still engaged.\n\nActively playing video is one of those signals. Every mobile OS defers the screen-lock timer while media is playing, because pausing a movie mid-scene to lock the screen would be a terrible experience. So people found the seam: play *something*, even if that something is deliberately nothing.\n\n```html\n\u003Cvideo id=\"keep-awake\" muted playsinline loop>\n  \u003Csource src=\"silent-1px.mp4\" type=\"video\u002Fmp4\" \u002F>\n\u003C\u002Fvideo>\n\u003Cscript>\n  document.getElementById(\"keep-awake\").play();\n\u003C\u002Fscript>\n```\n\n`muted` and `playsinline` are load-bearing too — without them, most mobile browsers either block the autoplay outright or hijack the screen with a fullscreen player. Libraries like NoSleep.js packaged exactly this pattern for years, because it worked, and because there wasn't anything better to reach for.\n\n## Where it falls apart\n\nIt's a real technique and it did the job — but borrowing \"video playback\" as a proxy for \"keep the screen awake\" comes with everything you'd expect from repurposing the wrong primitive:\n\n- **Autoplay policies fight you.** Some mobile browsers still block autoplaying video unless it happens inside a user gesture, so the trick can silently fail on exactly the browser version where you need it most.\n- **It costs a decoder, not a flag.** A one-pixel video is small, but \"small\" isn't \"free\" — you're spinning up video decoding hardware and a render loop to communicate a boolean.\n- **Nothing tells you it stopped working.** If the tab is backgrounded in a way the browser doesn't treat as \"still playing,\" the video pauses and your screen locks — with no error, no event, nothing to catch.\n- **It's semantically a lie.** Anyone reading that markup six months from now has to reverse-engineer *why* there's a phantom video before they can safely touch it.\n\nThe workaround earned its keep because the platform had a real gap. In 2019, Chrome closed it.\n\n## The API that says what it means\n\n\u003C!-- playground:start -->\n\n## 🎮 Try it yourself\n\n**[▶️ Open the interactive playground →](https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fscreen-wake-lock-api-keep-screen-on\u002Fplayground)**\n\n_Runs right in your browser — poke at it and watch the concept react live._\n\n\u003C!-- playground:end -->\n\nThe Screen Wake Lock API does exactly one thing, and its name doesn't lie about it:\n\n```js\nlet wakeLock = null;\n\nasync function requestWakeLock() {\n  try {\n    wakeLock = await navigator.wakeLock.request(\"screen\");\n    console.log(\"Screen will stay on\");\n  } catch (err) {\n    \u002F\u002F Fails if the document isn't visible, isn't a secure context,\n    \u002F\u002F or the platform refuses for its own reasons.\n    console.error(`${err.name}: ${err.message}`);\n  }\n}\n```\n\n`navigator.wakeLock.request(\"screen\")` — `\"screen\"` is currently the only lock type the spec defines — returns a promise for a `WakeLockSentinel`. While that sentinel is alive, the screen won't dim or lock on its own. No `\u003Cvideo>`, no decoder, no lying markup. It needs a secure context (HTTPS or localhost) and the document has to actually be visible when you call it, or the promise rejects with a `NotAllowedError`.\n\nReleasing it is just as direct:\n\n```js\nasync function releaseWakeLock() {\n  await wakeLock?.release();\n  wakeLock = null;\n}\n```\n\nThat would be the whole post, except the API has one behavior that catches almost everyone the first time.\n\n## The part the happy path hides\n\nSwitch away from the tab holding the lock — another window, another app, the phone's lock button — and the browser releases the wake lock for you. Silently. No exception. No rejected promise. Your `wakeLock` variable still points at a sentinel object; it's just that the sentinel's job is now over, and nothing forces you to notice.\n\nCome back to the tab, and the screen goes right back to locking on schedule — because as far as the platform's concerned, you never asked it not to. If your only test was \"click the button once, watch the screen stay on for thirty seconds,\" you'll ship this and find out from a support ticket instead.\n\nThe sentinel does expose a `release` event, and MDN's own guide handles the whole thing with a `visibilitychange` listener that re-requests the lock the moment the tab becomes visible again:\n\n```js\ndocument.addEventListener(\"visibilitychange\", async () => {\n  if (wakeLock !== null && document.visibilityState === \"visible\") {\n    await requestWakeLock();\n  }\n});\n```\n\nOne wrinkle worth planning for yourself: that condition only checks \"did we ever request a lock,\" not \"does the user still want one.\" If you also let people manually turn the feature off, null out `wakeLock` on that path too — otherwise switching tabs and back will quietly turn a lock the user explicitly released back on.\n\n## Ship it without breaking the browsers that don't have it\n\nFeature-detect before you touch any of this:\n\n```js\nif (\"wakeLock\" in navigator) {\n  requestWakeLock();\n} else {\n  \u002F\u002F Fall back to whatever you were doing before, or do nothing —\n  \u002F\u002F a screen that locks isn't a crash.\n}\n```\n\nSupport is solid across Chrome, Edge, and Opera, and Safari added it in 16.4. Firefox has historically lagged on this one — check caniuse.com for the current state before you rely on it, and always keep the feature-detect branch rather than assuming.\n\n## The one-pixel video, decoded\n\nNext time a cooking site keeps your screen alive while you're up to your elbows in dough, you'll know what's happening under the hood — and whether it's a phantom `\u003Cvideo>` tag or three lines calling an API built for exactly that job.\n\nIf you're still shipping the video trick somewhere, what's holding you back from swapping it — browser support, or just not knowing the replacement existed?\n\n\u003C!-- quiz:start -->\n\n## 🧠 Test yourself\n\nThink it clicked? **[Take the 7-question quiz →](https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fscreen-wake-lock-api-keep-screen-on\u002Fquiz)**\n\n_Instant feedback, a hint on every question, and an explanation for each answer — right or wrong._\n\n\u003C!-- quiz:end -->\n\n---\n\n🚀 **Want more like this?** Every guide, playground, and quiz lives on **[bestpractic.org](https:\u002F\u002Fbestpractic.org\u002F)** — open it and **[sign up free](https:\u002F\u002Fbestpractic.org\u002F)** so the next one finds you.\n\n*Thanks for reading! Let's stay connected:*\n\n- ⭐ **GitHub** — follow me and star the projects: [github.com\u002Fparsajiravand](https:\u002F\u002Fgithub.com\u002Fparsajiravand)\n- 💬 **Discord** — join the frontend best-practices community: [discord.gg\u002Fd9KRhuAwQ](https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ)\n- 📸 **Instagram** — frontend best practices, daily: [@bestpractice___](https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F)",{"title":93,"canonical":276,"description":277},"https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fscreen-wake-lock-api-keep-screen-on","Cooking sites, workout timers, and boarding-pass pages used to autoplay an invisible, muted, looping video for one job only: stopping your phone from locking its screen. The Screen","01a05cb5-e732-76ca-8865-1b21e501e53e",{"id":280,"locked":18},"01a05cb5-e76f-704f-ba23-da967296e34d",[282],{"id":283,"slug":92,"title":284,"_count":285},"01a05cb5-e791-71ee-ac63-ed6fcff25a35","Screen Wake Lock API",{"questions":286},7,[288],{"locale":13,"slug":92},{"id":283,"slug":92,"title":284,"_count":290,"questionCount":286},{"questions":286},{"items":292,"meta":416},[293,305,324,343,361,379,397],{"id":91,"slug":92,"title":93,"subtitle":94,"excerpt":95,"coverUrl":96,"locale":13,"readingMinutes":86,"publishedAt":97,"viewCount":294,"likeCount":19,"commentCount":19,"author":295,"vertical":296,"topic":297,"tags":298,"_count":303,"playground":304,"hasQuiz":17,"hasPlayground":17},24,{"id":100,"name":101,"username":102,"avatarUrl":94,"headline":103},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":50,"name":106},[299,300,301,302],{"slug":50,"name":51,"color":94},{"slug":46,"name":47,"color":94},{"slug":77,"name":78,"color":94},{"slug":112,"name":113,"color":94},{"assessments":115},{"slug":92},{"id":306,"slug":307,"title":308,"subtitle":94,"excerpt":309,"coverUrl":310,"locale":13,"readingMinutes":311,"publishedAt":312,"viewCount":313,"likeCount":19,"commentCount":19,"author":314,"vertical":315,"topic":316,"tags":317,"_count":322,"playground":323,"hasQuiz":17,"hasPlayground":17},"01a0632c-7248-73e3-9951-e8c6eaa578c7","react-weekly-compiler-memoization","React Compiler 1.0: What useMemo You Can Delete","React Compiler 1.0 is stable. Here's the re-render model it automates, which useMemo\u002FuseCallback\u002Fmemo calls you can delete, and what still needs you.","\u002Fmedia\u002Fcovers\u002Freact-weekly-compiler-memoization.png",13,"2026-09-05T10:17:49.849Z",100,{"id":100,"name":101,"username":102,"avatarUrl":94,"headline":103},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":73,"name":74},[318,319,320,321],{"slug":73,"name":74,"color":94},{"slug":50,"name":51,"color":94},{"slug":62,"name":63,"color":94},{"slug":46,"name":47,"color":94},{"assessments":115},{"slug":307},{"id":325,"slug":326,"title":327,"subtitle":94,"excerpt":328,"coverUrl":329,"locale":13,"readingMinutes":330,"publishedAt":331,"viewCount":332,"likeCount":19,"commentCount":19,"author":333,"vertical":334,"topic":335,"tags":336,"_count":341,"playground":342,"hasQuiz":17,"hasPlayground":17},"01a057f2-68b2-7521-a373-0ea70eae6f55","page-visibility-api-tab-aware-timers","Your Timer Doesn't Know You Tabbed Away","window blur feels like the obvious way to detect an idle tab, and it's wrong in ways that only show up in production. The Page Visibility API answers the actual question — can anyone see this? — so polling, timers, and video stop wasting work the moment nobody's looking.","\u002Fmedia\u002Fcovers\u002Fpage-visibility-api-tab-aware-timers.png",4,"2026-09-05T10:17:19.010Z",66,{"id":100,"name":101,"username":102,"avatarUrl":94,"headline":103},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":50,"name":106},[337,338,339,340],{"slug":50,"name":51,"color":94},{"slug":46,"name":47,"color":94},{"slug":77,"name":78,"color":94},{"slug":66,"name":67,"color":94},{"assessments":115},{"slug":326},{"id":344,"slug":345,"title":346,"subtitle":94,"excerpt":347,"coverUrl":348,"locale":13,"readingMinutes":86,"publishedAt":349,"viewCount":350,"likeCount":19,"commentCount":19,"author":351,"vertical":352,"topic":353,"tags":354,"_count":359,"playground":360,"hasQuiz":17,"hasPlayground":17},"01a04d81-723b-725d-9e99-7e11d03aa56a","clipboard-writetext-focus-bug","The await That Silently Breaks navigator.clipboard.writeText()","navigator.clipboard.writeText() only works while the document is focused and the user gesture is still fresh. Any await before the call can let both expire, so a copy button fails with an uncaught NotAllowedError and nobody ever sees why.","\u002Fmedia\u002Fcovers\u002Fclipboard-writetext-focus-bug.png","2026-09-03T17:23:32.218Z",161,{"id":100,"name":101,"username":102,"avatarUrl":94,"headline":103},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":50,"name":106},[355,356,357,358],{"slug":46,"name":47,"color":94},{"slug":50,"name":51,"color":94},{"slug":77,"name":78,"color":94},{"slug":54,"name":55,"color":94},{"assessments":115},{"slug":345},{"id":362,"slug":363,"title":364,"subtitle":94,"excerpt":365,"coverUrl":366,"locale":13,"readingMinutes":86,"publishedAt":367,"viewCount":368,"likeCount":19,"commentCount":19,"author":369,"vertical":370,"topic":371,"tags":372,"_count":377,"playground":378,"hasQuiz":17,"hasPlayground":17},"01a0499d-bb9f-709b-9e8a-9c426ae95530","declarative-shadow-dom-ssr-web-components","Shadow DOM Needed JavaScript to Exist. Now It Doesn't.","attachShadow() is a JavaScript-only API with no HTML serialization, so a server-rendered web component ships an empty host element until the client hydrates it. Declarative Shadow DOM attaches the real shadow root during HTML parsing — zero JS required.","\u002Fmedia\u002Fcovers\u002Fdeclarative-shadow-dom-ssr-web-components.png","2026-09-02T10:57:52.645Z",175,{"id":100,"name":101,"username":102,"avatarUrl":94,"headline":103},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":50,"name":106},[373,374,375,376],{"slug":46,"name":47,"color":94},{"slug":50,"name":51,"color":94},{"slug":84,"name":85,"color":94},{"slug":54,"name":55,"color":94},{"assessments":115},{"slug":363},{"id":380,"slug":381,"title":382,"subtitle":94,"excerpt":383,"coverUrl":384,"locale":13,"readingMinutes":86,"publishedAt":385,"viewCount":386,"likeCount":19,"commentCount":19,"author":387,"vertical":388,"topic":389,"tags":390,"_count":395,"playground":396,"hasQuiz":17,"hasPlayground":17},"01a04446-4fc4-73e1-b763-eda8c9cf631f","navigation-api-intercept-navigation","Your Router Doesn't Intercept Navigation. It Reacts To It.","Double-click a link during a slow route change and most SPA routers render two pages and settle on the wrong one — because they're listening for navigation after it already happened. The Navigation API lets you stop it before it starts.","\u002Fmedia\u002Fcovers\u002Fnavigation-api-intercept-navigation.png","2026-09-01T11:23:43.875Z",136,{"id":100,"name":101,"username":102,"avatarUrl":94,"headline":103},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":50,"name":106},[391,392,393,394],{"slug":50,"name":51,"color":94},{"slug":46,"name":47,"color":94},{"slug":77,"name":78,"color":94},{"slug":54,"name":55,"color":94},{"assessments":115},{"slug":381},{"id":398,"slug":399,"title":400,"subtitle":94,"excerpt":401,"coverUrl":402,"locale":13,"readingMinutes":403,"publishedAt":404,"viewCount":405,"likeCount":19,"commentCount":19,"author":406,"vertical":407,"topic":408,"tags":409,"_count":414,"playground":415,"hasQuiz":17,"hasPlayground":17},"019ff73a-fb5b-73ce-b725-2912167a7dde","weekly-debounce-and-throttle","Debounce and Throttle in JavaScript: The Complete Guide","Learn debounce and throttle in JavaScript step by step, with worked examples, edge cases, and a copy-paste cheat sheet for search, scroll, and resize.","\u002Fmedia\u002Fcovers\u002Fweekly-debounce-and-throttle.png",14,"2026-08-31T13:12:14.139Z",186,{"id":100,"name":101,"username":102,"avatarUrl":94,"headline":103},{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":50,"name":106},[410,411,412,413],{"slug":50,"name":51,"color":94},{"slug":46,"name":47,"color":94},{"slug":62,"name":63,"color":94},{"slug":66,"name":67,"color":94},{"assessments":115},{"slug":399},{"page":115,"perPage":286,"total":52,"totalPages":417},10,"\u003Cdiv class=\"shj shj-lang-html shj-multiline\" data-lang=\"html\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>\u003Cspan class=\"shj-var\">video\u003C\u002Fspan> \u003Cspan class=\"shj-class\">id\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">=\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"keep-awake\"\u003C\u002Fspan> \u003Cspan class=\"shj-class\">muted\u003C\u002Fspan> \u003Cspan class=\"shj-class\">playsinline\u003C\u002Fspan> \u003Cspan class=\"shj-class\">loop\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>\u003Cspan class=\"shj-var\">source\u003C\u002Fspan> \u003Cspan class=\"shj-class\">src\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">=\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"silent-1px.mp4\"\u003C\u002Fspan> \u003Cspan class=\"shj-class\">type\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">=\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"video\u002Fmp4\"\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">\u002F&gt;\u003C\u002Fspan>\n\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u002F\u003C\u002Fspan>\u003Cspan class=\"shj-var\">video\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>\u003Cspan class=\"shj-var\">script\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\n  document\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getElementById\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"keep-awake\"\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">play\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u002F\u003C\u002Fspan>\u003Cspan class=\"shj-var\">script\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003Cdiv>11\u003C\u002Fdiv>\u003Cdiv>12\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">let\u003C\u002Fspan> wakeLock \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-num\">null\u003C\u002Fspan>;\n\n\u003Cspan class=\"shj-kwd\">async\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">function\u003C\u002Fspan> \u003Cspan class=\"shj-func\">requestWakeLock\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">try\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n    wakeLock \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">await\u003C\u002Fspan> navigator\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>wakeLock\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">request\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"screen\"\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n    console\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">log\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"Screen will stay on\"\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">catch\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>err\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n    \u003Cspan class=\"shj-cmnt\">\u002F\u002F Fails if the document isn't visible, isn't a secure context,\n\u003C\u002Fspan>    \u003Cspan class=\"shj-cmnt\">\u002F\u002F or the platform refuses for its own reasons.\n\u003C\u002Fspan>    console\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">error\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">`\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">${\u003C\u002Fspan>err\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>name\u003Cspan class=\"shj-kwd\">}\u003C\u002Fspan>\u003Cspan class=\"shj-str\">: \u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">${\u003C\u002Fspan>err\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>message\u003Cspan class=\"shj-kwd\">}\u003C\u002Fspan>\u003Cspan class=\"shj-str\">`\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">async\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">function\u003C\u002Fspan> \u003Cspan class=\"shj-func\">releaseWakeLock\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">await\u003C\u002Fspan> wakeLock\u003Cspan class=\"shj-oper\">?.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">release\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  wakeLock \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> \u003Cspan class=\"shj-num\">null\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">document\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">addEventListener\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"visibilitychange\"\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">async\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">if\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>wakeLock \u003Cspan class=\"shj-oper\">!==\u003C\u002Fspan> \u003Cspan class=\"shj-num\">null\u003C\u002Fspan> \u003Cspan class=\"shj-oper\">&#38;&#38;\u003C\u002Fspan> document\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>visibilityState \u003Cspan class=\"shj-oper\">===\u003C\u002Fspan> \u003Cspan class=\"shj-str\">\"visible\"\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n    \u003Cspan class=\"shj-kwd\">await\u003C\u002Fspan> \u003Cspan class=\"shj-func\">requestWakeLock\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">if\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"wakeLock\"\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">in\u003C\u002Fspan> navigator\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-func\">requestWakeLock\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">else\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-cmnt\">\u002F\u002F Fall back to whatever you were doing before, or do nothing —\n\u003C\u002Fspan>  \u003Cspan class=\"shj-cmnt\">\u002F\u002F a screen that locks isn't a crash.\n\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>",{"locked":18,"total":19,"comments":424},[]]