[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"header-categories":3,"post-realtime-dashboard-nuxt-websockets":73,"parsed-post-c3669e83-0f8e-4471-b138-5ead5505a53c":147},{"success":4,"data":5},true,{"items":6,"pagination":70},[7,16,24,32,40,48,56,63],{"id":8,"name":9,"description":10,"parentId":11,"createdAt":12,"updatedAt":12,"parent":11,"children":13,"_count":14},"ai-future","AI & The Future","Artificial intelligence and emerging technology",null,"2026-07-24T06:02:45.990Z",[],{"posts":15},1,{"id":17,"name":18,"description":19,"parentId":11,"createdAt":20,"updatedAt":20,"parent":11,"children":21,"_count":22},"tools-productivity","Tools & Productivity","Developer tools and workflow optimization","2026-07-24T06:02:45.712Z",[],{"posts":23},7,{"id":25,"name":26,"description":27,"parentId":11,"createdAt":28,"updatedAt":28,"parent":11,"children":29,"_count":30},"career","Career & Growth","Professional development for developers","2026-07-24T06:02:45.486Z",[],{"posts":31},3,{"id":33,"name":34,"description":35,"parentId":11,"createdAt":36,"updatedAt":36,"parent":11,"children":37,"_count":38},"opinion","Opinion & Analysis","Industry analysis and technical opinions","2026-07-24T06:02:45.272Z",[],{"posts":39},6,{"id":41,"name":42,"description":43,"parentId":11,"createdAt":44,"updatedAt":44,"parent":11,"children":45,"_count":46},"tutorials","Tutorials","Step-by-step learning guides","2026-07-24T06:02:44.965Z",[],{"posts":47},21,{"id":49,"name":50,"description":51,"parentId":11,"createdAt":52,"updatedAt":52,"parent":11,"children":53,"_count":54},"software-engineering","Software Engineering","Best practices, patterns, and principles","2026-07-24T06:02:44.689Z",[],{"posts":55},24,{"id":57,"name":58,"description":59,"parentId":11,"createdAt":60,"updatedAt":60,"parent":11,"children":61,"_count":62},"devops-cloud","DevOps & Cloud","Infrastructure, deployment, and cloud computing","2026-07-24T06:02:44.453Z",[],{"posts":39},{"id":64,"name":65,"description":66,"parentId":11,"createdAt":67,"updatedAt":67,"parent":11,"children":68,"_count":69},"web-development","Web Development","Frontend and backend web development tutorials and guides","2026-07-24T06:02:44.169Z",[],{"posts":55},{"page":15,"limit":71,"total":71,"totalPages":15,"hasNext":72,"hasPrev":72},8,false,{"success":4,"data":74},{"id":75,"slug":76,"title":77,"excerpt":78,"content":79,"status":80,"visibility":81,"featuredImage":82,"canonicalUrl":11,"readingTime":83,"viewCount":84,"commentEnabled":4,"publishedAt":85,"scheduledAt":11,"createdAt":86,"updatedAt":87,"seoTitle":88,"seoDescription":78,"seoKeywords":11,"authorId":89,"author":90,"coAuthors":95,"tags":96,"categories":112,"comments":115,"_count":116,"relatedPosts":118},"c3669e83-0f8e-4471-b138-5ead5505a53c","realtime-dashboard-nuxt-websockets","Building a Real-Time Dashboard with Nuxt and WebSockets","Create a live-updating analytics dashboard using Nuxt 3 server-sent events and WebSocket connections for real-time data.","## Real-Time Without Complexity\n\nNot every real-time feature needs WebSockets. Let's explore the spectrum and pick the right tool.\n\n## Server-Sent Events (SSE)\n\nPerfect for one-way data: server pushes to client.\n\n```typescript\n\u002F\u002F server\u002Fapi\u002Fevents.get.ts\nexport default defineEventHandler(async (event) => {\n  setHeader(event, 'Content-Type', 'text\u002Fevent-stream')\n  setHeader(event, 'Cache-Control', 'no-cache')\n  setHeader(event, 'Connection', 'keep-alive')\n\n  const encoder = new TextEncoder()\n  const stream = new ReadableStream({\n    start(controller) {\n      const interval = setInterval(async () => {\n        const metrics = await getLatestMetrics()\n        const data = `data: ${JSON.stringify(metrics)}\\n\\n`\n        controller.enqueue(encoder.encode(data))\n      }, 1000)\n\n      \u002F\u002F Cleanup on disconnect\n      event.node.req.on('close', () => {\n        clearInterval(interval)\n        controller.close()\n      })\n    },\n  })\n\n  return sendStream(event, stream)\n})\n```\n\nClient-side:\n\n```vue\n\u003Cscript setup lang=\"ts\">\nconst metrics = ref\u003CMetrics | null>(null)\n\nonMounted(() => {\n  const source = new EventSource('\u002Fapi\u002Fevents')\n  source.onmessage = (event) => {\n    metrics.value = JSON.parse(event.data)\n  }\n  onUnmounted(() => source.close())\n})\n\u003C\u002Fscript>\n```\n\n## When to Use WebSockets\n\nUse WebSockets when you need **bidirectional** communication:\n\n- Chat applications\n- Collaborative editing\n- Gaming\n\n::callout{icon=\"i-lucide-info\" color=\"info\"}\nSSE is simpler, auto-reconnects, and works through most proxies. Choose WebSockets only when you need client-to-server streaming.\n::\n\n## Dashboard Layout\n\n```vue\n\u003Ctemplate>\n  \u003Cdiv class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 p-6\">\n    \u003CMetricCard\n      v-for=\"metric in metrics\"\n      :key=\"metric.id\"\n      :label=\"metric.label\"\n      :value=\"metric.value\"\n      :trend=\"metric.trend\"\n    \u002F>\n  \u003C\u002Fdiv>\n\n  \u003Cdiv class=\"grid grid-cols-1 lg:grid-cols-2 gap-6 p-6\">\n    \u003CLiveChart :data=\"chartData\" \u002F>\n    \u003CActivityFeed :events=\"recentEvents\" \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n```\n\n## Performance Tips\n\n1. **Throttle updates** — Don't push more than the UI can render (16ms frames)\n2. **Use `shallowRef`** — Avoid deep reactivity for frequently updated data\n3. **Virtual scrolling** — For long lists of real-time events\n4. **Reconnection logic** — Always handle disconnects gracefully\n\nReal-time features delight users. With SSE and Nuxt, you can add them in under an hour.\n","published","public","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1559028012-481c04fa702d?w=1200&q=80",10,571,"2026-07-03T06:03:11.834Z","2026-07-24T06:03:11.837Z","2026-07-28T17:13:33.281Z","Building a Real-Time Dashboard with Nuxt and WebSockets | BitBlog","fddb5d93-7a2c-4d86-a06a-fa32e73a01c6",{"email":91,"bio":92,"id":89,"name":93,"avatarUrl":94},"mbeahessilfieprince@gmail.com","Fullstack Software Developer ","Mbeah Essilfie","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F93322394?v=4",[],[97,102,107],{"id":98,"name":99,"color":100,"description":101},"typescript","TypeScript","#3178c6","Typed superset of JavaScript",{"id":103,"name":104,"color":105,"description":106},"nuxt","Nuxt","#00dc82","The Intuitive Vue Framework",{"id":108,"name":109,"color":110,"description":111},"nodejs","Node.js","#339933","JavaScript runtime built on V8",[113,114],{"id":64,"name":65,"description":66},{"id":41,"name":42,"description":43},[],{"comments":117},0,[119,128,137],{"id":120,"slug":121,"title":122,"excerpt":123,"featuredImage":124,"viewCount":125,"readingTime":71,"publishedAt":126,"author":127},"2997028f-4d22-4eb7-9d86-894a54cb559a","building-type-safe-apis-nuxt3-prisma","Building Type-Safe APIs with Nuxt 3 and Prisma","Learn how to build end-to-end type-safe APIs using Nuxt 3 server routes and Prisma ORM for a seamless developer experience.","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1498050108023-c5249f4df085?w=1200&q=80",1922,"2026-07-23T06:02:46.910Z",{"id":89,"name":93,"avatarUrl":94},{"id":129,"slug":130,"title":131,"excerpt":132,"featuredImage":133,"viewCount":134,"readingTime":83,"publishedAt":135,"author":136},"da9e4553-8b0d-411e-b4ec-f9684017e163","mastering-tailwind-css-design-systems","Mastering Tailwind CSS: From Utility Classes to Design Systems","Go beyond basic utility classes and learn how to build cohesive, maintainable design systems with Tailwind CSS.","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1555066931-4365d14bab8c?w=1200&q=80",257,"2026-07-21T06:02:49.268Z",{"id":89,"name":93,"avatarUrl":94},{"id":138,"slug":139,"title":140,"excerpt":141,"featuredImage":142,"viewCount":143,"readingTime":144,"publishedAt":145,"author":146},"50add5fc-4026-4267-b917-7f71ea9e35b0","complete-guide-vue3-composables","The Complete Guide to Vue 3 Composables","Understand the power of Vue 3's Composition API through practical, real-world composable patterns that you can use today.","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1517694712202-14dd9538aa97?w=1200&q=80",990,12,"2026-07-19T06:02:51.753Z",{"id":89,"name":93,"avatarUrl":94},{"data":148,"body":150,"toc":336},{"title":149,"description":149},"",{"type":151,"children":152},"root",[153,162,168,174,179,191,196,206,212,225,245,256,262,270,276,326,331],{"type":154,"tag":155,"props":156,"children":158},"element","h2",{"id":157},"real-time-without-complexity",[159],{"type":160,"value":161},"text","Real-Time Without Complexity",{"type":154,"tag":163,"props":164,"children":165},"p",{},[166],{"type":160,"value":167},"Not every real-time feature needs WebSockets. Let's explore the spectrum and pick the right tool.",{"type":154,"tag":155,"props":169,"children":171},{"id":170},"server-sent-events-sse",[172],{"type":160,"value":173},"Server-Sent Events (SSE)",{"type":154,"tag":163,"props":175,"children":176},{},[177],{"type":160,"value":178},"Perfect for one-way data: server pushes to client.",{"type":154,"tag":180,"props":181,"children":185},"pre",{"className":182,"code":183,"language":98,"meta":149,"style":184},"language-typescript","\u002F\u002F server\u002Fapi\u002Fevents.get.ts\nexport default defineEventHandler(async (event) => {\n  setHeader(event, 'Content-Type', 'text\u002Fevent-stream')\n  setHeader(event, 'Cache-Control', 'no-cache')\n  setHeader(event, 'Connection', 'keep-alive')\n\n  const encoder = new TextEncoder()\n  const stream = new ReadableStream({\n    start(controller) {\n      const interval = setInterval(async () => {\n        const metrics = await getLatestMetrics()\n        const data = `data: ${JSON.stringify(metrics)}\\n\\n`\n        controller.enqueue(encoder.encode(data))\n      }, 1000)\n\n      \u002F\u002F Cleanup on disconnect\n      event.node.req.on('close', () => {\n        clearInterval(interval)\n        controller.close()\n      })\n    },\n  })\n\n  return sendStream(event, stream)\n})\n","undefined",[186],{"type":154,"tag":187,"props":188,"children":189},"code",{"__ignoreMap":149},[190],{"type":160,"value":183},{"type":154,"tag":163,"props":192,"children":193},{},[194],{"type":160,"value":195},"Client-side:",{"type":154,"tag":180,"props":197,"children":201},{"className":198,"code":199,"language":200,"meta":149,"style":184},"language-vue","\u003Cscript setup lang=\"ts\">\nconst metrics = ref\u003CMetrics | null>(null)\n\nonMounted(() => {\n  const source = new EventSource('\u002Fapi\u002Fevents')\n  source.onmessage = (event) => {\n    metrics.value = JSON.parse(event.data)\n  }\n  onUnmounted(() => source.close())\n})\n\u003C\u002Fscript>\n","vue",[202],{"type":154,"tag":187,"props":203,"children":204},{"__ignoreMap":149},[205],{"type":160,"value":199},{"type":154,"tag":155,"props":207,"children":209},{"id":208},"when-to-use-websockets",[210],{"type":160,"value":211},"When to Use WebSockets",{"type":154,"tag":163,"props":213,"children":214},{},[215,217,223],{"type":160,"value":216},"Use WebSockets when you need ",{"type":154,"tag":218,"props":219,"children":220},"strong",{},[221],{"type":160,"value":222},"bidirectional",{"type":160,"value":224}," communication:",{"type":154,"tag":226,"props":227,"children":228},"ul",{},[229,235,240],{"type":154,"tag":230,"props":231,"children":232},"li",{},[233],{"type":160,"value":234},"Chat applications",{"type":154,"tag":230,"props":236,"children":237},{},[238],{"type":160,"value":239},"Collaborative editing",{"type":154,"tag":230,"props":241,"children":242},{},[243],{"type":160,"value":244},"Gaming",{"type":154,"tag":246,"props":247,"children":250},"callout",{"color":248,"icon":249},"info","i-lucide-info",[251],{"type":154,"tag":163,"props":252,"children":253},{},[254],{"type":160,"value":255},"SSE is simpler, auto-reconnects, and works through most proxies. Choose WebSockets only when you need client-to-server streaming.",{"type":154,"tag":155,"props":257,"children":259},{"id":258},"dashboard-layout",[260],{"type":160,"value":261},"Dashboard Layout",{"type":154,"tag":180,"props":263,"children":265},{"className":198,"code":264,"language":200,"meta":149,"style":184},"\u003Ctemplate>\n  \u003Cdiv class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4 p-6\">\n    \u003CMetricCard\n      v-for=\"metric in metrics\"\n      :key=\"metric.id\"\n      :label=\"metric.label\"\n      :value=\"metric.value\"\n      :trend=\"metric.trend\"\n    \u002F>\n  \u003C\u002Fdiv>\n\n  \u003Cdiv class=\"grid grid-cols-1 lg:grid-cols-2 gap-6 p-6\">\n    \u003CLiveChart :data=\"chartData\" \u002F>\n    \u003CActivityFeed :events=\"recentEvents\" \u002F>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n",[266],{"type":154,"tag":187,"props":267,"children":268},{"__ignoreMap":149},[269],{"type":160,"value":264},{"type":154,"tag":155,"props":271,"children":273},{"id":272},"performance-tips",[274],{"type":160,"value":275},"Performance Tips",{"type":154,"tag":277,"props":278,"children":279},"ol",{},[280,290,306,316],{"type":154,"tag":230,"props":281,"children":282},{},[283,288],{"type":154,"tag":218,"props":284,"children":285},{},[286],{"type":160,"value":287},"Throttle updates",{"type":160,"value":289}," — Don't push more than the UI can render (16ms frames)",{"type":154,"tag":230,"props":291,"children":292},{},[293,304],{"type":154,"tag":218,"props":294,"children":295},{},[296,298],{"type":160,"value":297},"Use ",{"type":154,"tag":187,"props":299,"children":301},{"className":300},[],[302],{"type":160,"value":303},"shallowRef",{"type":160,"value":305}," — Avoid deep reactivity for frequently updated data",{"type":154,"tag":230,"props":307,"children":308},{},[309,314],{"type":154,"tag":218,"props":310,"children":311},{},[312],{"type":160,"value":313},"Virtual scrolling",{"type":160,"value":315}," — For long lists of real-time events",{"type":154,"tag":230,"props":317,"children":318},{},[319,324],{"type":154,"tag":218,"props":320,"children":321},{},[322],{"type":160,"value":323},"Reconnection logic",{"type":160,"value":325}," — Always handle disconnects gracefully",{"type":154,"tag":163,"props":327,"children":328},{},[329],{"type":160,"value":330},"Real-time features delight users. With SSE and Nuxt, you can add them in under an hour.",{"type":154,"tag":332,"props":333,"children":334},"style",{},[335],{"type":160,"value":149},{"title":149,"searchDepth":337,"depth":337,"links":338},2,[339,340,341,342,343],{"id":157,"depth":337,"text":161},{"id":170,"depth":337,"text":173},{"id":208,"depth":337,"text":211},{"id":258,"depth":337,"text":261},{"id":272,"depth":337,"text":275}]