[{"data":1,"prerenderedAt":290},["ShallowReactive",2],{"project-43569961":3},{"id":4,"name":5,"line":6,"line_source":7,"title":8,"url":9,"domain":10,"maker":11,"posted_at":12,"year":13,"points":14,"comments":15,"rank_in_year":16,"shown_in_year":17,"top":18,"tier":19,"category":20,"subcategory":21,"format":22,"keywords":23,"reception":29,"sentiment":30,"stance_mix":31,"scored_comments":36,"aspects":37,"strip":43,"post_text":45,"what":46,"said":73,"maker_in_thread":143,"shape":155,"grid":159,"attempts":249,"same_week":255,"maker_shows":36,"maker_hidden":282,"reader_version":283,"card":284},"43569961","TabSub","Offline JavaScript PubSub between browser tabs","title","Show HN: Offline JavaScript PubSub between browser tabs","https:\u002F\u002Fsimon-frey.com\u002Ftabsub\u002F","simon-frey.com","l1am0",1743689399,2025,83,37,861,3837,23,"notable","dev_tools","javascript library","library",[24,25,26,27,28],"pubsub","browser tabs","localstorage","broadcastchannel","cross-tab messaging","curious",0.183,{"positive":32,"neutral":33,"mixed":34,"critical":35},3,8,0,1,12,{"idea":38,"performance":39,"execution":40,"privacy":42},{"positive":34,"critical":34},{"positive":34,"critical":35},{"positive":41,"critical":34},2,{"positive":34,"critical":34},[34,34,44,32,35,34,32,34,34,34,44,32,34,34,34,34,34,34,34,44,34,34,32,32,32,34,34,34,32,34,32,34,34,34,34,34,34],5,null,{"problem":47,"audience":45,"pricing":45,"motivation":45,"time_to_build":45,"stack":59,"openness":71,"stage":72,"team_size":72},{"value":48,"source":49,"evidence":50},"Lets scripts in different browser tabs of the same site send messages to each other","commenter",[51,55],{"id":52,"by":53,"text":54},"43570969","sisk","If I understand this correctly, the `BroadcastChannel` API solves a similar purpose. https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FAPI\u002FBroadcast_Channel_API",{"id":56,"by":57,"text":58},"43573560","sltkr","From the post: > As TabSub uses local store this only works on the same domain, as the browser separates the local storage by domains as security measure. (More precisely, the…",[60,67],{"value":61,"source":49,"evidence":62},"JavaScript",[63],{"id":64,"by":65,"text":66},"43570888","edweis","I love it, the code is so simple: https:\u002F\u002Fgithub.com\u002Fsimonfrey\u002Ftabsub\u002Fblob\u002Fmaster\u002Ftabsub.v1.js",{"value":68,"source":49,"evidence":69},"localStorage",[70],{"id":56,"by":57,"text":58},"open_source","unknown",{"praise":74,"objections":86,"requests":97,"questions":102,"alternatives":117},[75,79],{"value":76,"source":49,"evidence":77},"Simple, clean code",[78],{"id":64,"by":65,"text":66},{"value":80,"source":81,"evidence":82},"Works offline without a server","maker",[83],{"id":84,"by":11,"text":85},"43575368","It means, that you don't need an internet connection for this to work :) (so it is no rabbitmq or so which runs on a server and the browser is just the client) You can try on the…",[87,91],{"value":88,"source":49,"evidence":89},"Only works on the same origin",[90],{"id":56,"by":57,"text":58},{"value":92,"source":49,"evidence":93},"subscribe() installs a handler per topic, which is inefficient",[94],{"id":95,"by":57,"text":96},"43573741","The subscribe() implementation seems suboptimal in the case where there are many different topics: ``` subscribe(topic, callback) { if (this.listeners[topic] == undefined) { \u002F\u002F…",[98],{"value":99,"source":49,"evidence":100},"Use a single storage event handler for all topics",[101],{"id":95,"by":57,"text":96},[103,110],{"value":104,"source":49,"evidence":105},"Is localStorage a security risk across sites?",[106],{"id":107,"by":108,"text":109},"43573280","nottorp","Isn't this a security hole waiting to be exploited? How does the browser handle access control to the local storage, especially offline when they aren't loaded from the same…",{"value":111,"source":49,"evidence":112},"How does this work on Node.js across instances?",[113],{"id":114,"by":115,"text":116},"43574849","amazingamazing","I wonder how one does this on nodejs across instances gracefully.",[118,122,129,136],{"value":119,"source":49,"evidence":120},"BroadcastChannel API",[121],{"id":52,"by":53,"text":54},{"value":123,"source":49,"evidence":124},"SharedWorker",[125],{"id":126,"by":127,"text":128},"43572059","remram","You can use a SharedWorker now instead of picking a tab to do that work (and failing over to another tab if it gets closed). Support is still spotty though.",{"value":130,"source":49,"evidence":131},"Service worker",[132],{"id":133,"by":134,"text":135},"43572273","EGreg","Well, you can just use a service worker, instead of broadcast channels or shared workers. They have all the functionality you need, now. Any iframe that loads in a secure context…",{"value":137,"source":49,"evidence":138},"Web Locks API",[139],{"id":140,"by":141,"text":142},"43573218","realPubkey","This is likely done with the WebLocks API",{"comments":144,"answered":41,"key":145},7,[146,149,152],{"id":147,"text":148},"43571132","Oh, did not know about it :D Thank you! Added a link to this to the TabSub landingpage",{"id":150,"text":151},"43575518","Will check this tomorrow. If you come to it in the meantime, feel free to open a PR :) Thx",{"id":153,"text":154},"43571093","Thank you :) Simple because I don't know any better :'D",{"commenters":156,"max_depth":144,"maker_replies":144,"first_comment_mins":157,"lifespan_hours":158},20,61,30,[160,162,164,167,171,173,175,178,181,182,183,188,191,192,194,197,199,201,203,208,209,210,213,215,216,218,221,224,225,228,230,232,235,240,242,245,247],[52,34,34,161,53,34],"commenter\u002Fneutral\u002Fidea",[147,34,34,163,11,35],"maker\u002Fpositive\u002Fdocs",[165,34,44,166,53,34],"43571447","maker\u002Fpositive\u002Fnone",[168,34,32,169,170,34],"43580730","project\u002Fneutral\u002Fidea","nchmy",[95,35,35,172,57,34],"project\u002Fcritical\u002Fperformance",[150,35,34,174,11,35],"maker\u002Fneutral\u002Fexecution",[176,41,32,169,177,34],"43572402","Lerc",[179,32,34,180,134,34],"43571063","other\u002Fneutral\u002Fidea",[126,32,34,161,127,34],[133,32,34,161,134,34],[184,185,44,186,187,34],"43572498",4,"project\u002Fpositive\u002Fexecution","hombre_fatal",[189,44,32,169,190,34],"43572986","Minor49er",[140,44,34,161,141,34],[193,44,34,161,57,34],"43573595",[195,44,34,161,196,34],"43575027","0x457",[198,44,34,161,57,34],"43575293",[200,44,34,161,196,34],"43584442",[202,44,34,161,57,34],"43587314",[204,205,34,206,207,34],"43571763",6,"other\u002Fneutral\u002Fnone","kvemkon",[64,144,44,186,65,34],[153,144,34,174,11,35],[211,144,34,180,212,34],"43571226","stanac",[107,33,32,214,108,34],"project\u002Fneutral\u002Fprivacy",[56,33,32,214,57,34],[217,33,32,169,108,34],"43573685",[219,33,34,161,220,34],"43573904","godot",[222,33,34,223,11,35],"43575436","maker\u002Fneutral\u002Fidea",[84,33,34,223,11,35],[226,33,32,227,108,34],"43576489","maker\u002Fneutral\u002Fnone",[229,33,34,227,11,35],"43579157",[231,33,32,227,108,34],"43579547",[233,33,34,206,234,34],"43579038","crabmusket",[236,237,34,238,239,34],"43572607",9,"other\u002Fpositive\u002Fnone","qudat",[114,241,34,206,115,34],10,[243,241,34,206,244,34],"43575182","kolme",[246,241,34,206,115,34],"43575691",[248,241,34,206,11,35],"43579169",[250,254],{"id":251,"t":252,"points":253,"comments":41},"23261657",1590082324,15,{"id":4,"t":12,"points":14,"comments":15},[256,260,265,270,274,278],{"id":257,"name":258,"points":259,"category":20},"43613194","Browser MCP",616,{"id":261,"name":262,"points":263,"category":264},"43593789","Whatsit",513,"games",{"id":266,"name":267,"points":268,"category":269},"43569190","OpenNutrition",311,"data",{"id":271,"name":272,"points":273,"category":20},"43614285","Lux",268,{"id":275,"name":276,"points":277,"category":20},"43627758","DrawDB",263,{"id":279,"name":280,"points":281,"category":20},"43573539","GitMCP",185,false,"v2",{"id":285,"name":5,"line":6,"ai":282,"cat":20,"year":13,"points":14,"comments":15,"rec":29,"s":286,"top":18,"kw":287,"maker":11,"domain":10,"tier":19,"attempts":41,"strip":288,"url":9,"mix":289,"praise":76,"objection":88,"sub":21},43569961,0.18,[24,25,26,27,28],"0053103000530000000500333000303000000",[32,33,34,35],1794036672249]