<?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: Muhammed Metehan Yıldırım</title>
    <description>The latest articles on DEV Community by Muhammed Metehan Yıldırım (@stormcloud).</description>
    <link>https://dev.to/stormcloud</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4036676%2F4183e4df-79b0-48ca-b542-5f52b349c056.jpg</url>
      <title>DEV Community: Muhammed Metehan Yıldırım</title>
      <link>https://dev.to/stormcloud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/stormcloud"/>
    <language>en</language>
    <item>
      <title>Why Choose Native Languages Over Ionic / React Native?</title>
      <dc:creator>Muhammed Metehan Yıldırım</dc:creator>
      <pubDate>Tue, 21 Jul 2026 12:13:55 +0000</pubDate>
      <link>https://dev.to/stormcloud/why-choose-native-languages-over-ionic-react-native-5dop</link>
      <guid>https://dev.to/stormcloud/why-choose-native-languages-over-ionic-react-native-5dop</guid>
      <description>&lt;p&gt;One of the most common questions in mobile development: "Should I build one codebase for iOS and Android (&lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic&lt;/a&gt; / &lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;React Native&lt;/a&gt;), or build two native apps?"&lt;br&gt;
Short answer: &lt;em&gt;"It depends."&lt;/em&gt; But if you don't like short answers, let's dive deeper in a friendly, practical, and hands-on way.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Introduction: why this debate still matters&lt;/li&gt;
&lt;li&gt;Quick summary: Native vs Cross-platform (&lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic&lt;/a&gt; / &lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;React Native&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Performance &amp;amp; resource usage (startup time, memory, animations)&lt;/li&gt;
&lt;li&gt;User experience &amp;amp; platform fidelity (UI, accessibility, animations)&lt;/li&gt;
&lt;li&gt;Hardware and platform API access (camera, sensors, SDKs)&lt;/li&gt;
&lt;li&gt;Security, stability, and updates&lt;/li&gt;
&lt;li&gt;Technical debt, maintenance, and long-term cost&lt;/li&gt;
&lt;li&gt;When to choose native vs cross-platform: a practical decision tree&lt;/li&gt;
&lt;li&gt;Conclusion: practical recommendations and a checklist&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1) Why this debate is still alive
&lt;/h2&gt;

&lt;p&gt;Devices, operating systems and user expectations evolve constantly. Cross-platform tools (&lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic&lt;/a&gt;, &lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;React Native&lt;/a&gt;, etc.) make life easier: faster prototypes, a single language and codebase, and lower initial cost. But real-world apps are rarely just "UI"; they often need low latency, deep hardware integration, complex animations, robust security, and low battery use. In these areas native languages still provide meaningful advantages.&lt;/p&gt;




&lt;h2&gt;
  
  
  2) Short and clear: Native vs Ionic vs React Native
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Native (Kotlin/Java for Android, Swift/Obj-C for iOS):&lt;/strong&gt; Compiled against the platform SDK; offers the best performance, full API access, and the most precise UX control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;React Native&lt;/a&gt;:&lt;/strong&gt; Write in JS/TS and reuse many platform widgets, but communication between JS and native layers (the "bridge") can be a bottleneck for low-level or high-frequency tasks. With careful architecture, &lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;React Native&lt;/a&gt; apps can approach native performance for many use cases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic&lt;/a&gt; (&lt;a href="https://ionicframework.com/docs/core-concepts/webview" rel="noopener noreferrer"&gt;WebView&lt;/a&gt; / &lt;a href="https://capacitorjs.com/" rel="noopener noreferrer"&gt;Capacitor&lt;/a&gt;):&lt;/strong&gt; Build with HTML/CSS/JS and render inside a webview. Great for rapid prototypes and web developers, but the webview adds overhead and limitations for heavy computations and native-like animations.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3) Performance &amp;amp; resource usage: why native often wins
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Cold start time
&lt;/h3&gt;

&lt;p&gt;Native apps compile ahead-of-time and don't need to initialize a whole web runtime or additional JS bridge layers at startup. Especially on lower-end devices, webview or JS runtime initialization can be noticeable. Native apps can deliver faster cold starts and smaller runtime overhead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Animations &amp;amp; UI smoothness
&lt;/h3&gt;

&lt;p&gt;Native UI toolkits and GPU pipelines (e.g., Android View/RenderThread, iOS Core Animation / Metal) are designed for smooth, low-latency animations. If the JS thread is busy or the bridge is saturated, &lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;React Native&lt;/a&gt; animations can stutter. Native development minimizes those risks and gives you more predictable rendering.&lt;/p&gt;

&lt;h3&gt;
  
  
  CPU &amp;amp; memory
&lt;/h3&gt;

&lt;p&gt;Extra abstraction layers (webview or JS runtimes) typically increase memory footprint and CPU usage. For CPU-bound tasks such as real-time image processing, ML inference, AR, or complex game logic, native code tends to be more efficient and gives you finer control over performance.&lt;/p&gt;




&lt;h2&gt;
  
  
  4) User experience &amp;amp; platform fidelity
&lt;/h2&gt;

&lt;p&gt;Users notice small hiccups. With native development you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Follow the platform's latest UI patterns and gesture behaviors precisely.&lt;/li&gt;
&lt;li&gt;Provide the deepest accessibility support (VoiceOver / TalkBack) and the most polished interaction details.&lt;/li&gt;
&lt;li&gt;Fine-tune edge-case behaviors and micro-interactions that make an app feel "native".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For brands where UX is a differentiator (banking, health, high-interaction social apps), this fidelity matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  5) Hardware &amp;amp; platform API access
&lt;/h2&gt;

&lt;p&gt;New device features and platform APIs (advanced camera capabilities, LiDAR, custom BLE profiles, vendor SDKs) typically appear first in the native SDKs. Accessing the newest APIs or building deep integrations is often simpler, more reliable, and better documented on the native side. Cross-platform frameworks provide plugins and bridges, but those plugins need to be developed, maintained, and kept up-to-date, which may introduce delay and extra maintenance effort.&lt;/p&gt;




&lt;h2&gt;
  
  
  6) Security &amp;amp; stability
&lt;/h2&gt;

&lt;p&gt;Native apps align directly with the platform's security model (Keychain, Android Keystore, platform permissions), and they tend to have fewer extra abstraction layers that could introduce new attack surfaces. Cross-platform solutions add extra moving parts (webviews, native bridges, third-party plugins), so you must manage those layers carefully (dependency updates, plugin audits, content security policies, etc.) to maintain comparable security.&lt;/p&gt;




&lt;h2&gt;
  
  
  7) Technical debt, maintenance &amp;amp; long-term cost
&lt;/h2&gt;

&lt;p&gt;A single codebase sounds ideal: fewer developers, faster MVP. However:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As platform-specific needs grow, cross-platform codebases can become littered with conditional logic and native modules.&lt;/li&gt;
&lt;li&gt;The number of native bridge modules may increase, raising test complexity and integration effort.&lt;/li&gt;
&lt;li&gt;Large OS updates or major upgrades to the framework can force time-consuming migrations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the right team and disciplined architecture, many of these costs can be controlled, but it's important to include them in long-term planning.&lt;/p&gt;




&lt;h2&gt;
  
  
  8) When to pick native (practical guide)
&lt;/h2&gt;

&lt;p&gt;Prefer &lt;strong&gt;Native&lt;/strong&gt; when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;App performance is critical (games, real-time image processing, AR/ML).&lt;/li&gt;
&lt;li&gt;You need deep device integration (advanced camera features, sensors, proprietary SDKs).&lt;/li&gt;
&lt;li&gt;UX polish, platform-accurate interactions, and accessibility are top priorities.&lt;/li&gt;
&lt;li&gt;Security and regulatory constraints are strict (fintech, healthcare).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prefer &lt;strong&gt;&lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic&lt;/a&gt; / &lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;React Native&lt;/a&gt; / Cross-platform&lt;/strong&gt; when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need a fast MVP to validate product-market fit on both platforms.&lt;/li&gt;
&lt;li&gt;The app is content-centric or CRUD-heavy (news, blogs, catalogs).&lt;/li&gt;
&lt;li&gt;Your team consists mainly of web developers and native expertise is limited.&lt;/li&gt;
&lt;li&gt;Project budget or time-to-market strongly favors a single codebase.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  9) Quick decision checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Is the app CPU- or graphics-intensive? → &lt;strong&gt;Yes&lt;/strong&gt; → Native.&lt;/li&gt;
&lt;li&gt;Will you rely on the newest platform-specific APIs? → &lt;strong&gt;Yes&lt;/strong&gt; → Native.&lt;/li&gt;
&lt;li&gt;Do you need to launch quickly with limited native expertise? → &lt;strong&gt;Yes&lt;/strong&gt; → Cross-platform.&lt;/li&gt;
&lt;li&gt;Is long-term high-quality UX and low-latency behavior mandatory? → &lt;strong&gt;Yes&lt;/strong&gt; → Native.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  10) Practical tips if you choose cross-platform
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Measure early:&lt;/strong&gt; Profile on real devices: cold start, FPS, memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimize native bridge traffic:&lt;/strong&gt; Keep critical paths in native modules if needed; only use the bridge for what's necessary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Optimize bundles &amp;amp; lazy-load:&lt;/strong&gt; Use code-splitting, lazy loading, Hermes (for RN), and webview optimizations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automate testing:&lt;/strong&gt; Maintain an E2E matrix across devices and OS versions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan for updates:&lt;/strong&gt; Keep a proactive upgrade strategy for OS and framework versions and track plugin maintenance.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  11) A short real-world example
&lt;/h2&gt;

&lt;p&gt;Imagine a bank app: it needs high security, camera-based ID verification, complex animations and offline-safe transaction workflows. This scenario strongly favors native development for better security, performance, and a polished experience. Conversely, a news reader app can be launched faster and cheaper with &lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic&lt;/a&gt; or &lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;React Native&lt;/a&gt; and might meet user needs perfectly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion (TL;DR)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Cross-platform tools (&lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic&lt;/a&gt; / &lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;React Native&lt;/a&gt;) give speed and a single codebase, great for rapid prototyping and content apps.&lt;/li&gt;
&lt;li&gt;Native languages provide the best performance, deeper hardware access, and the most accurate platform UX. Choose them when performance, security, and long-term quality matter.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://reactnative.dev/" rel="noopener noreferrer"&gt;React Native&lt;/a&gt; can approach native performance with the right architecture, but the JS ⇄ native bridge and runtime constraints must be respected.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ionicframework.com/" rel="noopener noreferrer"&gt;Ionic&lt;/a&gt; (webview) solutions require extra optimization but can be more than sufficient for many business apps.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>mobile</category>
      <category>reactnative</category>
      <category>ionic</category>
      <category>webdev</category>
    </item>
    <item>
      <title>StorMIC Setup Guide: Free Self-Hosted P2P Voice Chat With Zero Data Retention</title>
      <dc:creator>Muhammed Metehan Yıldırım</dc:creator>
      <pubDate>Sun, 19 Jul 2026 16:07:07 +0000</pubDate>
      <link>https://dev.to/stormcloud/stormic-setup-guide-free-self-hosted-p2p-voice-chat-with-zero-data-retention-2i4k</link>
      <guid>https://dev.to/stormcloud/stormic-setup-guide-free-self-hosted-p2p-voice-chat-with-zero-data-retention-2i4k</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This guide walks a regular user through two things: putting the StorMIC signaling server online for free, and pointing the StorMIC desktop app at it. You do not need to be a backend developer. If you can copy a URL and paste it into a text box, you can finish this in under ten minutes.&lt;/p&gt;

&lt;p&gt;Repositories: &lt;a href="https://github.com/MMetehan/StorMIC" rel="noopener noreferrer"&gt;StorMIC (desktop app)&lt;/a&gt; and &lt;a href="https://github.com/MMetehan/StorMIC-Backend" rel="noopener noreferrer"&gt;StorMIC-Backend (signaling server)&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What StorMIC actually is&lt;/li&gt;
&lt;li&gt;Why it ships as two separate pieces&lt;/li&gt;
&lt;li&gt;The real point: a communication channel that keeps nothing&lt;/li&gt;
&lt;li&gt;What you need before you start&lt;/li&gt;
&lt;li&gt;Step 1: Deploy the signaling server for free on Render.com&lt;/li&gt;
&lt;li&gt;Step 2: Verify the server is alive&lt;/li&gt;
&lt;li&gt;Step 3: Download the desktop app from Releases&lt;/li&gt;
&lt;li&gt;Step 4: Connect the app to your server&lt;/li&gt;
&lt;li&gt;Step 5: Create a channel and invite someone&lt;/li&gt;
&lt;li&gt;Other hosting options (Heroku, VPS, PM2, local)&lt;/li&gt;
&lt;li&gt;The free tier and the cold start problem&lt;/li&gt;
&lt;li&gt;Troubleshooting common errors&lt;/li&gt;
&lt;li&gt;What the server can and cannot see&lt;/li&gt;
&lt;li&gt;FAQ&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. What StorMIC actually is
&lt;/h2&gt;

&lt;p&gt;StorMIC is a desktop voice and chat application built with Electron. It does voice with push to talk or open mic, camera sharing, screen sharing at up to 1080p and 60 fps, text chat, and drag and drop file transfer. On the surface it looks like the tools you already use every day.&lt;/p&gt;

&lt;p&gt;Underneath, it works in a fundamentally different way. Your audio, your video, your messages, and your files never touch a server. They travel directly from your computer to the other person's computer over WebRTC. The only server in the picture is a tiny WebSocket relay whose entire job is to introduce two people to each other, and then get out of the way.&lt;/p&gt;

&lt;p&gt;That relay is called the signaling server, and it is the part you are going to host yourself. It is the reason this guide exists.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faok3woc44uh7lt5vanq2.jpeg" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faok3woc44uh7lt5vanq2.jpeg" alt="A StorMIC voice channel with two participants and text chat side by side" width="800" height="581"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Why it ships as two separate pieces
&lt;/h2&gt;

&lt;p&gt;Most chat applications hand you one installer and quietly point it at infrastructure owned by whoever wrote the app. You never see that infrastructure. You cannot inspect it, you cannot move it, and you have no way to confirm what it does with your traffic. You are trusting a promise.&lt;/p&gt;

&lt;p&gt;StorMIC breaks that arrangement on purpose. The app and the server are two repositories because they are meant to be owned by two different people: I wrote the code, and you run the server. There is no shared StorMIC backend sitting somewhere with everyone's channels on it, because I deliberately did not build one. When you deploy the signaling server, the address it lives at belongs to you, the machine it runs on is billed to you, and the only people who can reach it are the ones you hand the URL to.&lt;/p&gt;

&lt;p&gt;The desktop app is distributed through GitHub Releases as a plain installer, with no server address baked into it by default. That is also intentional. An installer that already knows where to phone home is an installer that made a decision on your behalf. This one asks you instead.&lt;/p&gt;

&lt;p&gt;The result is a small amount of setup work that I am not going to pretend away. You trade five minutes of clicking for infrastructure that answers to you rather than to me. For a tool built around private conversation, that trade is the entire product.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. The real point: a communication channel that keeps nothing
&lt;/h2&gt;

&lt;p&gt;Both repositories state the same thing, and it is worth being precise about what it means in practice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No message storage. No user accounts. No persistence of any kind.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The signaling server holds all of its state in memory. It knows which usernames are currently sitting in which channel, for exactly as long as they are sitting there. When the last member leaves a channel, the channel is deleted. There is no database attached to the server, because there is nothing to write to a database. The full dependency list is a single package, &lt;code&gt;ws&lt;/code&gt;, for WebSocket support. No auth layer, no ORM, no analytics, no external services.&lt;/p&gt;

&lt;p&gt;Here is what the traffic actually looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client A ──ws──► Server ──ws──► Client B
         join and signal relay only

Once WebRTC is established:
Client A ◄──────── WebRTC P2P ────────► Client B
         (audio, video, chat, files)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server sees two things: a channel code and a username, plus the connection metadata (SDP offers and answers, ICE candidates) that two peers need in order to find a direct route to each other. It never sees a single word you type or a single second of what you say. Once the direct connection is up, the server's only remaining job is to notice when somebody joins or hangs up.&lt;/p&gt;

&lt;p&gt;Chat messages travel over a WebRTC data channel. Files are chunked into 16 KB binary pieces and sent over that same direct channel. Your camera and screen go peer to peer as media tracks. None of it is routed through anything you would need to trust.&lt;/p&gt;

&lt;p&gt;There is exactly one place where anything persists, and it is on your own machine: &lt;code&gt;localStorage&lt;/code&gt; holds your preferences, your selected microphone and speakers, your last used username, and the signaling server URL you entered. Nothing leaves your computer to be remembered somewhere else.&lt;/p&gt;

&lt;p&gt;This is what "a communication channel that keeps no data" means here. Not a policy. Not a setting you can toggle. There is no storage layer in the architecture to turn off.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. What you need before you start
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A GitHub account, free&lt;/li&gt;
&lt;li&gt;A Render.com account, free, which you can create with your GitHub login&lt;/li&gt;
&lt;li&gt;A Windows, macOS, or Linux desktop&lt;/li&gt;
&lt;li&gt;One friend to talk to, since a voice channel with one person in it is a lonely test&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You do &lt;strong&gt;not&lt;/strong&gt; need Node.js, a credit card, a domain name, or a server of your own. Render handles all of that. Node.js only matters if you choose to run the server locally, which is covered later.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Step 1: Deploy the signaling server for free on Render.com
&lt;/h2&gt;

&lt;p&gt;The backend repository already contains a &lt;code&gt;render.yaml&lt;/code&gt; blueprint, so Render can configure the whole service by reading the repo. You will not be typing any commands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.1 Fork the backend repository&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open &lt;a href="https://github.com/MMetehan/StorMIC-Backend" rel="noopener noreferrer"&gt;github.com/MMetehan/StorMIC-Backend&lt;/a&gt; and click &lt;strong&gt;Fork&lt;/strong&gt; in the top right. This copies the repo into your own GitHub account. Render needs it under your account so it has permission to read and deploy it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.2 Create a Blueprint on Render&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sign in at &lt;a href="https://render.com" rel="noopener noreferrer"&gt;render.com&lt;/a&gt;, using &lt;strong&gt;Sign in with GitHub&lt;/strong&gt; if you want to skip a step&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;New&lt;/strong&gt; in the top right, then choose &lt;strong&gt;Blueprint&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Pick your forked &lt;code&gt;StorMIC-Backend&lt;/code&gt; repository from the list&lt;/li&gt;
&lt;li&gt;Render reads &lt;code&gt;render.yaml&lt;/code&gt; and fills in the settings automatically. For reference, this is all it contains:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;web&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stormic-server&lt;/span&gt;
    &lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node&lt;/span&gt;
    &lt;span class="na"&gt;buildCommand&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;
    &lt;span class="na"&gt;startCommand&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node index.js&lt;/span&gt;
    &lt;span class="na"&gt;envVars&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NODE_ENV&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Leave the instance type on &lt;strong&gt;Free&lt;/strong&gt; and click &lt;strong&gt;Apply&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Render installs the single dependency and starts the server. This usually takes about a minute.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5.3 Copy your server URL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the deploy finishes, Render shows a URL that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;https://stormic-server-abc1.onrender.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That address is your server. Copy it and keep it somewhere handy. In the next steps you will convert &lt;code&gt;https://&lt;/code&gt; to &lt;code&gt;wss://&lt;/code&gt;, since the app connects over a secure WebSocket rather than a web page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;wss://stormic-server-abc1.onrender.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same address, different protocol prefix. Render already gives you TLS on that domain, so &lt;code&gt;wss://&lt;/code&gt; works immediately with no certificate setup on your side.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Step 2: Verify the server is alive
&lt;/h2&gt;

&lt;p&gt;Before touching the app, confirm the server is actually responding. Open the &lt;code&gt;https://&lt;/code&gt; version of your URL in a browser with &lt;code&gt;/health&lt;/code&gt; on the end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;https://stormic-server-abc1.onrender.com/health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see the word &lt;code&gt;ok&lt;/code&gt;. That endpoint returns &lt;code&gt;200 OK&lt;/code&gt; with the body &lt;code&gt;ok&lt;/code&gt;, and it exists precisely so that platforms and uptime monitors can poll it. If you see &lt;code&gt;ok&lt;/code&gt;, your server is running and you can move on.&lt;/p&gt;

&lt;p&gt;If the page takes fifteen or twenty seconds on the first try, that is the free tier waking up, not a failure. Section 11 explains why.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Step 3: Download the desktop app from Releases
&lt;/h2&gt;

&lt;p&gt;You are not building anything here. Go to the &lt;a href="https://github.com/MMetehan/StorMIC/releases" rel="noopener noreferrer"&gt;StorMIC releases page&lt;/a&gt; and grab the installer for your platform from the latest release, which at the time of writing is &lt;strong&gt;v2.4.1&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Each release publishes prebuilt binaries for Windows, macOS, and Linux under &lt;strong&gt;Assets&lt;/strong&gt;. Expand that section and pick the file that matches your operating system, then install it the way you would install anything else.&lt;/p&gt;

&lt;p&gt;A note for macOS and Windows users: StorMIC is an independent open source project without a paid code signing certificate, so your operating system may warn you that the developer is unidentified. On macOS you can right click the app and choose &lt;strong&gt;Open&lt;/strong&gt; to get past Gatekeeper. On Windows you may need to click &lt;strong&gt;More info&lt;/strong&gt; and then &lt;strong&gt;Run anyway&lt;/strong&gt; on the SmartScreen prompt. If that makes you uncomfortable, the source is public and the build commands are in the repository, so you can compile it yourself and trust your own binary instead.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Step 4: Connect the app to your server
&lt;/h2&gt;

&lt;p&gt;This is the step that ties the two halves together, and it is a single text field.&lt;/p&gt;

&lt;p&gt;Launch StorMIC. Because no server URL is baked into the public builds, the app starts without a default and expects you to supply one. Open the &lt;strong&gt;Settings&lt;/strong&gt; panel using the gear icon, find &lt;strong&gt;Signaling Server URL&lt;/strong&gt;, and paste in your &lt;code&gt;wss://&lt;/code&gt; address:&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F715qm44ackrq06stfcy4.jpeg" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F715qm44ackrq06stfcy4.jpeg" alt="The Settings panel, showing the Signaling Server URL field" width="799" height="579"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;wss://stormic-server-abc1.onrender.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also set it from the channel screen's server configuration toggle before joining anything. Both paths write to the same place.&lt;/p&gt;

&lt;p&gt;The URL is saved to &lt;code&gt;localStorage&lt;/code&gt;, so you enter it once and the app remembers it on every future launch. For anyone curious about the internals, the app resolves the URL in this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;localStorage&lt;/code&gt;&lt;/strong&gt;, the URL you typed into the Settings panel, which overrides everything else&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;signal-url.js&lt;/code&gt;&lt;/strong&gt;, a URL baked in at build time from a &lt;code&gt;.env&lt;/code&gt; file, only present if you built the app yourself&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;process.env.STORMIC_SIGNAL_URL&lt;/code&gt;&lt;/strong&gt;, a system environment variable for advanced setups&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Empty&lt;/strong&gt;, in which case the app waits for you to configure it in Settings&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Downloaded releases land on option 4 and you move them to option 1. That is the whole flow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Everyone who joins your channel needs the same URL in their copy of the app.&lt;/strong&gt; Two people pointed at two different signaling servers cannot see each other, no matter how correct the channel code is. Send your friends the &lt;code&gt;wss://&lt;/code&gt; address along with the channel code.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Step 5: Create a channel and invite someone
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhr25ndvu4mwnu8bz78x7.jpeg" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhr25ndvu4mwnu8bz78x7.jpeg" alt="StorMIC's channel screen for creating or joining a channel" width="800" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enter a username, which is remembered for next time&lt;/li&gt;
&lt;li&gt;Create a channel with a code of your choosing, which is any string you and your friends agree on&lt;/li&gt;
&lt;li&gt;Have your friend enter the same server URL, the same channel code, and a different username&lt;/li&gt;
&lt;li&gt;Their client sends a &lt;code&gt;join&lt;/code&gt; message, your server replies with the current peer list, and the two clients negotiate a direct WebRTC connection between themselves&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From that moment on, your server is a bystander. Push to talk, screen share, drag a file into the chat window, and none of it goes anywhere near Render.&lt;/p&gt;

&lt;p&gt;The channel exists only while somebody is in it. Close the app on both ends and the channel is gone from memory, with nothing left behind to delete.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; Typing &lt;code&gt;@&lt;/code&gt; in the chat box brings up the participant list so you can mention someone directly.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl27zj5izmbfd9enl5e5w.jpeg" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl27zj5izmbfd9enl5e5w.jpeg" alt="Typing @ in chat brings up the participant list to mention someone directly" width="800" height="578"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  10. Other hosting options
&lt;/h2&gt;

&lt;p&gt;Render is the shortest path, but nothing about StorMIC requires it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run it on your own computer
&lt;/h3&gt;

&lt;p&gt;Useful for testing, or for a LAN party where everyone is on the same network. You need Node.js 18 or newer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/MMetehan/StorMIC-Backend
&lt;span class="nb"&gt;cd &lt;/span&gt;StorMIC-Backend
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm start          &lt;span class="c"&gt;# production&lt;/span&gt;
npm run dev        &lt;span class="c"&gt;# auto restart on file changes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server listens on port &lt;code&gt;3000&lt;/code&gt; by default. Override it with an environment variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8080 npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then point the app at &lt;code&gt;ws://localhost:3000&lt;/code&gt;. Note the single &lt;code&gt;s&lt;/code&gt;: plain &lt;code&gt;ws://&lt;/code&gt; is fine on localhost, but not over the public internet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Heroku
&lt;/h3&gt;

&lt;p&gt;A &lt;code&gt;Procfile&lt;/code&gt; is included:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;heroku create your-app-name
git subtree push &lt;span class="nt"&gt;--prefix&lt;/span&gt; server heroku main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then use &lt;code&gt;wss://your-app-name.herokuapp.com&lt;/code&gt; as your URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Any VPS or cloud server
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/MMetehan/StorMIC-Backend
&lt;span class="nb"&gt;cd &lt;/span&gt;StorMIC-Backend
npm &lt;span class="nb"&gt;install
&lt;/span&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3000 node index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Put a reverse proxy with a TLS certificate in front of it so clients get &lt;code&gt;wss://&lt;/code&gt; rather than &lt;code&gt;ws://&lt;/code&gt;. Here is a working nginx configuration, with the WebSocket upgrade headers being the part people usually forget:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;signal.yourdomain.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt;     &lt;span class="n"&gt;/etc/letsencrypt/live/signal.yourdomain.com/fullchain.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="n"&gt;/etc/letsencrypt/live/signal.yourdomain.com/privkey.pem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt;         &lt;span class="s"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;   &lt;span class="s"&gt;Upgrade&lt;/span&gt; &lt;span class="nv"&gt;$http_upgrade&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;   &lt;span class="s"&gt;Connection&lt;/span&gt; &lt;span class="s"&gt;"upgrade"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt;   &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Keep it running with PM2
&lt;/h3&gt;

&lt;p&gt;On a VPS, a bare &lt;code&gt;node index.js&lt;/code&gt; dies the moment you close your terminal. PM2 fixes that:&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; &lt;span class="nt"&gt;-g&lt;/span&gt; pm2
pm2 start index.js &lt;span class="nt"&gt;--name&lt;/span&gt; stormic-server
pm2 save
pm2 startup        &lt;span class="c"&gt;# restart automatically after a reboot&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  11. The free tier and the cold start problem
&lt;/h2&gt;

&lt;p&gt;Render's free tier suspends your service after 15 minutes with no traffic. The next connection wakes it back up, which takes roughly 30 to 50 seconds.&lt;/p&gt;

&lt;p&gt;In practice this means the first person to join after a quiet evening waits a bit. StorMIC absorbs this reasonably well because the client reconnects with exponential backoff, starting at 1.5 seconds and doubling up to a 30 second cap, so it keeps retrying while the service boots instead of throwing an error at you.&lt;/p&gt;

&lt;p&gt;If the wait annoys you, there are three ways out. Upgrade to a paid Render instance and the service never sleeps. Or run the server on a VPS you already pay for. Or accept the cold start, since once the connection is established the server is irrelevant anyway and its sleep schedule stops mattering for the rest of the call.&lt;/p&gt;

&lt;p&gt;I would not add a keep alive pinger just to game the free tier. If the project matters enough to you to keep a server warm around the clock, it probably deserves the few dollars a month.&lt;/p&gt;




&lt;h2&gt;
  
  
  12. Troubleshooting common errors
&lt;/h2&gt;

&lt;p&gt;The server sends back exactly two error codes, and both are self explanatory once you know what they mean.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error code&lt;/th&gt;
&lt;th&gt;What happened&lt;/th&gt;
&lt;th&gt;What to do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CHANNEL_NOT_FOUND&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;You tried to join a channel that does not exist&lt;/td&gt;
&lt;td&gt;One person must create the channel first, and it disappears when the last member leaves&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;USERNAME_TAKEN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Somebody in that channel already has your name&lt;/td&gt;
&lt;td&gt;Pick a different username&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;CHANNEL_NOT_FOUND&lt;/code&gt; catches people out most often, and it is a direct consequence of the no persistence design. Channels are not records in a database that sit there waiting for you. They exist only while somebody is inside. If everyone leaves and you try to rejoin the same code, you are creating it again, not returning to it.&lt;/p&gt;

&lt;p&gt;Other things that go wrong:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The app cannot connect at all.&lt;/strong&gt; Check that your URL starts with &lt;code&gt;wss://&lt;/code&gt; and not &lt;code&gt;https://&lt;/code&gt; or &lt;code&gt;ws://&lt;/code&gt;. Then load &lt;code&gt;/health&lt;/code&gt; in a browser to confirm the server is up. If it is a free Render instance, wait through the cold start and let the reconnect logic do its work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You are in the channel but cannot see your friend.&lt;/strong&gt; You are almost certainly on two different signaling servers. Compare the URL in both Settings panels character by character.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Voice connects but nobody hears you.&lt;/strong&gt; That is a local media problem, not a server problem. Open Settings, confirm the right microphone is selected as your input device, and check whether push to talk is on with a key you have not pressed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Everything worked yesterday and now it does not.&lt;/strong&gt; If your Render service was redeployed it keeps the same URL, so that is rarely the cause. Check &lt;code&gt;/health&lt;/code&gt; first, since it isolates a server problem from an app problem in about five seconds.&lt;/p&gt;




&lt;h2&gt;
  
  
  13. What the server can and cannot see
&lt;/h2&gt;

&lt;p&gt;Worth stating plainly, because "peer to peer" gets used loosely enough that the word has lost most of its meaning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your signaling server sees:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The channel codes currently in use, in memory only, for as long as somebody is in them&lt;/li&gt;
&lt;li&gt;The usernames currently connected to those channels&lt;/li&gt;
&lt;li&gt;SDP and ICE metadata, which is the technical description of how two peers can reach each other, including IP address candidates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Your signaling server never sees:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Audio&lt;/li&gt;
&lt;li&gt;Video or screen shares&lt;/li&gt;
&lt;li&gt;Chat messages&lt;/li&gt;
&lt;li&gt;Files&lt;/li&gt;
&lt;li&gt;Anything at all after the direct connection is established&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That IP address point deserves honesty rather than marketing. WebRTC works by having peers discover routes to each other, and those candidate addresses pass through the signaling server during the handshake. Peers also learn each other's addresses, because that is how a direct connection is a direct connection. StorMIC is built for talking with people you know, not for anonymity against people you do not. It hides your conversation from the infrastructure. It does not hide your existence from the person you called.&lt;/p&gt;

&lt;p&gt;And since the server is yours, the party seeing that metadata is you.&lt;/p&gt;




&lt;h2&gt;
  
  
  14. FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Do I have to run a server? Can I just use yours?&lt;/strong&gt;&lt;br&gt;
There is no "mine." No shared StorMIC backend exists, which is the point of the whole design. Deploying your own on the free tier takes about five minutes, and section 5 is the entire process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it really free?&lt;/strong&gt;&lt;br&gt;
Yes, on Render's free tier, with the cold start caveat from section 11. The server's only dependency is &lt;code&gt;ws&lt;/code&gt;, so there is no database bill and no third party service to subscribe to.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How many people fit in a channel?&lt;/strong&gt;&lt;br&gt;
StorMIC creates a peer connection to every other participant, so traffic grows with the square of the group size. It is built for small groups: a handful of friends rather than a hundred person town hall. Your upstream bandwidth is the practical ceiling, particularly with screen sharing on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I share one server with my whole friend group?&lt;/strong&gt;&lt;br&gt;
Yes, and that is the expected setup. One person deploys, everyone else pastes the same &lt;code&gt;wss://&lt;/code&gt; URL into Settings. Anyone with the URL can create channels on it, so treat it as a group resource rather than a public one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does the app auto update?&lt;/strong&gt;&lt;br&gt;
No. New versions land on the &lt;a href="https://github.com/MMetehan/StorMIC/releases" rel="noopener noreferrer"&gt;releases page&lt;/a&gt; and you install them yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I need to redeploy the server when the app updates?&lt;/strong&gt;&lt;br&gt;
Usually not. The signaling protocol is small and stable. If a release ever requires a server change, it will say so in the release notes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I read the code?&lt;/strong&gt;&lt;br&gt;
Both repositories are MIT licensed and public. The client is roughly 1500 lines of vanilla JavaScript with no frameworks, and the server is small enough to read over a coffee. If you are going to trust software with your conversations, being able to read it is not a small feature.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/MMetehan/StorMIC" rel="noopener noreferrer"&gt;StorMIC desktop app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MMetehan/StorMIC-Backend" rel="noopener noreferrer"&gt;StorMIC signaling server&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MMetehan/StorMIC/releases" rel="noopener noreferrer"&gt;Latest releases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://render.com" rel="noopener noreferrer"&gt;Render.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API" rel="noopener noreferrer"&gt;WebRTC documentation on MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opensource</category>
      <category>webrtc</category>
      <category>electron</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
