[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"verticals":3,"quiz-broadcast-channel-cross-tab-messaging":32,"quiz-article-broadcast-channel-cross-tab-messaging":48},[4,20],{"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","Build. Learn. Ship.","Practical courses, engineering-grade articles and open-source tools for people who ship.","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.","Structured paths, listening drills and spaced repetition that actually sticks.","amber-400","⌘",[13,15,29],"es",{"courses":17,"paths":17,"articles":18,"exams":18,"flashcards":18,"packages":18,"community":17,"certificates":18,"teams":18,"commerce":17},2,{"id":33,"slug":34,"kind":35,"title":36,"description":37,"config":38,"verticalId":5,"vertical":43,"course":40,"_count":44,"access":45,"attempts":47,"questionCount":39},"019fe776-d1ef-7058-9ab7-5d1a725b756a","broadcast-channel-cross-tab-messaging","PRACTICE_QUIZ","BroadcastChannel API — cross-tab messaging","BroadcastChannel lets any tab, worker, or iframe on the same origin send and receive messages directly, with no localStorage side-channel required. These questions cover the API shape, scope restrictions, data types, browser support, and how it compares to the localStorage+storage-event workaround.",{"questionCount":39,"timeLimitSec":40,"shuffleQuestions":18,"shuffleOptions":17,"negativeMarking":19,"passScorePct":41,"maxAttempts":40,"revealAnswers":42,"allowFlagging":18,"allowBacktracking":17},9,null,70,"AFTER_SUBMIT",{"slug":6,"name":7},{"questions":39},{"allowed":17,"reason":46},"FREE",[],{"id":49,"slug":34,"title":50,"subtitle":40,"excerpt":51,"coverUrl":52,"locale":13,"readingMinutes":53,"publishedAt":54,"viewCount":55,"likeCount":19,"commentCount":19,"author":56,"vertical":61,"topic":62,"tags":65,"_count":77,"playground":79,"body":81,"bodyMd":221,"seo":222,"translationGroupId":226,"thread":227,"assessments":229,"translations":232,"quiz":234},"019fe660-fcbe-745e-a443-5ae33ac10aaf","Stop using the localStorage hack to sync browser tabs. BroadcastChannel does it natively.","Syncing state across browser tabs with localStorage events is a widely-used trick that requires JSON.stringify, event filtering, and careful cleanup. The Broadcast Channel API delivers messages between tabs directly, with none of the side effects.","\u002Fmedia\u002Fcovers\u002Fbroadcast-channel-cross-tab-messaging.png",4,"2026-08-09T07:02:41.629Z",56,{"id":57,"name":58,"username":59,"avatarUrl":40,"headline":60},"019fe637-3c25-7088-9034-39c9f15dc3c8","Parsa Jiravand","parsa","Frontend engineer · building bestpractic",{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":63,"name":64},"javascript","JavaScript",[66,68,71,74],{"slug":63,"name":67,"color":40},"Javascript",{"slug":69,"name":70,"color":40},"webdev","Webdev",{"slug":72,"name":73,"color":40},"frontend","Frontend",{"slug":75,"name":76,"color":40},"apis","Apis",{"assessments":78},1,{"slug":34,"title":80},"BroadcastChannel — interactive playground",{"blocks":82,"version":78},[83,87,91,97,100,103,107,110,113,117,120,123,126,130,133,137,140,143,146,153,156,159,162,165,168,171,174,177,180,183,186,189,192,195,198,201,204,207,210,213],{"id":84,"html":85,"type":86},"b1","\u003Cp>When a user logs out in one tab, the other tabs should follow. When they update their cart, every open window should reflect it. The common solution is a localStorage trick: write a sentinel value, listen for the \u003Ccode>storage\u003C\u002Fcode> event, read it, parse it, check if it&#39;s &quot;for you,&quot; and clean it up. It works — but it&#39;s a side-channel communication pattern built on a persistence API that was never meant for messaging. The Broadcast Channel API is the direct path.\u003C\u002Fp>","paragraph",{"id":88,"html":89,"text":89,"type":90,"level":31},"b2","The API","heading",{"id":92,"code":93,"type":94,"language":95,"highlight":96},"b3","\u002F\u002F Sender (any tab, worker, or iframe on the same origin)\nconst channel = new BroadcastChannel('app-sync');\nchannel.postMessage({ type: 'LOGOUT' });\n\n\u002F\u002F Receiver (every other context subscribed to the same name)\nconst channel = new BroadcastChannel('app-sync');\nchannel.onmessage = (event) => {\n  console.log(event.data); \u002F\u002F { type: 'LOGOUT' }\n};","code","js",[],{"id":98,"html":99,"type":86},"b4","\u003Cp>Two steps: open a channel by name, then send or listen. Any tab, worker, or iframe on the same origin that opens a channel with the same name receives every message sent on it — including messages sent \u003Cem>after\u003C\u002Fem> they subscribed. The sender does not receive its own messages.\u003C\u002Fp>",{"id":101,"html":102,"type":86},"b5","\u003Cp>Close the channel when you&#39;re done to release the listener:\u003C\u002Fp>",{"id":104,"code":105,"type":94,"language":95,"highlight":106},"b6","channel.close();",[],{"id":108,"html":109,"text":109,"type":90,"level":31},"b7","What the localStorage approach actually looks like",{"id":111,"html":112,"type":86},"b8","\u003Cp>The typical cross-tab sync pattern using \u003Ccode>storage\u003C\u002Fcode> events:\u003C\u002Fp>",{"id":114,"code":115,"type":94,"language":95,"highlight":116},"b9","\u002F\u002F Sender\nlocalStorage.setItem('__broadcast', JSON.stringify({ type: 'LOGOUT', t: Date.now() }));\nlocalStorage.removeItem('__broadcast'); \u002F\u002F clean up immediately\n\n\u002F\u002F Receiver\nwindow.addEventListener('storage', (event) => {\n  if (event.key !== '__broadcast') return; \u002F\u002F filter noise\n  if (!event.newValue) return;             \u002F\u002F ignore the removeItem\n  const message = JSON.parse(event.newValue);\n  if (message.type === 'LOGOUT') { \u002F* handle *\u002F }\n});",[],{"id":118,"html":119,"type":86},"b10","\u003Cp>Every part of this is load-bearing workaround: the timestamp prevents deduplication if the same value is sent twice; the \u003Ccode>removeItem\u003C\u002Fcode> triggers a second storage event that must be filtered out; \u003Ccode>JSON.stringify\u003C\u002Fcode>\u002F\u003Ccode>JSON.parse\u003C\u002Fcode> is required because storage only holds strings. BroadcastChannel replaces the entire block with a \u003Ccode>postMessage\u003C\u002Fcode> call.\u003C\u002Fp>",{"id":121,"html":122,"text":122,"type":90,"level":31},"b11","Real-world use cases",{"id":124,"html":125,"type":86},"b12","\u003Cp>\u003Cstrong>Logout across all tabs.\u003C\u002Fstrong> When the user logs out, invalidate the session in every open window simultaneously:\u003C\u002Fp>",{"id":127,"code":128,"type":94,"language":95,"highlight":129},"b13","\u002F\u002F auth.js — runs in every tab\nconst syncChannel = new BroadcastChannel('auth');\n\nexport function logout() {\n  clearSession();\n  syncChannel.postMessage({ type: 'SESSION_ENDED' });\n  redirect('\u002Flogin');\n}\n\nsyncChannel.onmessage = (event) => {\n  if (event.data.type === 'SESSION_ENDED') {\n    clearSession();\n    redirect('\u002Flogin');\n  }\n};",[],{"id":131,"html":132,"type":86},"b14","\u003Cp>\u003Cstrong>Cart sync in an e-commerce app.\u003C\u002Fstrong> Add to cart in one tab, see the count update in the header of every other tab:\u003C\u002Fp>",{"id":134,"code":135,"type":94,"language":95,"highlight":136},"b15","const cartChannel = new BroadcastChannel('cart');\n\nfunction addToCart(item) {\n  const updated = updateLocalCart(item);\n  cartChannel.postMessage({ type: 'CART_UPDATED', cart: updated });\n  renderCart(updated);\n}\n\ncartChannel.onmessage = (event) => {\n  if (event.data.type === 'CART_UPDATED') {\n    renderCart(event.data.cart);\n  }\n};",[],{"id":138,"html":139,"type":86},"b16","\u003Cp>\u003Cstrong>Live config refresh.\u003C\u002Fstrong> When an admin changes a feature flag in a settings tab, broadcast the update so every other open tab picks it up without a page reload.\u003C\u002Fp>",{"id":141,"html":142,"text":142,"type":90,"level":31},"b17","What you can send",{"id":144,"html":145,"type":86},"b18","\u003Cp>BroadcastChannel uses the \u003Ca href=\"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FWeb_Workers_API\u002FStructured_clone_algorithm\">structured clone algorithm\u003C\u002Fa> — the same one used by \u003Ccode>structuredClone()\u003C\u002Fcode> and \u003Ccode>postMessage()\u003C\u002Fcode> on workers. That means you can send:\u003C\u002Fp>",{"id":147,"type":148,"items":149,"ordered":18},"b19","list",[150,151,152],"Plain objects and arrays (including nested)","\u003Ccode>Date\u003C\u002Fcode>, \u003Ccode>Map\u003C\u002Fcode>, \u003Ccode>Set\u003C\u002Fcode>, \u003Ccode>ArrayBuffer\u003C\u002Fcode>, \u003Ccode>Blob\u003C\u002Fcode>","Primitive values — strings, numbers, booleans, \u003Ccode>null\u003C\u002Fcode>",{"id":154,"html":155,"type":86},"b20","\u003Cp>You \u003Cstrong>cannot\u003C\u002Fstrong> send functions, DOM nodes, or anything not serializable by structured clone. If you try, the call throws a \u003Ccode>DataCloneError\u003C\u002Fcode>. For the message payloads most apps actually use — event objects with typed fields — structured clone covers everything without the JSON roundtrip.\u003C\u002Fp>",{"id":157,"html":158,"text":158,"type":90,"level":31},"b21","Scope and limits",{"id":160,"html":161,"type":86},"b22","\u003Cp>BroadcastChannel is scoped to \u003Cstrong>same-origin contexts\u003C\u002Fstrong> — same protocol, hostname, and port. A channel named \u003Ccode>&#39;app-sync&#39;\u003C\u002Fcode> on \u003Ccode>https:\u002F\u002Fexample.com\u003C\u002Fcode> is completely isolated from a channel with the same name on \u003Ccode>https:\u002F\u002Fstaging.example.com\u003C\u002Fcode>. You cannot use it to communicate between different origins.\u003C\u002Fp>",{"id":163,"html":164,"type":86},"b23","\u003Cp>The channel name is your namespace. If multiple features in your app use BroadcastChannel, give each a distinct name (\u003Ccode>&#39;auth&#39;\u003C\u002Fcode>, \u003Ccode>&#39;cart&#39;\u003C\u002Fcode>, \u003Ccode>&#39;notifications&#39;\u003C\u002Fcode>) rather than sharing a single \u003Ccode>&#39;app&#39;\u003C\u002Fcode> channel and multiplexing message types through it — separate channels are cleaner and don&#39;t require filtering.\u003C\u002Fp>",{"id":166,"html":167,"text":167,"type":90,"level":31},"b24","Browser support",{"id":169,"html":170,"type":86},"b25","\u003Cp>BroadcastChannel is \u003Cstrong>Baseline 2022\u003C\u002Fstrong>: Chrome 54 (2016), Firefox 38 (2015), Safari 15.4 (March 2022). The API has been in Chromium and Firefox for nearly a decade; Safari joined in 2022. It&#39;s available in all currently-supported browser versions and in Web Workers and Service Workers, not just the main thread.\u003C\u002Fp>",{"id":172,"html":173,"type":86},"b26","\u003C!-- playground:start -->",{"id":175,"html":176,"text":176,"type":90,"level":31},"b27","🎮 Try it yourself",{"id":178,"html":179,"type":86},"b28","\u003Cp>\u003Cstrong>\u003Ca href=\"https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fposts\u002F2026-08-09-broadcast-channel-cross-tab-messaging\u002Fplayground\u002F\">▶️ Open the interactive playground →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":181,"html":182,"type":86},"b29","\u003Cp>\u003Cem>Runs right in your browser — poke at it and watch the concept react live.\u003C\u002Fem>\u003C\u002Fp>",{"id":184,"html":185,"type":86},"b30","\u003C!-- playground:end -->",{"id":187,"html":188,"type":86},"b31","\u003C!-- quiz:start -->",{"id":190,"html":191,"text":191,"type":90,"level":31},"b32","🧠 Test yourself",{"id":193,"html":194,"type":86},"b33","\u003Cp>Think it clicked? \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fquiz\u002Ftake.html?post=2026-08-09-broadcast-channel-cross-tab-messaging\">Take the 9-question quiz →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":196,"html":197,"type":86},"b34","\u003Cp>\u003Cem>Instant feedback, a hint on every question, and an explanation for each answer — right or wrong.\u003C\u002Fem>\u003C\u002Fp>",{"id":199,"html":200,"type":86},"b35","\u003C!-- quiz:end -->",{"id":202,"html":203,"text":203,"type":90,"level":31},"b36","The takeaway",{"id":205,"html":206,"type":86},"b37","\u003Cp>Search your codebase for \u003Ccode>storage\u003C\u002Fcode> event listeners paired with a \u003Ccode>localStorage.setItem\u003C\u002Fcode> that immediately gets removed. That pattern is cross-tab messaging through a storage side-channel — exactly what BroadcastChannel exists to replace. Swap it out: open a channel by name, call \u003Ccode>postMessage\u003C\u002Fcode>, listen with \u003Ccode>onmessage\u003C\u002Fcode>. You get structured data without serialization, no storage event noise to filter, and no cleanup sentinel to manage. The intent becomes clear in the code; the runtime handles the delivery.\u003C\u002Fp>",{"id":208,"type":209},"b38","divider",{"id":211,"html":212,"type":86},"b39","\u003Cp>\u003Cem>Thanks for reading! Let&#39;s stay connected:\u003C\u002Fem>\u003C\u002Fp>",{"id":214,"type":148,"items":215,"ordered":18},"b40",[216,217,218,219,220],"⭐ \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>","💼 \u003Cstrong>LinkedIn\u003C\u002Fstrong> — \u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fparsa-jiravand\u002F\">linkedin.com\u002Fin\u002Fparsa-jiravand\u003C\u002Fa>","✉️ \u003Cstrong>Email\u003C\u002Fstrong> (work &amp; contract inquiries): \u003Ca href=\"mailto:bestpractice2026@gmail.com\">bestpractice2026@gmail.com\u003C\u002Fa>","When a user logs out in one tab, the other tabs should follow. When they update their cart, every open window should reflect it. The common solution is a localStorage trick: write a sentinel value, listen for the `storage` event, read it, parse it, check if it's \"for you,\" and clean it up. It works — but it's a side-channel communication pattern built on a persistence API that was never meant for messaging. The Broadcast Channel API is the direct path.\n\n## The API\n\n```js\n\u002F\u002F Sender (any tab, worker, or iframe on the same origin)\nconst channel = new BroadcastChannel('app-sync');\nchannel.postMessage({ type: 'LOGOUT' });\n\n\u002F\u002F Receiver (every other context subscribed to the same name)\nconst channel = new BroadcastChannel('app-sync');\nchannel.onmessage = (event) => {\n  console.log(event.data); \u002F\u002F { type: 'LOGOUT' }\n};\n```\n\nTwo steps: open a channel by name, then send or listen. Any tab, worker, or iframe on the same origin that opens a channel with the same name receives every message sent on it — including messages sent *after* they subscribed. The sender does not receive its own messages.\n\nClose the channel when you're done to release the listener:\n\n```js\nchannel.close();\n```\n\n## What the localStorage approach actually looks like\n\nThe typical cross-tab sync pattern using `storage` events:\n\n```js\n\u002F\u002F Sender\nlocalStorage.setItem('__broadcast', JSON.stringify({ type: 'LOGOUT', t: Date.now() }));\nlocalStorage.removeItem('__broadcast'); \u002F\u002F clean up immediately\n\n\u002F\u002F Receiver\nwindow.addEventListener('storage', (event) => {\n  if (event.key !== '__broadcast') return; \u002F\u002F filter noise\n  if (!event.newValue) return;             \u002F\u002F ignore the removeItem\n  const message = JSON.parse(event.newValue);\n  if (message.type === 'LOGOUT') { \u002F* handle *\u002F }\n});\n```\n\nEvery part of this is load-bearing workaround: the timestamp prevents deduplication if the same value is sent twice; the `removeItem` triggers a second storage event that must be filtered out; `JSON.stringify`\u002F`JSON.parse` is required because storage only holds strings. BroadcastChannel replaces the entire block with a `postMessage` call.\n\n## Real-world use cases\n\n**Logout across all tabs.** When the user logs out, invalidate the session in every open window simultaneously:\n\n```js\n\u002F\u002F auth.js — runs in every tab\nconst syncChannel = new BroadcastChannel('auth');\n\nexport function logout() {\n  clearSession();\n  syncChannel.postMessage({ type: 'SESSION_ENDED' });\n  redirect('\u002Flogin');\n}\n\nsyncChannel.onmessage = (event) => {\n  if (event.data.type === 'SESSION_ENDED') {\n    clearSession();\n    redirect('\u002Flogin');\n  }\n};\n```\n\n**Cart sync in an e-commerce app.** Add to cart in one tab, see the count update in the header of every other tab:\n\n```js\nconst cartChannel = new BroadcastChannel('cart');\n\nfunction addToCart(item) {\n  const updated = updateLocalCart(item);\n  cartChannel.postMessage({ type: 'CART_UPDATED', cart: updated });\n  renderCart(updated);\n}\n\ncartChannel.onmessage = (event) => {\n  if (event.data.type === 'CART_UPDATED') {\n    renderCart(event.data.cart);\n  }\n};\n```\n\n**Live config refresh.** When an admin changes a feature flag in a settings tab, broadcast the update so every other open tab picks it up without a page reload.\n\n## What you can send\n\nBroadcastChannel uses the [structured clone algorithm](https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FWeb_Workers_API\u002FStructured_clone_algorithm) — the same one used by `structuredClone()` and `postMessage()` on workers. That means you can send:\n\n- Plain objects and arrays (including nested)\n- `Date`, `Map`, `Set`, `ArrayBuffer`, `Blob`\n- Primitive values — strings, numbers, booleans, `null`\n\nYou **cannot** send functions, DOM nodes, or anything not serializable by structured clone. If you try, the call throws a `DataCloneError`. For the message payloads most apps actually use — event objects with typed fields — structured clone covers everything without the JSON roundtrip.\n\n## Scope and limits\n\nBroadcastChannel is scoped to **same-origin contexts** — same protocol, hostname, and port. A channel named `'app-sync'` on `https:\u002F\u002Fexample.com` is completely isolated from a channel with the same name on `https:\u002F\u002Fstaging.example.com`. You cannot use it to communicate between different origins.\n\nThe channel name is your namespace. If multiple features in your app use BroadcastChannel, give each a distinct name (`'auth'`, `'cart'`, `'notifications'`) rather than sharing a single `'app'` channel and multiplexing message types through it — separate channels are cleaner and don't require filtering.\n\n## Browser support\n\nBroadcastChannel is **Baseline 2022**: Chrome 54 (2016), Firefox 38 (2015), Safari 15.4 (March 2022). The API has been in Chromium and Firefox for nearly a decade; Safari joined in 2022. It's available in all currently-supported browser versions and in Web Workers and Service Workers, not just the main thread.\n\n\n\u003C!-- playground:start -->\n\n## 🎮 Try it yourself\n\n**[▶️ Open the interactive playground →](https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fposts\u002F2026-08-09-broadcast-channel-cross-tab-messaging\u002Fplayground\u002F)**\n\n_Runs right in your browser — poke at it and watch the concept react live._\n\n\u003C!-- playground:end -->\n\n\u003C!-- quiz:start -->\n\n## 🧠 Test yourself\n\nThink it clicked? **[Take the 9-question quiz →](https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fquiz\u002Ftake.html?post=2026-08-09-broadcast-channel-cross-tab-messaging)**\n\n_Instant feedback, a hint on every question, and an explanation for each answer — right or wrong._\n\n\u003C!-- quiz:end -->\n## The takeaway\n\nSearch your codebase for `storage` event listeners paired with a `localStorage.setItem` that immediately gets removed. That pattern is cross-tab messaging through a storage side-channel — exactly what BroadcastChannel exists to replace. Swap it out: open a channel by name, call `postMessage`, listen with `onmessage`. You get structured data without serialization, no storage event noise to filter, and no cleanup sentinel to manage. The intent becomes clear in the code; the runtime handles the delivery.\n\n---\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)\n- 💼 **LinkedIn** — [linkedin.com\u002Fin\u002Fparsa-jiravand](https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fparsa-jiravand\u002F)\n- ✉️ **Email** (work & contract inquiries): [bestpractice2026@gmail.com](mailto:bestpractice2026@gmail.com)",{"title":223,"canonical":224,"description":225},"Stop using the localStorage hack to sync browser tabs. BroadcastChanne","https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fbroadcast-channel-cross-tab-messaging","Syncing state across browser tabs with localStorage events is a widely-used trick that requires JSON.stringify, event filtering, and careful cleanup. The Broadcast Channel API deli","019fe660-fcbe-745e-a443-5db97da0d9ba",{"id":228,"locked":18},"019fe661-03c5-77bc-9a10-0bcd6223f910",[230],{"id":33,"slug":34,"title":36,"_count":231},{"questions":39},[233],{"locale":13,"slug":34},{"id":33,"slug":34,"title":36,"_count":235,"questionCount":39},{"questions":39}]