@uptimizr/dashboard 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +76 -0
  3. package/out/404.html +1 -0
  4. package/out/__next.__PAGE__.txt +9 -0
  5. package/out/__next._full.txt +20 -0
  6. package/out/__next._head.txt +6 -0
  7. package/out/__next._index.txt +5 -0
  8. package/out/__next._tree.txt +4 -0
  9. package/out/_next/static/93W3szqylNKDg-afLRmVW/_buildManifest.js +11 -0
  10. package/out/_next/static/93W3szqylNKDg-afLRmVW/_clientMiddlewareManifest.js +1 -0
  11. package/out/_next/static/93W3szqylNKDg-afLRmVW/_ssgManifest.js +1 -0
  12. package/out/_next/static/chunks/0-2y-_oomza2l.js +87 -0
  13. package/out/_next/static/chunks/00k_j_r7bv_eb.js +266 -0
  14. package/out/_next/static/chunks/00zdau6mcqeae.js +1 -0
  15. package/out/_next/static/chunks/023axeoslq39i.js +1 -0
  16. package/out/_next/static/chunks/068j6934u8j16.js +1 -0
  17. package/out/_next/static/chunks/0_rf76jneiwal.js +176 -0
  18. package/out/_next/static/chunks/0aznt7717miff.js +1 -0
  19. package/out/_next/static/chunks/0cu-q5q3a7uf3.js +1 -0
  20. package/out/_next/static/chunks/0cz1d0mv5g_q7.js +1 -0
  21. package/out/_next/static/chunks/0dm32-jq30tg8.js +1 -0
  22. package/out/_next/static/chunks/0dn0yx0rn6mpf.js +1 -0
  23. package/out/_next/static/chunks/0flc7nppbmsl1.js +3 -0
  24. package/out/_next/static/chunks/0fskcfh9vbhtv.js +1 -0
  25. package/out/_next/static/chunks/0gv7mblzv3dl3.js +87 -0
  26. package/out/_next/static/chunks/0impkpmxx3ttp.js +1 -0
  27. package/out/_next/static/chunks/0jmn7u31w95ly.js +91 -0
  28. package/out/_next/static/chunks/0n8n481szj90g.js +1 -0
  29. package/out/_next/static/chunks/0o6ayai0s01js.js +1 -0
  30. package/out/_next/static/chunks/0rys92_73hdb0.js +22 -0
  31. package/out/_next/static/chunks/0tl_moiyi2txt.js +1 -0
  32. package/out/_next/static/chunks/0tx1j_ghpz7rc.css +3 -0
  33. package/out/_next/static/chunks/0ufbyo1x3qkmo.js +1 -0
  34. package/out/_next/static/chunks/0v82oqyoy9zol.js +1 -0
  35. package/out/_next/static/chunks/0wrm9jr-9bw0e.js +1893 -0
  36. package/out/_next/static/chunks/0wwcfw8i3j_zx.js +1 -0
  37. package/out/_next/static/chunks/0ys9-ozuluawt.js +1 -0
  38. package/out/_next/static/chunks/1-61zh4waha61.js +1 -0
  39. package/out/_next/static/chunks/10r_824wzt8hj.js +1 -0
  40. package/out/_next/static/chunks/112hws17nz665.js +7 -0
  41. package/out/_next/static/chunks/123xxske5c9na.js +1 -0
  42. package/out/_next/static/chunks/13isnf0--pmx1.js +1 -0
  43. package/out/_next/static/chunks/157d9euci08yu.js +1 -0
  44. package/out/_next/static/chunks/15s7425ffrec9.js +3 -0
  45. package/out/_next/static/chunks/163fa70v4mgxj.js +1 -0
  46. package/out/_next/static/chunks/17q0c2h5ui10r.js +4 -0
  47. package/out/_next/static/chunks/18u58lorfahxi.js +4 -0
  48. package/out/_next/static/chunks/1_aahautsz2v_.js +1 -0
  49. package/out/_next/static/chunks/1a9l89j7e6mqu.js +23 -0
  50. package/out/_next/static/chunks/1dsy2ngmfflis.js +123 -0
  51. package/out/_next/static/chunks/1flb8adpj6_2o.js +62 -0
  52. package/out/_next/static/chunks/1lsg-22yob8dx.js +1 -0
  53. package/out/_next/static/chunks/1nj82er7msdto.js +2 -0
  54. package/out/_next/static/chunks/1o1d0p-v1z8ty.js +1 -0
  55. package/out/_next/static/chunks/1pdep2_c530sg.js +1 -0
  56. package/out/_next/static/chunks/1thjncpj7u6pq.js +1 -0
  57. package/out/_next/static/chunks/1vdjn0pkoyypn.js +1 -0
  58. package/out/_next/static/chunks/1yehxf-fmeicg.js +1 -0
  59. package/out/_next/static/chunks/1zvc1tv--w8nn.js +1 -0
  60. package/out/_next/static/chunks/1zx2q-r32thv1.js +4 -0
  61. package/out/_next/static/chunks/2-sjjedfr0kfq.js +1 -0
  62. package/out/_next/static/chunks/21o42k82w4llc.js +1 -0
  63. package/out/_next/static/chunks/25b9x-li-tvk2.js +1 -0
  64. package/out/_next/static/chunks/2712627rfsmwn.js +1 -0
  65. package/out/_next/static/chunks/296w2ke-v5tbm.js +9 -0
  66. package/out/_next/static/chunks/29tfeb6amdkjb.js +23 -0
  67. package/out/_next/static/chunks/2a3spdq-m8drh.js +3 -0
  68. package/out/_next/static/chunks/2aelw3far6rii.js +1 -0
  69. package/out/_next/static/chunks/2aor7m-wbis85.js +1 -0
  70. package/out/_next/static/chunks/2cbmf9m7lqv6k.js +4 -0
  71. package/out/_next/static/chunks/2d09v5u7dfq0q.js +1 -0
  72. package/out/_next/static/chunks/2feca0xcipcyt.js +850 -0
  73. package/out/_next/static/chunks/2fh-_9b6tqhvb.js +1 -0
  74. package/out/_next/static/chunks/2g5gecypj0rqe.js +1 -0
  75. package/out/_next/static/chunks/2kazjq29jeamx.js +1109 -0
  76. package/out/_next/static/chunks/2p2vv6cc9i-3q.js +255 -0
  77. package/out/_next/static/chunks/2szdcpl41-kzv.js +1 -0
  78. package/out/_next/static/chunks/2tws5udjdcmh3.js +1 -0
  79. package/out/_next/static/chunks/2u6shh3oeycm-.js +1 -0
  80. package/out/_next/static/chunks/2unhhuv0arlcv.js +1 -0
  81. package/out/_next/static/chunks/2xwy0-qfho1iz.js +91 -0
  82. package/out/_next/static/chunks/2ycvtdd68gub7.js +1 -0
  83. package/out/_next/static/chunks/2yiy_l8bwiw2_.js +3 -0
  84. package/out/_next/static/chunks/2yph6f7khgqii.js +1 -0
  85. package/out/_next/static/chunks/3-shckrcpvbxu.js +1681 -0
  86. package/out/_next/static/chunks/30fq_t9e2_fv-.js +1 -0
  87. package/out/_next/static/chunks/30yzu213bqtq0.js +5 -0
  88. package/out/_next/static/chunks/310uz81hnnzsu.js +1 -0
  89. package/out/_next/static/chunks/3218lp8l0a5g_.js +1 -0
  90. package/out/_next/static/chunks/35h5n42wxwgzk.js +123 -0
  91. package/out/_next/static/chunks/37vzwr3ciejf1.js +1 -0
  92. package/out/_next/static/chunks/38fhw7fatsyvd.js +3 -0
  93. package/out/_next/static/chunks/3be6s4_kn9q-o.js +1 -0
  94. package/out/_next/static/chunks/3i3gbhccmhu7j.js +210 -0
  95. package/out/_next/static/chunks/3l1dr_qm_x5kp.js +1 -0
  96. package/out/_next/static/chunks/3mqy-84_ul3t2.js +1 -0
  97. package/out/_next/static/chunks/3nz-dh9d7cehk.js +1 -0
  98. package/out/_next/static/chunks/3pufs8g4ui943.js +1 -0
  99. package/out/_next/static/chunks/3sjq_xoi4rbyg.js +31 -0
  100. package/out/_next/static/chunks/3t06schbtqonl.js +1 -0
  101. package/out/_next/static/chunks/3v3-7fio3nw_t.js +1 -0
  102. package/out/_next/static/chunks/3v5ha25nxo43j.js +1 -0
  103. package/out/_next/static/chunks/3yfrsm8lfi6ls.js +22 -0
  104. package/out/_next/static/chunks/3zskk1hxu3-_o.js +1 -0
  105. package/out/_next/static/chunks/turbopack-2ropzf0axp1x9.js +1 -0
  106. package/out/_next/static/media/0c89a48fa5027cee-s.p.2cyn07wtgehh0.woff2 +0 -0
  107. package/out/_next/static/media/13bf9871fe164e7f-s.2f7nqdagzwx2-.woff2 +0 -0
  108. package/out/_next/static/media/28868e710e86be81-s.2eksvhm1z0jwa.woff2 +0 -0
  109. package/out/_next/static/media/32687112bd2dd8db-s.1gepa_7fcx9fm.woff2 +0 -0
  110. package/out/_next/static/media/3fe682a82f50d426-s.0vfdmo25voy_0.woff2 +0 -0
  111. package/out/_next/static/media/70bc3e132a0a741e-s.p.3t6q91iet4nsy.woff2 +0 -0
  112. package/out/_next/static/media/71b036adf157cdcf-s.0bp8oijd_gu96.woff2 +0 -0
  113. package/out/_next/static/media/89b21bb081cb7469-s.1fby2rem9ngyr.woff2 +0 -0
  114. package/out/_next/static/media/cc545e633e20c56d-s.176arc174-8zp.woff2 +0 -0
  115. package/out/_next/static/media/icon.08h29dad3pcxg.svg +4 -0
  116. package/out/_not-found/__next._full.txt +16 -0
  117. package/out/_not-found/__next._head.txt +6 -0
  118. package/out/_not-found/__next._index.txt +5 -0
  119. package/out/_not-found/__next._not-found.__PAGE__.txt +5 -0
  120. package/out/_not-found/__next._not-found.txt +5 -0
  121. package/out/_not-found/__next._tree.txt +2 -0
  122. package/out/_not-found.html +1 -0
  123. package/out/_not-found.txt +16 -0
  124. package/out/api/projects +1 -0
  125. package/out/icon.svg +4 -0
  126. package/out/index.html +1 -0
  127. package/out/index.txt +20 -0
  128. package/out/logo.svg +46 -0
  129. package/package.json +67 -0
  130. package/server/standalone.mjs +182 -0
package/out/index.html ADDED
@@ -0,0 +1 @@
1
+ <!DOCTYPE html><html lang="en" class="space_grotesk_59d6dcf5-module__z_Ctiq__variable jetbrains_mono_38c99671-module__5Dhsuq__variable"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="/_next/static/media/0c89a48fa5027cee-s.p.2cyn07wtgehh0.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/70bc3e132a0a741e-s.p.3t6q91iet4nsy.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" as="image" href="/logo.svg"/><link rel="stylesheet" href="/_next/static/chunks/0tx1j_ghpz7rc.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/3sjq_xoi4rbyg.js"/><script src="/_next/static/chunks/30yzu213bqtq0.js" async=""></script><script src="/_next/static/chunks/0tl_moiyi2txt.js" async=""></script><script src="/_next/static/chunks/turbopack-2ropzf0axp1x9.js" async=""></script><script src="/_next/static/chunks/0impkpmxx3ttp.js" async=""></script><script src="/_next/static/chunks/00zdau6mcqeae.js" async=""></script><script src="/_next/static/chunks/1flb8adpj6_2o.js" async=""></script><script src="/_next/static/chunks/2yiy_l8bwiw2_.js" async=""></script><meta name="next-size-adjust" content=""/><title>Uptimizr — 3D Scene Analytics</title><meta name="description" content="Open-source analytics dashboard for 3D scenes."/><link rel="icon" href="/icon.svg?icon.08h29dad3pcxg.svg" sizes="any" type="image/svg+xml"/><script src="/_next/static/chunks/0cz1d0mv5g_q7.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><main class="mx-auto max-w-6xl px-6 py-8"><header class="mb-6 flex items-center gap-3"><img src="/logo.svg" alt="Uptimizr" width="36" height="36" class="h-9 w-9 shrink-0"/><div><h1 class="font-display text-2xl font-bold text-fg-hi">Uptimizr</h1><p class="text-sm text-fg-muted">Analytics for 3D scenes — open-source collector.</p></div></header><form class="mb-6 flex flex-wrap items-end gap-3 rounded-xl border border-edge bg-panel p-4"><label class="flex flex-1 flex-col gap-1 text-xs text-fg-muted">Collector URL<input class="min-w-56 rounded-md border border-edge bg-ink px-3 py-2 text-sm text-fg outline-none focus:border-saffron" placeholder="http://localhost:4318" value="http://localhost:4318"/></label><label class="flex flex-1 flex-col gap-1 text-xs text-fg-muted">Project API key<input class="min-w-56 rounded-md border border-edge bg-ink px-3 py-2 text-sm text-fg outline-none focus:border-saffron" type="password" placeholder="utk_…" value=""/></label><button type="submit" class="rounded-md bg-amber px-4 py-2 text-sm font-medium text-ink transition hover:bg-ember disabled:opacity-50">Load</button></form><p class="text-sm text-fg-muted">Enter your collector URL and a project API key, then load to view analytics.</p></main><!--$--><!--/$--><script src="/_next/static/chunks/3sjq_xoi4rbyg.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[87346,[\"/_next/static/chunks/0impkpmxx3ttp.js\"],\"default\"]\n3:I[62327,[\"/_next/static/chunks/0impkpmxx3ttp.js\"],\"default\"]\n4:I[97541,[\"/_next/static/chunks/0impkpmxx3ttp.js\"],\"ClientPageRoot\"]\n5:I[14936,[\"/_next/static/chunks/0impkpmxx3ttp.js\",\"/_next/static/chunks/00zdau6mcqeae.js\",\"/_next/static/chunks/1flb8adpj6_2o.js\",\"/_next/static/chunks/2yiy_l8bwiw2_.js\"],\"default\"]\n8:I[96686,[\"/_next/static/chunks/0impkpmxx3ttp.js\"],\"OutletBoundary\"]\n9:\"$Sreact.suspense\"\nb:I[96686,[\"/_next/static/chunks/0impkpmxx3ttp.js\"],\"ViewportBoundary\"]\nd:I[96686,[\"/_next/static/chunks/0impkpmxx3ttp.js\"],\"MetadataBoundary\"]\nf:I[50404,[\"/_next/static/chunks/0impkpmxx3ttp.js\"],\"default\",1]\n:HL[\"/_next/static/chunks/0tx1j_ghpz7rc.css\",\"style\"]\n:HL[\"/_next/static/media/0c89a48fa5027cee-s.p.2cyn07wtgehh0.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/70bc3e132a0a741e-s.p.3t6q91iet4nsy.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",16],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0tx1j_ghpz7rc.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0impkpmxx3ttp.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"space_grotesk_59d6dcf5-module__z_Ctiq__variable jetbrains_mono_38c99671-module__5Dhsuq__variable\",\"children\":[\"$\",\"body\",null,{\"children\":[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"$L4\",null,{\"Component\":\"$5\",\"serverProvidedParams\":{\"searchParams\":{},\"params\":{},\"promises\":[\"$@6\",\"$@7\"]}}],[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/00zdau6mcqeae.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/1flb8adpj6_2o.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-2\",{\"src\":\"/_next/static/chunks/2yiy_l8bwiw2_.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L8\",null,{\"children\":[\"$\",\"$9\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@a\"}]}]]}],{},null,false,null]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$Lb\",null,{\"children\":\"$Lc\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Ld\",null,{\"children\":[\"$\",\"$9\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Le\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$f\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0tx1j_ghpz7rc.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"93W3szqylNKDg-afLRmVW\"}\n"])</script><script>self.__next_f.push([1,"6:{}\n7:\"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params\"\n"])</script><script>self.__next_f.push([1,"c:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"10:I[74838,[\"/_next/static/chunks/0impkpmxx3ttp.js\"],\"IconMark\"]\na:null\ne:[[\"$\",\"title\",\"0\",{\"children\":\"Uptimizr — 3D Scene Analytics\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Open-source analytics dashboard for 3D scenes.\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/icon.svg?icon.08h29dad3pcxg.svg\",\"sizes\":\"any\",\"type\":\"image/svg+xml\"}],[\"$\",\"$L10\",\"3\",{}]]\n"])</script></body></html>
package/out/index.txt ADDED
@@ -0,0 +1,20 @@
1
+ 1:"$Sreact.fragment"
2
+ 2:I[87346,["/_next/static/chunks/0impkpmxx3ttp.js"],"default"]
3
+ 3:I[62327,["/_next/static/chunks/0impkpmxx3ttp.js"],"default"]
4
+ 4:I[97541,["/_next/static/chunks/0impkpmxx3ttp.js"],"ClientPageRoot"]
5
+ 5:I[14936,["/_next/static/chunks/0impkpmxx3ttp.js","/_next/static/chunks/00zdau6mcqeae.js","/_next/static/chunks/1flb8adpj6_2o.js","/_next/static/chunks/2yiy_l8bwiw2_.js"],"default"]
6
+ 8:I[96686,["/_next/static/chunks/0impkpmxx3ttp.js"],"OutletBoundary"]
7
+ 9:"$Sreact.suspense"
8
+ b:I[96686,["/_next/static/chunks/0impkpmxx3ttp.js"],"ViewportBoundary"]
9
+ d:I[96686,["/_next/static/chunks/0impkpmxx3ttp.js"],"MetadataBoundary"]
10
+ f:I[50404,["/_next/static/chunks/0impkpmxx3ttp.js"],"default",1]
11
+ :HL["/_next/static/chunks/0tx1j_ghpz7rc.css","style"]
12
+ :HL["/_next/static/media/0c89a48fa5027cee-s.p.2cyn07wtgehh0.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
13
+ :HL["/_next/static/media/70bc3e132a0a741e-s.p.3t6q91iet4nsy.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
14
+ 0:{"P":null,"c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",16],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0tx1j_ghpz7rc.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/0impkpmxx3ttp.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","className":"space_grotesk_59d6dcf5-module__z_Ctiq__variable jetbrains_mono_38c99671-module__5Dhsuq__variable","children":["$","body",null,{"children":["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L4",null,{"Component":"$5","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@6","$@7"]}}],[["$","script","script-0",{"src":"/_next/static/chunks/00zdau6mcqeae.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/1flb8adpj6_2o.js","async":true,"nonce":"$undefined"}],["$","script","script-2",{"src":"/_next/static/chunks/2yiy_l8bwiw2_.js","async":true,"nonce":"$undefined"}]],["$","$L8",null,{"children":["$","$9",null,{"name":"Next.MetadataOutlet","children":"$@a"}]}]]}],{},null,false,null]},null,false,null],["$","$1","h",{"children":[null,["$","$Lb",null,{"children":"$Lc"}],["$","div",null,{"hidden":true,"children":["$","$Ld",null,{"children":["$","$9",null,{"name":"Next.Metadata","children":"$Le"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$f",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/0tx1j_ghpz7rc.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]]],"S":true,"h":null,"s":"$undefined","l":"$undefined","p":"$undefined","d":"$undefined","b":"93W3szqylNKDg-afLRmVW"}
15
+ 6:{}
16
+ 7:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params"
17
+ c:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
18
+ 10:I[74838,["/_next/static/chunks/0impkpmxx3ttp.js"],"IconMark"]
19
+ a:null
20
+ e:[["$","title","0",{"children":"Uptimizr — 3D Scene Analytics"}],["$","meta","1",{"name":"description","content":"Open-source analytics dashboard for 3D scenes."}],["$","link","2",{"rel":"icon","href":"/icon.svg?icon.08h29dad3pcxg.svg","sizes":"any","type":"image/svg+xml"}],["$","$L10","3",{}]]
package/out/logo.svg ADDED
@@ -0,0 +1,46 @@
1
+ <svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Uptimizr logo">
2
+ <defs>
3
+ <linearGradient id="uz-top" x1="54" y1="40" x2="202" y2="124" gradientUnits="userSpaceOnUse">
4
+ <stop offset="0" stop-color="#F7CE57"/><stop offset="1" stop-color="#EDAE42"/>
5
+ </linearGradient>
6
+ <linearGradient id="uz-left" x1="54" y1="82" x2="128" y2="212" gradientUnits="userSpaceOnUse">
7
+ <stop offset="0" stop-color="#EC9B3D"/><stop offset="1" stop-color="#D9633A"/>
8
+ </linearGradient>
9
+ <linearGradient id="uz-right" x1="128" y1="124" x2="202" y2="212" gradientUnits="userSpaceOnUse">
10
+ <stop offset="0" stop-color="#D4513A"/><stop offset="1" stop-color="#A82E26"/>
11
+ </linearGradient>
12
+ <!-- Occlusion = the groove's PORTAL: the U-band opening on the front faces plus the two
13
+ top-face openings where the cut emerges. The solid wedge between the openings (near
14
+ vertex 4) is excluded, hiding the small triangle that projects up behind it. -->
15
+ <clipPath id="frontfaces">
16
+ <path d="M83.6 98.8 L83.6 151.3 L128.0 176.5 L172.4 151.3 L172.4 98.8 L157.6 107.2 L157.6 142.7 L128.0 159.5 L98.4 142.7 L98.4 107.2 Z"/>
17
+ <path d="M98.4 107.2 L83.6 98.8 L91.0 94.6 L105.8 103.0 Z"/>
18
+ <path d="M157.6 107.2 L172.4 98.8 L165.0 94.6 L150.2 103.0 Z"/>
19
+ </clipPath>
20
+ </defs>
21
+
22
+ <!-- Transparent mark (app-icon plate omitted): sits on any header background. -->
23
+
24
+ <!-- Isometric cube, faces shaded as a thermal heatmap. -->
25
+ <path d="M128 40 L202 82 L128 124 L54 82 Z" fill="url(#uz-top)"/>
26
+ <path d="M54 82 L128 124 L128 212 L54 170 Z" fill="url(#uz-left)"/>
27
+ <path d="M202 82 L202 170 L128 212 L128 124 Z" fill="url(#uz-right)"/>
28
+
29
+ <!-- U-shaped hole, flat-shaded per 3D face: recessed floor + walls (incl. top openings).
30
+ Clipped to the front faces so the centre-joint sliver stays behind the top face. -->
31
+ <g clip-path="url(#frontfaces)">
32
+ <path d="M91.0 94.6 L91.0 147.1 L128.0 168.1 L128.0 151.1 L105.8 138.5 L105.8 103.0 Z" fill="#71461f"/>
33
+ <path d="M128.0 168.1 L165.0 147.1 L165.0 94.6 L150.2 103.0 L150.2 138.5 L128.0 151.1 Z" fill="#4c1a14"/>
34
+ <path d="M83.6 151.3 L128.0 176.5 L128.0 168.1 L91.0 147.1 Z" fill="#dc893c"/>
35
+ <path d="M128.0 176.5 L172.4 151.3 L165.0 147.1 L128.0 168.1 Z" fill="#bb4030"/>
36
+ <path d="M83.6 98.8 L83.6 151.3 L91.0 147.1 L91.0 94.6 Z" fill="#7f4f23"/>
37
+ <path d="M172.4 151.3 L172.4 98.8 L165.0 94.6 L165.0 147.1 Z" fill="#892f23"/>
38
+ <path d="M157.6 142.7 L128.0 159.5 L128.0 151.1 L150.2 138.5 Z" fill="#bb4030"/>
39
+ <path d="M128.0 159.5 L98.4 142.7 L105.8 138.5 L128.0 151.1 Z" fill="#dc893c"/>
40
+ <path d="M157.6 107.2 L157.6 142.7 L150.2 138.5 L150.2 103.0 Z" fill="#892f23"/>
41
+ <path d="M98.4 142.7 L98.4 107.2 L105.8 103.0 L105.8 138.5 Z" fill="#7f4f23"/>
42
+ <path d="M172.4 98.8 L157.6 107.2 L150.2 103.0 L165.0 94.6 Z" fill="#4c1a14"/>
43
+ <path d="M98.4 107.2 L83.6 98.8 L91.0 94.6 L105.8 103.0 Z" fill="#71461f"/>
44
+ </g>
45
+
46
+ </svg>
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@uptimizr/dashboard",
3
+ "version": "0.1.0",
4
+ "description": "Uptimizr analytics dashboard — a static-export SPA that reads the collector query API. Serve it standalone, all-in-one via the collector, or drop the assets on any static host.",
5
+ "keywords": [
6
+ "uptimizr",
7
+ "analytics",
8
+ "dashboard",
9
+ "nextjs",
10
+ "3d",
11
+ "heatmap",
12
+ "visualization"
13
+ ],
14
+ "license": "Apache-2.0",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/RaananW/Uptimizr.git",
18
+ "directory": "oss/apps/dashboard"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/RaananW/Uptimizr/issues"
22
+ },
23
+ "homepage": "https://github.com/RaananW/Uptimizr/tree/main/oss/apps/dashboard#readme",
24
+ "publishConfig": {
25
+ "access": "public"
26
+ },
27
+ "type": "module",
28
+ "bin": {
29
+ "uptimizr-dashboard": "./server/standalone.mjs"
30
+ },
31
+ "files": [
32
+ "out",
33
+ "server",
34
+ "README.md",
35
+ "LICENSE"
36
+ ],
37
+ "dependencies": {
38
+ "@babylonjs/core": "^9.13.0",
39
+ "next": "^16.2.9",
40
+ "react": "^19.2.7",
41
+ "react-dom": "^19.2.7",
42
+ "@uptimizr/heatmap": "0.1.0",
43
+ "@uptimizr/replay": "0.1.0",
44
+ "@uptimizr/react": "0.1.0"
45
+ },
46
+ "devDependencies": {
47
+ "@types/node": "^22.19.21",
48
+ "@types/react": "^19.2.17",
49
+ "@types/react-dom": "^19.2.3",
50
+ "@tailwindcss/postcss": "^4.3.1",
51
+ "postcss": "^8.5.15",
52
+ "tailwindcss": "^4.3.1",
53
+ "typescript": "^6.0.3",
54
+ "vitest": "^4.1.9"
55
+ },
56
+ "scripts": {
57
+ "dev": "dotenv -e ../../../.env -- next dev -p 3000",
58
+ "build": "NODE_ENV=production next build",
59
+ "build:static": "NODE_ENV=production DASHBOARD_STATIC=1 next build",
60
+ "start": "NODE_ENV=production next start -p 3000",
61
+ "serve:static": "node server/standalone.mjs",
62
+ "lint": "eslint .",
63
+ "typecheck": "tsc -p tsconfig.json --noEmit",
64
+ "test": "vitest run",
65
+ "clean": "rm -rf .next out"
66
+ }
67
+ }
@@ -0,0 +1,182 @@
1
+ #!/usr/bin/env node
2
+ // Standalone static server for the exported Uptimizr dashboard (ADR 0029 A.3).
3
+ //
4
+ // Serves the prebuilt static export (`out/`) on its own port for users who want
5
+ // the UI as a separate process from the collector. Zero dependencies — just
6
+ // Node's http/fs — so the published package stays light. The collector URL is
7
+ // supplied at runtime (the in-UI connection bar), so the same assets work
8
+ // against any collector without a rebuild.
9
+ //
10
+ // Usage:
11
+ // uptimizr-dashboard # serve out/ on :3000
12
+ // uptimizr-dashboard --port 8080 # or DASHBOARD_PORT / PORT env
13
+ import { createReadStream, existsSync, readdirSync, readFileSync, statSync } from "node:fs";
14
+ import { createHash } from "node:crypto";
15
+ import { createServer } from "node:http";
16
+ import { extname, join, normalize, resolve } from "node:path";
17
+ import { fileURLToPath } from "node:url";
18
+
19
+ const here = fileURLToPath(new URL(".", import.meta.url));
20
+ // The bin lives at <pkg>/server/, so the export sits at <pkg>/out/.
21
+ const ROOT = resolve(here, "..", "out");
22
+
23
+ const MIME = {
24
+ ".html": "text/html; charset=utf-8",
25
+ ".js": "text/javascript; charset=utf-8",
26
+ ".mjs": "text/javascript; charset=utf-8",
27
+ ".css": "text/css; charset=utf-8",
28
+ ".json": "application/json; charset=utf-8",
29
+ ".txt": "text/plain; charset=utf-8",
30
+ ".svg": "image/svg+xml",
31
+ ".png": "image/png",
32
+ ".jpg": "image/jpeg",
33
+ ".jpeg": "image/jpeg",
34
+ ".gif": "image/gif",
35
+ ".webp": "image/webp",
36
+ ".ico": "image/x-icon",
37
+ ".woff": "font/woff",
38
+ ".woff2": "font/woff2",
39
+ ".ttf": "font/ttf",
40
+ ".map": "application/json; charset=utf-8",
41
+ ".wasm": "application/wasm",
42
+ };
43
+
44
+ function parsePort() {
45
+ const flagIdx = process.argv.indexOf("--port");
46
+ const fromFlag = flagIdx !== -1 ? process.argv[flagIdx + 1] : undefined;
47
+ const raw = fromFlag ?? process.env.DASHBOARD_PORT ?? process.env.PORT ?? "3000";
48
+ const port = Number(raw);
49
+ if (!Number.isInteger(port) || port < 0 || port > 65535) {
50
+ console.error(`Invalid port: ${raw}`);
51
+ process.exit(1);
52
+ }
53
+ return port;
54
+ }
55
+
56
+ /** Resolve a request path to a file inside ROOT, or null if it escapes ROOT. */
57
+ function safeResolve(urlPath) {
58
+ // Strip query/hash and decode, then normalize away any `..` segments.
59
+ const decoded = decodeURIComponent(urlPath.split("?")[0].split("#")[0]);
60
+ const rel = normalize(decoded).replace(/^(\.\.[/\\])+/, "");
61
+ const abs = join(ROOT, rel);
62
+ if (abs !== ROOT && !abs.startsWith(ROOT + (process.platform === "win32" ? "\\" : "/"))) {
63
+ return null;
64
+ }
65
+ return abs;
66
+ }
67
+
68
+ /**
69
+ * Build a Content-Security-Policy for the exported dashboard. A Next.js static
70
+ * export has no server to mint per-request nonces, so its inline bootstrap
71
+ * scripts are pinned by SHA-256 hash instead of allowed via `'unsafe-inline'`.
72
+ * We enumerate the inline scripts across the exported HTML at startup.
73
+ */
74
+ function scriptHashes() {
75
+ const hashes = new Set();
76
+ let files;
77
+ try {
78
+ files = readdirSync(ROOT).filter((f) => f.endsWith(".html"));
79
+ } catch {
80
+ return [];
81
+ }
82
+ for (const file of files) {
83
+ try {
84
+ const html = readFileSync(join(ROOT, file), "utf8");
85
+ const re = /<script(?![^>]*\bsrc=)[^>]*>([\s\S]*?)<\/script>/gi;
86
+ let m;
87
+ while ((m = re.exec(html)) !== null) {
88
+ if (m[1].length === 0) continue;
89
+ hashes.add(`'sha256-${createHash("sha256").update(m[1], "utf8").digest("base64")}'`);
90
+ }
91
+ } catch {
92
+ // Skip unreadable files; remaining hashes still apply.
93
+ }
94
+ }
95
+ return [...hashes];
96
+ }
97
+
98
+ function securityHeaders() {
99
+ const scriptSrc = ["'self'", ...scriptHashes()].join(" ");
100
+ const csp = [
101
+ "default-src 'self'",
102
+ "base-uri 'self'",
103
+ "object-src 'none'",
104
+ "frame-ancestors 'none'",
105
+ "form-action 'self'",
106
+ `script-src ${scriptSrc}`,
107
+ "style-src 'self' 'unsafe-inline'",
108
+ "img-src 'self' data: blob:",
109
+ "font-src 'self' data:",
110
+ "worker-src 'self' blob:",
111
+ // The collector URL is supplied at runtime, so analytics queries / SSE may
112
+ // target any origin the operator points the connection bar at.
113
+ "connect-src 'self' https: http: ws: wss:",
114
+ ].join("; ");
115
+ return {
116
+ "content-security-policy": csp,
117
+ "x-content-type-options": "nosniff",
118
+ "x-frame-options": "DENY",
119
+ "referrer-policy": "no-referrer",
120
+ };
121
+ }
122
+
123
+ const SECURITY_HEADERS = securityHeaders();
124
+
125
+ function send(res, status, filePath) {
126
+ const type = MIME[extname(filePath).toLowerCase()] ?? "application/octet-stream";
127
+ res.writeHead(status, { ...SECURITY_HEADERS, "content-type": type });
128
+ createReadStream(filePath).pipe(res);
129
+ }
130
+
131
+ const indexHtml = join(ROOT, "index.html");
132
+
133
+ const server = createServer((req, res) => {
134
+ if (req.method !== "GET" && req.method !== "HEAD") {
135
+ res.writeHead(405, { "content-type": "application/json; charset=utf-8" });
136
+ res.end(JSON.stringify({ error: "Method Not Allowed" }));
137
+ return;
138
+ }
139
+
140
+ const abs = safeResolve(req.url ?? "/");
141
+ if (abs === null) {
142
+ res.writeHead(403, { "content-type": "application/json; charset=utf-8" });
143
+ res.end(JSON.stringify({ error: "Forbidden" }));
144
+ return;
145
+ }
146
+
147
+ // Directory → its index.html; existing file → that file.
148
+ let target = abs;
149
+ if (existsSync(target) && statSync(target).isDirectory()) {
150
+ target = join(target, "index.html");
151
+ }
152
+ if (existsSync(target) && statSync(target).isFile()) {
153
+ send(res, 200, target);
154
+ return;
155
+ }
156
+
157
+ // SPA deep-link fallback (`/projects/:id/...`): serve the app entry so the
158
+ // client router can resolve the route on a refresh or shared link.
159
+ send(res, 200, indexHtml);
160
+ });
161
+
162
+ function main() {
163
+ if (!existsSync(indexHtml)) {
164
+ console.error(
165
+ `No static export found at ${ROOT}.\n` +
166
+ `Build it first: pnpm --filter @uptimizr/dashboard build:static`,
167
+ );
168
+ process.exit(1);
169
+ }
170
+ const port = parsePort();
171
+ const host = process.env.DASHBOARD_HOST ?? "0.0.0.0";
172
+ server.listen(port, host, () => {
173
+ console.log(`Uptimizr dashboard serving ${ROOT}`);
174
+ console.log(` http://localhost:${port}`);
175
+ console.log(`Set the collector URL in the dashboard's connection bar.`);
176
+ });
177
+ const close = () => server.close(() => process.exit(0));
178
+ process.on("SIGINT", close);
179
+ process.on("SIGTERM", close);
180
+ }
181
+
182
+ main();