<?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: WavePlay Staff</title>
    <description>The latest articles on DEV Community by WavePlay Staff (@waveplay-staff).</description>
    <link>https://dev.to/waveplay-staff</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%2F1174683%2F308a8da8-1c55-4d57-848d-78efb857c472.png</url>
      <title>DEV Community: WavePlay Staff</title>
      <link>https://dev.to/waveplay-staff</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/waveplay-staff"/>
    <language>en</language>
    <item>
      <title>Hacktoberfest 2025: Create Discord Features or Videos to Win Rewards 🎉</title>
      <dc:creator>WavePlay Staff</dc:creator>
      <pubDate>Mon, 06 Oct 2025 15:30:00 +0000</pubDate>
      <link>https://dev.to/waveplay/hacktoberfest-2025-create-discord-features-or-videos-to-win-rewards-2d48</link>
      <guid>https://dev.to/waveplay/hacktoberfest-2025-create-discord-features-or-videos-to-win-rewards-2d48</guid>
      <description>&lt;p&gt;🎉 &lt;strong&gt;Welcome to Hacktoberfest 2025!&lt;/strong&gt; 🎉&lt;/p&gt;

&lt;p&gt;It’s time to flex your creativity and snag awesome swag. Built a Discord bot, activity, or website? Prefer teaching with videos instead of code?  Either works!🌟&lt;/p&gt;

&lt;p&gt;Every participant gets &lt;strong&gt;Discord Nitro&lt;/strong&gt;. Top contributors earn an &lt;strong&gt;exclusive Robo.js Hacktoberfest 2025 T‑Shirt&lt;/strong&gt;, upgrades, and cash. The more people join, the bigger (and better) the prize pool gets. 🎁&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Event window:&lt;/strong&gt; October 1–31, 2025&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  ✨ What is Robo.js?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://robojs.dev/" rel="noopener noreferrer"&gt;Robo.js&lt;/a&gt;&lt;/strong&gt; is a framework for building &lt;strong&gt;&lt;a href="https://robojs.dev/discord-bots/getting-started" rel="noopener noreferrer"&gt;Discord Bots&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://robojs.dev/discord-activities/getting-started" rel="noopener noreferrer"&gt;Discord Activities&lt;/a&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;a href="https://robojs.dev/templates/overview#web-apps" rel="noopener noreferrer"&gt;Web Apps&lt;/a&gt;&lt;/strong&gt;—with batteries included. It streamlines your workflow via plugins, sensible defaults, and a smooth DX so you can ship faster.&lt;/p&gt;

&lt;p&gt;Here’s what you can expect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://robojs.dev/plugins/directory" rel="noopener noreferrer"&gt;Ecosystem&lt;/a&gt;&lt;/strong&gt;: A growing directory of plugins, templates, and tools to help you move from idea to MVP in record time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://robojs.dev/robojs/flashcore" rel="noopener noreferrer"&gt;Integrated Database&lt;/a&gt;&lt;/strong&gt;: A built-in KV store (Flashcore) with adapters so you can point at your favorite data source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://robojs.dev/robojs/typescript" rel="noopener noreferrer"&gt;TypeScript Support&lt;/a&gt;&lt;/strong&gt;: First-class TypeScript, zero config required.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out the &lt;strong&gt;&lt;a href="https://robojs.dev/getting-started" rel="noopener noreferrer"&gt;Getting Started&lt;/a&gt;&lt;/strong&gt; guide.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;strong&gt;Robo.js&lt;/strong&gt; does &lt;em&gt;not&lt;/em&gt; replace &lt;strong&gt;Discord.js&lt;/strong&gt; for bots. It’s a higher-level framework that helps you build more complex projects with less effort. Bring your favorite libraries—Robo.js plays nicely with them.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧪 Our Vibe on Coding
&lt;/h2&gt;

&lt;p&gt;We accept &lt;strong&gt;vibe coding&lt;/strong&gt; as long as your contribution - and please actually read and review the code you generate (don’t just hope AI got it right).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Works&lt;/strong&gt; and does exactly what it claims.&lt;/li&gt;
&lt;li&gt;Is &lt;strong&gt;well‑tested&lt;/strong&gt; (unit/integration where appropriate) with clear steps to verify.&lt;/li&gt;
&lt;li&gt;Has &lt;strong&gt;clean code&lt;/strong&gt; (readable, typed, documented) and passes lint/build checks.&lt;/li&gt;
&lt;li&gt;Comes with a concise &lt;strong&gt;README&lt;/strong&gt; and examples where relevant.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To help you ship faster, we have several &lt;code&gt;AGENTS.md&lt;/code&gt; files scattered throughout the monorepo to guide AI coding tools (e.g., Codex, Claude Code) with context, patterns, and commands. Feel free to rely on them while you build.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎁 Rewards
&lt;/h2&gt;

&lt;p&gt;As participation grows, so do the rewards.&lt;/p&gt;

&lt;h3&gt;
  
  
  Starting Rewards
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exclusive Robo.js Hacktoberfest 2025 T‑Shirt&lt;/strong&gt; for the top 3 contributors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free Discord Nitro&lt;/strong&gt; for everyone who makes a meaningful contribution, while supplies last&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$25 USD&lt;/strong&gt; optional alternative for the top contributor&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Stretch Rewards
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Over 10 Participants:&lt;/strong&gt; Add a free month of &lt;strong&gt;RoboPlay&lt;/strong&gt; for the top 3 contributors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Over 25 Participants:&lt;/strong&gt; Expand top‑contributor rewards to top 5. Cash prize increases to &lt;strong&gt;$50 USD&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Over 50 Participants:&lt;/strong&gt; Top 5 may upgrade their T‑Shirt to a higher prize tier. Cash prize increases to &lt;strong&gt;$100 USD&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Over 75 Participants:&lt;/strong&gt; All top participants receive event stickers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Over 100 Participants:&lt;/strong&gt; Expand top‑contributor rewards to top 10. Cash prizes extend to top 3.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cash prizes are sent via PayPal or another agreed method. Rewards may be limited by local laws or restrictions.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Share the event to unlock every milestone! 🚀&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 How to Participate
&lt;/h2&gt;

&lt;p&gt;Contribute plugins, templates, video content, or features to the core framework. Every meaningful contribution is an entry—submit more, increase your odds.&lt;/p&gt;

&lt;p&gt;Getting started is easy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-robo &amp;lt;project-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Boom! You’ve scaffolded a &lt;strong&gt;Robo.js&lt;/strong&gt; project. Build something cool and send a PR to qualify. 🎉&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Wave-Play/robo.js/pulls" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: Submit a Pull Request&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://roboplay.dev/discord" rel="noopener noreferrer"&gt;&lt;strong&gt;Discord&lt;/strong&gt;: Join the Community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Contributions must add real value. “Hello World” plugins won’t count, but anything that unlocks new interactions or improves the dev experience will—even if it’s not for Discord!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧮 Points &amp;amp; Contribution Types
&lt;/h2&gt;

&lt;p&gt;Each accepted contribution type earns points. Points (plus impact and quality) help determine top contributors.&lt;/p&gt;

&lt;h4&gt;
  
  
  🐞 Bug Fix (1 point)
&lt;/h4&gt;

&lt;p&gt;Fix a bug in the core or an official plugin. Documentation-only changes don’t count for points (but we still ❤️ them).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Wave-Play/robo.js/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: How to Contribute&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  📦 Template (2 points)
&lt;/h4&gt;

&lt;p&gt;Templates are ready-made project starters. Examples: a music-enabled Discord bot, a quiz activity, or a streamlined web app.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://robojs.dev/templates/overview" rel="noopener noreferrer"&gt;&lt;strong&gt;Docs&lt;/strong&gt;: Template Collection&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  🧩 Plugin — &lt;strong&gt;7–10 points&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;NPM packages that snap extra features into &lt;strong&gt;Robo.js&lt;/strong&gt; (e.g., command packs, dashboards, storage adapters, integration bridges).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Scoring guidance:&lt;/strong&gt; Complexity, test coverage, UX polish, docs, and adoption potential push you toward the &lt;strong&gt;10&lt;/strong&gt; end of the range.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://robojs.dev/plugins/create" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;&lt;/strong&gt;&lt;a href="https://robojs.dev/plugins/create" rel="noopener noreferrer"&gt;: Creating Plugins&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://robojs.dev/plugins/directory" rel="noopener noreferrer"&gt;Directory&lt;/a&gt;&lt;/strong&gt;&lt;a href="https://robojs.dev/plugins/directory" rel="noopener noreferrer"&gt;: Browse Ideas&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  🎥 Video Tutorial — &lt;strong&gt;5 points&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Teach the community—record a walkthrough, live‑coding session, or deep‑dive. Upload to YouTube and PR the link.&lt;/p&gt;

&lt;h4&gt;
  
  
  🧠 Core Framework Feature — &lt;strong&gt;3–5 points&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Propose and ship a scoped core feature (after community discussion). Start a thread, align on scope, and follow the contribution guidelines.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/Wave-Play/robo.js/issues" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/strong&gt;&lt;a href="https://github.com/Wave-Play/robo.js/issues" rel="noopener noreferrer"&gt;: Issues&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://robojs.dev/robojs/internals" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;&lt;/strong&gt;&lt;a href="https://robojs.dev/robojs/internals" rel="noopener noreferrer"&gt;: Robo Internals&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;If in doubt, start with a plugin or template; many ideas shine better outside core.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  📝 Prepared #hacktoberfest Issues
&lt;/h2&gt;

&lt;p&gt;We’ve prepped well‑detailed issues to help you hit the ground running. &lt;strong&gt;Most include optional bonus features&lt;/strong&gt; that can grant &lt;strong&gt;extra points&lt;/strong&gt; beyond their base value if implemented. These are just a few—there are &lt;strong&gt;more &lt;code&gt;#hacktoberfest&lt;/code&gt; issues&lt;/strong&gt; across the repo.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Links below are placeholders—you’ll find the real links in the issue tracker.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;@robojs/prefix — Prefix Commands Plugin&lt;/strong&gt; &lt;em&gt;(plugin)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@robojs/social — Social Alerts (Twitch, YouTube, RSS/Atom)&lt;/strong&gt;** — Social Alerts (Twitch, YouTube, RSS/Atom)** &lt;em&gt;(plugin)&lt;/em&gt; — &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@robojs/welcome — Welcome &amp;amp; Goodbye for Discord bots&lt;/strong&gt; &lt;em&gt;(plugin)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@robojs/giveaways — One-click Discord giveaways&lt;/strong&gt; — One‑click Discord giveaways** &lt;em&gt;(plugin)&lt;/em&gt; — &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;@robojs/cooldown&lt;/code&gt;&lt;/strong&gt; — Cooldowns &amp;amp; Rate‑Limiting** &lt;em&gt;(plugin)&lt;/em&gt; — &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;@robojs/announcements&lt;/code&gt;&lt;/strong&gt; — Scheduled announcements for servers** &lt;em&gt;(plugin)&lt;/em&gt; — &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;@robojs/tickets&lt;/code&gt;&lt;/strong&gt; — Thread‑based support tickets** &lt;em&gt;(plugin)&lt;/em&gt; — &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Tip: Many issues have a &lt;strong&gt;“Good first issue”&lt;/strong&gt; label and include &lt;strong&gt;acceptance criteria, test hints, and bonus ideas.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🎨 Creation Ideas
&lt;/h2&gt;

&lt;p&gt;Need inspiration? Try these starters.&lt;/p&gt;

&lt;h3&gt;
  
  
  🎮 Discord Activities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Game Engine Template:&lt;/strong&gt; Unity, Unreal, or Godot wired to Robo.js.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live Whiteboard:&lt;/strong&gt; Real‑time drawing via &lt;strong&gt;WebSockets&lt;/strong&gt; or &lt;strong&gt;&lt;code&gt;@robojs/sync&lt;/code&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Video Tutorial:&lt;/strong&gt; From setup to multiplayer—show your build and thought process.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🤖 Discord Bots
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Music Bot Template:&lt;/strong&gt; Playback, queues, and intuitive UX.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ticketing &amp;amp; Support Threads Plugin:&lt;/strong&gt; Create, route, and auto‑close support tickets with transcripts, tags, and slash commands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Video Tutorial:&lt;/strong&gt; Walk through commands, modals, embeds, and permissions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🌐 Other Suggestions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Integration Templates:&lt;/strong&gt; Pair Robo.js with &lt;strong&gt;Better Stack&lt;/strong&gt;, &lt;strong&gt;Notion&lt;/strong&gt;, or another favorite service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bot Dashboard Plugin:&lt;/strong&gt; Settings, logs, analytics—optionally as a Discord Activity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Video Showcase:&lt;/strong&gt; Demo your coolest Robo.js build—what it does and how you made it.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ✅ What We Look For (Quality Signals)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Clear &lt;strong&gt;problem/solution&lt;/strong&gt; summary and scope.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tests&lt;/strong&gt; (unit/integration) and easy repro steps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean code&lt;/strong&gt;: types, naming, comments, and small PRs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docs&lt;/strong&gt; &amp;amp; examples: README, usage notes, screenshots or gifs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DX polish&lt;/strong&gt;: sensible errors, helpful logs, zero‑config defaults where possible.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Spread the Word!
&lt;/h2&gt;

&lt;p&gt;Invite friends, post your progress, and help us smash every milestone. The more builders we have, the better the rewards for&lt;/p&gt;

&lt;p&gt;Questions? Need a hand getting started? Hop in our &lt;strong&gt;&lt;a href="https://roboplay.dev/discord" rel="noopener noreferrer"&gt;Discord Server&lt;/a&gt;&lt;/strong&gt; — we’re excited to see what you create!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Happy coding and happy Hacktoberfest 2025! 🎉&lt;/em&gt;&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>discord</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Hacktoberfest Extended Until November 30 for Robo.js</title>
      <dc:creator>WavePlay Staff</dc:creator>
      <pubDate>Fri, 01 Nov 2024 15:00:00 +0000</pubDate>
      <link>https://dev.to/waveplay/hacktoberfest-extended-until-november-30-for-robojs-h2i</link>
      <guid>https://dev.to/waveplay/hacktoberfest-extended-until-november-30-for-robojs-h2i</guid>
      <description>&lt;p&gt;This event is over, but &lt;strong&gt;&lt;a href="https://robojs.dev/discord" rel="noopener noreferrer"&gt;join our Discord server&lt;/a&gt;&lt;/strong&gt; for more!&lt;/p&gt;




&lt;p&gt;Now that October is over, all good things must come to an end, right? Not so for &lt;strong&gt;Robo.js&lt;/strong&gt;! We're extending our &lt;strong&gt;Hacktoberfest&lt;/strong&gt; event until &lt;strong&gt;November 30&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This means you have an extra month to create templates, plugins, video tutorials, or general contributions. The more you contribute, the more points you earn, and the better prizes you unlock.&lt;/p&gt;

&lt;p&gt;See our main post for more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://robojs.dev/hacktoberfest" rel="noopener noreferrer"&gt;🎃 &lt;strong&gt;Hacktoberfest:&lt;/strong&gt; Build stuff, win free swag ✨&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Updated Grading Criteria
&lt;/h2&gt;

&lt;p&gt;We've also updated the grading criteria. Templates can now earn you up to 5 points, and general contributions may earn you between 1 and 10 points based on complexity.&lt;/p&gt;

&lt;p&gt;See the &lt;code&gt;Points&lt;/code&gt; label on GitHub issues tagged &lt;code&gt;#hacktoberfest&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Leaderboard
&lt;/h2&gt;

&lt;p&gt;We now have a &lt;strong&gt;leaderboard&lt;/strong&gt; to see how you're doing compared to others. Join our Discord server and check out the #leaderboard channel!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Web version of the leaderboard coming soon.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://roboplay.dev/discord" rel="noopener noreferrer"&gt;&lt;strong&gt;Discord&lt;/strong&gt;: Join the Community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>hacktoberfest</category>
      <category>javascript</category>
      <category>discord</category>
      <category>node</category>
    </item>
    <item>
      <title>Hacktoberfest 2024: Code Templates and Win Rewards 🎉</title>
      <dc:creator>WavePlay Staff</dc:creator>
      <pubDate>Fri, 11 Oct 2024 15:00:00 +0000</pubDate>
      <link>https://dev.to/waveplay/hacktoberfest-2024-code-templates-and-win-rewards-166n</link>
      <guid>https://dev.to/waveplay/hacktoberfest-2024-code-templates-and-win-rewards-166n</guid>
      <description>&lt;p&gt;This event is over, but &lt;strong&gt;&lt;a href="https://robojs.dev/discord" rel="noopener noreferrer"&gt;join our Discord server&lt;/a&gt;&lt;/strong&gt; for more!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Welcome to Week 2 of Hacktoberfest 2024!&lt;/strong&gt; This week our spotlight is one of the most accessible and creative ways to contribute to &lt;strong&gt;&lt;a href="https://robojs.dev" rel="noopener noreferrer"&gt;Robo.js&lt;/a&gt;&lt;/strong&gt; during Hacktoberfest: &lt;a href="https://robojs.dev/templates/overview" rel="noopener noreferrer"&gt;&lt;strong&gt;Templates&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Not only are templates fun to make, but they also help others get started faster, and, of course, they qualify you for &lt;strong&gt;free Discord Nitro&lt;/strong&gt;. Top contributors are also in the running for an &lt;strong&gt;exclusive Robo.js Hacktoberfest 2024 T-Shirt&lt;/strong&gt; and other prizes. 🎁&lt;/p&gt;

&lt;p&gt;For more details, check out the main event page.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://roboplay.dev/hacktoberfest" rel="noopener noreferrer"&gt;&lt;strong&gt;Hacktoberfest 2024&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Robo.js&lt;/strong&gt; is a framework that helps developers easily build a &lt;strong&gt;&lt;a href="https://robojs.dev/discord-bots/getting-started" rel="noopener noreferrer"&gt;Discord Bot&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://robojs.dev/discord-activities/getting-started" rel="noopener noreferrer"&gt;Discord Activity&lt;/a&gt;&lt;/strong&gt;, or &lt;strong&gt;&lt;a href="https://robojs.dev/templates/overview#web-apps" rel="noopener noreferrer"&gt;Web App&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  📦 What Are Templates?
&lt;/h2&gt;

&lt;p&gt;Templates are boilerplate projects that give others a head start by providing a solid foundation to build on. They make it easy for anyone to spin up a project like a without starting from scratch. Using &lt;strong&gt;Robo.js&lt;/strong&gt;, you can create templates that include all sorts of features—perfect for getting someone off the ground quickly.&lt;/p&gt;

&lt;p&gt;Here are some ideas to get you started:&lt;/p&gt;

&lt;h3&gt;
  
  
  Discord Activities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Game Engine Template&lt;/strong&gt;: Create a starter template that integrates Robo.js with your favorite game engine, like Unity or Unreal Engine. This will help others set up Discord activities that use game engines with minimal configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Discord Bots
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Music Bot Template&lt;/strong&gt;: Build a music bot template that plays music from external platforms. This could be a popular project for those wanting to add a bit of life to their Discord servers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Other Suggestions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Integration Templates&lt;/strong&gt;: Build templates that connect &lt;strong&gt;Robo.js&lt;/strong&gt; with platforms like &lt;strong&gt;&lt;a href="https://www.notion.so/" rel="noopener noreferrer"&gt;Notion&lt;/a&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;a href="https://betterstack.com/" rel="noopener noreferrer"&gt;Better Stack&lt;/a&gt;&lt;/strong&gt;. These integrations make it easy for others to use Robo.js alongside their favorite tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more inspiration, check out the entire &lt;a href="https://robojs.dev/templates/overview" rel="noopener noreferrer"&gt;&lt;strong&gt;Templates Collection&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✨ Getting Started
&lt;/h2&gt;

&lt;p&gt;Getting started is simple. Run the following command to set up a new &lt;strong&gt;Robo.js&lt;/strong&gt; project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-robo &amp;lt;project-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modify it, add features, and when you're ready, submit a pull request to the &lt;strong&gt;&lt;a href="https://github.com/Wave-Play/robo.js" rel="noopener noreferrer"&gt;Robo.js repository&lt;/a&gt;&lt;/strong&gt; to qualify for the rewards. Creating templates is an easy way to get your feet wet, help others, and potentially win prizes! 🎁&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Wave-Play/robo.js/pulls" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: Submit a Pull Request&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://roboplay.dev/discord" rel="noopener noreferrer"&gt;&lt;strong&gt;Discord&lt;/strong&gt;: Join the Community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can't wait to see the creative templates you come up with. Remember, the more people who contribute, the better the rewards—so invite your friends to participate too! 🚀&lt;/p&gt;

&lt;h2&gt;
  
  
  📣 Spread the Word!
&lt;/h2&gt;

&lt;p&gt;Share this event with your friends and help us reach our milestones. The more participants we have, the better the rewards for everyone. Let's make Hacktoberfest 2024 the best one yet! 🚀&lt;/p&gt;

&lt;p&gt;If you have any questions or need help getting started, don't hesitate to reach out on our &lt;strong&gt;&lt;a href="https://roboplay.dev/discord" rel="noopener noreferrer"&gt;Discord Server&lt;/a&gt;&lt;/strong&gt;. We're excited to see what you create!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://roboplay.dev/discord" rel="noopener noreferrer"&gt;&lt;strong&gt;Discord&lt;/strong&gt;: Join the Community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Happy coding and happy Hacktoberfest! 🎉&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>hacktoberfest</category>
      <category>programming</category>
      <category>discord</category>
    </item>
    <item>
      <title>Hacktoberfest 2024: Create Discord Features or Videos to Win Rewards 🎉</title>
      <dc:creator>WavePlay Staff</dc:creator>
      <pubDate>Wed, 02 Oct 2024 14:30:00 +0000</pubDate>
      <link>https://dev.to/waveplay/hacktoberfest-2024-create-discord-features-or-videos-to-win-rewards-25pl</link>
      <guid>https://dev.to/waveplay/hacktoberfest-2024-create-discord-features-or-videos-to-win-rewards-25pl</guid>
      <description>&lt;p&gt;This event is over, but &lt;strong&gt;&lt;a href="https://robojs.dev/discord" rel="noopener noreferrer"&gt;join our Discord server&lt;/a&gt;&lt;/strong&gt; for more!&lt;/p&gt;




&lt;p&gt;🎉 &lt;strong&gt;Welcome to Hacktoberfest 2024!&lt;/strong&gt; 🎉&lt;/p&gt;

&lt;p&gt;The time has come to show off your creativity and win free stuff! Ever built a Discord bot, activity, or website? Don't feel confident coding but like making videos about code? This is your time to shine! 🌟&lt;/p&gt;

&lt;p&gt;Every participant gets free &lt;strong&gt;Discord Nitro&lt;/strong&gt;. Top contributors get an &lt;strong&gt;exclusive Robo.js Hacktoberfest 2024 T-Shirt&lt;/strong&gt;, upgrades, and cash. The more people participate, the more and better prizes we'll give out. 🎁&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%2Fpivas9hiu8kc3rpfit8z.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%2Fpivas9hiu8kc3rpfit8z.png" alt="Image" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✨ What is Robo.js?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://robojs.dev/" rel="noopener noreferrer"&gt;Robo.js&lt;/a&gt;&lt;/strong&gt; is a framework for building &lt;strong&gt;&lt;a href="https://robojs.dev/discord-bots/getting-started" rel="noopener noreferrer"&gt;Discord Bots&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://robojs.dev/discord-activities/getting-started" rel="noopener noreferrer"&gt;Discord Activities&lt;/a&gt;&lt;/strong&gt;, and &lt;strong&gt;&lt;a href="https://robojs.dev/templates/overview#web-apps" rel="noopener noreferrer"&gt;Web Apps&lt;/a&gt;&lt;/strong&gt;. It simplifies the process by providing an ecosystem of plugins and features to help you build your project faster and more efficiently. It's simple, straightforward to use, and &lt;strong&gt;&lt;a href="https://robojs.dev/hosting/overview" rel="noopener noreferrer"&gt;easy to host&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here's what you can expect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://robojs.dev/plugins/directory" rel="noopener noreferrer"&gt;Ecosystem&lt;/a&gt;&lt;/strong&gt;: A growing ecosystem of plugins, templates, and tools to help you build faster with less effort.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://robojs.dev/robojs/flashcore" rel="noopener noreferrer"&gt;Integrated Database&lt;/a&gt;&lt;/strong&gt;: Robo.js has a built-in KV database that can be pointed to any data source via adapters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://robojs.dev/robojs/typescript" rel="noopener noreferrer"&gt;TypeScript Support&lt;/a&gt;&lt;/strong&gt;: TypeScript works out of the box, so you can use it without any additional setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out our &lt;strong&gt;&lt;a href="https://robojs.dev/getting-started" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;&lt;/strong&gt; for more.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://robojs.dev/getting-started" rel="noopener noreferrer"&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: Getting Started&lt;/a&gt;&lt;/li&gt;
&lt;/ul&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%2Fj0ten2yhm38klnva59gr.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%2Fj0ten2yhm38klnva59gr.png" alt="Image" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &lt;strong&gt;Robo.js&lt;/strong&gt; does &lt;em&gt;not&lt;/em&gt; replace &lt;strong&gt;Discord.js&lt;/strong&gt; for bots. It's a higher-level framework that allows you to build more complex projects with less effort. Use your favorite libraries and tools alongside Robo.js!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🎁 Rewards
&lt;/h2&gt;

&lt;p&gt;Depending on the number of participants, we'll give out more and better prizes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Starting Rewards
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Exclusive Robo.js Hacktoberfest 2024 T-Shirt&lt;/strong&gt; for top 3 contributors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free Discord Nitro&lt;/strong&gt; for everyone who makes a meaningful contribution, while supplies last.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$25 USD&lt;/strong&gt; as an optional alternative reward for the top contributor.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Stretch Rewards
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Over 10 Participants&lt;/strong&gt;: We include a free month of &lt;strong&gt;RoboPlay&lt;/strong&gt; for the top 3 contributors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Over 25 Participants&lt;/strong&gt;: We expand the top contributor rewards to include the top 5 participants. Cash prize increases to &lt;strong&gt;$50 USD&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Over 50 Participants&lt;/strong&gt;: The top 5 get to upgrade their T-Shirt to a higher prize. Cash prize increases to &lt;strong&gt;$100 USD&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Over 75 Participants&lt;/strong&gt;: All top participants get free event stickers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Over 100 Participants&lt;/strong&gt;: We expand the top contributor rewards to include the top 10 participants. Cash prize is expanded to top 3.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cash prizes will be sent via PayPal or another agreed-upon method. Rewards may not be available in all regions, due to U.S. export laws and other restrictions.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Share this event with your friends and help us reach these milestones and unlock more rewards! 🚀&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 How to Participate
&lt;/h2&gt;

&lt;p&gt;Contribute plugins, templates, video content, or even features to the core framework. You can contribute as many times as you want, and each contribution counts as an entry for the prizes. The more you contribute, the more likely you are to win.&lt;/p&gt;

&lt;p&gt;Sound complicated? It's really not! Run this in your terminal to get started:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-robo &amp;lt;project-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ta-dah! You now have a &lt;strong&gt;Robo.js&lt;/strong&gt; project. Modify it, add features, and submit a pull request to qualify! 🎉&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Wave-Play/robo.js/pulls" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: Submit a Pull Request&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://roboplay.dev/discord" rel="noopener noreferrer"&gt;&lt;strong&gt;Discord&lt;/strong&gt;: Join the Community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each type of contribution is worth a different amount of entries. They must be meaningful and add value to the community. Things like plugins that add "Hello World" commands won't count, but a plugin that adds a new way to interact will, even if it's not for Discord. Check out some ideas below!&lt;/p&gt;

&lt;h4&gt;
  
  
  🐞 Bug Fix (1 point)
&lt;/h4&gt;

&lt;p&gt;Fix a bug in the core framework or a plugin. It's a small contribution, but it's a start! Documentation fixes don't count, but they're still appreciated.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Wave-Play/robo.js/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: How to Contribute&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  📦 Template (2 points)
&lt;/h4&gt;

&lt;p&gt;Templates are boilerplate projects that help you get started with a specific type of project. For example, a template could be a Discord bot with a music feature or a Discord activity with a quiz.&lt;/p&gt;

&lt;p&gt;Use the &lt;code&gt;create-robo&lt;/code&gt; command to create a new project and modify it to your liking. Once you're done, submit a pull request to the &lt;strong&gt;Robo.js&lt;/strong&gt; repository. Check out our &lt;strong&gt;&lt;a href="https://robojs.dev/templates/overview" rel="noopener noreferrer"&gt;Template Collection&lt;/a&gt;&lt;/strong&gt; for inspiration!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://robojs.dev/templates/overview" rel="noopener noreferrer"&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: Template Collection&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  🧩 Plugin (5 points)
&lt;/h4&gt;

&lt;p&gt;Plugins are NPM packages that instantly add features to &lt;strong&gt;Robo.js&lt;/strong&gt; projects. For example, a plugin could add a new command or a new way to interact with &lt;strong&gt;Discord&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Creating a plugin is no different from creating a normal &lt;strong&gt;Robo.js&lt;/strong&gt; project, except that it's packaged as an NPM package. See our &lt;strong&gt;&lt;a href="https://robojs.dev/plugins/directory" rel="noopener noreferrer"&gt;Plugin Directory&lt;/a&gt;&lt;/strong&gt; for inspiration!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://robojs.dev/plugins/create" rel="noopener noreferrer"&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: Creating Plugins&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  🎥 Video Tutorial (5 points)
&lt;/h4&gt;

&lt;p&gt;Video tutorials are a great way to teach others how to use &lt;strong&gt;Robo.js&lt;/strong&gt; or how to build something cool with it. They can be as simple as a screen recording with voiceover or as complex as a full-blown tutorial series.&lt;/p&gt;

&lt;p&gt;Upload your video to YouTube and submit a pull request to the &lt;strong&gt;Robo.js&lt;/strong&gt; repository with a link to your video.&lt;/p&gt;

&lt;h4&gt;
  
  
  🌟 Core Framework Feature (7 points)
&lt;/h4&gt;

&lt;p&gt;This is the big one! Add a new feature to the core &lt;strong&gt;Robo.js&lt;/strong&gt; framework. Please discuss your idea with the community first to make sure it's a good fit, and make sure to follow the &lt;strong&gt;&lt;a href="https://github.com/Wave-Play/robo.js/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;Contributing Guidelines&lt;/a&gt;&lt;/strong&gt;. It may also help to learn about the &lt;strong&gt;&lt;a href="https://robojs.dev/robojs/internals" rel="noopener noreferrer"&gt;Robo Internals&lt;/a&gt;&lt;/strong&gt; first.&lt;/p&gt;

&lt;p&gt;We're strict about this one, but that's how we keep things high-quality. If you're not sure, start with a plugin or a template! Some ideas are best left as plugins, so don't be discouraged if your feature doesn't make it into the core framework.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Wave-Play/robo.js/issues" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: Issues&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🎨 Creation Ideas
&lt;/h2&gt;

&lt;p&gt;Not sure what to contribute? Here are some ideas to get you started.&lt;/p&gt;

&lt;h4&gt;
  
  
  🎮 Discord Activities
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Game Engine&lt;/strong&gt;: Create a template of your favorite game engine, like Unity or Unreal Engine, for &lt;strong&gt;Robo.js&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live Whiteboard&lt;/strong&gt;: Create a plugin that allows users to draw on a shared canvas in real-time, built with &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSocket" rel="noopener noreferrer"&gt;WebSockets&lt;/a&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;a href="https://robojs.dev/plugins/sync" rel="noopener noreferrer"&gt;@robojs/sync&lt;/a&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Video Tutorial&lt;/strong&gt;: Create a video tutorial on how to build a Discord activity with &lt;strong&gt;Robo.js&lt;/strong&gt;. You could cover the basics, like setting up a project, or more advanced topics, like adding multiplayer support.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  🤖 Discord Bots
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Music Bot&lt;/strong&gt;: Create a template for a music bot that can play music from an external platform.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leveling System&lt;/strong&gt;: Create a plugin that adds a leveling system to your Discord bot. Users can earn XP and level up by chatting in your server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Video Tutorial&lt;/strong&gt;: Create a video tutorial on how to build a Discord bot with &lt;strong&gt;Robo.js&lt;/strong&gt;. You could cover the basics, like setting up a project, or more advanced topics, modals and embeds.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Other Suggestions
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Integration Templates&lt;/strong&gt;: Create templates for integrating &lt;strong&gt;Robo.js&lt;/strong&gt; with other platforms, like &lt;strong&gt;&lt;a href="https://betterstack.com/" rel="noopener noreferrer"&gt;Better Stack&lt;/a&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;a href="https://www.notion.so/" rel="noopener noreferrer"&gt;Notion&lt;/a&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bot Dashboard&lt;/strong&gt;: Create a plugin that adds a web dashboard to your Discord bot. Users could configure settings, view logs, and more. Could even be viewed as a Discord Activity!&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Video Showcase&lt;/strong&gt;: Create a video showcasing your favorite &lt;strong&gt;Robo.js&lt;/strong&gt; project. Maybe it's a bot, an activity, or a web app. Show off what you've built and how it works!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://robojs.dev/templates/overview" rel="noopener noreferrer"&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: Plugin Directory&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://robojs.dev/templates/overview" rel="noopener noreferrer"&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: Template Collection&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Spread the Word!
&lt;/h2&gt;

&lt;p&gt;Share this event with your friends and help us reach our milestones! The more participants we have, the better the rewards for everyone. Let's make Hacktoberfest 2024 the best one yet! 🚀&lt;/p&gt;

&lt;p&gt;If you have any questions or need help getting started, don't hesitate to reach out on our &lt;strong&gt;&lt;a href="https://roboplay.dev/discord" rel="noopener noreferrer"&gt;Discord Server&lt;/a&gt;&lt;/strong&gt;. We're excited to see what you create!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://roboplay.dev/discord" rel="noopener noreferrer"&gt;&lt;strong&gt;Discord&lt;/strong&gt;: Join the Community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Happy coding and happy Hacktoberfest! 🎉&lt;/em&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>discord</category>
      <category>hacktoberfest</category>
    </item>
    <item>
      <title>Missing Launch Button in your Discord Activity? Fix the Entry Point Command!</title>
      <dc:creator>WavePlay Staff</dc:creator>
      <pubDate>Tue, 01 Oct 2024 13:30:00 +0000</pubDate>
      <link>https://dev.to/waveplay/missing-launch-button-in-your-discord-activity-fix-the-entry-point-command-1fpg</link>
      <guid>https://dev.to/waveplay/missing-launch-button-in-your-discord-activity-fix-the-entry-point-command-1fpg</guid>
      <description>&lt;p&gt;Got a fancy new &lt;strong&gt;&lt;a href="https://robojs.dev/discord-activities/getting-started" rel="noopener noreferrer"&gt;Discord Activity&lt;/a&gt;&lt;/strong&gt; but found that your Launch button went missing? We've got a patch for that!&lt;/p&gt;

&lt;p&gt;This happens when your &lt;strong&gt;Discord App&lt;/strong&gt; is too old to have it, or if you've accidentally deleted it when, say, cleaning up your &lt;strong&gt;&lt;a href="https://robojs.dev/discord-bots/getting-started" rel="noopener noreferrer"&gt;Discord Bot's&lt;/a&gt;&lt;/strong&gt; slash commands. We have different ways for you to choose, depending on what you're using.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 1: Node.js Script
&lt;/h2&gt;

&lt;p&gt;We've open sourced a smol &lt;strong&gt;&lt;a href="https://nodejs.org/en/download/prebuilt-installer" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;&lt;/strong&gt; script that you can just run in your &lt;strong&gt;terminal&lt;/strong&gt;. It'll automatically create the missing entry command for you if it doesn't exist. &lt;strong&gt;Download the script&lt;/strong&gt; and run it like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node entry-fix.js &amp;lt;DISCORD_CLIENT_ID&amp;gt; &amp;lt;DISCORD_TOKEN&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;🔗 &lt;strong&gt;GitHub:&lt;/strong&gt; Download or copy script&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Replace &lt;code&gt;&amp;lt;DISCORD_CLIENT_ID&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;DISCORD_TOKEN&amp;gt;&lt;/code&gt; with the actual values in your &lt;strong&gt;&lt;a href="https://discord.com/developers/applications" rel="noopener noreferrer"&gt;Discord Developer Portal&lt;/a&gt;&lt;/strong&gt;. Yes, you need a &lt;strong&gt;Discord Bot&lt;/strong&gt; token to fix your &lt;strong&gt;Discord Activity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This method is recommended for those with &lt;strong&gt;Node.js&lt;/strong&gt; installed, even if making &lt;strong&gt;Discord Apps&lt;/strong&gt; using other languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Method 2: @robojs/patch
&lt;/h2&gt;

&lt;p&gt;Woah, you're using &lt;strong&gt;&lt;a href="https://robojs.dev" rel="noopener noreferrer"&gt;Robo.js&lt;/a&gt;&lt;/strong&gt;? You're creating in luxury!&lt;/p&gt;

&lt;p&gt;All you need to do is install &lt;strong&gt;&lt;a href="https://robojs.dev/plugins/patch" rel="noopener noreferrer"&gt;@robojs/patch&lt;/a&gt;&lt;/strong&gt;. That's it! It's a &lt;strong&gt;&lt;a href="https://robojs.dev/plugins/overview" rel="noopener noreferrer"&gt;Robo Plugin&lt;/a&gt;&lt;/strong&gt;, so it's integrated instantly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx robo add @robojs/patch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;a href="https://robojs.dev/plugins/patch" rel="noopener noreferrer"&gt;🔗 &lt;strong&gt;Documentation:&lt;/strong&gt; @robojs/patch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This method is recommended for those using &lt;strong&gt;Robo.js&lt;/strong&gt; to build their &lt;strong&gt;Discord Activities&lt;/strong&gt;. If you're not using &lt;strong&gt;Robo.js&lt;/strong&gt;, we highly recommend you check it out!&lt;/p&gt;

&lt;h2&gt;
  
  
  Discord Activities are Fun!
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Discord Activities&lt;/strong&gt; are a fun way to engage with your community. They're like mini-games or interactive experiences that you can create and share with others. &lt;strong&gt;&lt;a href="https://robojs.dev" rel="noopener noreferrer"&gt;Robo.js&lt;/a&gt;&lt;/strong&gt; is a powerful framework that makes building &lt;strong&gt;Discord Activities&lt;/strong&gt; easy and fun. &lt;strong&gt;Discord Activities&lt;/strong&gt; are often built using &lt;strong&gt;HTML&lt;/strong&gt;, &lt;strong&gt;CSS&lt;/strong&gt;, and &lt;strong&gt;JavaScript&lt;/strong&gt; like any other web app, but they run inside &lt;strong&gt;Discord&lt;/strong&gt; itself.&lt;/p&gt;

&lt;p&gt;If you don't already have a &lt;strong&gt;Discord Activity&lt;/strong&gt;, you can create one in seconds with &lt;strong&gt;Robo.js&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-robo &amp;lt;projectName&amp;gt; &lt;span class="nt"&gt;-k&lt;/span&gt; activity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out our &lt;strong&gt;tutorial&lt;/strong&gt; to learn more.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://robojs.dev/discord-activities/getting-started" rel="noopener noreferrer"&gt;✨ &lt;strong&gt;Documentation:&lt;/strong&gt; Getting Started with Discord Activities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/waveplay/how-to-build-a-discord-activity-easily-with-robojs-5bng"&gt;🔗 &lt;strong&gt;Tutorial:&lt;/strong&gt; Creating a Discord Activity in seconds with Robo.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Don't let a missing launch button ruin your day. Use one of the methods above to fix your &lt;strong&gt;Discord Activity&lt;/strong&gt; and get back to building awesome experiences for your community.&lt;/p&gt;

&lt;p&gt;You can join our Discord Server to chat with other developers, ask questions, and share your projects. We're a friendly bunch and always happy to help! Plus, our very own AI Robo, Sage, is there to assist you with any questions you may have.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://roboplay.dev/discord" rel="noopener noreferrer"&gt;🚀 &lt;strong&gt;Community:&lt;/strong&gt; Join our Discord server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>discord</category>
      <category>programming</category>
      <category>node</category>
    </item>
    <item>
      <title>Patch Your Discord Activity’s Network Requests for Smooth CSP Compliance</title>
      <dc:creator>WavePlay Staff</dc:creator>
      <pubDate>Tue, 17 Sep 2024 14:00:00 +0000</pubDate>
      <link>https://dev.to/waveplay/patch-your-discord-activitys-network-requests-for-smooth-csp-compliance-432c</link>
      <guid>https://dev.to/waveplay/patch-your-discord-activitys-network-requests-for-smooth-csp-compliance-432c</guid>
      <description>&lt;p&gt;When running a &lt;strong&gt;&lt;a href="https://robojs.dev/discord-activities/getting-started" rel="noopener noreferrer"&gt;Discord Activity&lt;/a&gt;&lt;/strong&gt; through &lt;strong&gt;Discord&lt;/strong&gt;, you may encounter &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP" rel="noopener noreferrer"&gt;Content Security Policy (CSP)&lt;/a&gt;&lt;/strong&gt; issues. You can fix these by making sure network requests follow &lt;strong&gt;&lt;a href="https://robojs.dev/discord-activities/proxy" rel="noopener noreferrer"&gt;Discord Proxy&lt;/a&gt;&lt;/strong&gt; rules. &lt;/p&gt;

&lt;p&gt;This can be done manually... or you can let &lt;strong&gt;&lt;a href="https://robojs.dev/plugins/patch" rel="noopener noreferrer"&gt;@robojs/patch&lt;/a&gt;&lt;/strong&gt; handle it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is CSP?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4rr7xajb7ggu14gnlpw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh4rr7xajb7ggu14gnlpw.png" alt="Image" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content Security Policy (CSP)&lt;/strong&gt; is a security standard that helps prevent &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Cross-Site_Scripting" rel="noopener noreferrer"&gt;Cross-Site Scripting (XSS)&lt;/a&gt;&lt;/strong&gt; attacks. It controls which resources a page can load and where it can send data. &lt;/p&gt;

&lt;p&gt;When you run a &lt;strong&gt;Discord Activity&lt;/strong&gt; in &lt;strong&gt;Discord&lt;/strong&gt;, you're actually using the &lt;strong&gt;Discord Proxy&lt;/strong&gt; as a middleman, meaning it sets its own &lt;strong&gt;CSP&lt;/strong&gt; rules. If your network requests don't follow these rules, they'll be blocked. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Relative requests like &lt;code&gt;/api/token&lt;/code&gt; will be blocked unless prefixed with &lt;code&gt;/.proxy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;External requests like &lt;code&gt;https://example.com/api/token&lt;/code&gt; will be blocked unless they're &lt;strong&gt;&lt;a href="https://robojs.dev/discord-activities/proxy#url-mapping" rel="noopener noreferrer"&gt;mapped&lt;/a&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;a href="https://dev.to/waveplay/resolve-content-security-policy-csp-issues-in-your-discord-activity-using-a-nodejs-proxy-2634"&gt;proxied&lt;/a&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resolving CSP Violations
&lt;/h2&gt;

&lt;p&gt;As stated above, all you have to do is make sure your network requests follow the &lt;strong&gt;Discord Proxy&lt;/strong&gt; rules. In some cases, that includes adding &lt;code&gt;/.proxy&lt;/code&gt; to the beginning of your request path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before&lt;/span&gt;
&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// After&lt;/span&gt;
&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/.proxy/api/token&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;However, &lt;strong&gt;WebSockets&lt;/strong&gt; can be a bit trickier. Especially when relying on &lt;strong&gt;&lt;a href="https://www.sanity.io/glossary/hot-module-replacement" rel="noopener noreferrer"&gt;Hot Module Replacement (HMR)&lt;/a&gt;&lt;/strong&gt; that loads before your own activity like in &lt;strong&gt;&lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt;&lt;/strong&gt;. So, we created &lt;strong&gt;&lt;a href="https://robojs.dev/plugins/patch" rel="noopener noreferrer"&gt;@robojs/patch&lt;/a&gt;&lt;/strong&gt; to handle everything for you.&lt;/p&gt;
&lt;h2&gt;
  
  
  Patching Your Activity
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;@robojs/patch&lt;/strong&gt; is a lightweight package that patches your network requests to follow &lt;strong&gt;Discord Proxy&lt;/strong&gt; rules. It works by updating the &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API" rel="noopener noreferrer"&gt;&lt;code&gt;fetch&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebSocket" rel="noopener noreferrer"&gt;&lt;code&gt;WebSocket&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; globals.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @robojs/patch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We have different ways to apply this patch depending on your project setup.&lt;/p&gt;
&lt;h4&gt;
  
  
  Method 1: Vite Plugin (Recommended)
&lt;/h4&gt;

&lt;p&gt;If you're using &lt;strong&gt;Vite&lt;/strong&gt;, you can apply the patch as a plugin in your &lt;strong&gt;Vite&lt;/strong&gt; config file.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;DiscordProxy&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="s1"&gt;@robojs/patch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&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="s1"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;DiscordProxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Vite&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;We recommend this method because it allows the patch to run before before &lt;strong&gt;Vite&lt;/strong&gt;'s HMR client, ensuring that it works correctly.&lt;/p&gt;
&lt;h4&gt;
  
  
  Method 2: Function Call
&lt;/h4&gt;

&lt;p&gt;If you're not using &lt;strong&gt;Vite&lt;/strong&gt;, you can apply the patch by calling a function directly.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;DiscordProxy&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="s1"&gt;@robojs/patch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

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

&lt;/div&gt;


&lt;p&gt;Be sure to call this at the very beginning of your project, before other scripts are loaded. (e.g. the top of your &lt;code&gt;index.js&lt;/code&gt; file)&lt;/p&gt;

&lt;p&gt;➞ &lt;a href="https://robojs.dev/plugins/patch" rel="noopener noreferrer"&gt;📚 &lt;strong&gt;Documentation:&lt;/strong&gt; @robojs/patch&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  External Requests
&lt;/h3&gt;

&lt;p&gt;This does not affect requests made to external URLs. If you're having &lt;strong&gt;CSP&lt;/strong&gt; issues with those, you may be able to fix them by &lt;strong&gt;&lt;a href="https://dev.to/waveplay/resolve-content-security-policy-csp-issues-in-your-discord-activity-using-a-nodejs-proxy-2634"&gt;creating your own Proxy&lt;/a&gt;&lt;/strong&gt; or mapping them in the &lt;strong&gt;Discord Developer Portal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;➞ &lt;a href="https://dev.to/waveplay/resolve-content-security-policy-csp-issues-in-your-discord-activity-using-a-nodejs-proxy-2634"&gt;📚 &lt;strong&gt;Tutorial:&lt;/strong&gt; Resolve CSP Issues with a Proxy&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/waveplay" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F7676%2F197dbe7a-3b5a-4f7a-a9e8-84e99b2e309b.png" alt="WavePlay" width="800" height="750"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1174683%2F308a8da8-1c55-4d57-848d-78efb857c472.png" alt="" width="800" height="750"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/waveplay/resolve-content-security-policy-csp-issues-in-your-discord-activity-using-a-nodejs-proxy-2634" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Resolve Content Security Policy (CSP) Issues in Your Discord Activity Using a Node.js Proxy&lt;/h2&gt;
      &lt;h3&gt;WavePlay Staff for WavePlay ・ Jun 17&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#discord&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Interested in Discord Activities?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fny52f1vct85yuilxnatt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fny52f1vct85yuilxnatt.png" alt="Image" width="800" height="659"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://robojs.dev/" rel="noopener noreferrer"&gt;Robo.js&lt;/a&gt;&lt;/strong&gt; is a powerful framework for building &lt;strong&gt;Discord Activities&lt;/strong&gt; with ease. It provides a wide range of features and tools to help you create epic Discord experiences!&lt;/p&gt;

&lt;p&gt;Join our &lt;strong&gt;Discord Server&lt;/strong&gt; to chat with other developers, ask questions, and share your projects. We're a friendly bunch and always happy to help! Plus, our very own AI Robo, &lt;strong&gt;Sage&lt;/strong&gt;, is there to assist you with any questions you may have.&lt;/p&gt;

&lt;p&gt;➞ &lt;a href="https://roboplay.dev/discord" rel="noopener noreferrer"&gt;🚀 &lt;strong&gt;Community:&lt;/strong&gt; Join our Discord server&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;➞ &lt;a href="https://dev.to/waveplay/how-to-build-a-discord-activity-easily-with-robojs-5bng"&gt;📚 &lt;strong&gt;Tutorial:&lt;/strong&gt; Creating a Discord Activity in seconds with Robo.js&lt;/a&gt;&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://discord.com/invite/fASAKnJxUP" rel="noopener noreferrer" class="c-link"&gt;
          Robo - Imagine Magic
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Power up Discord with effortless activities, bots, servers, and more! ⚡ | 83 members
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--VtQgo2-a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://discord.com/assets/favicon.ico" width="256" height="256"&gt;
        discord.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;div class="ltag__link"&gt;
  &lt;a href="/waveplay" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F7676%2F197dbe7a-3b5a-4f7a-a9e8-84e99b2e309b.png" alt="WavePlay" width="800" height="750"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1174683%2F308a8da8-1c55-4d57-848d-78efb857c472.png" alt="" width="800" height="750"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/waveplay/how-to-build-a-discord-activity-easily-with-robojs-5bng" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Creating a Discord Activity in seconds with Robo.js&lt;/h2&gt;
      &lt;h3&gt;WavePlay Staff for WavePlay ・ Apr 9&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#discord&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#sdk&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#bot&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>discord</category>
      <category>node</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Build a Portable AI Companion with Discord’s User-Installable Apps (GPT 4o)</title>
      <dc:creator>WavePlay Staff</dc:creator>
      <pubDate>Tue, 18 Jun 2024 14:30:00 +0000</pubDate>
      <link>https://dev.to/waveplay/build-a-portable-ai-companion-with-discords-user-installable-apps-gpt-4o-5f20</link>
      <guid>https://dev.to/waveplay/build-a-portable-ai-companion-with-discords-user-installable-apps-gpt-4o-5f20</guid>
      <description>&lt;p&gt;Discord &lt;strong&gt;&lt;a href="https://discord.com/developers/docs/change-log#userinstallable-apps-preview" rel="noopener noreferrer"&gt;User-Installable Apps&lt;/a&gt;&lt;/strong&gt; are here, which means you can bring &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/discord-bots/getting-started" rel="noopener noreferrer"&gt;Discord Bots&lt;/a&gt;&lt;/strong&gt; with you wherever you go - DMs and even other servers your bot isn't in. Best of all, they're not that different from regular bots!&lt;/p&gt;

&lt;p&gt;So, what if you could have an AI companion that's always there to help you out, tell you jokes, and even give you advice? We'll be using &lt;strong&gt;&lt;a href="https://discord.js.org/" rel="noopener noreferrer"&gt;Discord.js&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://roboplay.dev/docs" rel="noopener noreferrer"&gt;Robo.js&lt;/a&gt;&lt;/strong&gt; to create one. Beginners are welcome!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fk2ibjaqnlx8gtnlj3d43.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fk2ibjaqnlx8gtnlj3d43.png" alt="Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Exciting, right? Let's get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Your Bot Project
&lt;/h2&gt;

&lt;p&gt;Make sure you have &lt;strong&gt;&lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;&lt;/strong&gt; and an editor like &lt;strong&gt;&lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VS Code&lt;/a&gt;&lt;/strong&gt; installed then run the following in your &lt;strong&gt;&lt;a href="https://www.freecodecamp.org/news/command-line-for-beginners/" rel="noopener noreferrer"&gt;terminal&lt;/a&gt;&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx create-robo my-ai-companion &lt;span class="nt"&gt;-k&lt;/span&gt; bot


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

&lt;/div&gt;
&lt;p&gt;This will create a new &lt;strong&gt;Discord.js&lt;/strong&gt; project ready to use as a &lt;strong&gt;Discord Bot&lt;/strong&gt;, made easier with the &lt;strong&gt;Robo.js&lt;/strong&gt; framework. We'll be opting out of &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/robojs/typescript" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;&lt;/strong&gt; to keep things simple.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fjasmcp2d8o4wmmfgnm8w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fjasmcp2d8o4wmmfgnm8w.png" alt="Image"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/waveplay" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F7676%2F197dbe7a-3b5a-4f7a-a9e8-84e99b2e309b.png" alt="WavePlay"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1174683%2F308a8da8-1c55-4d57-848d-78efb857c472.png" alt=""&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/waveplay/how-to-build-a-discord-activity-easily-with-robojs-5bng" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Creating a Discord Activity in seconds with Robo.js&lt;/h2&gt;
      &lt;h3&gt;WavePlay Staff for WavePlay ・ Apr 9&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#discord&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#sdk&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#bot&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding AI Capabilities
&lt;/h2&gt;

&lt;p&gt;Now that we have a shiny new bot, let's give it some AI capabilities!&lt;/p&gt;

&lt;p&gt;Normally, you'd have to handle commands, events, and AI logic yourself, but with &lt;strong&gt;Robo.js&lt;/strong&gt;, you can use plugins to get it instantly. Install the &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/plugins/ai" rel="noopener noreferrer"&gt;@robojs/ai&lt;/a&gt;&lt;/strong&gt; plugin using your &lt;strong&gt;terminal&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx robo add @robojs/ai


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

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Ta-dah!&lt;/strong&gt; Your bot can now chat with users! ✨&lt;/p&gt;

&lt;p&gt;... at least, it will once you get an OpenAI key. &lt;strong&gt;&lt;a href="https://platform.openai.com/signup" rel="noopener noreferrer"&gt;Sign up for OpenAI&lt;/a&gt;&lt;/strong&gt; and get your &lt;strong&gt;&lt;a href="https://platform.openai.com/api-keys" rel="noopener noreferrer"&gt;API key&lt;/a&gt;&lt;/strong&gt;. Once you have it, add it to your project's &lt;code&gt;.env&lt;/code&gt; file:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

OPENAI_API_KEY="your-api-key-here"


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

&lt;/div&gt;
&lt;p&gt;You now have the &lt;code&gt;/chat&lt;/code&gt; and &lt;code&gt;/imagine&lt;/code&gt; slash commands from &lt;strong&gt;@robojs/ai&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Making Your App User-Installable
&lt;/h2&gt;

&lt;p&gt;User installable apps are new, so let's enable this feature in our project's configuration. Open the &lt;code&gt;robo.mjs&lt;/code&gt; file in the &lt;code&gt;config&lt;/code&gt; folder and add the following:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ... rest of config&lt;/span&gt;
    &lt;span class="na"&gt;experimental&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;userInstall&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This will tell &lt;strong&gt;Robo.js&lt;/strong&gt; to register all commands as user installable.&lt;/p&gt;

&lt;p&gt;Next, enable the "User Install" authorization method for this app in the &lt;strong&gt;&lt;a href="https://discord.com/developers/applications" rel="noopener noreferrer"&gt;Discord Developer Portal&lt;/a&gt;&lt;/strong&gt; and give it the &lt;code&gt;application.commands&lt;/code&gt; scope. Oh, and make sure the "Public Bot" setting is enabled. You can share the &lt;strong&gt;Discord Provided Link&lt;/strong&gt; to let users install this app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F0etr52w3691tlhd2yp5t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F0etr52w3691tlhd2yp5t.png" alt="Image"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Trying It Out
&lt;/h2&gt;

&lt;p&gt;Use the &lt;strong&gt;Discord Provided Link&lt;/strong&gt; to install the app to your account then run your project in development mode:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm run dev


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

&lt;/div&gt;
&lt;p&gt;Go on a test server or DM someone and try out the &lt;code&gt;/chat&lt;/code&gt; command. Your AI companion should respond to you!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fpufuow6b47vc0vxcmmj1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fpufuow6b47vc0vxcmmj1.png" alt="Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wanna personalize your AI companion? Open the &lt;code&gt;ai.mjs&lt;/code&gt; file in the &lt;code&gt;/config/plugins/robojs&lt;/code&gt; folder and change the &lt;code&gt;systemMessage&lt;/code&gt; to something you like better. You can change the &lt;code&gt;model&lt;/code&gt; to something smarter like &lt;code&gt;gpt-4o&lt;/code&gt;, or even feed it documents to learn from.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gpt-4o&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;systemMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;You are Darth Vader. Respond like a Sith Lord.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Learn more in the &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/plugins/ai" rel="noopener noreferrer"&gt;@robojs/ai documentation&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ffrf3sd0y0sx8pei6aeg8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ffrf3sd0y0sx8pei6aeg8.png" alt="Image"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating a Context Command
&lt;/h2&gt;

&lt;p&gt;Talking to your AI is fun and all, but what if you want it to respond to other messages? &lt;strong&gt;User-Installable Apps&lt;/strong&gt; support &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/discord-bots/commands" rel="noopener noreferrer"&gt;Context Commands&lt;/a&gt;&lt;/strong&gt; too! They're different from &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/discord-bots/context-menu" rel="noopener noreferrer"&gt;Slash Commands&lt;/a&gt;&lt;/strong&gt; as they take the context of the message into account.&lt;/p&gt;

&lt;p&gt;Let's create a context command called &lt;code&gt;Reply&lt;/code&gt; that responds to any message with "I have no idea what you're talking about" as a placeholder for now. Create a new file in the &lt;code&gt;/src/context/message&lt;/code&gt; folder called &lt;code&gt;Reply.js&lt;/code&gt;. Remember to create the folder if it doesn't exist.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interaction&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;interaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I have no idea what you're talking about&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Right click on the message you want to reply to, look for "Apps", and click on the &lt;code&gt;Reply&lt;/code&gt; context command.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fijndol3597gyp32svwzn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fijndol3597gyp32svwzn.png" alt="Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's replace the placeholder with a more meaningful response. &lt;strong&gt;@robojs/ai&lt;/strong&gt; exports an &lt;code&gt;AI&lt;/code&gt; object to get responses programatically. Update &lt;code&gt;Reply.js&lt;/code&gt; to use it:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&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;AI&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="s1"&gt;@robojs/ai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_interaction&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;AI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chatSync&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;content&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;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I don't know what to say&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Now run the &lt;code&gt;Reply&lt;/code&gt; context command on a message again and watch your AI companion respond!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fsqi7098o4hexk1mrc87u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fsqi7098o4hexk1mrc87u.png" alt="Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why does it work, you ask?&lt;/strong&gt; You may have noticed that our bot was able to access &lt;code&gt;message.content&lt;/code&gt; despite the "Message Content" intent being disabled. This is because &lt;strong&gt;Context Commands&lt;/strong&gt; have access to message content by default.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;interaction&lt;/code&gt; object is also optional when using &lt;strong&gt;Robo.js&lt;/strong&gt;. You can simply return the result instead of using &lt;code&gt;interaction.reply&lt;/code&gt;. Replies are even automatically deferred when your default export is &lt;code&gt;async&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Enjoy Your New Companion!
&lt;/h2&gt;

&lt;p&gt;Now that you have your own User-Installable AI companion, you can take it with you wherever you go on Discord. You can even share it with your friends! You can find the full code for this project written in &lt;strong&gt;TypeScript&lt;/strong&gt; on as a &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/templates/overview" rel="noopener noreferrer"&gt;Robo.js Template&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;➞ &lt;a href="https://github.com/Wave-Play/robo.js/tree/main/templates/discord-bots/purrth-vader" rel="noopener noreferrer"&gt;🔗 &lt;strong&gt;Template:&lt;/strong&gt; Purrth Vader AI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check out the &lt;strong&gt;&lt;a href="https://roboplay.dev/docs" rel="noopener noreferrer"&gt;Robo.js documentation&lt;/a&gt;&lt;/strong&gt; for more cool features and plugins. You can even use it to &lt;strong&gt;&lt;a href="https://dev.to/waveplay/how-to-build-a-discord-activity-easily-with-robojs-5bng"&gt;build Discord Activities in seconds&lt;/a&gt;&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Don't forget to &lt;strong&gt;&lt;a href="https://roboplay.dev/discord" rel="noopener noreferrer"&gt;join our Discord server&lt;/a&gt;&lt;/strong&gt; to chat with other developers, ask questions, and share your projects. We're here to help you build amazing apps with &lt;strong&gt;Robo.js&lt;/strong&gt;! 🚀&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://discord.com/invite/fASAKnJxUP" rel="noopener noreferrer" class="c-link"&gt;
          Robo - Imagine Magic
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Power up Discord with effortless activities, bots, servers, and more! ⚡ | 95 members
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdiscord.com%2Fassets%2Ffavicon.ico"&gt;
        discord.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Our very own Robo, Sage, is there to answer any questions about Robo.js, Discord.js, and more.&lt;/p&gt;

</description>
      <category>discord</category>
      <category>node</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Resolve Content Security Policy (CSP) Issues in Your Discord Activity Using a Node.js Proxy</title>
      <dc:creator>WavePlay Staff</dc:creator>
      <pubDate>Mon, 17 Jun 2024 15:00:00 +0000</pubDate>
      <link>https://dev.to/waveplay/resolve-content-security-policy-csp-issues-in-your-discord-activity-using-a-nodejs-proxy-2634</link>
      <guid>https://dev.to/waveplay/resolve-content-security-policy-csp-issues-in-your-discord-activity-using-a-nodejs-proxy-2634</guid>
      <description>&lt;p&gt;If you're building a &lt;strong&gt;&lt;a href="https://support.discord.com/hc/en-us/articles/4422142836759-Activities-on-Discord" rel="noopener noreferrer"&gt;Discord Activity&lt;/a&gt;&lt;/strong&gt;, you may encounter issues with &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP" rel="noopener noreferrer"&gt;Content Security Policy (CSP)&lt;/a&gt;&lt;/strong&gt; restrictions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSP&lt;/strong&gt; is a security feature that helps prevent &lt;strong&gt;&lt;a href="https://owasp.org/www-community/attacks/xss" rel="noopener noreferrer"&gt;cross-site scripting attacks&lt;/a&gt;&lt;/strong&gt; by restricting the resources a web page can load. However, it can sometimes interfere with loading external resources like images, fonts, or scripts in your activity.&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%2Fh4rr7xajb7ggu14gnlpw.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%2Fh4rr7xajb7ggu14gnlpw.png" alt="Image" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The recommended fix is to use Discord's &lt;strong&gt;&lt;a href="https://discord.com/developers/applications" rel="noopener noreferrer"&gt;URL Mapping&lt;/a&gt;&lt;/strong&gt; feature to rewrite URLs and bypass &lt;strong&gt;CSP&lt;/strong&gt; restrictions. However, this method has limitations and may not work in all cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Proxies to the Rescue
&lt;/h2&gt;

&lt;p&gt;An alternative solution is to use a &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Proxy_servers_and_tunneling" rel="noopener noreferrer"&gt;proxy server&lt;/a&gt;&lt;/strong&gt; to fetch external resources and serve them from your server. This way, you can bypass &lt;strong&gt;CSP&lt;/strong&gt; restrictions and load resources without any issues.&lt;/p&gt;

&lt;p&gt;The way it works is simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your activity makes a request to your server for an external resource.&lt;/li&gt;
&lt;li&gt;Your server fetches the resource and streams it back as a response.&lt;/li&gt;
&lt;li&gt;Your activity receives the resource from your server, bypassing &lt;strong&gt;CSP&lt;/strong&gt; restrictions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This method allows you to load any content from any source without having to map each domain individually in Discord's &lt;strong&gt;URL Mapping&lt;/strong&gt;. It may sound complex, but it's &lt;strong&gt;literally one line of code&lt;/strong&gt; if you created your &lt;strong&gt;Discord Activity&lt;/strong&gt; with &lt;strong&gt;&lt;a href="https://roboplay.dev/docs" rel="noopener noreferrer"&gt;Robo.js&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Discord Activity Project
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://dev.to/waveplay/how-to-build-a-discord-activity-easily-with-robojs-5bng"&gt;Create a Discord Activity with Robo.js&lt;/a&gt;&lt;/strong&gt; if you don't have one already:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-robo my-activity &lt;span class="nt"&gt;-k&lt;/span&gt; activity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We'll be using &lt;strong&gt;&lt;a href="https://react.dev" rel="noopener noreferrer"&gt;React&lt;/a&gt;&lt;/strong&gt; for this example, but you can apply the same principles to any frontend framework or vanilla &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML" rel="noopener noreferrer"&gt;HTML&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS" rel="noopener noreferrer"&gt;CSS&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We highly recommend using &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/cli/create-robo" rel="noopener noreferrer"&gt;create-robo&lt;/a&gt;&lt;/strong&gt; to create a &lt;strong&gt;Discord Activity&lt;/strong&gt; project. &lt;strong&gt;&lt;a href="https://roboplay.dev/docs" rel="noopener noreferrer"&gt;Robo.js&lt;/a&gt;&lt;/strong&gt; providers a lot of features and tools to help you build your activity faster and more efficiently, such as &lt;strong&gt;&lt;a href="https://dev.to/waveplay/how-to-add-multiplayer-to-your-discord-activity-lo1"&gt;Multiplayer Support&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/discord-activities/hosting" rel="noopener noreferrer"&gt;Easy Hosting&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/discord-activities/tunnels" rel="noopener noreferrer"&gt;Streamlined Tunnels&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/robojs/flashcore" rel="noopener noreferrer"&gt;Built-in Database&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/plugins/overview" rel="noopener noreferrer"&gt;Plugin System&lt;/a&gt;&lt;/strong&gt;, and so much more!&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/waveplay" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&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%2Forganization%2Fprofile_image%2F7676%2F197dbe7a-3b5a-4f7a-a9e8-84e99b2e309b.png" alt="WavePlay" width="800" height="750"&gt;
      &lt;div class="ltag__link__user__pic"&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%2Fuser%2Fprofile_image%2F1174683%2F308a8da8-1c55-4d57-848d-78efb857c472.png" alt="" width="800" height="750"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/waveplay/how-to-build-a-discord-activity-easily-with-robojs-5bng" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Creating a Discord Activity in seconds with Robo.js&lt;/h2&gt;
      &lt;h3&gt;WavePlay Staff for WavePlay ・ Apr 9&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#discord&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#sdk&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#bot&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Making a Music Player
&lt;/h2&gt;

&lt;p&gt;Let's say you want to add an audio player to your activity that plays music from an external source. You might run into &lt;strong&gt;CSP&lt;/strong&gt; issues when trying to load the audio file due to restrictions on loading external resources.&lt;/p&gt;

&lt;p&gt;Let's create a simple music player using the &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt; element in &lt;strong&gt;React&lt;/strong&gt; by adding a new file named &lt;code&gt;Player.tsx&lt;/code&gt; inside the &lt;code&gt;/src/app&lt;/code&gt; folder:&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;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRef&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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Player&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;audioRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isPlaying&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsPlaying&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;togglePlayPause&lt;/span&gt; &lt;span class="o"&gt;=&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;audio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;audioRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&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;audio&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;isPlaying&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;audio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pause&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&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;audio&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isPlaying&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;audio&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="nf"&gt;setIsPlaying&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isPlaying&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="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;audio&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;audioRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;preload&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"auto"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;togglePlayPause&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isPlaying&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pause&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;Play&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&amp;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;Then update your &lt;code&gt;Activity.tsx&lt;/code&gt; file to use it:&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;Player&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="s1"&gt;./Player&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ExternalUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://media.waveplay.com/t/ckwldfuiq6608re6x8dzc5tyt.mp3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Activity&lt;/span&gt; &lt;span class="o"&gt;=&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/rocket.png"&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"logo"&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Discord"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, World&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Player&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ExternalUrl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;small&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    Powered by&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"robojs"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://roboplay.dev/docs"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        Robo.js
                    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;small&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;In this example, we're loading an audio file from an external source and playing it using the &lt;code&gt;&amp;lt;audio&amp;gt;&lt;/code&gt; element. However, this also triggers a &lt;strong&gt;CSP&lt;/strong&gt; violation because &lt;code&gt;https://media.waveplay.com&lt;/code&gt; is not whitelisted in &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/discord-activities/proxy" rel="noopener noreferrer"&gt;Discord's Proxy&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's fix this by creating a proxy!&lt;/p&gt;
&lt;h2&gt;
  
  
  Create Your Own Proxy
&lt;/h2&gt;

&lt;p&gt;Create a new file named &lt;code&gt;proxy.js&lt;/code&gt; inside the &lt;code&gt;/src/api&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&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="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&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;&lt;em&gt;That's it!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/plugins/server" rel="noopener noreferrer"&gt;@robojs/server&lt;/a&gt;&lt;/strong&gt; plugin used in this &lt;strong&gt;Robo.js&lt;/strong&gt; project extends the standard web &lt;strong&gt;&lt;a href="https://developer.mozilla.org/docs/Web/API/Request" rel="noopener noreferrer"&gt;Request&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://developer.mozilla.org/docs/Web/API/Response" rel="noopener noreferrer"&gt;Response&lt;/a&gt;&lt;/strong&gt; interfaces which work seamlessly with &lt;strong&gt;&lt;a href="https://developer.mozilla.org/docs/Web/API/Fetch_API" rel="noopener noreferrer"&gt;Fetch API&lt;/a&gt;&lt;/strong&gt;, which is why we can return the result directly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Heads up!&lt;/strong&gt; You'll need at least &lt;strong&gt;@robojs/server&lt;/strong&gt; version &lt;code&gt;0.5.3&lt;/code&gt; or newer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, update your &lt;code&gt;Activity.tsx&lt;/code&gt; file to use the proxy:&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Player&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/proxy?url=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;ExternalUrl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;By adding the &lt;code&gt;/api/proxy?url=&lt;/code&gt; prefix to the audio URL, we're telling our server to fetch the audio file and serve it back to the activity without triggering &lt;strong&gt;CSP&lt;/strong&gt; violations.&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%2Fu3obwnrg2yk3jkupu8jy.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%2Fu3obwnrg2yk3jkupu8jy.png" alt="Image" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use this method to proxy any external resource in your activity, such as images, fonts, scripts, or other media files. For more complex scenarios, such as web pages, our upcoming &lt;strong&gt;@robojs/browser&lt;/strong&gt; plugin will provide a more robust solution.&lt;/p&gt;
&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;p&gt;While this method is effective for bypassing &lt;strong&gt;CSP&lt;/strong&gt; restrictions, it does introduce additional latency because your server has to fetch the resource before serving it back to the activity. This may impact the performance of your activity, especially for large files or high traffic, so make sure your &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/discord-activities/hosting" rel="noopener noreferrer"&gt;Hosting Service&lt;/a&gt;&lt;/strong&gt; can handle it.&lt;/p&gt;

&lt;p&gt;Be aware of potential security risks when using a proxy server, such as &lt;strong&gt;&lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html" rel="noopener noreferrer"&gt;URL Injections&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://owasp.org/Top10/A10_2021-Server-Side_Request_Forgery_(SSRF)" rel="noopener noreferrer"&gt;SSRF (Server-Side Request Forgery)&lt;/a&gt;&lt;/strong&gt; attacks. Always use Discord's &lt;strong&gt;URL Mapping&lt;/strong&gt; whenever possible and only resort to proxies when necessary.&lt;/p&gt;
&lt;h2&gt;
  
  
  Easy, Right?
&lt;/h2&gt;

&lt;p&gt;By creating a simple proxy server, you can bypass &lt;strong&gt;CSP&lt;/strong&gt; restrictions and load external resources in your &lt;strong&gt;Discord Activity&lt;/strong&gt; without any issues. This method is easy and effective, allowing you to focus on building your activity without worrying about security restrictions. You can find the complete source code for this example available in &lt;strong&gt;TypeScript&lt;/strong&gt; as a &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/templates/overview" rel="noopener noreferrer"&gt;Robo.js Template&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;➞ &lt;a href="https://github.com/Wave-Play/robo.js/tree/main/templates/discord-activities/music-player-proxy" rel="noopener noreferrer"&gt;🔗 &lt;strong&gt;Template:&lt;/strong&gt; Music Player Proxy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't forget to &lt;strong&gt;&lt;a href="https://roboplay.dev/discord" rel="noopener noreferrer"&gt;join our Discord server&lt;/a&gt;&lt;/strong&gt; to chat with other developers, ask questions, and share your projects. We're here to help you build amazing apps with &lt;strong&gt;Robo.js&lt;/strong&gt;! 🚀&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://discord.com/invite/fASAKnJxUP" rel="noopener noreferrer" class="c-link"&gt;
          Robo - Imagine Magic
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Power up Discord with effortless activities, bots, servers, and more! ⚡ | 178 members
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdiscord.com%2Fassets%2Ffavicon.ico" width="800" height="400"&gt;
        discord.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;Our very own Robo, &lt;strong&gt;Sage&lt;/strong&gt;, is there to answer any questions about Robo.js, Discord.js, and more!&lt;/p&gt;

</description>
      <category>discord</category>
      <category>programming</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Achieve Game-Like Scaling in Discord Activities and Web Apps Using CSS</title>
      <dc:creator>WavePlay Staff</dc:creator>
      <pubDate>Mon, 03 Jun 2024 15:30:00 +0000</pubDate>
      <link>https://dev.to/waveplay/achieve-game-like-scaling-in-discord-activities-and-web-apps-using-css-874</link>
      <guid>https://dev.to/waveplay/achieve-game-like-scaling-in-discord-activities-and-web-apps-using-css-874</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;a href="https://support.discord.com/hc/en-us/articles/4422142836759-Activities-on-Discord" rel="noopener noreferrer"&gt;Discord Activities&lt;/a&gt;&lt;/strong&gt; are awesome! They run inside Discord and can be all sorts of cool things like games, quizzes, and more. But if you're developing using web technologies rather than game engines, you might run into a common problem: scaling.&lt;/p&gt;

&lt;p&gt;In this article, we'll show you how to achieve game-like scaling in your Discord Activities and web apps using plain CSS. This will allow you to create responsive designs that look great on any device, &lt;strong&gt;&lt;a href="https://docs.unity3d.com/2020.1/Documentation/Manual/HOWTO-UIMultiResolution.html" rel="noopener noreferrer"&gt;just like a game&lt;/a&gt;&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F8ak6x8twhs5fbnc7q15x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F8ak6x8twhs5fbnc7q15x.png" alt="Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Scaling
&lt;/h2&gt;

&lt;p&gt;Screen sizes vary widely, even among devices of the same type. This can make it challenging to create a design that looks good on all screens. If you've ever built a Discord Activity using HTML and CSS, you've probably encountered this issue. &lt;/p&gt;

&lt;p&gt;Suppose you have a button with a fixed size. On a large desktop screen, the button might look tiny, while on a smaller screen, it might be too big and take up a large portion of the screen. That's fine for standard web apps, but for Discord Activities, you may want everyone to have a similar experience, regardless of their screen size.&lt;/p&gt;

&lt;p&gt;This is even more of a problem when you minimize the activity window or navigate elsewhere in Discord. Your page might look tiny and miss out a lot of the content, or it might be too large and require scrolling to see everything!&lt;/p&gt;

&lt;p&gt;Before scaling, content looks huge and most of it is cut off:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fdui0h7pkqqs7htb6r9ql.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fdui0h7pkqqs7htb6r9ql.png" alt="Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After scaling, content fits the screen and is fully visible:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fqe2qhertaml03di76vdr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fqe2qhertaml03di76vdr.png" alt="Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a Discord Activity Project
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://dev.to/waveplay/how-to-build-a-discord-activity-easily-with-robojs-5bng"&gt;Create a Discord Activity project&lt;/a&gt;&lt;/strong&gt; if you don't have one already:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx create-robo my-activity &lt;span class="nt"&gt;-k&lt;/span&gt; activity


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

&lt;/div&gt;
&lt;p&gt;We'll be using &lt;strong&gt;&lt;a href="https://react.dev" rel="noopener noreferrer"&gt;React&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/robojs/typescript" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;&lt;/strong&gt; for this example, but you can apply the same principles to any frontend framework or vanilla &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML" rel="noopener noreferrer"&gt;HTML&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS" rel="noopener noreferrer"&gt;CSS&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We highly recommend using &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/cli/create-robo" rel="noopener noreferrer"&gt;create-robo&lt;/a&gt;&lt;/strong&gt; to create a &lt;strong&gt;Discord Activity&lt;/strong&gt; project. &lt;strong&gt;&lt;a href="https://roboplay.dev/docs" rel="noopener noreferrer"&gt;Robo.js&lt;/a&gt;&lt;/strong&gt; providers a lot of features and tools to help you build your activity faster and more efficiently, such as &lt;strong&gt;&lt;a href="https://dev.to/waveplay/how-to-add-multiplayer-to-your-discord-activity-lo1"&gt;Multiplayer Support&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/discord-activities/hosting" rel="noopener noreferrer"&gt;Easy Hosting&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/discord-activities/tunnels" rel="noopener noreferrer"&gt;Streamlined Tunnels&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/robojs/flashcore" rel="noopener noreferrer"&gt;Built-in Database&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/plugins/overview" rel="noopener noreferrer"&gt;Plugin System&lt;/a&gt;&lt;/strong&gt;, and so much more!&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/waveplay" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F7676%2F197dbe7a-3b5a-4f7a-a9e8-84e99b2e309b.png" alt="WavePlay"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1174683%2F308a8da8-1c55-4d57-848d-78efb857c472.png" alt=""&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/waveplay/how-to-build-a-discord-activity-easily-with-robojs-5bng" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Creating a Discord Activity in seconds with Robo.js&lt;/h2&gt;
      &lt;h3&gt;WavePlay Staff for WavePlay ・ Apr 9&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#discord&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#sdk&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#bot&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Achieving Game-Like Scaling
&lt;/h2&gt;

&lt;p&gt;First, decide on a base resolution for your activity. This will be the resolution you design your activity for. For this example, let's use &lt;code&gt;1280x720&lt;/code&gt;. This is a common resolution for games and will work well for our purposes, especially since Discord enforces this aspect ratio for activities.&lt;/p&gt;

&lt;p&gt;In game design, developers often create assets for a &lt;strong&gt;&lt;a href="https://gamemaker.io/en/tutorials/the-basics-of-scaling-the-game-camera" rel="noopener noreferrer"&gt;base resolution&lt;/a&gt;&lt;/strong&gt; and scale up or down from there to fit the player's screen. This ensures consistency in the visual experience. We can apply the same principle to our Discord Activities and web apps using CSS via the &lt;code&gt;transform&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;Next, let's create a wrapper component that will handle the scaling for us. We'll use the &lt;code&gt;transform&lt;/code&gt; property to scale the content based on the user's screen size. Here's a simple example:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// src/components/ScaleProvider.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ReactNode&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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ScaleContextType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;ScaleContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ScaleContextType&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;useScale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;ScaleContextType&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;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ScaleContext&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;useScale must be used within a ScaleProvider&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ScaleProviderProps&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;baseWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;
    &lt;span class="nx"&gt;baseHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;ReactNode&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ScaleProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ScaleProviderProps&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;baseWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;baseHeight&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="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setScale&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleResize&lt;/span&gt; &lt;span class="o"&gt;=&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;scaleWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerWidth&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;baseWidth&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scaleHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;baseHeight&lt;/span&gt;
            &lt;span class="nf"&gt;setScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scaleWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;scaleHeight&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nf"&gt;handleResize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleResize&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;resize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleResize&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="nx"&gt;baseWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;baseHeight&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ScaleContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
                &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`scale(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;scale&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="na"&gt;transformOrigin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;top left&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100vw&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;100vh&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;
                    &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;baseWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;baseHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ScaleContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;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;Now, wrap your main app component with the &lt;code&gt;ScaleProvider&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// src/app/App.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DiscordContextProvider&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="s1"&gt;../hooks/useDiscordSdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Activity&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="s1"&gt;./Activity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ScaleProvider&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="s1"&gt;./ScaleProvider&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DiscordContextProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ScaleProvider&lt;/span&gt; &lt;span class="na"&gt;baseWidth&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;1280&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;baseHeight&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;720&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Activity&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ScaleProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;DiscordContextProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;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;This &lt;code&gt;ScaleProvider&lt;/code&gt; component will scale its children based on the user's screen size. It calculates the scale factor by dividing the screen width and height by the base resolution. It then applies this scale factor to the content using the &lt;code&gt;transform&lt;/code&gt; property. Transforms run on the GPU, so they're very efficient and won't cause performance issues!&lt;/p&gt;

&lt;p&gt;If you need to reference the scale factor in your components, you can use the &lt;code&gt;useScale&lt;/code&gt; hook.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;scale&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useScale&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


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

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

&lt;p&gt;Now, your activity will scale up or down based on the user's screen size, providing a consistent experience for everyone. You can design your activity for the base resolution and trust that it will look great on any screen!&lt;/p&gt;

&lt;p&gt;Don't forget to &lt;strong&gt;&lt;a href="https://roboplay.dev/discord" rel="noopener noreferrer"&gt;join our Discord server&lt;/a&gt;&lt;/strong&gt; to chat with other developers, ask questions, and share your projects. We're here to help you build amazing apps with &lt;strong&gt;Robo.js&lt;/strong&gt;! 🚀&lt;/p&gt;

&lt;p&gt;&lt;a href="https://roboplay.dev/discord" class="ltag_cta ltag_cta--branded" rel="noopener noreferrer"&gt;🚀 Community: Join our Discord Server&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;Our very own Robo, &lt;strong&gt;Sage&lt;/strong&gt;, is there to answer any questions about Robo.js, Discord.js, and more!&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://discord.com/invite/fASAKnJxUP" rel="noopener noreferrer" class="c-link"&gt;
          Robo - Imagine Magic
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Power up Discord with effortless activities, bots, servers, and more! ⚡ | 95 members
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdiscord.com%2Fassets%2Ffavicon.ico"&gt;
        discord.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




&lt;div class="ltag__link"&gt;
  &lt;a href="/waveplay" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F7676%2F197dbe7a-3b5a-4f7a-a9e8-84e99b2e309b.png" alt="WavePlay"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1174683%2F308a8da8-1c55-4d57-848d-78efb857c472.png" alt=""&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/waveplay/how-to-add-multiplayer-to-your-discord-activity-lo1" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;How to Add Multiplayer to Your Discord Activity&lt;/h2&gt;
      &lt;h3&gt;WavePlay Staff for WavePlay ・ May 21&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#discord&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>javascript</category>
      <category>programming</category>
      <category>node</category>
      <category>discord</category>
    </item>
    <item>
      <title>Add Advanced Features to Your Discord Bot Without Code (Discord.js + Robo.js)</title>
      <dc:creator>WavePlay Staff</dc:creator>
      <pubDate>Fri, 31 May 2024 15:30:00 +0000</pubDate>
      <link>https://dev.to/waveplay/easily-add-advanced-features-to-your-discord-bot-without-coding-discordjs-robojs-13lp</link>
      <guid>https://dev.to/waveplay/easily-add-advanced-features-to-your-discord-bot-without-coding-discordjs-robojs-13lp</guid>
      <description>&lt;p&gt;Got a &lt;strong&gt;Discord Bot&lt;/strong&gt; you'd like to enhance with advanced features? &lt;strong&gt;&lt;a href="https://roboplay.dev/docs"&gt;Robo.js&lt;/a&gt;&lt;/strong&gt; is a powerful framework compatible with &lt;strong&gt;&lt;a href="https://discord.js.org/"&gt;Discord.js&lt;/a&gt;&lt;/strong&gt; with a &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/plugins/overview"&gt;plugin system&lt;/a&gt;&lt;/strong&gt; so powerful, you can add new features to your bot without writing a single line of code. If you're a beginner, you can add powerful features as you learn how to code the rest of it!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv35lgujwa1dbbulcckm7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv35lgujwa1dbbulcckm7.png" alt="Image" width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a New Discord Bot
&lt;/h2&gt;

&lt;p&gt;If you haven't already created a &lt;strong&gt;Discord Bot&lt;/strong&gt;, you can do so by running the following command in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-robo &amp;lt;projectName&amp;gt; &lt;span class="nt"&gt;-k&lt;/span&gt; bot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will spawn a new &lt;strong&gt;Robo.js&lt;/strong&gt; project ready to use as a &lt;strong&gt;Discord Bot&lt;/strong&gt;. We call these &lt;strong&gt;Robos&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Features
&lt;/h2&gt;

&lt;p&gt;Once you have your &lt;strong&gt;Discord Bot&lt;/strong&gt; set up, you can add new features using &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/plugins/overview"&gt;Robo Plugins&lt;/a&gt;&lt;/strong&gt;. These plugins integrate seamlessly with your &lt;strong&gt;Robo&lt;/strong&gt; to provide new functionality as if you had written the code yourself. For example, you can add AI chatbot capabilities, moderation tools, maintenance mode, economy systems, and more.&lt;/p&gt;

&lt;p&gt;Run this in your terminal, replacing  with the name of the plugin you want to install (e.g. &lt;strong&gt;@robojs/ai&lt;/strong&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx robo add &amp;lt;package&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install the package and register it in your Robo's configuration. To install many at once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx robo add @robojs/ai @robojs/moderation @robojs/server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also create a new Robo project with plugins pre-installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-robo &amp;lt;projectName&amp;gt; &lt;span class="nt"&gt;--plugins&lt;/span&gt; @robojs/ai @robojs/moderation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Existing Bots
&lt;/h2&gt;

&lt;p&gt;If you have an existing &lt;strong&gt;Discord.js Bot&lt;/strong&gt; and want to add new features, you'll need to &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/docs/discord-bots/migrate"&gt;migrate&lt;/a&gt;&lt;/strong&gt; your bot to &lt;strong&gt;Robo.js&lt;/strong&gt;. This process is straightforward and involves moving your existing code into the &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/robojs/files"&gt;Robo File Structure&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once your bot is migrated, you can add new features using &lt;strong&gt;Robo Plugins&lt;/strong&gt; as described above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to Find Plugins
&lt;/h2&gt;

&lt;p&gt;You can find a list of available plugins in the &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/plugins/directory"&gt;Robo Plugin Directory&lt;/a&gt;&lt;/strong&gt;. Browse through the directory to find plugins that suit your needs and add them to your bot. You can also &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/plugins/create"&gt;create your own plugins&lt;/a&gt;&lt;/strong&gt; and share them with the community.&lt;/p&gt;

&lt;p&gt;➞ &lt;a href="https://docs.roboplay.dev/plugins/directory"&gt;🔌 &lt;strong&gt;Plugin Directory:&lt;/strong&gt; Explore more plugins&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What's more, &lt;strong&gt;Robo.js&lt;/strong&gt; comes with a lot of other features and tools to help you build your bot faster and more efficiently, such as &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/robojs/flashcore"&gt;Flashcore Database&lt;/a&gt;&lt;/strong&gt; to persist data easily, &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/robojs/typescript"&gt;TypeScript&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/hosting/overview"&gt;Easy Hosting&lt;/a&gt;&lt;/strong&gt;, and so much more. You can even use it to &lt;strong&gt;&lt;a href="https://dev.to/waveplay/how-to-build-a-discord-activity-easily-with-robojs-5bng"&gt;build Discord Activities in seconds&lt;/a&gt;&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Don't forget to &lt;strong&gt;&lt;a href="https://roboplay.dev/discord"&gt;join our Discord server&lt;/a&gt;&lt;/strong&gt; to chat with other developers, ask questions, and share your projects. We're here to help you build amazing apps with &lt;strong&gt;Robo.js&lt;/strong&gt;! 🚀&lt;/p&gt;

&lt;p&gt;➞ &lt;a href="https://roboplay.dev/discord"&gt;🚀 &lt;strong&gt;Community:&lt;/strong&gt; Join our Discord Server&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our very own Robo, &lt;strong&gt;Sage&lt;/strong&gt;, is there to answer any questions about Robo.js, Discord.js, and more!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>programming</category>
      <category>discord</category>
    </item>
    <item>
      <title>How to Fix Stuck Ready Event in Discord Embedded App SDK</title>
      <dc:creator>WavePlay Staff</dc:creator>
      <pubDate>Mon, 27 May 2024 22:00:00 +0000</pubDate>
      <link>https://dev.to/waveplay/how-to-fix-stuck-ready-event-in-discord-embedded-app-sdk-h9e</link>
      <guid>https://dev.to/waveplay/how-to-fix-stuck-ready-event-in-discord-embedded-app-sdk-h9e</guid>
      <description>&lt;p&gt;If you've been following Discord's &lt;strong&gt;&lt;a href="https://discord.com/developers/docs/activities/building-an-activity"&gt;Building Your First Activity&lt;/a&gt;&lt;/strong&gt; tutorial, you may have encountered an issue where the &lt;strong&gt;&lt;a href="https://github.com/discord/embedded-app-sdk"&gt;Embedded App SDK&lt;/a&gt;&lt;/strong&gt; gets stuck on the &lt;code&gt;READY&lt;/code&gt; event. This issue can be caused by a few different things, but the most common cause is &lt;strong&gt;&lt;a href="https://vitejs.dev/"&gt;Vite's&lt;/a&gt;&lt;/strong&gt; hot module reloading &lt;strong&gt;&lt;a href="https://vitejs.dev/guide/api-hmr.html"&gt;(HMR)&lt;/a&gt;&lt;/strong&gt; feature.&lt;/p&gt;

&lt;p&gt;We've seen &lt;strong&gt;&lt;a href="https://github.com/discord/embedded-app-sdk/issues/41"&gt;this issue&lt;/a&gt;&lt;/strong&gt; pop up in a &lt;strong&gt;&lt;a href="https://discord.com/channels/613425648685547541/1219458343513358356"&gt;few different places&lt;/a&gt;&lt;/strong&gt;, so we wanted to provide a quick guide on how to fix it. This post will explain it in more detail and suggest ways around it.&lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR; Quick Fix
&lt;/h2&gt;

&lt;p&gt;If you're in a hurry, the quickest way to fix this without disabling HMR is to make sure you're creating only one instance of the &lt;code&gt;DiscordSDK&lt;/code&gt; close to the root of your app. Check out &lt;strong&gt;&lt;a href="https://github.com/Wave-Play/robo.js/tree/main/templates/starter-app-js-react"&gt;this template&lt;/a&gt;&lt;/strong&gt; to see how it's done.&lt;/p&gt;

&lt;p&gt;You can also create a new &lt;strong&gt;Discord Activity&lt;/strong&gt; project with the fix already included by running this in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-robo &amp;lt;projectName&amp;gt; &lt;span class="nt"&gt;-k&lt;/span&gt; activity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What's Happening?
&lt;/h2&gt;

&lt;p&gt;When you're developing a &lt;strong&gt;Discord Activity&lt;/strong&gt; with &lt;strong&gt;Vite&lt;/strong&gt;, the hot module reloading feature can cause the SDK to be re-created multiple times. This is because &lt;strong&gt;Vite&lt;/strong&gt; reloads the module when you make changes, which can cause the &lt;code&gt;DiscordSDK&lt;/code&gt; to be reinitialized. &lt;/p&gt;

&lt;p&gt;Unfortunately, &lt;code&gt;discordSdk.ready()&lt;/code&gt; gets stuck on the &lt;code&gt;READY&lt;/code&gt; event because &lt;strong&gt;&lt;a href="https://github.com/discord/embedded-app-sdk/issues/41#issuecomment-2062926815"&gt;Discord sends the payload once per instance&lt;/a&gt;&lt;/strong&gt;. That means your activity will be left waiting for the &lt;code&gt;READY&lt;/code&gt; event to fire, but it never will until you restart it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting Fresh with a Fix
&lt;/h2&gt;

&lt;p&gt;To fix this issue, you need to ensure that you're only creating one instance of the &lt;code&gt;DiscordSDK&lt;/code&gt; close to the root of your app. This way, the SDK won't be re-initialized every time you make changes, thus you won't need to &lt;code&gt;await discordSdk.ready()&lt;/code&gt; more than once.&lt;/p&gt;

&lt;p&gt;The easiest and fastest way to prevent this is to make sure you start from a template that already has this fix in place. You can &lt;strong&gt;&lt;a href=""&gt;clone this template&lt;/a&gt;&lt;/strong&gt; or create a new project with the fix included by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-robo &amp;lt;projectName&amp;gt; &lt;span class="nt"&gt;-k&lt;/span&gt; activity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new &lt;strong&gt;Discord Activity&lt;/strong&gt; project with the fix already in place, so you won't have to worry about this issue. Check out our guide for more info!&lt;/p&gt;

&lt;p&gt;➞ &lt;a href="https://dev.to/waveplay/how-to-build-a-discord-activity-easily-with-robojs-5bng"&gt;✨ &lt;strong&gt;Guide:&lt;/strong&gt; Creating a Discord Activity in seconds with Robo.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6dtw3dql9wofx0coon46.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6dtw3dql9wofx0coon46.png" alt="Image" width="800" height="593"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing Your Existing Project
&lt;/h2&gt;

&lt;p&gt;If you're already working on a project and don't want to start over, you can fix this issue by ensuring that you're only creating one instance of the &lt;code&gt;DiscordSDK&lt;/code&gt; close to the root of your app. For example, in a &lt;strong&gt;&lt;a href="https://react.dev"&gt;React&lt;/a&gt;&lt;/strong&gt; app, you can use a &lt;strong&gt;&lt;a href="https://react.dev/docs/context"&gt;Context&lt;/a&gt;&lt;/strong&gt; to manage the SDK instance.&lt;/p&gt;

&lt;p&gt;Here's a simplified example:&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;DiscordSDK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DiscordSDKMock&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="s1"&gt;@discord/embedded-app-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useContext&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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;discordSdk&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;DiscordSDK&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_DISCORD_CLIENT_ID&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;DiscordContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;discordSdk&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;DiscordContextProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&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="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="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;setupResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDiscordSdkSetup&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DiscordContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setupResult&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;DiscordContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useDiscordSdk&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="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;DiscordContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useDiscordSdkSetup&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 setup logic here (e.g., discordSdk.ready() in a useEffect)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;discordSdk&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;Then apply the &lt;code&gt;DiscordContextProvider&lt;/code&gt; at the root of your app:&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;DiscordContextProvider&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="s1"&gt;../hooks/useDiscordSdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Activity&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="s1"&gt;./Activity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DiscordContextProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Activity&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;DiscordContextProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;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;This way, &lt;strong&gt;Vite&lt;/strong&gt; won't re-initialize the &lt;code&gt;DiscordSDK&lt;/code&gt; every time you make changes, and you won't get stuck on the &lt;code&gt;READY&lt;/code&gt; event. It works like so:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;DiscordSDK&lt;/code&gt; is created once and passed down through the context.&lt;/li&gt;
&lt;li&gt;The SDK is initialized in the context provider.&lt;/li&gt;
&lt;li&gt;Components can access the SDK through the custom &lt;code&gt;useDiscordSdk&lt;/code&gt; hook.&lt;/li&gt;
&lt;li&gt;The same SDK instance will be re-used, as long as you don't edit the &lt;code&gt;useDiscordSdk&lt;/code&gt; file.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;React's &lt;strong&gt;&lt;a href="https://react.dev/docs/context"&gt;Context&lt;/a&gt;&lt;/strong&gt; is a great way to manage global state in your app, and it's perfect for managing the &lt;code&gt;DiscordSDK&lt;/code&gt; instance. By ensuring that you only create one instance of the SDK close to the root of your app, you can prevent the &lt;code&gt;READY&lt;/code&gt; event from getting stuck and avoid the need to restart your activity every time you make changes.&lt;/p&gt;

&lt;p&gt;We highly recommend using &lt;code&gt;create-robo&lt;/code&gt; to create a &lt;strong&gt;Discord Activity&lt;/strong&gt; project. These templates are designed to help you get started quickly and avoid common issues like this one. What's more, they come with a lot of other features and tools to help you build your activity faster and more efficiently, such as &lt;strong&gt;&lt;a href="https://dev.to/waveplay/how-to-add-multiplayer-to-your-discord-activity-lo1"&gt;Multiplayer Support&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/robojs/typescript"&gt;TypeScript&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/discord-activities/hosting"&gt;Easy Hosting&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/discord-activities/tunnels"&gt;Streamlined Tunnels&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/robojs/flashcore"&gt;Built-in Database&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/plugins/overview"&gt;Plugin System&lt;/a&gt;&lt;/strong&gt;, and so much more!&lt;/p&gt;

&lt;p&gt;Don't forget to &lt;strong&gt;&lt;a href="https://roboplay.dev/discord"&gt;join our Discord server&lt;/a&gt;&lt;/strong&gt; to chat with other developers, ask questions, and share your projects. We're here to help you build amazing apps with &lt;strong&gt;Robo.js&lt;/strong&gt;! 🚀&lt;/p&gt;

&lt;p&gt;➞ &lt;a href="https://roboplay.dev/discord"&gt;🚀 &lt;strong&gt;Community:&lt;/strong&gt; Join our Discord Server&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our very own Robo, &lt;strong&gt;Sage&lt;/strong&gt;, is there to answer any questions about Robo.js, Discord.js, and more&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>discord</category>
      <category>node</category>
    </item>
    <item>
      <title>How to Add Multiplayer to Your Discord Activity</title>
      <dc:creator>WavePlay Staff</dc:creator>
      <pubDate>Tue, 21 May 2024 20:45:00 +0000</pubDate>
      <link>https://dev.to/waveplay/how-to-add-multiplayer-to-your-discord-activity-lo1</link>
      <guid>https://dev.to/waveplay/how-to-add-multiplayer-to-your-discord-activity-lo1</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;a href="https://support.discord.com/hc/en-us/articles/4422142836759-Activities-on-Discord" rel="noopener noreferrer"&gt;Discord Activities&lt;/a&gt;&lt;/strong&gt; are web apps that run inside Discord, typically in the form of games or other interactive content using Discord's &lt;strong&gt;&lt;a href="https://github.com/discord/embedded-app-sdk/" rel="noopener noreferrer"&gt;Embedded App SDK&lt;/a&gt;&lt;/strong&gt;. They're currently in preview, but you can start building them today!&lt;/p&gt;

&lt;p&gt;In this guide, we'll create a video player that everyone in a channel can control as a &lt;strong&gt;Discord Activity&lt;/strong&gt; using &lt;strong&gt;&lt;a href="https://roboplay.dev/docs" rel="noopener noreferrer"&gt;Robo.js&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;React&lt;/a&gt;&lt;/strong&gt;. Let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the Activity Project
&lt;/h2&gt;

&lt;p&gt;First, you'll need to have &lt;strong&gt;&lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;&lt;/strong&gt; installed and an editor like &lt;strong&gt;&lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VS Code&lt;/a&gt;&lt;/strong&gt; to get started. Next, create a new &lt;strong&gt;Discord Activity&lt;/strong&gt; project using the following command in your terminal:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx create-robo &amp;lt;projectName&amp;gt; &lt;span class="nt"&gt;-k&lt;/span&gt; activity


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

&lt;/div&gt;

&lt;p&gt;This will spawn a new &lt;strong&gt;Discord Activity&lt;/strong&gt; project ready to use and made easier with the &lt;strong&gt;Robo.js&lt;/strong&gt; framework. For this guide, we'll be using &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/robojs/typescript" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;React&lt;/a&gt;&lt;/strong&gt;. We've named our project &lt;strong&gt;&lt;code&gt;teamplay&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F47nrlpiadpiuo324xa6k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F47nrlpiadpiuo324xa6k.png" alt="Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If this is your first time making a &lt;strong&gt;Discord Activity&lt;/strong&gt;, you'll need to create an app in the &lt;strong&gt;&lt;a href="https://discord.com/developers/applications" rel="noopener noreferrer"&gt;Discord Developer Portal&lt;/a&gt;&lt;/strong&gt; and get your &lt;strong&gt;Client ID&lt;/strong&gt; and &lt;strong&gt;Client Secret&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Need more help?&lt;/strong&gt; Check out &lt;strong&gt;&lt;a href="https://dev.to/waveplay/how-to-build-a-discord-activity-easily-with-robojs-5bng"&gt;Creating a Discord Activity in seconds with Robo.js&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the Activity
&lt;/h2&gt;

&lt;p&gt;Now that our project is set up, open it in your code editor and run the following command in your terminal:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npm run dev


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

&lt;/div&gt;

&lt;p&gt;This will start the Robo project in development mode, refreshing with every change in code. It will also create a free &lt;strong&gt;&lt;a href="https://www.cloudflare.com/products/tunnel/" rel="noopener noreferrer"&gt;Cloudflare tunnel&lt;/a&gt;&lt;/strong&gt; for testing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F7687z7deulo8vcdwmoj3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F7687z7deulo8vcdwmoj3.png" alt="Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the tunnel URL and paste it into your Discord App's &lt;strong&gt;URL Mappings&lt;/strong&gt; in the &lt;strong&gt;&lt;a href="https://discord.com/developers/applications/" rel="noopener noreferrer"&gt;Discord Developer Portal&lt;/a&gt;&lt;/strong&gt;. This will allow Discord to communicate with it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fhdznq68x51snd3o00jqi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fhdznq68x51snd3o00jqi.png" alt="Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the project running, join a voice channel in your test Discord server and click the rocket button to join a Discord Activity. You should see your activity running in Discord!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Feu5qu7o5dyncqg444rhh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Feu5qu7o5dyncqg444rhh.png" alt="Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up the Video Player
&lt;/h2&gt;

&lt;p&gt;We need a video file to play. You can use any video file you like, but for this guide, we'll be using a sample video you can &lt;strong&gt;&lt;a href="https://coverr.co/videos/cat-at-the-breakfast-table-hng084z6j3" rel="noopener noreferrer"&gt;download from Coverr&lt;/a&gt;&lt;/strong&gt;. Let's name it &lt;code&gt;sample.mp4&lt;/code&gt; and place it in the &lt;code&gt;/public&lt;/code&gt; folder of your new project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F626t217sw0p1j7vrkjq5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F626t217sw0p1j7vrkjq5.png" alt="Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the video file in place, let's add a &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; element to our main page. Open the &lt;code&gt;Activity.tsx&lt;/code&gt; file in the &lt;code&gt;/src/app&lt;/code&gt; folder and replace the existing code with the following:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Activity&lt;/span&gt; &lt;span class="o"&gt;=&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isPlaying&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPlaying&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;videoPlayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLVideoElement&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&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;onPause&lt;/span&gt; &lt;span class="o"&gt;=&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isPlaying&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;setPlaying&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="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onPlay&lt;/span&gt; &lt;span class="o"&gt;=&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isPlaying&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;setPlaying&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="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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isPlaying&lt;/span&gt;&lt;span class="p"&gt;)&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="nx"&gt;current&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="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isPlaying&lt;/span&gt;&lt;span class="p"&gt;)&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="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;pause&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="nx"&gt;isPlaying&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/rocket.png"&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"logo"&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Discord"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;video&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;videoPlayer&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"video"&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/sample.mp4"&lt;/span&gt; &lt;span class="na"&gt;controls&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;loop&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;br&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isPlaying&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;onPause&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;onPlay&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isPlaying&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Pause&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;Play&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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 also adjust the video player styling a bit. Add the following CSS to the &lt;code&gt;App.css&lt;/code&gt; file in the &lt;code&gt;/src/app&lt;/code&gt; folder:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;video&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&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;Ta-dah! We now have a video player in our Discord Activity that can be controlled by a button. Let's add some multiplayer features to it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Controling the Video
&lt;/h2&gt;

&lt;p&gt;To allow everyone to control the video player, we'll use the &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/plugins/sync" rel="noopener noreferrer"&gt;@robojs/sync&lt;/a&gt;&lt;/strong&gt; plugin to sync the video player state across all clients in real-time. There's many ways to add multiplayer features but this is the easiest.&lt;/p&gt;

&lt;p&gt;Run the following in your terminal:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

npx robo add @robojs/sync


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

&lt;/div&gt;

&lt;p&gt;Then wrap the &lt;code&gt;Activity&lt;/code&gt; component with &lt;code&gt;SyncContextProvider&lt;/code&gt; in &lt;code&gt;App.tsx&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;SyncContextProvider&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="s1"&gt;@robojs/sync&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DiscordContextProvider&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="s1"&gt;../hooks/useDiscordSdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Activity&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="s1"&gt;./Activity&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;DiscordContextProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SyncContextProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Activity&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;SyncContextProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;DiscordContextProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;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;We now have a websocket-powered connection between clients! This would normally require a lot of code, but &lt;strong&gt;@robojs/sync&lt;/strong&gt; automatically upgrades your web server to handle websockets and syncs the state for you.&lt;/p&gt;

&lt;p&gt;If you're already familiar with React's &lt;code&gt;useState&lt;/code&gt; hook, you'll feel right at home with &lt;code&gt;useSyncState&lt;/code&gt;. You can use it just like React's &lt;code&gt;useState&lt;/code&gt; hook, but the state will be synced across all clients in real-time. Just provide a dependency array that acts as a unique identifier for the state.&lt;/p&gt;

&lt;p&gt;To make it multiplayer, replace the &lt;code&gt;useState&lt;/code&gt; hook in &lt;code&gt;Activity.tsx&lt;/code&gt; with &lt;code&gt;useSyncState&lt;/code&gt; and provide a unique identifier for the state. In this case, we'll use the string &lt;code&gt;'video'&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;useSyncState&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="s1"&gt;@robojs/sync&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRef&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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Activity&lt;/span&gt; &lt;span class="o"&gt;=&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isPlaying&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPlaying&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSyncState&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;video&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="c1"&gt;// ... rest of the code remains the same&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now, when you click the play button, everyone using your activity will see the video playing. And when you pause it, everyone will see it pause!&lt;/p&gt;

&lt;p&gt;But wait, what if you want to sync state by channels? You can do that too! Just provide the channel ID as the second argument in &lt;code&gt;useSyncState&lt;/code&gt;, which you can get from the Discord SDK.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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;useDiscordSdk&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="s1"&gt;../hooks/useDiscordSdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useSyncState&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="s1"&gt;@robojs/sync&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRef&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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Activity&lt;/span&gt; &lt;span class="o"&gt;=&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;discordSdk&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDiscordSdk&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isPlaying&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPlaying&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSyncState&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;video&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;discordSdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;channelId&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="c1"&gt;// ... rest of the code remains the same&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now each channel has their own state! &lt;strong&gt;&lt;a href="https://support.discord.com/hc/en-us/articles/4422142836759-Activities-on-Discord#h_01GSX5T6WVXS25BCSSDW3TAGYM" rel="noopener noreferrer"&gt;Invite a friend&lt;/a&gt;&lt;/strong&gt; to join your &lt;strong&gt;Discord Activity&lt;/strong&gt; and see the video player in action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fj4o1mdoahtpyuw5aicgj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fj4o1mdoahtpyuw5aicgj.png" alt="Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wasn't That Easy?
&lt;/h2&gt;

&lt;p&gt;With &lt;strong&gt;Robo.js&lt;/strong&gt; and &lt;strong&gt;@robojs/sync&lt;/strong&gt;, adding multiplayer features to your &lt;strong&gt;Discord Activity&lt;/strong&gt; is a breeze. You can now create interactive experiences that everyone in a channel can enjoy together! You can also add more features like volume control, seeking, and even mouse tracking using &lt;code&gt;useSyncState&lt;/code&gt;! 🚀&lt;/p&gt;

&lt;p&gt;What's more, you can use the built-in &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/robojs/flashcore" rel="noopener noreferrer"&gt;Flashcore Database&lt;/a&gt;&lt;/strong&gt; to persist data easily or &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/plugins/directory" rel="noopener noreferrer"&gt;Explore Plugins&lt;/a&gt;&lt;/strong&gt; to add new features with one command, such as &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/plugins/ai" rel="noopener noreferrer"&gt;AI Chatbot Features&lt;/a&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/plugins/server" rel="noopener noreferrer"&gt;Web Servers&lt;/a&gt;&lt;/strong&gt;. You can even &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/discord-bots/getting-started" rel="noopener noreferrer"&gt;create Discord Bots&lt;/a&gt;&lt;/strong&gt; with it! If you're looking for something more powerful, we also have a &lt;strong&gt;&lt;a href="https://docs.roboplay.dev/templates/overview#multiplayer" rel="noopener noreferrer"&gt;Colyseus Discord Activity Template&lt;/a&gt;&lt;/strong&gt; for real-time multiplayer games.&lt;/p&gt;

&lt;p&gt;Don't forget to &lt;strong&gt;&lt;a href="https://roboplay.dev/discord" rel="noopener noreferrer"&gt;join our Discord server&lt;/a&gt;&lt;/strong&gt; to chat with other developers, ask questions, and share your projects. We're here to help you build amazing apps with &lt;strong&gt;Robo.js&lt;/strong&gt;! 🚀&lt;/p&gt;

&lt;p&gt;➞ &lt;a href="https://roboplay.dev/discord" rel="noopener noreferrer"&gt;🚀 &lt;strong&gt;Community:&lt;/strong&gt; Join our Discord Server&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our very own Robo, &lt;strong&gt;Sage&lt;/strong&gt;, is there to answer any questions about Robo.js, Discord.js, and more&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>discord</category>
      <category>node</category>
    </item>
  </channel>
</rss>
