<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vitor Norton</title>
    <description>The latest articles on DEV Community by Vitor Norton (@vtnorton).</description>
    <link>https://dev.to/vtnorton</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F187288%2F24ebe72c-4af5-4af9-a6dc-5a58abd5f12d.jpg</url>
      <title>DEV Community: Vitor Norton</title>
      <link>https://dev.to/vtnorton</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vtnorton"/>
    <language>en</language>
    <item>
      <title>I tried to fork GSD, or: it's for vibe coders, not real devs</title>
      <dc:creator>Vitor Norton</dc:creator>
      <pubDate>Mon, 15 Jun 2026 15:48:58 +0000</pubDate>
      <link>https://dev.to/vtnorton/i-tried-to-fork-gsd-or-its-for-vibe-coders-not-real-devs-kkl</link>
      <guid>https://dev.to/vtnorton/i-tried-to-fork-gsd-or-its-for-vibe-coders-not-real-devs-kkl</guid>
      <description>&lt;p&gt;&lt;em&gt;As a senior engineer I deep dive into spec-driven AI development: the architecture, the maintenance math, a 250-fork graveyard, a rejected GitHub issue, and how I chose between GSD, GitHub Spec Kit, and OpenSpec.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I genuinely like GSD. Its research, planning, and roadmap/phase model are some of the best I've used. It still doesn't fit how I work.&lt;/li&gt;
&lt;li&gt;My problem was never a missing setting. It was the &lt;strong&gt;category&lt;/strong&gt; of tool: GSD is an &lt;em&gt;autonomous orchestrator&lt;/em&gt;. I'm a senior engineer who wants a &lt;em&gt;human-in-the-loop assistant&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;I considered forking it into a "lite" version. The maintenance math says a divergent fork is the worst available option, and a scan of all 250 forks confirms it: not one is a successful start point to me.&lt;/li&gt;
&lt;li&gt;I'm switching to &lt;strong&gt;GitHub Spec Kit&lt;/strong&gt;, with &lt;strong&gt;OpenSpec&lt;/strong&gt; as a close runner-up. This is the entire reasoning, including the parts that argue against me.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Loving a tool that doesn't fit you
&lt;/h2&gt;

&lt;p&gt;There's a specific kind of frustration that doesn't get written about much: when a tool is &lt;em&gt;good&lt;/em&gt;, you can see the craft in it, and it still fights you on every project.&lt;/p&gt;

&lt;p&gt;That's GSD for me. GSD ("Git. Ship. Done.") is a spec-driven, context-engineering framework for AI coding agents. It drives an agent through a disciplined loop (&lt;strong&gt;discuss → plan → execute → verify → ship&lt;/strong&gt;) running the heavy research and planning work in fresh-context subagents so your main session never rots. The phase/roadmap model is excellent. The research step is excellent. I &lt;em&gt;like&lt;/em&gt; the ceremony. For me it's a comprehension gate, the thing that forces the agent (and me) to actually understand the work before touching code.&lt;/p&gt;

&lt;p&gt;And yet, every time I ran it on a real project, it worked &lt;em&gt;against&lt;/em&gt; the way I work. I'm a senior engineer. My job is to be helped, not replaced. GSD is built to take the wheel.&lt;/p&gt;

&lt;p&gt;I almost did the obvious engineer thing: fork it, file off the parts I don't like, ship my own "GSD lite". This post is what I found when I actually did the homework first, and why I'm doing something else entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  What GSD actually is, under the hood
&lt;/h2&gt;

&lt;p&gt;Before you can reason about forking or replacing a tool, you have to know how it's wired. So I read the repo.&lt;/p&gt;

&lt;p&gt;GSD is three layers stacked on top of each other:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;What it is&lt;/th&gt;
&lt;th&gt;Do I care about it?&lt;/th&gt;
&lt;th&gt;Cost to maintain in a fork&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Markdown "brain"&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;commands/&lt;/code&gt; → &lt;code&gt;workflows/&lt;/code&gt; → &lt;code&gt;agents/&lt;/code&gt; → &lt;code&gt;references/&lt;/code&gt; → &lt;code&gt;templates/&lt;/code&gt;: the prompts that drive the whole loop&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Yes, this is what I love&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;High&lt;/strong&gt;, these are the most-churned files upstream&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CJS tooling + installer&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;gsd-tools.cjs&lt;/code&gt;  • ~104 library modules, plus a ~10,700-line multi-runtime installer and a set of hooks&lt;/td&gt;
&lt;td&gt;Almost none&lt;/td&gt;
&lt;td&gt;Medium/high, and it's work that gives me nothing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Config&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.planning/config.json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;This is where the cheap wins live&lt;/td&gt;
&lt;td&gt;~Zero&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two facts fall out of this that matter for &lt;em&gt;any&lt;/em&gt; customization decision:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The workflows aren't standalone prompts.&lt;/strong&gt; They call &lt;code&gt;gsd-tools&lt;/code&gt; constantly, to load context, update state, and commit. So "just lift the good prompts into my own tool" isn't a copy-paste. The prompts assume a 104-module CLI sitting next to them. Lifting the brain means lifting the whole nervous system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Most of GSD's complexity is infrastructure I'd never touch.&lt;/strong&gt; The installer alone supports 16+ runtimes (Claude Code, Codex, Gemini CLI, Cursor, Windsurf, Copilot, and more). There are 33 agents, ~67 skills, 11 hooks, a capability registry, and a supply-chain gate against hallucinated packages. It's impressive engineering. It's also 90% surface area I don't need but would inherit the moment I forked.&lt;/p&gt;

&lt;p&gt;There's a name for what GSD is, and it's the crux of this entire post: &lt;strong&gt;GSD is an autonomous orchestrator.&lt;/strong&gt; It spawns subagents, commits per task, and advances on its own. The human approves at checkpoints. That's by design, and its made for a different operator than me.&lt;/p&gt;




&lt;h2&gt;
  
  
  The one hard "no": atomic per-task commits
&lt;/h2&gt;

&lt;p&gt;If I strip my complaints down to the irreducible core, it's this: &lt;strong&gt;GSD commits automatically, one commit per task, as it executes.&lt;/strong&gt; Here's the literal guidance from its &lt;code&gt;git-integration.md&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;| Task completed | YES | Atomic unit of work (1 commit per task) |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# How GSD stages and commits during execution&lt;/span&gt;
git add src/api/auth.ts src/types/user.ts
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"feat(08-02): create user registration endpoint"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The workflow I actually want is human-in-the-loop:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the agent does the work, &lt;strong&gt;locally, uncommitted&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;it &lt;strong&gt;stops&lt;/strong&gt;. I validate on my machine&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I&lt;/strong&gt; give the order: now test it, run the checks, do the code review, open the PR&lt;/li&gt;
&lt;li&gt;the commit happens &lt;strong&gt;under my command, late&lt;/strong&gt;, not per task, not automatically&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is not a niche preference. The 2026 consensus on agentic workflows says the same thing in plain terms: &lt;em&gt;"code review is the step most agentic workflows quietly drop,"&lt;/em&gt; and the healthy pattern is &lt;em&gt;"a human reviews the plan before execution begins, not after."&lt;/em&gt; GSD's auto-commit removes exactly the control points a senior engineer needs.&lt;/p&gt;

&lt;p&gt;Plus, I cannot touch the code. If I change one line, if I do anything, it will just mess the entire commit history and it would spend a few minutes (and lots of tokens) to understand that: “yeah, I can do my one code, thank you”. &lt;/p&gt;

&lt;h2&gt;
  
  
  So I opened an issue…
&lt;/h2&gt;

&lt;p&gt;I filed issue #745: add a config option to defer all commits during execution, leave the working tree dirty, and let me review the whole phase as one diff before anything lands.&lt;/p&gt;

&lt;p&gt;The maintainer's response was fast and unambiguous:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"this is how its designed, not interested in changing the design at this time. the commits are there to protect against loss of context or other. this would be a redesign of how it works, not an enhancement."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I want to be fair here, because this is the part that actually clarified everything: &lt;strong&gt;the maintainer is right, from inside GSD's design.&lt;/strong&gt; If your tool is an autonomous agent that may lose its context window mid-run, then committing every task &lt;em&gt;is&lt;/em&gt; a feature, a crash-recovery and context-recovery mechanism. My request wasn't a tweak to that design. It was a request for a &lt;em&gt;different philosophy&lt;/em&gt;. We don't disagree about quality. We disagree about who holds the wheel.&lt;/p&gt;

&lt;p&gt;But the practical consequence is sharp: &lt;strong&gt;I can't upstream my way out of this.&lt;/strong&gt; The thing I most want to change is precisely what the maintainer defends as the core of the design, and will keep elaborating with every release, rightfully so. Any customization I keep would be fighting an actively-maintained opposite opinion.&lt;/p&gt;

&lt;h2&gt;
  
  
  The subtler tax: it looks like collaboration, right up until it isn't
&lt;/h2&gt;

&lt;p&gt;Auto-commit is the complaint I can point at. The one that actually cost me is harder to name, because it wears the disguise of &lt;em&gt;good work&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here's the shape of it. I had a tiny, one-off task on a small personal repo: pull a handful of scattered notes into a single file. Twenty minutes by hand. I ran it through the proper loop anyway: discuss → plan → execute. Roughly &lt;strong&gt;two hours later&lt;/strong&gt; it handed me a polished, completely wrong deliverable: a reusable, &lt;em&gt;unit-tested&lt;/em&gt; tool for what was a one-time edit. Something I never asked for, never wanted, and now had to unwind. &lt;/p&gt;

&lt;p&gt;The maddening part is &lt;em&gt;where&lt;/em&gt; it went wrong. The discuss step is the part I like most, the comprehension gate, the thing that's supposed to catch exactly this. And it didn't. Not because discussion is bad, but because it has a grain: it latches onto one reading of what you said and drives hard in that direction, confidently, past the point where it still makes sense. It keeps asking sharp questions (which &lt;em&gt;feels&lt;/em&gt; like rigor) while quietly walking off the edge of the scope you actually gave it. By the time the drift is visible it's already downstream in a plan, then in code, and you're the one paying to reel it back.&lt;/p&gt;

&lt;p&gt;And the whole time it &lt;em&gt;looks&lt;/em&gt; productive. It's debating. It's planning. It's spinning up research. Every signal says "this is going well," so you trust it, and the bill only arrives at the end, as hours spent generating something that misses the nuance you could never get it to hold. That's the real failure mode of a highly-opinionated orchestrator: the opinions are load-bearing, and when your intent doesn't match them the tool can't bend. It can only drift, eloquently. &lt;/p&gt;

&lt;p&gt;And this isn't one unlucky run. On a recent &lt;strong&gt;70-phase&lt;/strong&gt; project I had to &lt;strong&gt;redo or restructure at least 50 of them.&lt;/strong&gt; The ones that survived only did because I'd front-loaded a lot of time organizing the code and kept each phase small and tightly scoped, and &lt;em&gt;even then&lt;/em&gt;, every ~5 phases I had to stop and fix things in the code by hand so the &lt;em&gt;next&lt;/em&gt; 5 wouldn't wander off. The review-and-re-prompt loop isn't the exception. It's the steady state. A huge share of my time on these projects goes to catching the tool before it commits to the wrong idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  The maintenance math I did next
&lt;/h2&gt;

&lt;p&gt;If you can't upstream it, your options are fork, patch, config, or build from scratch. I worked through all four.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Config can turn things off. It can't reshape the flow.&lt;/strong&gt; GSD's &lt;code&gt;config.json&lt;/code&gt; is genuinely deep. You can lean it out a lot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"interactive"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"granularity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"coarse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"workflow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"research"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"plan_check"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"verifier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"discuss_mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"assumptions"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"planning"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"commit_docs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"parallelization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But no key reshapes the &lt;em&gt;flow&lt;/em&gt;. You can't tell config "merge discuss into plan," "change how discussion works," or "commit my way." Reshaping behavior means editing the workflow Markdown, the hottest files in the repo. Which lands you in the maintenance trap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fork-vs-patch comparison is less flattering to patches than people think:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Fork (tracking upstream)&lt;/th&gt;
&lt;th&gt;Patch repo&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Conflict frequency&lt;/td&gt;
&lt;td&gt;Same, breaks when upstream edits your lines&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Same&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Conflict resolution&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;git merge&lt;/code&gt; is 3-way (knows the ancestor) → resolves better&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;git apply&lt;/code&gt; is 2-way → rejects more on moved code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real advantage&lt;/td&gt;
&lt;td&gt;"I own the tree"&lt;/td&gt;
&lt;td&gt;Legibility: your delta is a small, separate artifact&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;As a public product&lt;/td&gt;
&lt;td&gt;Installs cleanly&lt;/td&gt;
&lt;td&gt;Bad UX: two-step install, version-coupled rejects hit &lt;em&gt;your&lt;/em&gt; users&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The only overlay pattern that survives upstream churn &lt;em&gt;cleanly&lt;/em&gt; is &lt;strong&gt;additive files marked &lt;code&gt;merge=ours&lt;/code&gt;&lt;/strong&gt;: you only ever &lt;em&gt;add&lt;/em&gt; files, never edit existing ones, so a periodic sync never conflicts. That's powerful, but it has a hard limit: it works for things you can &lt;em&gt;add&lt;/em&gt; (your config, a launcher, your own skills, a host-side wrapper) and never for &lt;em&gt;behavior edits&lt;/em&gt;. My change is a behavior edit. So it's stuck in the expensive lane no matter what.&lt;/p&gt;

&lt;p&gt;The conclusion that reframed my whole decision: &lt;strong&gt;for a public tool that re-opinionates the flow, a fork is the worst quadrant.&lt;/strong&gt; It makes you maintain 90% infrastructure you don't want &lt;em&gt;and&lt;/em&gt; fight merge conflicts on exactly the files you customized.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fork graveyard
&lt;/h2&gt;

&lt;p&gt;I didn't want to argue this from theory, so I looked at the evidence: every fork of the repo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;250 forks. Not one is a successful divergent "lite."&lt;/strong&gt; The breakdown:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The vast majority&lt;/strong&gt; are stale snapshots carrying an old name the upstream itself used: untouched personal copies, not projects.&lt;/li&gt;
&lt;li&gt;A few are &lt;strong&gt;README rebrands or translations&lt;/strong&gt;, one commit of real work.&lt;/li&gt;
&lt;li&gt;One is a &lt;strong&gt;runtime adapter&lt;/strong&gt; with zero commits on its main branch despite an ambitious description.&lt;/li&gt;
&lt;li&gt;The only serious one is an &lt;strong&gt;integration wrapper&lt;/strong&gt;, and it's the most instructive object in the whole study.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That serious fork belongs to a company embedding GSD into a product. Their entire diff against upstream is this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;added     .gitattributes              (merge=ours rules)
added     scripts/sync-upstream.sh
added     NOTICE / CONTRIBUTING-UPSTREAM.md
modified  README.md                   (their banner only)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Their README states the strategy outright: &lt;strong&gt;"GSD itself runs unmodified."&lt;/strong&gt; They wrap it host-side via the Claude Agent SDK and intercept the approval checkpoints in their own orchestrator. And their &lt;code&gt;.gitattributes&lt;/code&gt; is the &lt;code&gt;merge=ours&lt;/code&gt; trick in the wild:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# Keep "ours" on merge with upstream so periodic
# sync-upstream.sh runs don't conflict on files we maintain.
&lt;/span&gt;&lt;span class="err"&gt;NOTICE&lt;/span&gt;                    &lt;span class="py"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ours&lt;/span&gt;
&lt;span class="err"&gt;scripts/sync-upstream.sh&lt;/span&gt;  &lt;span class="py"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ours&lt;/span&gt;
&lt;span class="err"&gt;.gitattributes&lt;/span&gt;            &lt;span class="py"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;ours&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The reframe that changed everything
&lt;/h2&gt;

&lt;p&gt;Here's the thing I wish I'd understood on day one. When you line GSD up against the rest of the field, a split appears that has nothing to do with features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Autonomous orchestrators&lt;/strong&gt; (GSD, BMAD): they take the wheel. Spawn subagents, commit on their own, advance on their own. The human approves occasionally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spec/planning layers&lt;/strong&gt; (GitHub Spec Kit, OpenSpec, Agent OS, Taskmaster): they hand you structure and hold the door. They generate spec/plan/tasks, and execution runs through your &lt;em&gt;normal&lt;/em&gt; agent, where you're already in the loop and commits are yours by default.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The landscape
&lt;/h2&gt;

&lt;p&gt;Spec-driven development exploded in 2026. A community map tracks 30+ frameworks. Mapped against what I, as a senior engineer, actually care about:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Commit / HIL&lt;/th&gt;
&lt;th&gt;Keeps ideas open?&lt;/th&gt;
&lt;th&gt;Research/planning depth&lt;/th&gt;
&lt;th&gt;Cost to me&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GSD&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Autonomous orchestrator&lt;/td&gt;
&lt;td&gt;Auto-commit + auto-advance&lt;/td&gt;
&lt;td&gt;Locks requirements early&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;High&lt;/strong&gt; (4 parallel researchers + plan-check + verifier)&lt;/td&gt;
&lt;td&gt;Fork = &lt;strong&gt;high&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OpenSpec&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Spec layer&lt;/td&gt;
&lt;td&gt;You drive; no auto-commit&lt;/td&gt;
&lt;td&gt;Yes, per-change proposals&lt;/td&gt;
&lt;td&gt;Lean&lt;/td&gt;
&lt;td&gt;Adopt = &lt;strong&gt;low&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Spec Kit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Spec layer&lt;/td&gt;
&lt;td&gt;Human review each phase&lt;/td&gt;
&lt;td&gt;Yes, per-feature&lt;/td&gt;
&lt;td&gt;Medium (&lt;code&gt;/clarify&lt;/code&gt;  • &lt;code&gt;/plan&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Adopt = &lt;strong&gt;low&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agent OS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Standards layer&lt;/td&gt;
&lt;td&gt;"Complements, doesn't replace"&lt;/td&gt;
&lt;td&gt;Encodes &lt;em&gt;your&lt;/em&gt; standards&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Adopt = low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;BMAD&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Multi-agent orchestrator&lt;/td&gt;
&lt;td&gt;Approves docs, but heavy&lt;/td&gt;
&lt;td&gt;PRD + arch + epics locked&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Adopt = medium; ceremony enormous&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Taskmaster&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Task layer&lt;/td&gt;
&lt;td&gt;You drive&lt;/td&gt;
&lt;td&gt;Incremental&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Adopt = low&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The two that fit a senior engineer who likes ceremony but wants the wheel are &lt;strong&gt;GitHub Spec Kit&lt;/strong&gt; and &lt;strong&gt;OpenSpec&lt;/strong&gt;. So I went deep on both.&lt;/p&gt;

&lt;h2&gt;
  
  
  Spec Kit vs OpenSpec, for real
&lt;/h2&gt;

&lt;p&gt;The difference between them is conceptual, not a matter of commands. In one line each:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Spec Kit&lt;/strong&gt; = &lt;em&gt;"specify the feature, then build it."&lt;/em&gt; The unit is the &lt;strong&gt;feature&lt;/strong&gt;. You start from a &lt;em&gt;constitution&lt;/em&gt; (project principles). Each feature flows &lt;code&gt;spec → plan → tasks → implement&lt;/code&gt;, on its own git branch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenSpec&lt;/strong&gt; = &lt;em&gt;"propose a change as a delta to a living spec."&lt;/em&gt; The unit is the &lt;strong&gt;change&lt;/strong&gt;. There's a &lt;code&gt;specs/&lt;/code&gt; folder (current truth) and a &lt;code&gt;changes/&lt;/code&gt; folder (proposals). Each proposal folds into &lt;code&gt;specs/&lt;/code&gt; only when you apply and archive it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's &lt;strong&gt;feature-centric vs change-centric&lt;/strong&gt;, and nearly everything else derives from it.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Axis&lt;/th&gt;
&lt;th&gt;GitHub Spec Kit&lt;/th&gt;
&lt;th&gt;OpenSpec&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mental model&lt;/td&gt;
&lt;td&gt;Spec the feature → build&lt;/td&gt;
&lt;td&gt;Delta change over a living spec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Structure&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;constitution.md&lt;/code&gt;  • &lt;code&gt;specs/&amp;lt;feature&amp;gt;/{spec,plan,tasks}.md&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;specs/&lt;/code&gt; (truth) + &lt;code&gt;changes/&amp;lt;name&amp;gt;/{proposal,specs,design,tasks}.md&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Git&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Creates a branch per feature&lt;/strong&gt; (&lt;code&gt;001-...&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;You manage git; the "change" is the review unit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ceremony&lt;/td&gt;
&lt;td&gt;Higher (constitution, &lt;code&gt;/clarify&lt;/code&gt;, checklists)&lt;/td&gt;
&lt;td&gt;Deliberately lean ("no personas, fluid")&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Greenfield vs brownfield&lt;/td&gt;
&lt;td&gt;Both, greenfield-leaning&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Brownfield-first&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Encode "my way"&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Constitution&lt;/strong&gt; every spec inherits&lt;/td&gt;
&lt;td&gt;Conventions in agent files (lighter)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Commit behavior&lt;/td&gt;
&lt;td&gt;Yours (scaffolds a branch, no per-task auto-commit)&lt;/td&gt;
&lt;td&gt;Yours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ecosystem&lt;/td&gt;
&lt;td&gt;GitHub-backed, &lt;strong&gt;105 extensions, 22 presets, 200+ contributors&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Fission-AI, ~54k★, healthy but smaller&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The same task through both, to feel it, &lt;em&gt;"add dark mode to an existing app"&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Spec Kit
/speckit.specify   → branch 002-dark-mode + spec.md  (you review)
/speckit.plan      → plan.md + research.md            (you review)
/speckit.tasks     → tasks.md
/speckit.implement → builds; you commit

# OpenSpec
/opsx:propose dark mode → changes/add-dark-mode/ (proposal + tasks)  (you review)
/opsx:apply             → implements; you validate locally
/opsx:archive           → the delta folds into specs/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In both, the commit and the PR are mine.&lt;/p&gt;

&lt;h2&gt;
  
  
  About benchmarks (and why they lie a little)
&lt;/h2&gt;

&lt;p&gt;You'll see a benchmark passed around: one CRM dashboard built three ways: &lt;strong&gt;OpenSpec ~12 min, Spec Kit ~90 min, BMAD ~5.5 h.&lt;/strong&gt; Useful for order-of-magnitude, but it's one task and one reviewer. So I ran my own measurement against something real.&lt;/p&gt;

&lt;p&gt;The method is simple and reproducible: &lt;strong&gt;read the git commit timestamps.&lt;/strong&gt; On a real production project,, I took three consecutive GSD phases, each wiring one external integration, and measured wall-clock from the first to the last commit of each phase.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Span (first → last commit)&lt;/th&gt;
&lt;th&gt;Duration&lt;/th&gt;
&lt;th&gt;Plans&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;small, single adapter&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~31 min&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;larger, 4 plans / 3 waves&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~44 min&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;medium (+ a mid-phase re-scope)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~50 min&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Average ~&lt;strong&gt;40 minutes per phase&lt;/strong&gt;. But the revealing part is the breakdown. In the most complete phase, code generation itself was the small part. The bulk was discuss + plan + research + verify. In another, the &lt;em&gt;pure execution&lt;/em&gt; was about &lt;strong&gt;3 minutes&lt;/strong&gt; for three plans. The rest was context-gathering and a scope decision I made.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The takeaway:&lt;/strong&gt; GSD's wall-clock isn't the machine grinding. It's the &lt;strong&gt;ceremony&lt;/strong&gt;, the part I actually value.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That reframes "is it slow?" entirely. On a rough scale it lands between OpenSpec and BMAD, but who cares, because the time goes where I want it to. The real lesson for choosing a replacement: a tool with similar ceremony (Spec Kit) will &lt;em&gt;feel&lt;/em&gt; about the same. A leaner tool (OpenSpec) is faster mostly because it cuts the comprehension gate I like. Speed was never my axis.&lt;/p&gt;

&lt;h2&gt;
  
  
  The verdict
&lt;/h2&gt;

&lt;p&gt;For my posture (a senior engineer, existing projects, a backlog in triage, someone who &lt;em&gt;likes&lt;/em&gt; ceremony as a comprehension gate, whose only hard "no" is atomic per-task commits), &lt;strong&gt;I'm going with GitHub Spec Kit.&lt;/strong&gt; Mapping it to what I actually weighed:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;My criterion&lt;/th&gt;
&lt;th&gt;Winner&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ceremony as a comprehension gate&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Spec Kit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Heavier on purpose, OpenSpec strips it by philosophy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Research + planning depth&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Spec Kit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;/clarify&lt;/code&gt;  • &lt;code&gt;/plan&lt;/code&gt; → &lt;code&gt;research.md&lt;/code&gt;, &lt;code&gt;data-model.md&lt;/code&gt;, &lt;code&gt;contracts/&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Branch-per-feature&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Spec Kit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native; OpenSpec leaves git to you&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Roadmap / phases&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Spec Kit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not built in, but the extension ecosystem can add whole phases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No atomic commits (my one "no")&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Tie&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Neither auto-commits per task&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Encode my own standards&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Spec Kit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;constitution.md&lt;/code&gt; is the native lever&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;One standard, longevity&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Spec Kit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;GitHub-backed, MIT, biggest ecosystem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Brownfield + in-tool triage&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;OpenSpec&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;But I already triage in Notion, so it's partly redundant for me&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;OpenSpec is the runner-up, and an excellent tool&lt;/strong&gt;: leaner, brownfield-first, with a genuinely elegant change-as-delta model. The only thing that should flip my decision is a hands-on test where Spec Kit's ceremony feels like &lt;em&gt;friction&lt;/em&gt; instead of &lt;em&gt;comprehension&lt;/em&gt; on my existing repos. That's the test I'll run next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources &amp;amp; further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GSD: open-gsd/gsd-core · original gsd-build/get-shit-done · issue #745&lt;/li&gt;
&lt;li&gt;GitHub Spec Kit · Spec Kit docs&lt;/li&gt;
&lt;li&gt;OpenSpec (Fission-AI)&lt;/li&gt;
&lt;li&gt;BMAD-METHOD · Agent OS · claude-task-master&lt;/li&gt;
&lt;li&gt;Spec-Driven Development: a map of 30+ frameworks (2026)&lt;/li&gt;
&lt;li&gt;BMAD vs Spec Kit vs OpenSpec (Reenbit)&lt;/li&gt;
&lt;li&gt;9 Best Spec-Driven Tools 2026 (MarkTechPost)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>agentskills</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Realtime meets AI: How we used gaming to showcase our new library, now open source!</title>
      <dc:creator>Vitor Norton</dc:creator>
      <pubDate>Mon, 11 Nov 2024 14:09:31 +0000</pubDate>
      <link>https://dev.to/superviz/realtime-meets-ai-how-we-used-gaming-to-showcase-our-new-library-now-open-souce-3fgm</link>
      <guid>https://dev.to/superviz/realtime-meets-ai-how-we-used-gaming-to-showcase-our-new-library-now-open-souce-3fgm</guid>
      <description>&lt;p&gt;We're excited to announce that &lt;a href="https://github.com/SuperViz/sv-activiation-app" rel="noopener noreferrer"&gt;we're open sourcing the code we used to create an interactive experience&lt;/a&gt; that synchronized data for over 3,000 users at major tech events, demonstrating the power and scalability of our &lt;a href="https://docs.superviz.com/releases/2024/october#a-new-and-more-powerful-realtime-sdk" rel="noopener noreferrer"&gt;newly released Realtime library&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multiplayer Infinite Craft
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6fn2kjqik6vj4kfabhx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6fn2kjqik6vj4kfabhx.jpg" alt="Infinite Craft" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One key part of this was making the Super, which was based on &lt;a href="https://dev.to/vtnorton/how-i-made-infinite-craft-a-multiplayer-game-with-a-few-lines-of-code-4ne7"&gt;Infinite Craft&lt;/a&gt;, multiplayer. The game consists of combining different elements to create new ones, fostering creativity.&lt;/p&gt;

&lt;p&gt;Users would start with the essential elements: "Fire", "Water", "Earth", "Wind", "Coffee", "JavaScript", and "Developer". After combining "Fire" and "JavaScript", an AI would analyze the combination and create "Firebase".&lt;/p&gt;

&lt;p&gt;Because these events would gather a huge number of people (sometimes 3.5k people), we couldn't synchronize every new element among everyone. This was mainly because the gameplay would not be fun; instead, it would be confusing and stressful. By the end of these events, that would add up to 16k elements. Can you imagine how to display 16k non-structured elements on a mobile screen?&lt;/p&gt;

&lt;p&gt;We took a different approach by making it a bit of a race. Everyone would play with a single instance, but in case they found a first discovery (meaning no one before had tried this combination), new points were added to the user, and everyone at the event would get a push notification. With more points, there was a greater chance to win a big prize at the end of the day.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Real-time
&lt;/h3&gt;

&lt;p&gt;We had build with a Next.js project, using our &lt;code&gt;@superviz/realtime&lt;/code&gt; package, which offers a WebSocket infrastructure, that is based on a Publisher/Subscriber (PubSub) design pattern. This allowed for efficient event-driven communication between different instances of the application.&lt;/p&gt;

&lt;p&gt;For this, we had created &lt;a href="https://docs.superviz.com/realtime/features/channels" rel="noopener noreferrer"&gt;two different channels&lt;/a&gt;, the &lt;code&gt;default&lt;/code&gt; and the &lt;code&gt;game&lt;/code&gt;. The default channel was the communication of the whole experience, it would tell if an activation has awarded points to the user, and would sync across other parts of the system (mostly syncing user dada). We had a dedicated channel for the game, that would notify every one that was listening to the &lt;code&gt;new.element&lt;/code&gt; event.&lt;/p&gt;

&lt;p&gt;When someone combined two elements, it would send a request to our API. The API would analyze if the user was valid and if the element combination already existed in our database. If neither of these conditions were met, it would send a prompt to OpenAI to create the element. Before returning the result, we would update the database and publish several events.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="nx"&gt;defaultChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;activation.game.update&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;points&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;

  &lt;span class="nx"&gt;gameChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new.element&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;points&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the frontend of the game, we would listen to the &lt;code&gt;new.event&lt;/code&gt; and add a push notification using toast. Like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleGameUpdate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userFromMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userFromMessage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt;
    &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;USERDATA_KEY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userFromMessage&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; just discovered &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt; and has more chance of winnin!`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;gameChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new.element&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleGameUpdate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the application magic happened on the dashboard and with the other event being dispatched.&lt;/p&gt;

&lt;h2&gt;
  
  
  A playful dashboard
&lt;/h2&gt;

&lt;p&gt;On our stand, we had a giant TV to display the dashboard. It was designed to be both informative and mesmerizing , displaying real-time updates of player activities and discoveries. It was a visual representation of every single participant activity. Not only kept participants informed of their scores but also fueled friendly competition and excitement throughout the event.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0eu2ijhxodu8cgzwcn0w.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0eu2ijhxodu8cgzwcn0w.jpg" alt="Playful dashboard" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The dashboard was inspired by the popular multiplayer game Agar.io. Much like how players in Agar.io grow by consuming smaller cells, our dashboard represented each participant as a dynamic entity that expanded as they gained points.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4drlxgwcv5r4do7cxlp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi4drlxgwcv5r4do7cxlp.png" alt="User Rings" width="101" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The design concept revolved around creating a visually engaging and intuitive representation of real-time data. Each participant was depicted as a circular entity, with concentric rings expanding outward to indicate their score and level of engagement. This organic, cell-like visualization not only made the data easy to interpret at a glance but also added an element of gamification to the event experience.  We also would add transparency to those users that was offline to showcase &lt;a href="https://docs.superviz.com/realtime/features/presence" rel="noopener noreferrer"&gt;our recent released presence feature&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Behind the scene
&lt;/h3&gt;

&lt;p&gt;To make this happen, this page would listen to every single event, and that was plenty! This is the list of the listening events the page was subscribed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;defaultChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;activation.start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleActivationStart&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;defaultChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;activation.complete&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleActivationComplete&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;defaultChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;activation.game.update&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleGameUpdate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;gameChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;new.element&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleGameUpdate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;defaultChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;presence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;presence.leave&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;handleParticipantStatusChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;defaultChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;presence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;presence.joined-room&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;handleParticipantStatusChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;defaultChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;presence&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;presence.update&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nf"&gt;handleParticipantUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down those events our dashboard listens to and explore how each contributes to creating a dynamic, real-time experience:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Activation events:&lt;/strong&gt; The dashboard listens for &lt;code&gt;activation.start&lt;/code&gt; and &lt;code&gt;activation.complete&lt;/code&gt; events, which add a progress ring when an activation starts and add a complete ring when it finishes. The rings were added based on the order that the person would participate in the activations, providing a real-time visual story of their journey through the event.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;activation.game.update&lt;/code&gt; event was responsable to showcase real-time progress in the game. It updates the player's score, which is visually represented by expanding the ring around their entity on the dashboard. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fklsuba52wvvx1tie0irf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fklsuba52wvvx1tie0irf.gif" alt="Game ring evolution" width="750" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Game updates:&lt;/strong&gt; It subscribes to &lt;code&gt;new.element&lt;/code&gt; events from the game channel, which would display a toast notification with the new element created. This feature gathered people around the screen to see what others were creating in real-time, creating a sense of community and shared excitement.&lt;/p&gt;

&lt;p&gt;We had seen the creation of beautiful elements, like “Real-time communication”, “Web sockets”, “Collaboration environment”, “Remote work” and funny ones like “Intergalactic coffee”! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Presence events:&lt;/strong&gt; The code subscribes to various presence-related events, which play a crucial role in maintaining an up-to-date representation of participant activity. These events include: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;presence.leave&lt;/code&gt;: Triggered when a participant goes offline, causing their representation to become semi-transparent on the dashboard.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;presence.joined-room&lt;/code&gt;: &lt;code&gt;presence.joined-room&lt;/code&gt;: Fired when a participant comes online. For new participants, a new cell would enter the screen. For returning participants, it would restore the brightness of their existing cell. This effect allows participants and organizers to easily spot who is currently active in the event.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This real-time updating creates a dynamic, engaging experience for all participants, showcasing the power and versatility of the Realtime library in handling multiple simultaneous events and updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hackathon AI meets Realtime
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qrpcx2x1o2zv0c1zctc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qrpcx2x1o2zv0c1zctc.jpg" alt="Hackathon" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We recently hosted an Super Hackathon 2.0, with the challenge: AI meets Realtime challenge, pushing the boundaries of innovation by combining artificial intelligence with real-time communication technologies. &lt;/p&gt;

&lt;p&gt;Participants were given the freedom to create anything they could imagine, much like our Super! (But we couldn’t participate of our own hackathon with this project 😢)&lt;/p&gt;

&lt;p&gt;The hackathon saw an impressive projects that leveraged our Realtime library alongside various AI technologies. The creativity and innovation displayed by the participants were truly remarkable. If you're curious about the winning projects and want to explore how they combined AI with real-time capabilities, we invite you to &lt;a href="https://superviz.com/announcing-the-winners-of-super-hackathon-2-0-celebrating-innovation-and-creativity" rel="noopener noreferrer"&gt;read our detailed blog post about the hackathon winners&lt;/a&gt;. It's a great source of inspiration and showcases the potential of our Realtime library when paired with AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  After many request, it’s open source
&lt;/h2&gt;

&lt;p&gt;The overwhelming enthusiasm for our game didn't end with the events. Participants were eager to continue playing, explore without limitations, people were legitimately addicted to the gameplay. We heard your requests loud and clear! &lt;/p&gt;

&lt;p&gt;Now that our &lt;a href="https://docs.superviz.com/realtime/getting-started/quickstart" rel="noopener noreferrer"&gt;new Realtime library&lt;/a&gt; is officially released, we're excited to announce that we're making the code for this project open source! This allows you to not only continue playing but also gain a better understanding of how everything works behind the scenes.&lt;/p&gt;

&lt;p&gt;You can find the &lt;a href="https://github.com/SuperViz/sv-activiation-app" rel="noopener noreferrer"&gt;repository on our GitHub page&lt;/a&gt;. We encourage you to clone it, experiment with it, and maybe even contribute your own improvements or variations. &lt;/p&gt;

&lt;p&gt;Happy coding and crafting!&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>openai</category>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>SuperViz Hackathon 2.0: AI meets RealTime</title>
      <dc:creator>Vitor Norton</dc:creator>
      <pubDate>Wed, 02 Oct 2024 17:39:02 +0000</pubDate>
      <link>https://dev.to/superviz/superviz-hackathon-ai-meets-realtime-bci</link>
      <guid>https://dev.to/superviz/superviz-hackathon-ai-meets-realtime-bci</guid>
      <description>&lt;p&gt;A couple of months after &lt;a href="https://superviz.com/super-hackathon-celebrating-innovation-and-announcing-our-winner" rel="noopener noreferrer"&gt;our first hackathon&lt;/a&gt;, we are ready to announce: The Super Hackathon 2.0!&lt;/p&gt;

&lt;p&gt;Get ready to participate in our Super Hackathon 2.0 this October to showcase your innovative real-time AI communication solutions! Hosted by &lt;a href="https://superviz.com/" rel="noopener noreferrer"&gt;SuperViz&lt;/a&gt;, this exciting hackathon is the perfect opportunity for developers to unleash their creativity and push the boundaries of using AI with real-time technology.&lt;/p&gt;

&lt;p&gt;With $5,000 in prizes up for grabs, we challenge you to integrate AI with SuperViz's real-time platform, pushing the boundaries of interactive communication.&lt;/p&gt;

&lt;p&gt;You can utilize any language model, such as GPT, Gemini, LLaMA, or Claude, to create innovative tools that elevate the real-time experience, making communication smarter and more efficient. How will you combine AI with real-time data to create meaningful improvements in collaboration and productivity?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Event Details:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Date:&lt;/strong&gt;&amp;nbsp;October 18-27, 2024&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prizes:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Fist Place: $3,500&lt;/li&gt;
&lt;li&gt;Second Place: $1,000&lt;/li&gt;
&lt;li&gt;Third Place: $500&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform:&lt;/strong&gt;&amp;nbsp;Online&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will have workshops, feedback sessions, and make sure you have all the resources you need to create the best solution to compete!&lt;/p&gt;

&lt;p&gt;Ready to join? Visit the &lt;a href="https://hackathon.superviz.com/" rel="noopener noreferrer"&gt;Super Hackathon 2.0 website&lt;/a&gt; to register and stay updated. Let's create something amazing!&lt;/p&gt;

</description>
      <category>watercooler</category>
      <category>hackathon</category>
      <category>coding</category>
    </item>
    <item>
      <title>How to implement real-time mouse pointers into a web-application using SuperViz React SDK</title>
      <dc:creator>Vitor Norton</dc:creator>
      <pubDate>Wed, 28 Aug 2024 16:23:49 +0000</pubDate>
      <link>https://dev.to/superviz/how-to-implement-real-time-mouse-pointers-into-a-web-application-using-superviz-react-sdk-46kc</link>
      <guid>https://dev.to/superviz/how-to-implement-real-time-mouse-pointers-into-a-web-application-using-superviz-react-sdk-46kc</guid>
      <description>&lt;p&gt;In this tutorial, we will guide you through adding &lt;a href="https://docs.superviz.com/react-sdk/presence/mouse-pointers" rel="noopener noreferrer"&gt;real-time mouse pointers&lt;/a&gt; to a web application using the SuperViz React SDK. Real-time mouse pointers are essential for collaborative applications, allowing users to see each other's cursor movements and interactions on a shared screen. This feature enhances communication and collaboration, making it easier for participants to follow along with each other's actions.&lt;/p&gt;

&lt;p&gt;We'll demonstrate how to use SuperViz to implement real-time mouse pointers in a React application. Although we’ll use a &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element for rendering shared content, the real-time mouse pointers component is versatile and can be used with other HTML elements as well. This flexibility allows developers to integrate real-time pointers in a variety of web application contexts, providing a dynamic and interactive experience similar to collaborative platforms like Google Docs or Figma. Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;p&gt;To follow this tutorial, you will need a SuperViz account and a developer token. If you already have an account and a developer token, you can move on to the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create an Account
&lt;/h3&gt;

&lt;p&gt;To create an account, go to &lt;a href="https://dashboard.superviz.com/register" rel="noopener noreferrer"&gt;https://dashboard.superviz.com/register&lt;/a&gt; and sign up using either Google or an email/password. Note that if you choose email/password, you will receive a confirmation link that you'll need to click to verify your account.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieving a Developer Token
&lt;/h3&gt;

&lt;p&gt;To use the SDK, you’ll need a developer token, which is essential for associating SDK requests with your account. You can retrieve both development and production SuperViz tokens from the &lt;a href="https://dashboard.superviz.com/developer/keys" rel="noopener noreferrer"&gt;the dashboard&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Copy and save the developer token, as you will need it in the next steps of this tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Set Up Your React Application
&lt;/h2&gt;

&lt;p&gt;To begin, you'll need to set up a new React project where we will integrate the SuperViz SDK for real-time mouse pointers.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create a New React Project
&lt;/h3&gt;

&lt;p&gt;First, create a new React application using Create React App with TypeScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm create vite@latest mouse-pointers-demo -- --template react-ts
cd mouse-pointers-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Install SuperViz SDK
&lt;/h3&gt;

&lt;p&gt;Next, install SuperViz, which will enable us to add real-time mouse pointer features to our application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @superviz/react-sdk uuid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;@superviz/react-sdk:&lt;/strong&gt; SDK for integrating real-time collaboration features, including mouse pointers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;uuid:&lt;/strong&gt; A library for generating unique identifiers, useful for creating unique participant IDs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Configure Tailwind
&lt;/h3&gt;

&lt;p&gt;In this tutorial, we'll use the &lt;a href="https://tailwindcss.com" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt; framework. First, install the Tailwind package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then need to configure the template path. Open &lt;code&gt;tailwind.config.js&lt;/code&gt; in the root of the project and insert the following code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we need to add the tailwind directives to the global CSS file the &lt;code&gt;src/index.css&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@tailwind base;
@tailwind components;
@tailwind utilities;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Set Up Environment Variables
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file in your project root and add your SuperViz developer key. This key will be used to authenticate your application with SuperViz services.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VITE_SUPERVIZ_API_KEY=YOUR_SUPERVIZ_DEVELOPER_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Implement the Main Application
&lt;/h2&gt;

&lt;p&gt;In this step, we'll implement the main application logic to initialize SuperViz and handle real-time mouse pointers.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Implement the App Component
&lt;/h3&gt;

&lt;p&gt;Open &lt;code&gt;src/App.tsx&lt;/code&gt; and set up the main application component using the &lt;code&gt;SuperVizRoomProvider&lt;/code&gt; to manage the collaborative environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { SuperVizRoomProvider } from '@superviz/react-sdk'
import { v4 as generateId } from 'uuid'
import Room from './Room'

const developerKey = import.meta.env.VITE_SUPERVIZ_API_KEY;
const participantId = generateId()

export default function App() {
  return (
    &amp;lt;SuperVizRoomProvider
      developerKey={developerKey}
      group={{
        id: 'realtime-mouse-pointers',
        name: 'realtime-mouse-pointers',
      }}
      participant={{
        id: participantId,
        name: 'Participant',
      }}
      roomId='realtime-mouse-pointers'
    &amp;gt;
      &amp;lt;Room /&amp;gt;
    &amp;lt;/SuperVizRoomProvider&amp;gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SuperVizRoomProvider:&lt;/strong&gt; This component wraps the application to enable real-time features and provides configuration for group and participant details.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;developerKey:&lt;/strong&gt; Retrieves the developer key from environment variables to authenticate with SuperViz.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;participantId:&lt;/strong&gt; Generates a unique ID for each participant using the &lt;code&gt;uuid&lt;/code&gt; library.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Room Component:&lt;/strong&gt; Contains the logic for rendering the canvas and handling mouse pointers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Implement the Room Component
&lt;/h3&gt;

&lt;p&gt;Create a new file named &lt;code&gt;src/Room.tsx&lt;/code&gt; and add the following implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { MousePointers } from "@superviz/react-sdk";

export default function Room() {
  return (
    &amp;lt;div className='w-full h-full bg-gray-200 flex items-center justify-center flex-col'&amp;gt;
      &amp;lt;header className='w-full p-5 bg-purple-400 flex items-center justify-between'&amp;gt;
        &amp;lt;h2 className='text-white text-2xl font-bold'&amp;gt;SuperViz Real-Time Mouse Pointers&amp;lt;/h2&amp;gt;
      &amp;lt;/header&amp;gt;
      &amp;lt;main className='flex-1 w-full h-full'&amp;gt;
        &amp;lt;div className='w-full h-full'&amp;gt;
          &amp;lt;canvas id="canvas" className='w-full h-full'&amp;gt;&amp;lt;/canvas&amp;gt;
        &amp;lt;/div&amp;gt;

        &amp;lt;MousePointers elementId="canvas" /&amp;gt;
      &amp;lt;/main&amp;gt;
    &amp;lt;/div&amp;gt;
  )
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MousePointers Component:&lt;/strong&gt; Displays the real-time location of each participant's mouse cursor on the canvas, allowing users to see where others are interacting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;elementId:&lt;/strong&gt; Specifies the ID of the element (canvas) where the mouse pointers will be shown. The component can also be used with other HTML elements such as &lt;code&gt;div&lt;/code&gt; or &lt;code&gt;svg&lt;/code&gt;, offering flexibility in its application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Canvas Element:&lt;/strong&gt; A &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element is used to render the shared content, with an ID that matches the &lt;code&gt;elementId&lt;/code&gt; specified in &lt;code&gt;MousePointers&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3: Understanding the Project Structure
&lt;/h2&gt;

&lt;p&gt;Here's a quick overview of how the project structure supports real-time mouse pointers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;App.tsx&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initializes the SuperViz environment.&lt;/li&gt;
&lt;li&gt;Sets up participant information and room details.&lt;/li&gt;
&lt;li&gt;Renders the &lt;code&gt;Room&lt;/code&gt; component within the &lt;code&gt;SuperVizRoomProvider&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;Room.tsx&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contains the main UI elements, including the canvas.&lt;/li&gt;
&lt;li&gt;Integrates the &lt;code&gt;MousePointers&lt;/code&gt; component to show real-time cursor movements.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 4: Running the Application
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Start the React Application
&lt;/h3&gt;

&lt;p&gt;To run your application, use the following command in your project directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will start the development server and open your application in the default web browser. You can interact with the canvas and see mouse pointers in real-time as other participants join the session.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Test the Application
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real-Time Mouse Pointers:&lt;/strong&gt; Open the application in multiple browser windows or tabs to simulate multiple participants and verify that mouse movements are displayed in real-time for all users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaborative Interaction:&lt;/strong&gt; Test the responsiveness of the application by moving the mouse around the canvas and observing the pointers of other participants.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we implemented real-time mouse pointers in a web application using SuperViz and React. We configured a React application to display mouse pointers for all participants, enabling seamless collaboration and interaction. This setup can be extended and customized to fit various scenarios where real-time collaboration and visual feedback are required.&lt;/p&gt;

&lt;p&gt;Feel free to explore the full code and further examples in the &lt;a href="https://github.com/SuperViz/tutorials/tree/main/mouse-pointers" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; for more details.&lt;/p&gt;

</description>
      <category>react</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to integrate Contextual Comments into Matterport SDK</title>
      <dc:creator>Vitor Norton</dc:creator>
      <pubDate>Mon, 19 Aug 2024 15:12:36 +0000</pubDate>
      <link>https://dev.to/superviz/how-to-integrate-contextual-comments-into-matterport-sdk-3jmn</link>
      <guid>https://dev.to/superviz/how-to-integrate-contextual-comments-into-matterport-sdk-3jmn</guid>
      <description>&lt;p&gt;In this tutorial, we will guide you through adding contextual comments to a &lt;a href="https://support.matterport.com/s/article/API-SDK-Developer-Tools-Overview?language=en_US" rel="noopener noreferrer"&gt;Matterport SDK&lt;/a&gt; application using SuperViz. Contextual comments enable users to leave feedback directly within a 3D model, making it easier to collaborate on design reviews, walkthroughs, and virtual tours. This feature is particularly useful in scenarios where precise feedback within a spatial context is critical.&lt;/p&gt;

&lt;p&gt;We'll demonstrate how to integrate SuperViz with &lt;a href="https://matterport.com/" rel="noopener noreferrer"&gt;Matterport&lt;/a&gt;, allowing participants to add and view comments within the 3D environment in real-time. By the end of this tutorial, you'll have a fully functional Matterport application with a robust commenting system that enhances collaboration and communication.&lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;p&gt;To follow this tutorial, you will need a SuperViz account and a developer token. If you already have an account and a developer token, you can move on to the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create an Account
&lt;/h3&gt;

&lt;p&gt;To create an account, go to &lt;a href="https://dashboard.superviz.com/register" rel="noopener noreferrer"&gt;https://dashboard.superviz.com/register&lt;/a&gt; and sign up using either Google or an email/password. Note that if you choose email/password, you will receive a confirmation link that you'll need to click to verify your account.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieving a Developer Token
&lt;/h3&gt;

&lt;p&gt;To use the SDK, you’ll need a developer token, which is essential for associating SDK requests with your account. You can retrieve both development and production SuperViz tokens from the &lt;a href="https://dashboard.superviz.com/developer/keys" rel="noopener noreferrer"&gt;the dashboard&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Copy and save the developer token, as you will need it in the next steps of this tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Set Up Your React Application
&lt;/h2&gt;

&lt;p&gt;To begin, you'll need to set up a new React project where we will integrate SuperViz and the Matterport SDK.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create a New React Project
&lt;/h3&gt;

&lt;p&gt;First, create a new React application using Create React App with TypeScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create vite@latest matterport-comments &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; react-ts
&lt;span class="nb"&gt;cd &lt;/span&gt;matterport-comments
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Install Required Libraries
&lt;/h3&gt;

&lt;p&gt;Next, install the necessary libraries for our project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @superviz/sdk @superviz/matterport-plugin uuid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;@superviz/sdk:&lt;/strong&gt; For integrating real-time collaboration features, including comments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@superviz/matterport-plugin:&lt;/strong&gt; Plugin for adding SuperViz interaction features to a Matterport Viewer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;uuid:&lt;/strong&gt; A library for generating unique identifiers, useful for creating unique participant IDs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Set Up Environment Variables
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file in your project root and add your SuperViz developer key and Matterport application key. These credentials will be used to authenticate your application with SuperViz and Matterport services.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VITE_SUPERVIZ_API_KEY=YOUR_SUPERVIZ_DEVELOPER_KEY
VITE_MATTERPORT_KEY=YOUR_MATTERPORT_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Implement the Main Application
&lt;/h2&gt;

&lt;p&gt;In this step, we'll implement the main application logic to initialize SuperViz and the Matterport Viewer, and handle real-time contextual comments.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Implement the App Component
&lt;/h3&gt;

&lt;p&gt;Open &lt;code&gt;src/App.tsx&lt;/code&gt; and set up the main application component using SuperViz to manage the collaborative environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { v4 as generateId } from 'uuid';
import { useCallback, useEffect, useRef } from "react";
import SuperVizRoom, { Comments } from '@superviz/sdk';
import { MatterportPin } from '@superviz/matterport-plugin';
import type { MpSdk } from '@superviz/matterport-plugin/dist/common/types/matterport.types.d.ts';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Imports:&lt;/strong&gt; Import necessary components from React, SuperViz, Matterport Plugin, and UUID for managing state, initializing SuperViz, and enabling contextual comments within the Matterport SDK.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Define Constants
&lt;/h3&gt;

&lt;p&gt;Define constants for the API key, Matterport key, and room ID.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const apiKey = import.meta.env.VITE_SUPERVIZ_API_KEY as string;
const matterportKey = import.meta.env.VITE_MATTERPORT_KEY as string;

const ROOM_ID = 'matterport-comments';
const PLAYER_ID = generateId();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;apiKey &amp;amp; matterportKey:&lt;/strong&gt; Retrieves the SuperViz and Matterport API keys from environment variables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ROOM_ID &amp;amp; PLAYER_ID:&lt;/strong&gt; Defines the room ID for the SuperViz session and generates a unique player ID.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Create the App Component
&lt;/h3&gt;

&lt;p&gt;Set up the main &lt;code&gt;App&lt;/code&gt; component and initialize references for the Matterport SDK.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default function App() {
  const matterportSDK = useRef&amp;lt;MpSdk | null&amp;gt;(null);

  useEffect(() =&amp;gt; {
    initializeMatterport();
  }, []);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;matterportSDK:&lt;/strong&gt; A ref to store the Matterport SDK instance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;useEffect:&lt;/strong&gt; Calls the &lt;code&gt;initializeMatterport&lt;/code&gt; function once when the component mounts, setting up the Matterport Viewer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Initialize SuperViz
&lt;/h3&gt;

&lt;p&gt;Create a function to initialize SuperViz and integrate the contextual commenting system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const initializeSuperViz = useCallback(async () =&amp;gt; {
  const superviz = await SuperVizRoom(apiKey, {
    roomId: ROOM_ID,
    participant: {
      id: PLAYER_ID,
      name: 'player-name',
    },
    group: {
      id: 'matterport-comments',
      name: 'matterport-comments',
    }
  });

  const pinAdapter = new MatterportPin(matterportSDK.current!, document.getElementById('showcase')!);
  const comments = new Comments(pinAdapter, {
    buttonLocation: 'top-right',
  });
  superviz.addComponent(comments);
}, []);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;initializeSuperViz:&lt;/strong&gt; An asynchronous function that initializes SuperViz and adds the contextual comments component to the Matterport Viewer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MatterportPin:&lt;/strong&gt; Adapts the Matterport SDK to work with SuperViz's commenting system, allowing users to pin comments directly in the 3D space.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Initialize Matterport Viewer
&lt;/h3&gt;

&lt;p&gt;Create a function to initialize the Matterport Viewer with the necessary credentials and configurations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const initializeMatterport = useCallback(async () =&amp;gt; {
  const showcase = document.getElementById('showcase') as MatterportIframe;
  const showcaseWindow = showcase.contentWindow as MatterportIframe['window'];
  const source = \`/vendor/matterport/showcase.html?&amp;amp;play=1&amp;amp;qs=1&amp;amp;applicationKey=\${matterportKey}&amp;amp;m=Zh14WDtkjdC\`;
  showcase.setAttribute('src', source);

  await new Promise((resolve) =&amp;gt; {
    showcase.addEventListener('load', async () =&amp;gt; {
      matterportSDK.current = await showcaseWindow?.MP_SDK.connect(showcaseWindow, matterportKey);
      resolve(matterportSDK.current);
    });
  });

  initializeSuperViz();
}, [initializeSuperViz]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;initializeMatterport:&lt;/strong&gt; Loads the Matterport Viewer in an iframe, connects the Matterport SDK, and then initializes SuperViz for real-time collaboration and commenting.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3: Render the Application
&lt;/h2&gt;

&lt;p&gt;Finally, return the JSX structure for rendering the Matterport Viewer and the SuperViz-powered interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return (
  &amp;lt;div className='w-full h-full bg-gray-200 flex items-center justify-center flex-col'&amp;gt;
    &amp;lt;header className='w-full p-5 bg-purple-400 flex items-center justify-between'&amp;gt;
      &amp;lt;h2 className='text-white text-2xl font-bold'&amp;gt;SuperViz Matterport Comments&amp;lt;/h2&amp;gt;
    &amp;lt;/header&amp;gt;
    &amp;lt;main className='w-full h-full flex items-center justify-center relative'&amp;gt;
      &amp;lt;iframe id='showcase' className='w-full h-full' /&amp;gt;
    &amp;lt;/main&amp;gt;
  &amp;lt;/div&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Explanation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Viewer Container:&lt;/strong&gt; The &lt;code&gt;showcase&lt;/code&gt; iframe is where the Matterport Viewer will be rendered, filling the entire screen. This is where users will interact with the 3D space and collaborate in real time with contextual comments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 4: Understanding the Project Structure
&lt;/h2&gt;

&lt;p&gt;Here's a quick overview of how the project structure supports adding contextual comments to a Matterport SDK application:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;App.tsx&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initializes SuperViz.&lt;/li&gt;
&lt;li&gt;Sets up the Matterport Viewer with real-time commenting features.&lt;/li&gt;
&lt;li&gt;Handles the loading of 3D spaces and integration of collaborative tools.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Matterport Viewer&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Renders the 3D space, allowing users to navigate, inspect, and leave comments in a shared virtual environment.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SuperViz Components&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MatterportPin &amp;amp; Comments:&lt;/strong&gt; Enables users to pin comments to specific locations in the 3D model, enhancing collaborative review sessions.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 5: Running the Application
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Start the React Application
&lt;/h3&gt;

&lt;p&gt;To run your application, use the following command in your project directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will start the development server and open your application in the default web browser. You can interact with the 3D space and see real-time comments from other participants.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Test the Application
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Contextual Comments:&lt;/strong&gt; Open the application in multiple browser windows or tabs to simulate multiple participants and verify that comments are updated in real-time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaborative Interaction:&lt;/strong&gt; Test the commenting feature by adding comments to the 3D model and observing how they appear for other participants.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this tutorial, we integrated contextual comments into a Matterport SDK application using SuperViz. We configured a React application to handle 3D space navigation and commenting, enabling multiple users to collaborate seamlessly within a shared virtual environment. This setup can be extended and customized to fit various scenarios where real-time collaboration on 3D spaces is required.&lt;/p&gt;

&lt;p&gt;Feel free to explore the full code and further examples in the &lt;a href="https://github.com/SuperViz/tutorials/tree/main/matterport-comments" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; for more details.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What is channels and the benefits of using it when working with events</title>
      <dc:creator>Vitor Norton</dc:creator>
      <pubDate>Thu, 15 Aug 2024 12:15:02 +0000</pubDate>
      <link>https://dev.to/superviz/what-is-channels-and-the-benefits-of-using-it-when-working-with-events-1j8g</link>
      <guid>https://dev.to/superviz/what-is-channels-and-the-benefits-of-using-it-when-working-with-events-1j8g</guid>
      <description>&lt;p&gt;Event handling is a critical aspect of any application development process. It allows applications to respond to user interactions or system occurrences by executing specific sets of code. There are various ways to manage these events, but one effective method is through the use of channels. Within this blog post, I will explore what channels are and the benefits they offer when working with events.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Channels?
&lt;/h2&gt;

&lt;p&gt;Channels are a communication mechanism used in concurrent programming for passing data between different parts of a software system. They are essentially pipelines through which you can send and receive values with the channel operator.&lt;/p&gt;

&lt;p&gt;Channels provide a way for different routines, threads, or processes to communicate and synchronize. The major concept is that data can flow from one end of the channel to another, enabling different parts of a system to communicate seamlessly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Multiple Channels?
&lt;/h2&gt;

&lt;p&gt;While it's possible to use just one channel in your application, there are several reasons for using multiple channels.&lt;/p&gt;

&lt;p&gt;One of the main reasons is to keep your application organized and maintainable. Each channel can be dedicated to a specific type of event or interaction, making it easier to manage and debug the application. For example, one channel could handle user interface events, another could handle a chat application, and so on. This separation of concerns makes your application more modular and easier to understand.&lt;/p&gt;

&lt;p&gt;Another reason to use multiple channels is to increase the efficiency of your application. Different channels can be processed in parallel, which can lead to performance improvements, especially in multi-core or multi-threaded environments. In contrast, if all events are sent through a single channel, they would have to be processed one after another, which could lead to bottlenecks and reduce the responsiveness of your application.&lt;/p&gt;

&lt;p&gt;Lastly, using multiple channels can help prevent data loss. If a single channel is overwhelmed with too many events, it may start dropping events or crash altogether. By spreading the load across multiple channels, you can help ensure that all events are processed successfully.&lt;/p&gt;

&lt;p&gt;However, it's important to note that using multiple channels also comes with its own challenges, such as coordinating between different channels and managing concurrency issues. Therefore, it's crucial to design your application carefully and choose the right number of channels based on your specific needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  What It Looks Like
&lt;/h3&gt;

&lt;p&gt;The code snippet provided below showcases an example of how channels can be used in a real-life setting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Realtime&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@superviz/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;realtime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Realtime&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;uxChannel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;realtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;chatChannel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;realtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;buttonClicked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#buttonId&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;uxChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;handle.click&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;buttonClicked&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Olá mundo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;chatChannel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;handle.newMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;connection&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this scenario, two separate channels are created for handling different types of events - one for User Experience (UX) events and another for chat events. These events are then published to their respective channels, demonstrating how tasks can be effectively segregated and managed using multiple channels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Channels and SuperViz
&lt;/h2&gt;

&lt;p&gt;We recently introduced the &lt;a href="https://docs.superviz.com/sdk/realtime/channel" rel="noopener noreferrer"&gt;multi-channel feature&lt;/a&gt; to our &lt;a href="https://docs.superviz.com/sdk/presence/real-time-data-engine" rel="noopener noreferrer"&gt;Real-Time Data Engine&lt;/a&gt;. It has significantly improved how we handle events on our &lt;a href="http://superviz.com/" rel="noopener noreferrer"&gt;SuperViz&lt;/a&gt; platform.&lt;/p&gt;

&lt;p&gt;Now, it is possible to dedicate different channels for different types of events, increasing the efficiency and organization of your application. In addition, the ability to process channels in parallel allows for better performance, especially in multi-core or multi-threaded environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Super Hackathon Invitation - Win $5.000
&lt;/h2&gt;

&lt;p&gt;So, while you are here, let me invite you to participate in our upcoming &lt;a href="https://hackathon.superviz.com/" rel="noopener noreferrer"&gt;Super Hackathon this August&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;From Aug 9-31, you'll be challenge to transform your virtual interactions with &lt;a href="https://superviz.com/" rel="noopener noreferrer"&gt;SuperViz&lt;/a&gt;’s real-time communication and data synchronization platform and a chance to win a prize of $5,000.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hackathon.superviz.com/" rel="noopener noreferrer"&gt;Register now&lt;/a&gt; to receive updates, tips and resources and get ready to hack!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>architecture</category>
      <category>designpatterns</category>
      <category>backend</category>
    </item>
    <item>
      <title>Top design patterns for frontend</title>
      <dc:creator>Vitor Norton</dc:creator>
      <pubDate>Thu, 08 Aug 2024 12:31:07 +0000</pubDate>
      <link>https://dev.to/superviz/top-design-patterns-for-frontend-1bk5</link>
      <guid>https://dev.to/superviz/top-design-patterns-for-frontend-1bk5</guid>
      <description>&lt;p&gt;Over the past couple of month, I have shared some trending design patterns for frontend developers. These include patterns like Singleton, Facade, Observer, Publisher/Subscriber and more. Today, I want to summarize some of the key points and benefits of these patterns and how they can be used to improve your frontend development process.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Design Patterns
&lt;/h2&gt;

&lt;p&gt;Design patterns are reusable solutions to common problems that occur in software design. They represent the best practices used by experienced object-oriented software developers. These patterns can speed up the development process by providing a proven way of resolving frequent issues.&lt;/p&gt;

&lt;h1&gt;
  
  
  Top Design Patterns
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;1. Singleton Pattern&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Singleton Pattern is a type of design pattern that restricts the creation of a class to only one instance. This is useful in scenarios where a single point of control or coordination is required. In other words, it ensures that a class has only one instance and provides a global point of access to it.&lt;/p&gt;

&lt;p&gt;A real use of the Singleton Pattern is managing a configuration settings object in a large-scale application, like a web app. This ensures only one instance of the configuration object (holding settings like database strings and API keys) exists, providing a single access point and preventing conflicts.&lt;/p&gt;

&lt;p&gt;Learn more about the &lt;a href="https://dev.to/superviz/design-pattern-1-singleton-for-frontend-developers-14p9"&gt;Singleton Pattern&lt;/a&gt; and how to code it&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;2. Facade Pattern&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Facade Pattern provides a simplified interface to a larger body of code. It makes a software library easier to read and understand, and wraps a poorly designed collection of APIs with a single well-designed API.&lt;/p&gt;

&lt;p&gt;In a complex e-commerce platform, the Facade Pattern unifies multiple third-party services for payment, shipping, and inventory into a single interface. This simplifies interactions, making tasks like order placement easier, and keeps the main application code cleaner and more understandable.&lt;/p&gt;

&lt;p&gt;Learn more about the &lt;a href="https://dev.to/superviz/design-pattern-2-facade-pattern-1dhl"&gt;Facade Pattern&lt;/a&gt; and how to code it&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;3. Observer Pattern&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Observer Pattern allows an object (known as the subject) to notify other objects (known as observers) when its state changes. This is useful in scenarios where a change to one object requires changing others, and where the actual set of objects is expected to change dynamically.&lt;/p&gt;

&lt;p&gt;Learn more about the &lt;a href="https://dev.to/superviz/design-pattern-3-observer-pattern-36eo"&gt;Observer Pattern&lt;/a&gt; and how to code it&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;3. Publisher/Subscriber Pattern&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Publisher/Subscriber Pattern is a messaging pattern where senders of messages, known as publishers, don't program the messages to be sent directly to specific receivers, called subscribers. Instead, published messages are categorized into classes without the publishers knowing the subscribers' identities. It's an effective way to handle event-driven programming.&lt;/p&gt;

&lt;p&gt;In the Publisher/Subscriber pattern, publishers don't communicate directly with subscribers. Instead, these messages are classified and sent to subscribers by the message bus. This can provide more flexibility and scalability in complex systems. To dive deeper into the difference between PubSub and Observer patterns and their differences, check out this detailed article.&lt;/p&gt;

&lt;p&gt;Learn more about the &lt;a href="https://dev.to/superviz/design-pattern-4-publishersubscriber-pattern-4jg9"&gt;Publisher/Subscriber ****Pattern&lt;/a&gt; and how to code it&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-time Data Engine
&lt;/h3&gt;

&lt;p&gt;Architecting software to sync data between different instances can be challenging, but not the core business focus. The solution is the &lt;a href="https://docs.superviz.com/sdk/presence/real-time-data-engine" rel="noopener noreferrer"&gt;Real-time Data Engine&lt;/a&gt; tools, specifically &lt;a href="https://superviz.com/" rel="noopener noreferrer"&gt;SuperViz&lt;/a&gt;. It provides real-time collaboration and communication for web apps. SuperViz allows an easy-to-integrate tool for developers for the creation of a room where an event published by one participant is broadcast to all others across different devices and networks, ensuring real-time updates and a seamless experience.&lt;/p&gt;

&lt;p&gt;SuperViz provides the infrastructure necessary to build real-time, collaborative applications. This includes the ability to also catch these events on your backend using webhooks, and as well to publish an event with a simple HTTP request, to name a few features.&lt;/p&gt;

&lt;p&gt;Learn more about &lt;a href="https://dev.to/superviz/understanding-and-implementing-event-driven-communication-in-front-end-development-e75"&gt;Real-time Data Engine and how to use it&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;5. Adapter Pattern&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Adapter Pattern allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others without modifying their source code, which can be particularly useful when they are from different libraries or frameworks.&lt;/p&gt;

&lt;p&gt;A real case scenario of the Adapter Pattern can be seen in integrating legacy systems with modern applications. For instance, suppose you have an old payment processing system with a proprietary API that doesn't conform to the modern RESTful API standards used by your new e-commerce platform. By using an Adapter, you can create a wrapper that translates the requests and responses between the old system and the new platform, allowing seamless communication without altering the legacy system's code.&lt;/p&gt;

&lt;p&gt;Learn more about the &lt;a href="https://dev.to/superviz/design-pattern-5-adapter-pattern-4gif"&gt;Adapter Pattern&lt;/a&gt; and how to code it&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Composite Pattern
&lt;/h2&gt;

&lt;p&gt;The Composite Pattern allows you to compose objects into tree structures to represent part-whole hierarchies. It lets clients treat individual objects and compositions of objects uniformly, making it easier to work with complex structures or recursive algorithms.&lt;/p&gt;

&lt;p&gt;The Composite Pattern is useful for developing a restaurant's ordering app menu system. A menu can include individual items like "Burger" or composite items like "Combo Meal" (burger and fries). This pattern allows the app to uniformly handle operations like displaying the menu, calculating prices, or applying discounts on both single items and combos, simplifying management and expansion as new items or combos are added.&lt;/p&gt;

&lt;p&gt;Learn more about the &lt;a href="https://dev.to/superviz/design-pattern-6-composite-pattern-2k1l"&gt;Composite Pattern&lt;/a&gt; and how to code it&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Builder Pattern
&lt;/h2&gt;

&lt;p&gt;The Builder Pattern allows for the step-by-step construction of complex objects. It separates the construction of a complex object from its representation, enabling the same construction process to create different representations. This pattern is particularly useful when building objects with many optional parameters or when the creation process involves several steps.&lt;/p&gt;

&lt;p&gt;A real case scenario for the Builder Pattern can be seen in the construction of a complex user interface component, such as a customizable dashboard. By using the Builder Pattern, developers can create a dashboard with various optional widgets like graphs, charts, and tables, each configured with specific parameters such as data sources, styles, and update intervals. This pattern allows developers to assemble the dashboard step-by-step, ensuring that each component is properly configured before the final dashboard is created, providing flexibility and control over the customization process.&lt;/p&gt;

&lt;p&gt;Learn more about the &lt;a href="https://dev.to/superviz/design-pattern-7-builder-pattern-10j4"&gt;Builder Pattern&lt;/a&gt; and how to code it&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Using design patterns can enhance frontend development by offering organized solutions to common challenges, making your code easier to maintain and scale. Patterns like Singleton, Facade, Observer, Publisher/Subscriber, Adapter, Composite, and Builder ensure a strong, flexible application architecture. Experiment with these patterns to find the best fit for your workflow and project needs.&lt;/p&gt;

&lt;p&gt;If you have any questions feel free to drop a comment below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Super Hackathon Invitation - Win $5.000
&lt;/h2&gt;

&lt;p&gt;So, while you are here, let me invite you to participate in our upcoming &lt;a href="https://hackathon.superviz.com/" rel="noopener noreferrer"&gt;Super Hackathon this August&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;From Aug 9-31, you'll be challenge to transform your virtual interactions with &lt;a href="https://superviz.com/" rel="noopener noreferrer"&gt;SuperViz&lt;/a&gt;’s real-time communication and data synchronization platform and a chance to win a prize of $5,000.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hackathon.superviz.com/" rel="noopener noreferrer"&gt;Register now&lt;/a&gt; to receive updates, tips and resources and get ready to hack!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>learning</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Design Pattern #7 - Builder Pattern</title>
      <dc:creator>Vitor Norton</dc:creator>
      <pubDate>Fri, 02 Aug 2024 13:31:08 +0000</pubDate>
      <link>https://dev.to/superviz/design-pattern-7-builder-pattern-10j4</link>
      <guid>https://dev.to/superviz/design-pattern-7-builder-pattern-10j4</guid>
      <description>&lt;p&gt;This article is the last one in our series on design patterns for frontend development. Throughout this series, we've looked at various patterns, like the &lt;a href="https://dev.to/superviz/design-pattern-3-observer-pattern-36eo"&gt;Observer&lt;/a&gt; and &lt;a href="https://dev.to/superviz/design-pattern-4-publishersubscriber-pattern-4jg9"&gt;PubSub pattern&lt;/a&gt;, that help developers write better code. The Builder Pattern, which we will talk about here, is another useful tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Builder Pattern
&lt;/h2&gt;

&lt;p&gt;The Builder Pattern is a creational design pattern that allows developers to construct complex objects step-by-step. It separates the construction of an object from its representation, enabling the same construction process to create different representations. &lt;/p&gt;

&lt;p&gt;In JavaScript, this pattern is particularly useful when dealing with objects that require numerous optional parameters or when the construction process involves several steps. By using the Builder Pattern, developers can create more readable and maintainable code by chaining method calls to set properties and ultimately build the desired object in a controlled manner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real case scenario
&lt;/h2&gt;

&lt;p&gt;Imagine a frontend developer tasked with creating a complex dashboard for a web application. The challenge is to allow users to customize their dashboard with various widgets such as charts, tables, and notifications. Each widget needs different settings such as data sources, display options, and refresh intervals. Managing all these options through a single constructor or multiple setters can become cumbersome and prone to mistakes.&lt;/p&gt;

&lt;p&gt;The Builder Pattern provides an elegant solution by using a &lt;code&gt;DashboardBuilder&lt;/code&gt; class, developers can chain method calls to set properties for each widget, ensuring that all necessary configurations are applied before the dashboard is built. This approach not only makes the code more readable and maintainable but also allows for flexibility in creating different types of dashboards with varying complexities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hands on
&lt;/h2&gt;

&lt;p&gt;The code below exemplifies the discussed scenario. It shows how a frontend developer can use the Builder Pattern to create a this dashboard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DashboardBuilder&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;widgets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;addChart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;widgets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;chartType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;addTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;widgets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;table&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;addNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;widgets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;notification&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Dashboard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Dashboard&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;widgets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;widgets&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;widgets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;widget&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Rendering a &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chartType&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; chart with data:`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;table&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Rendering a table with data:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;notification&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Showing notification:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;widget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unknown widget type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dashboard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DashboardBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addChart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;line&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addTable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Age&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="na"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Bob&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Welcome to your dashboard!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;dashboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code demonstrates the implementation of the Builder Pattern for creating a customizable dashboard. Here's a breakdown of the main components:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. &lt;code&gt;DashboardBuilder&lt;/code&gt; class:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manages the construction of the dashboard&lt;/li&gt;
&lt;li&gt;Has methods to add different types of widgets (charts, tables, notifications)&lt;/li&gt;
&lt;li&gt;Each method returns &lt;code&gt;this&lt;/code&gt; to allow method chaining&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;build()&lt;/code&gt; method creates and returns a new Dashboard instance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Dashboard class:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Represents the final product&lt;/li&gt;
&lt;li&gt;Takes a &lt;code&gt;DashboardBuilder&lt;/code&gt; instance in its constructor&lt;/li&gt;
&lt;li&gt;Has a &lt;code&gt;render()&lt;/code&gt; method to display the widgets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Usage example:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates a new dashboard with a line chart, a table, and a notification&lt;/li&gt;
&lt;li&gt;Uses method chaining to add widgets in a readable manner&lt;/li&gt;
&lt;li&gt;Calls &lt;code&gt;build()&lt;/code&gt; to create the Dashboard instance&lt;/li&gt;
&lt;li&gt;Finally, calls &lt;code&gt;render()&lt;/code&gt; to display the dashboard&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This pattern allows for flexible and readable creation of complex dashboard objects with various widgets and configurations.&lt;/p&gt;

&lt;p&gt;Overall, the Builder Pattern is a powerful tool in software development, especially when dealing with complex object creation scenarios. It promotes cleaner code, reduces the likelihood of errors, and enhances the maintainability of the codebase.&lt;/p&gt;

&lt;p&gt;If you have any questions feel free to drop a comment below. Also, make sure to check out the other articles in our frontend design patterns series!&lt;/p&gt;

&lt;h3&gt;
  
  
  Super Hackathon Invitation - Win $5.000
&lt;/h3&gt;

&lt;p&gt;So, while you are here, let me invite you to participate in our upcoming &lt;a href="https://hackathon.superviz.com/" rel="noopener noreferrer"&gt;Super Hackathon this August&lt;/a&gt;! &lt;/p&gt;

&lt;p&gt;From Aug 9-31, you'll be challenge to transform your virtual interactions with &lt;a href="https://superviz.com" rel="noopener noreferrer"&gt;SuperViz&lt;/a&gt;’s real-time communication and data synchronization platform and a chance to win a prize of $5,000. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://hackathon.superviz.com/" rel="noopener noreferrer"&gt;Register now&lt;/a&gt; to receive updates, tips and resources and get ready to hack!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>architecture</category>
      <category>learning</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Design Pattern #6 - Composite Pattern</title>
      <dc:creator>Vitor Norton</dc:creator>
      <pubDate>Thu, 25 Jul 2024 13:09:17 +0000</pubDate>
      <link>https://dev.to/superviz/design-pattern-6-composite-pattern-2k1l</link>
      <guid>https://dev.to/superviz/design-pattern-6-composite-pattern-2k1l</guid>
      <description>&lt;p&gt;In today’s article, which is part of our series about frontend design patterns, I will explain the Composite Pattern, explore real-world examples, and provide a hands-on JavaScript implementation. Let's dive in!&lt;/p&gt;

&lt;p&gt;Composite Pattern is a structural design pattern that organizes objects into tree structures for representing whole-part hierarchies. It helps you handle individual objects and groups of objects in the same way. This pattern is handy for working with tree-like structures, like user interfaces or organizational hierarchies.&lt;/p&gt;

&lt;p&gt;In JavaScript, the Composite Pattern can be implemented by creating a base component class that defines the common interface for both simple and composite objects. “Leaf” objects represent the end objects in the composition, while composite objects can contain other leaf or composite objects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real case scenario
&lt;/h2&gt;

&lt;p&gt;A common challenge developers face is managing a complex UI with nested elements, such as menus with submenus or file systems with directories and files. Without a structured approach, the code can become difficult to manage and extend, leading to potential bugs and inefficiencies.&lt;/p&gt;

&lt;p&gt;This is where the Composite Pattern comes into play. By treating individual UI elements and groups of elements uniformly, developers can simplify the management of nested components. For instance, consider a menu system where we have two types of components: &lt;code&gt;MenuItem&lt;/code&gt; and &lt;code&gt;Menu&lt;/code&gt;. &lt;code&gt;MenuItem&lt;/code&gt; represents a single menu item, while &lt;code&gt;Menu&lt;/code&gt; can contain multiple &lt;code&gt;MenuItem&lt;/code&gt; objects and other &lt;code&gt;Menu&lt;/code&gt; objects. Both &lt;code&gt;MenuItem&lt;/code&gt; and &lt;code&gt;Menu&lt;/code&gt; implement a common interface, allowing the main menu to treat them uniformly. This pattern not only makes the code more manageable but also enhances its extensibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hands-on
&lt;/h2&gt;

&lt;p&gt;To better understand the Composite Pattern, let's implement a simple example using JavaScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Component interface&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MenuComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nf"&gt;getChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Leaf object&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MenuItem&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;MenuComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Composite object&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Menu&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;MenuComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;child&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;getChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Client code&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mainMenu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Main Menu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;menuItem1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MenuItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Item 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;menuItem2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MenuItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Item 2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subMenu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Menu&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sub Menu&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subMenuItem1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MenuItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sub Item 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;mainMenu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;menuItem1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;mainMenu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;menuItem2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;mainMenu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subMenu&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;subMenu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subMenuItem1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Display the menu structure&lt;/span&gt;
&lt;span class="nx"&gt;mainMenu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;display&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down the code:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MenuComponent:&lt;/strong&gt; This is the base class, serving as an interface for both leaf and composite objects. It defines the common methods like &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;remove&lt;/code&gt;, &lt;code&gt;getChild&lt;/code&gt;, and &lt;code&gt;display&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MenuItem:&lt;/strong&gt; This class represents the leaf objects in the composite pattern. It extends &lt;code&gt;MenuComponent&lt;/code&gt; and implements the &lt;code&gt;display&lt;/code&gt; method to output its name.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Menu:&lt;/strong&gt; This class represents composite objects that can contain children (both &lt;code&gt;MenuItem&lt;/code&gt; and other &lt;code&gt;Menu&lt;/code&gt; objects). It extends &lt;code&gt;MenuComponent&lt;/code&gt; and implements methods to add, remove, retrieve, and display its children.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Client code:&lt;/strong&gt; The example creates a menu structure with a main menu, menu items, and a sub-menu. It then adds items to the main menu and the sub-menu, and finally displays the entire structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By applying the Composite Pattern, you can manage complex UI components efficiently, handle organizational hierarchies, and structure data representations such as file systems. This pattern makes your codebase more maintainable and scalable, particularly in scenarios where you need to treat individual objects and compositions of objects uniformly.&lt;/p&gt;

&lt;p&gt;If you have any questions feel free to drop a comment below. Also, make sure to check out the other articles in our frontend design patterns series!&lt;/p&gt;

&lt;p&gt;Stay tuned for our next post coming next week!&lt;/p&gt;

&lt;h3&gt;
  
  
  Super Invitation - Win $5.000
&lt;/h3&gt;

&lt;p&gt;So, while you are here, let me invite you to participate in our upcoming &lt;a href="https://hackathon.superviz.com/" rel="noopener noreferrer"&gt;Super Hackathon this August&lt;/a&gt;! &lt;/p&gt;

&lt;p&gt;From Aug 9-31, you'll be challenge to transform your virtual interactions with &lt;a href="https://superviz.com" rel="noopener noreferrer"&gt;SuperViz&lt;/a&gt;’s real-time communication and data synchronization platform and a chance to win a prize of $5,000. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://hackathon.superviz.com/" rel="noopener noreferrer"&gt;Register now&lt;/a&gt; to receive updates, tips and resources and get ready to hack!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>architecture</category>
      <category>learning</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Announcing the SuperViz Hackathon</title>
      <dc:creator>Vitor Norton</dc:creator>
      <pubDate>Thu, 18 Jul 2024 14:29:48 +0000</pubDate>
      <link>https://dev.to/superviz/announcing-our-supervizs-hackathon-1gkg</link>
      <guid>https://dev.to/superviz/announcing-our-supervizs-hackathon-1gkg</guid>
      <description>&lt;p&gt;Join the Super Hackathon this August to showcase your innovative real-time communication solutions! Hosted by &lt;a href="https://superviz.com" rel="noopener noreferrer"&gt;SuperViz&lt;/a&gt;, this exciting hackathon is the perfect opportunity for developers to unleash their creativity and push the boundaries of virtual interactions.&lt;/p&gt;

&lt;p&gt;With a $5,000 prize up for grabs, we challenge you to use &lt;a href="https://superviz.com" rel="noopener noreferrer"&gt;SuperViz's advanced SDK&lt;/a&gt; to create applications that boost user engagement and productivity. Whether it's building on an existing platform or developing something entirely new, your project will showcase your innovative ideas in real-time communication!&lt;/p&gt;

&lt;p&gt;Register now, and let's transform the future of virtual interactions together!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Event Details:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Event:&lt;/strong&gt; SuperViz Super Hackathon&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Date:&lt;/strong&gt; August 9-25, 2024&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prize:&lt;/strong&gt; $5,000&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform:&lt;/strong&gt; Online&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ready to join? Visit the &lt;a href="https://hackathon.superviz.com" rel="noopener noreferrer"&gt;Super Hackathon website&lt;/a&gt; to register and stay updated. Let's create something amazing!&lt;/p&gt;

</description>
      <category>coding</category>
      <category>hackathon</category>
      <category>watercooler</category>
    </item>
    <item>
      <title>Design Pattern #5 - Adapter Pattern</title>
      <dc:creator>Vitor Norton</dc:creator>
      <pubDate>Thu, 11 Jul 2024 18:56:16 +0000</pubDate>
      <link>https://dev.to/superviz/design-pattern-5-adapter-pattern-4gif</link>
      <guid>https://dev.to/superviz/design-pattern-5-adapter-pattern-4gif</guid>
      <description>&lt;p&gt;Over the past few weeks, I have shared some of the trending design patterns, like the &lt;a href="https://dev.to/superviz/design-pattern-4-publishersubscriber-pattern-4jg9"&gt;PubSub&lt;/a&gt; and the &lt;a href="https://dev.to/superviz/design-pattern-1-singleton-for-frontend-developers-14p9"&gt;Singleton&lt;/a&gt; ones. Today, I'm going to share one more article of this series, but please comment below and tell me which design pattern I should cover next!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Adapter Pattern
&lt;/h2&gt;

&lt;p&gt;The Adapter Pattern is a structural design pattern that allows objects with incompatible interfaces to collaborate. It's often used when you want to make existing classes work with others without modifying their source code. This pattern is particularly useful when the interface of an existing class does not match the one you need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real Case Scenario
&lt;/h3&gt;

&lt;p&gt;Let's consider a real-life example. You've been tasked to integrate a third-party video player into your application. However, the video player functions differently and has a different method interface than what your application expects. In this case, you could use the Adapter Pattern to create a wrapper class around the video player, making the third-party code compatible with your existing application code.&lt;/p&gt;

&lt;p&gt;Here is the code you'd use in this case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Adapter class&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;VideoPlayerAdapter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;externalPlayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ThirdPartyVideoPlayer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="c1"&gt;// some configuration&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;externalPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getVideo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;externalPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;playVideo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// additional parameters&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Your application code&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Application&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;videoPlayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;VideoPlayerAdapter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Play video using your application code&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;videoPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;play&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break down the code above:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;ThirdPartyVideoPlayer&lt;/code&gt; is a hypothetical external library that your application wants to use. However, its interface might not be compatible with your application.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;VideoPlayerAdapter&lt;/code&gt; is the adapter class. It wraps around &lt;code&gt;ThirdPartyVideoPlayer&lt;/code&gt;. The adapter's interface is compatible with your application. When the adapter's &lt;code&gt;play()&lt;/code&gt; method is called, it internally calls the necessary methods on &lt;code&gt;ThirdPartyVideoPlayer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Application&lt;/code&gt; is your application code. It creates an instance of &lt;code&gt;VideoPlayerAdapter&lt;/code&gt; and uses it as if it were a regular video player. When it calls the &lt;code&gt;play()&lt;/code&gt; method on the adapter, the adapter translates that into the appropriate calls to &lt;code&gt;ThirdPartyVideoPlayer&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This way, the &lt;code&gt;Application&lt;/code&gt; class doesn't need to know anything about how &lt;code&gt;ThirdPartyVideoPlayer&lt;/code&gt; works. If you ever need to replace &lt;code&gt;ThirdPartyVideoPlayer&lt;/code&gt; with a different library, you only need to write a new adapter — the &lt;code&gt;Application&lt;/code&gt; class can stay the same. This is the main benefit of the Adapter pattern: it decouples your application code from the specifics of third-party libraries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Differences Between Adapter Pattern and Facade Pattern
&lt;/h3&gt;

&lt;p&gt;While the Adapter Pattern and the &lt;a href="https://dev.to/superviz/design-pattern-2-facade-pattern-1dhl"&gt;Facade Pattern&lt;/a&gt; might seem similar, they serve different purposes and are used in different contexts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Adapter Pattern&lt;/strong&gt;: The primary purpose of the Adapter Pattern is to make two incompatible interfaces compatible with each other. It allows an existing class with a different interface to be used as if it implemented a different interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Facade Pattern&lt;/strong&gt;: The main purpose of the Facade Pattern is to provide a simplified interface to a complex subsystem. It hides the complexities of the subsystem and provides a higher-level interface that makes the subsystem easier to use.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Usage&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Adapter Pattern&lt;/strong&gt;: It is used when you need to integrate a new class or library that does not match the existing class or interface in your application. The Adapter Pattern is about adapting a particular interface to an expected interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Facade Pattern&lt;/strong&gt;: It is used when you want to simplify interactions with a complex subsystem. The Facade provides a straightforward method for interacting with the system, hiding its complexity.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Adapter Pattern&lt;/strong&gt;: Typically involves creating a new class (the Adapter) that implements the interface expected by the client and translates calls to the adapted class.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Facade Pattern&lt;/strong&gt;: Involves creating a Facade class that provides simplified methods to the client, often aggregating multiple functionalities from the subsystem.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In summary, while both patterns provide a way to work with existing code, the Adapter Pattern focuses on interface compatibility, whereas the Facade Pattern focuses on simplifying the interaction with a complex system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Super Invitation - Win $5.000
&lt;/h3&gt;

&lt;p&gt;So, while you are here, let me invite you to participate in our upcoming &lt;a href="https://hackathon.superviz.com/" rel="noopener noreferrer"&gt;Superthis August&lt;/a&gt;! &lt;/p&gt;

&lt;p&gt;This remote event gives you the chance to showcase your skills and creativity by tackling the challenge to transform your virtual interactions with our real-time communication tools. With SuperViz, you stand a chance to win a prize of $5,000. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://hackathon.superviz.com/" rel="noopener noreferrer"&gt;Register now&lt;/a&gt; to receive updates, tips and resources and get ready to hack!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>architecture</category>
      <category>learning</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Pub/Sub pattern vs Observer Pattern: what's the difference?</title>
      <dc:creator>Vitor Norton</dc:creator>
      <pubDate>Thu, 04 Jul 2024 13:53:12 +0000</pubDate>
      <link>https://dev.to/superviz/pubsub-pattern-vs-observer-pattern-whats-the-difference-10mb</link>
      <guid>https://dev.to/superviz/pubsub-pattern-vs-observer-pattern-whats-the-difference-10mb</guid>
      <description>&lt;p&gt;Over the past few weeks, I've been delving into the trending design patterns in frontend development. I've covered the &lt;a href="https://dev.to/superviz/design-pattern-1-singleton-for-frontend-developers-14p9"&gt;Singleton&lt;/a&gt;, the &lt;a href="https://dev.to/superviz/design-pattern-2-facade-pattern-1dhl"&gt;Facade&lt;/a&gt;, the &lt;a href="https://dev.to/superviz/design-pattern-3-observer-pattern-36eo"&gt;Observer&lt;/a&gt;, and most recently, the &lt;a href="https://dev.to/superviz/design-pattern-4-publishersubscriber-pattern-4jg9"&gt;Pub Sub Pattern Design&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The last two articles focused on the Pub/Sub and Observer patterns. While these two patterns share some conceptual similarities, I thought it would be interesting to explore their differences. Hence, this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Main difference
&lt;/h2&gt;

&lt;p&gt;Both of these patterns have a concept of publishing something and subscribing to an observer, right? So what’s the difference?&lt;/p&gt;

&lt;p&gt;The Observer pattern solves this by allowing the Client to attach itself as an Observer to the Store. When the iPhone arrives, the store notifies all attached Observers. While in the PubSub application, it publishes an event/data to an event broker, and then the subscribers listen for it. The publisher is unaware of its observers.&lt;/p&gt;

&lt;p&gt;In our Client-Store scenario, the event broker of the PubSub application could be like a marketplace. It would need to keep track of product availability in the store. When a new iPhone arrives, the marketplace system would register this event and notify all subscribers (customers who expressed interest in the iPhone) by sending them an email or a push notification.&lt;/p&gt;

&lt;p&gt;Observer patterns are mostly used when you want different parts of a single application to share data with each other, usually in real-time. In this case, the entity providing the data is aware of who is receiving it.&lt;/p&gt;

&lt;p&gt;On the other hand, the Pub-Sub pattern allows data to be shared across multiple applications. This usually happens asynchronously but can be made synchronous using specific SDKs, like the SuperViz Real-time Data Engine. In this pattern, the one sharing the data doesn't know who's receiving it - they just put it out there for anyone interested.&lt;/p&gt;

&lt;p&gt;The main difference is that the Pub-Sub pattern supports a more decoupled architecture, where the data sharers and receivers can work independently from each other. This is not the case in the Observer pattern.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Cases for Observer Patterns
&lt;/h3&gt;

&lt;p&gt;Observer Patterns are often used in GUI development, where one part of the application (the button) needs to notify another part of the application (the click event handler) when a certain event (the button being clicked) occurs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Cases for Publisher Subscriber Pattern
&lt;/h3&gt;

&lt;p&gt;In the context of frontend development, Publisher Subscriber Patterns can be instrumental. For instance, in a complex web application, different components may need to exchange data in real-time, like in a chat application, tracking the GPS of a taxi, or even real-time stock market data updates. These are situations where different components need to stay updated without having a direct relationship with each other.&lt;/p&gt;

&lt;p&gt;Let me know in the comments area if you have other scenarios where the Observer or the PubSub is helpful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-time Data Engine
&lt;/h2&gt;

&lt;p&gt;If you're building a web application that requires real-time data sharing and communication, &lt;a href="http://superviz.com/" rel="noopener noreferrer"&gt;SuperViz&lt;/a&gt; is an SDK tool worth considering. It offers a &lt;a href="https://docs.superviz.com/react-sdk/presence/real-time-data-engine" rel="noopener noreferrer"&gt;real-time collaboration and communication SDK and API&lt;/a&gt;, designed for developers building real-time web applications.&lt;/p&gt;

&lt;p&gt;Using SuperViz, you can create a room with several participants. When publishing an event, it will be broadcasted to all the participants in the room who are accessing it through different devices and networks. This means that any updates made by one participant will be reflected in real time across all devices, providing a seamless and collaborative experience.&lt;/p&gt;

&lt;p&gt;SuperViz provides the infrastructure necessary to build real-time, collaborative applications. This includes the ability to catch these events on your backend using webhooks, as well as to publish an event with a simple HTTP Request, to name a few features.&lt;/p&gt;

&lt;p&gt;You can easily test it with our &lt;a href="https://github.com/SuperViz/samples" rel="noopener noreferrer"&gt;open-source sample codes&lt;/a&gt; that run with a glance.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>learning</category>
      <category>webdev</category>
      <category>coding</category>
    </item>
  </channel>
</rss>
