<?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: jzombie</title>
    <description>The latest articles on DEV Community by jzombie (@jzombie).</description>
    <link>https://dev.to/jzombie</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%2F244010%2F5c0b6023-ad1a-44a9-9073-d073c6fe65a0.jpg</url>
      <title>DEV Community: jzombie</title>
      <link>https://dev.to/jzombie</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jzombie"/>
    <language>en</language>
    <item>
      <title>Moving Away from Evernote: A Simpler Solution for Those with ADD</title>
      <dc:creator>jzombie</dc:creator>
      <pubDate>Wed, 19 Jul 2023 02:12:04 +0000</pubDate>
      <link>https://dev.to/jzombie/moving-away-from-evernote-a-simpler-solution-for-those-with-add-i6l</link>
      <guid>https://dev.to/jzombie/moving-away-from-evernote-a-simpler-solution-for-those-with-add-i6l</guid>
      <description>&lt;p&gt;As someone living with ADD, maintaining focus and productivity is crucial. Unfortunately, my experience with Evernote has been more of a hindrance than a help. The constant interruptions by paywalls not only disrupt my workflow but also make me forget why I was using the app in the first place. It's as if the app is more interested in monetizing than in providing a seamless user experience.&lt;/p&gt;

&lt;p&gt;Maybe it's time to consider other options.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Downfalls of Evernote
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Poor Performance and Buggy App:&lt;/strong&gt; Evernote has become slow and buggy over time, affecting my productivity and overall user experience. This could be due to outdated technology or lack of optimization, but either way, it's a significant drawback.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Syncing Issues:&lt;/strong&gt; Note synchronization across different devices, a critical feature for a note-taking app, has become unreliable. This has significantly impacted my trust in the app and its reliability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Restrictive Device Limitations:&lt;/strong&gt; Evernote has imposed restrictions on the number of devices that can be used simultaneously on certain plans. This has been frustrating as I often need to access my notes across multiple devices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pricing and Monetization Strategy:&lt;/strong&gt; Evernote's pricing strategy has changed over time, and not for the better. The value I get from the service no longer justifies the cost - and I'm not even paying for it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Loss of Core Features:&lt;/strong&gt; Evernote has removed or limited some of its core features, such as the ability to export notes and the inclusion of reminders without needing to connect to Google or Outlook.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lack of Innovation:&lt;/strong&gt; While competitors have introduced new features and integrations, Evernote seems to be stuck in time. The company doesn't appear to be innovating or updating its service to keep up with user expectations and market trends.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Leadership Changes:&lt;/strong&gt; Frequent changes in leadership have led to inconsistency in vision and strategy, which may have contributed to some of the issues I've experienced with Evernote.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Simplicity and Efficiency of Markdown
&lt;/h2&gt;

&lt;p&gt;In light of these issues, I've decided to switch to a simpler, more efficient solution: a markdown format in a GitHub repo. Here's why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplicity:&lt;/strong&gt; Markdown is easy to learn and use. It's a straightforward way to format text, without the need for complex tools or software.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexibility:&lt;/strong&gt; With markdown, I can create and edit notes on any device. There are no device limitations or syncing issues to worry about.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Control:&lt;/strong&gt; Using a GitHub repo for my notes gives me complete control over my data. I can easily export my notes, and I don't have to worry about changes in pricing or features.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Collaboration:&lt;/strong&gt; GitHub makes it easy to collaborate with others, whether it's sharing notes or working on a project together.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Version Control:&lt;/strong&gt; With GitHub, every change is tracked. This means I can see the history of my notes and easily revert back to a previous version if needed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In conclusion, while Evernote has its merits, the recent issues have made it clear that it's not the best solution for me. By switching to a markdown format in a GitHub repo, I'm hoping to simplify my note-taking process and improve my productivity. If you're also frustrated with Evernote, it might be worth considering a similar switch.&lt;/p&gt;

</description>
      <category>productivitytools</category>
      <category>evernotealternatives</category>
      <category>markdown</category>
      <category>github</category>
    </item>
    <item>
      <title>Understanding Open-Source Licenses: A Comparative Guide</title>
      <dc:creator>jzombie</dc:creator>
      <pubDate>Sun, 09 Jul 2023 20:26:51 +0000</pubDate>
      <link>https://dev.to/jzombie/understanding-open-source-licenses-a-comparative-guide-57c0</link>
      <guid>https://dev.to/jzombie/understanding-open-source-licenses-a-comparative-guide-57c0</guid>
      <description>&lt;ul&gt;
&lt;li&gt;
Preface

&lt;ul&gt;
&lt;li&gt;Why Create Open-Source?&lt;/li&gt;
&lt;li&gt;Choosing an Appropriate License&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;MIT License&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Apache License 2.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GNU General Public License (GPL)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;GNU Lesser General Public License (LGPL)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;BSD Licenses&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mozilla Public License 2.0&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creative Commons Licenses&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Summary&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Additional Resources&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Conclusion&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Disclaimer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stay Connected for More!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;When you're unaware of the rules, it becomes impossible to knowingly break them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Create Open-Source?
&lt;/h3&gt;

&lt;p&gt;Open-source software provides valuable benefits for individuals and the software ecosystem. It fosters community-driven innovation, leveraging the collective intelligence and creativity of diverse developers. This collaborative approach leads to faster iterations, increased reliability, and the ability to solve complex challenges more effectively.&lt;/p&gt;

&lt;p&gt;Contributing to open-source projects is a long-term investment. Your contributions have a lasting impact, benefiting the project and its users over time. Additionally, active participation in open-source projects helps you enhance your skills, gain practical experience, and build a strong reputation within the developer community.&lt;/p&gt;

&lt;p&gt;Open-source software offers flexibility and adaptability. Access to the source code allows developers to customize and tailor the software to specific needs, empowering them to shape the technology according to requirements. The vibrant ecosystems surrounding open-source projects provide a wide range of complementary tools and resources, further expanding the software's potential.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choosing an Appropriate License
&lt;/h3&gt;

&lt;p&gt;Choosing the correct open-source license, however, can be a complex task. Different licenses have specific terms and conditions that govern how the software can be used, modified, and distributed. It's crucial to carefully evaluate and select the appropriate license that aligns with your project's goals and ensures the desired level of openness and collaboration.&lt;/p&gt;

&lt;p&gt;Open source licenses are legal and binding contracts between the creator and the user of the software. They dictate how the software can be used, modified, and distributed. In this article, we'll explore the key differences between some of the most popular open source licenses.&lt;/p&gt;

&lt;h2&gt;
  
  
  MIT License
&lt;/h2&gt;

&lt;p&gt;The MIT License is one of the most permissive open-source licenses. It allows users to do almost anything with the code, provided that the original license and copyright notice are included. This includes using, copying, modifying, merging, publishing, distributing, sublicensing, and/or selling copies of the software.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Scenario:
&lt;/h3&gt;

&lt;p&gt;You're developing a library that you want others to use freely in their own projects, without any obligation to disclose their source code or to use the same license. For example, you've created a new data visualization library in JavaScript and you want it to be as accessible and reusable as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Apache License 2.0
&lt;/h2&gt;

&lt;p&gt;The Apache License 2.0 is similar to the MIT License, but it also includes an explicit grant of patent rights from contributors to users. It also has a more robust set of conditions, including a requirement to include a copy of the license and any notices in all copies of the software.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Scenario:
&lt;/h3&gt;

&lt;p&gt;You're developing a software that may have patentable technology and you want to protect contributors and users from patent litigation. For instance, you're creating a new machine learning algorithm that could potentially be patented, but you want the open-source community to be able to use and contribute to it without fear of patent claims.&lt;/p&gt;

&lt;h2&gt;
  
  
  GNU General Public License (GPL)
&lt;/h2&gt;

&lt;p&gt;The GPL is a copyleft license, meaning that any derivative work must be distributed under the same license terms. This ensures that any modifications or improvements made to the software are also made available to the community. There are different versions of the GPL, with the GPLv3 being the most recent and comprehensive.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Scenario:
&lt;/h3&gt;

&lt;p&gt;You're developing a software and you want any derivative work to be open sourced under the same license. For example, you're creating a new operating system and you want to ensure that all modifications and improvements made by others are also made freely available to the community.&lt;/p&gt;

&lt;h2&gt;
  
  
  GNU Lesser General Public License (LGPL)
&lt;/h2&gt;

&lt;p&gt;The LGPL is a more permissive version of the GPL. It allows you to link to an LGPL library in your software without having to release your software under the LGPL. This makes it a popular choice for libraries and other reusable components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Scenario:
&lt;/h3&gt;

&lt;p&gt;You're developing a library and you want others to use it in their own projects, even if they are not open-source, but any changes to your library itself must be open sourced. For instance, you're creating a new image processing library and you want it to be usable in both open-source and proprietary software, but any improvements to the library itself should be shared.&lt;/p&gt;

&lt;h2&gt;
  
  
  BSD Licenses
&lt;/h2&gt;

&lt;p&gt;There are several versions of the BSD license, but they all have in common a high degree of permissiveness. The main difference between the BSD licenses and the MIT License is in the handling of advertising materials and endorsements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Scenario:
&lt;/h3&gt;

&lt;p&gt;You're developing a software that you want others to use freely with minimal restrictions, even in proprietary software, but they must retain your copyright notice. For example, you've created a new database management system and you want it to be as accessible as possible, but you want your contribution to be acknowledged.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mozilla Public License 2.0
&lt;/h2&gt;

&lt;p&gt;The Mozilla Public License 2.0 is a compromise between the permissive MIT License and the copyleft GPL. It allows you to freely use, modify, and distribute the software, but any modifications you make must be made available under the same license.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Scenario:
&lt;/h3&gt;

&lt;p&gt;You're developing a software and you want to allow others to use, modify, and distribute the original or modified versions of the software under their own license, but they must disclose changes made to your code. For instance, you're creating a new web browser and you want to encourage both open-source and proprietary derivatives, but changes to your code must be shared.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creative Commons Licenses
&lt;/h2&gt;

&lt;p&gt;While not typically used for software, Creative Commons licenses are popular for other types of open content like documentation, images, and music. They offer a range of options from very permissive (CC BY) to more restrictive (CC BY-NC-ND).&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Scenario:
&lt;/h3&gt;

&lt;p&gt;You're creating content like documentation, images, or music that you want to share with the community under certain conditions. For example, you've written a comprehensive guide on using a particular software and you want others to be able to use, share, and build upon your guide, but they must give you credit and they can't use it for commercial purposes.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MIT License&lt;/strong&gt;: Highly permissive, allows almost any action with the software, provided the original license and copyright notice are included.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apache License 2.0&lt;/strong&gt;: Similar to MIT but includes an explicit grant of patent rights and requires inclusion of the license and any notices in all copies of the software.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GNU General Public License (GPL)&lt;/strong&gt;: A copyleft license that requires any derivative work to be distributed under the same license terms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GNU Lesser General Public License (LGPL)&lt;/strong&gt;: A more permissive version of the GPL, allows linking to an LGPL library in your software without having to release your software under the LGPL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BSD Licenses&lt;/strong&gt;: Highly permissive like MIT, but with different handling of advertising materials and endorsements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mozilla Public License 2.0&lt;/strong&gt;: A compromise between the permissive MIT License and the copyleft GPL, requires modifications to be made available under the same license.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Creative Commons Licenses&lt;/strong&gt;: Not typically used for software, but popular for other types of open content, offers a range of options from very permissive to more restrictive.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;p&gt;Here are some resources that might help you navigate through open-source licensing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://katedowninglaw.com/full-service-free-and-open-source-software-counseling/"&gt;Full Service Free and Open Source Software Counseling&lt;/a&gt;: This firm specializes in helping companies implement a long-term, customized open source compliance strategy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://kr.law/practice-areas/open-source-licensing-lawyer"&gt;Open-Source Licensing Lawyer - Kronenberger Rosenfeld, LLP&lt;/a&gt;: Their lawyers have an extensive technical background as open-source contributors, enabling them to provide personalized counsel for your matter.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.losey.law/intelligence/100-open-source-licensing"&gt;Open Source Licensing - Losey PLLC&lt;/a&gt;: They offer services related to open source licensing, including use, copy, modify, and distribute software.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.orrick.com/en/Insights/2023/06/Open-Source-Software-Licenses-Novel-Case-Explores-Who-Can-Enforce-Them"&gt;Open Source Software Licenses: Novel Case Explores Who Can ...&lt;/a&gt;: This article from Orrick discusses a case that may broaden open-source license enforcement and disclosure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.toptal.com/open-source/developers-guide-to-open-source-licenses"&gt;Developer's Guide to Open Source Licenses - Toptal&lt;/a&gt;: This guide from Toptal provides a comprehensive overview of some of the most popular open-source licenses, and several rules of thumb to follow when choosing a license.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Please note that the price, effectiveness, and quality of these services may vary, and it would be best to contact these organizations directly for more specific information.&lt;/p&gt;

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

&lt;p&gt;Choosing the right open-source license for your project is a critical decision. It's important to understand the implications of each license and to consider your goals for the project. Do you want to encourage wide usage and adaptation, or do you want to ensure that all modifications are made freely available? The answer to this question will guide you towards the license that's right for you.&lt;/p&gt;

&lt;p&gt;It's important to note that this list is not exhaustive and serves as a simplified overview of some available resources. It should not be interpreted as legal advice. For decisions related to software licensing, it's always recommended to consult with a legal professional.&lt;/p&gt;

&lt;p&gt;Disclaimer: The information provided in this article is for informational purposes only and should not be considered legal advice. It is essential to conduct thorough research and review the appropriate licenses in their entirety before making any decisions regarding open-source licenses. I am not an attorney, and therefore, I cannot be held responsible for any errors, inaccuracies, or omissions in this article. Always consult with a qualified legal professional for specific legal advice related to open-source licensing matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stay Connected for More!
&lt;/h2&gt;

&lt;p&gt;Thanks for reading! If you enjoyed this article and want to see more of my work, be sure to check out my GitHub profile at &lt;a href="https://github.com/zenosmosis"&gt;github.com/zenosmosis&lt;/a&gt;. Don't forget to give it a ⭐️ if you find it helpful!&lt;/p&gt;

&lt;p&gt;You can also find me on &lt;a href="https://www.linkedin.com/in/jeremyharrisconsultant/"&gt;LinkedIn&lt;/a&gt; and &lt;a href="https://news.ycombinator.com/user?id=jzombie"&gt;Hacker News&lt;/a&gt;.&lt;/p&gt;

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

</description>
      <category>opensource</category>
      <category>softwareengineering</category>
      <category>licensing</category>
      <category>legal</category>
    </item>
    <item>
      <title>Jasmine-based Ubiquitous Test Runner for Shared Codebases</title>
      <dc:creator>jzombie</dc:creator>
      <pubDate>Sun, 06 Nov 2022 06:23:59 +0000</pubDate>
      <link>https://dev.to/jzombie/test-in-nodejs-and-in-browser-with-the-same-unit-tests-15l1</link>
      <guid>https://dev.to/jzombie/test-in-nodejs-and-in-browser-with-the-same-unit-tests-15l1</guid>
      <description>&lt;p&gt;Sometimes you may need to write code which runs in a browser as well as Node.js, and most test runners do not support this functionality out of the box, in order to run unit tests across all environments without duplicating the tests per environment.&lt;/p&gt;

&lt;p&gt;So I made a little project with the number one goal of being a "ubiquitous" test runner, running tests against real browsers as well as Node.js w/o modifying tests to run between environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/zenOSmosis/karma-jasmine-typescript-boilerplate"&gt;https://github.com/zenOSmosis/karma-jasmine-typescript-boilerplate&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not Playwright, Jest, or...?
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Ubiquity: Test code in multiple environments without duplicating test cases or using multiple runners.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The goals of this project are to execute the testing code directly in the individual environments w/o using a web driver.  This way, the same tests can execute across all major browsers as well as Node.js.&lt;/p&gt;

&lt;p&gt;This use case might not be suitable for all projects but makes it better suited for code that is intended to run across all environments: i.e. algorithms, custom WebSocket implementations, etc.&lt;/p&gt;

&lt;p&gt;So tests like the following can run regardless of which environment they are in, w/o needing to be eval-ed through a web driver message request.&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isBrowser&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../src/index&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;basic tests&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;determines if running in browser&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isBrowser&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;generates fibonacci&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fibonacci&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;55&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Take a look at the &lt;a href="https://github.com/zenOSmosis/karma-jasmine-typescript-boilerplate/tree/main/test"&gt;included tests&lt;/a&gt; for more examples as well as the &lt;a href="https://github.com/zenOSmosis/karma-jasmine-typescript-boilerplate/tree/main/.github/workflows/ci.yml"&gt;example CI pipeline&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;More information is below regarding additional considerations for Jest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running Tests
&lt;/h2&gt;

&lt;p&gt;Note, the default configuration runs the same tests across the environments you choose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Browser and Node tests:&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;&lt;span class="nv"&gt;$ &lt;/span&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Browser-only tests:&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;&lt;span class="nv"&gt;$ &lt;/span&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;:browser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Node-only tests:&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;&lt;span class="nv"&gt;$ &lt;/span&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;:node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Test Coverage Reporting
&lt;/h2&gt;

&lt;p&gt;Code coverage is provided by &lt;a href="https://github.com/istanbuljs"&gt;Istanbul&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Default settings are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Browser code coverage is generated automatically and placed in {root}/coverage as HTML files&lt;/li&gt;
&lt;li&gt;Node.js test coverage reports are placed in .nyc_output as JSON files&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Some Credits
&lt;/h2&gt;

&lt;p&gt;Portions of this were borrowed from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/piecioshka/boilerplate-jasmine-typescript"&gt;https://github.com/piecioshka/boilerplate-jasmine-typescript&lt;/a&gt; (for Node.js configuration)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/monounity/karma-typescript/tree/master/packages/karma-typescript"&gt;https://github.com/monounity/karma-typescript/tree/master/packages/karma-typescript&lt;/a&gt; (for Karma / browser configuration)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/google/karma-webkit-launcher"&gt;https://github.com/google/karma-webkit-launcher&lt;/a&gt; (for helping fix flaky Safari tests)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.freecodecamp.org/news/jasmine-unit-testing-tutorial-4e757c2cbf42/"&gt;https://www.freecodecamp.org/news/jasmine-unit-testing-tutorial-4e757c2cbf42/&lt;/a&gt; (for helping w/ Jasmine tests)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Misc
&lt;/h2&gt;

&lt;p&gt;As much as I'd like to try to get Jest to work instead (for running tests in a browser as well), here's a thread that indicates it may be a bit difficult to accomplish: &lt;a href="https://github.com/facebook/jest/issues/139"&gt;https://github.com/facebook/jest/issues/139&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post shows some polyfills to sort of fake it: &lt;a href="https://github.com/tom-sherman/blog/blob/main/posts/02-running-jest-tests-in-a-browser.md"&gt;https://github.com/tom-sherman/blog/blob/main/posts/02-running-jest-tests-in-a-browser.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Playwright was also added as a dependency to help locate the WebKit bin path on the host system (see: &lt;a href="https://github.com/google/karma-webkit-launcher#usage"&gt;Headless Webkit with Playwright&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Roadmap
&lt;/h2&gt;

&lt;p&gt;In the future I'd like to add configuration options for &lt;a href="https://www.browserstack.com/"&gt;BrowserStack&lt;/a&gt; and potentially &lt;a href="https://saucelabs.com/"&gt;Sauce Labs&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>jasmine</category>
      <category>karma</category>
      <category>typescript</category>
    </item>
    <item>
      <title>"Most Useless Demo Ever" Deepgram Hackathon Submission</title>
      <dc:creator>jzombie</dc:creator>
      <pubDate>Mon, 11 Apr 2022 12:49:00 +0000</pubDate>
      <link>https://dev.to/jzombie/most-useless-demo-ever-deepgram-hackathon-submission-54jn</link>
      <guid>https://dev.to/jzombie/most-useless-demo-ever-deepgram-hackathon-submission-54jn</guid>
      <description>&lt;h3&gt;
  
  
  Overview of My Submission
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Utilizing Deepgram as a virtual speech input in a web desktop.
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/zenOSmosis/reshell" rel="noopener noreferrer"&gt;https://github.com/zenOSmosis/reshell&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Wacky Wildcards&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Code on GitHub
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/zenOSmosis/reshell" rel="noopener noreferrer"&gt;https://github.com/zenOSmosis/reshell&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;Video of the most useless demo ever: &lt;a href="https://user-images.githubusercontent.com/1139657/162651792-32cb216c-2257-40f5-a75d-0b2062b65897.mov" rel="noopener noreferrer"&gt;https://user-images.githubusercontent.com/1139657/162651792-32cb216c-2257-40f5-a75d-0b2062b65897.mov&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;This is a project that I actually take great pride in, however, when trying to balance development time with my full-time job as well as spending time with my family, I wasn't able to complete the project to my satisfaction, so I called it, "The Most Useless Demo Ever."&lt;/p&gt;

&lt;h3&gt;
  
  
  My Deepgram Use-Case
&lt;/h3&gt;

&lt;p&gt;For several years some buddies and I have been talking about using virtual speech inputs in some programs that we are writing.  And we've done that with varying degrees of success.&lt;/p&gt;

&lt;p&gt;I've personally had a strong desire to make a web desktop over the past 10 years or so which is inspired by many concepts in Unix-based operating systems.&lt;/p&gt;

&lt;p&gt;So I'm presenting the largely incomplete ReShell desktop system which features mobile and desktop paradigm support.&lt;/p&gt;

&lt;p&gt;There are several variants of this desktop, some of which are dedicated for peer-to-peer (P2P) calling.&lt;/p&gt;

&lt;p&gt;In time, these multiple variants will converge into a single "portal" and become decentralized, where users can bring their own backends.&lt;/p&gt;

&lt;p&gt;This Deepgram submission is basically my way of saying, "we support voice, are supporting multiple input interfaces, and we have a long road ahead."&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In our UI, I've integrated Deepgram and Azure's speech recognition services, and they can be run concurrently.  If wanting more feedback as to the pros / cons of each and what I have experienced, feel free to reach out to me.&lt;/p&gt;

&lt;p&gt;You can find me on LinkedIn at: &lt;a href="https://www.linkedin.com/in/jeremyharrisconsultant/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/jeremyharrisconsultant/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>hackwithdg</category>
      <category>speechrecognition</category>
      <category>javascript</category>
      <category>virtualdesktop</category>
    </item>
    <item>
      <title>Taking Grammarly for a Test-Drive</title>
      <dc:creator>jzombie</dc:creator>
      <pubDate>Tue, 29 Mar 2022 02:28:54 +0000</pubDate>
      <link>https://dev.to/jzombie/taking-grammarly-for-a-test-drive-1gja</link>
      <guid>https://dev.to/jzombie/taking-grammarly-for-a-test-drive-1gja</guid>
      <description>&lt;p&gt;&lt;em&gt;I signed up for &lt;a href="https://app.grammarly.com"&gt;Grammarly&lt;/a&gt; to improve my writing skills and am testing it on the &lt;a href="https://github.com/zenOSmosis/speaker.app"&gt;Speaker.app&lt;/a&gt; verbiage, a project I have notoriously gone overboard with trying to describe.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Speaker.app is a batteries-included, quasi-decentralized, alternative free speech audio platform compatible with any device that supports a modern web browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Virtual Server in your Browser
&lt;/h2&gt;

&lt;p&gt;Speaker.app utilizes virtual server technology to route group calls and form virtual networks.&lt;/p&gt;

&lt;p&gt;To host a call, one participant's device acts as the network host, to which all of the other callers connect directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ephemeral Networks
&lt;/h2&gt;

&lt;p&gt;Messages and other media will pass through this host participant's device. If the device goes offline, the network and its history are gone.&lt;/p&gt;

&lt;h2&gt;
  
  
  No User Accounts
&lt;/h2&gt;

&lt;p&gt;No user accounts or passwords are required to join a public network. User identities are generated using Ethereum, with a randomized user profile, by default. Users can change their description to their liking, while their profile information is stored locally via local storage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration to Create this Project
&lt;/h2&gt;

&lt;p&gt;I was faced with building a WebRTC bridge between two third-party services in the virtual healthcare industry. After some initial experimentation, I discovered that using a headless Chrome server was the path of least resistance. Fewer bugs were present at the expense of it not being exceptionally efficient.&lt;/p&gt;

&lt;p&gt;However, the idea was compelling enough for me to continue exploring and scale it out as efficiently as possible with limited resources. The idea to use the client browser as a virtual server was born.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>react</category>
      <category>webrtc</category>
      <category>writing</category>
    </item>
    <item>
      <title>Azure Trial Hackathon - Speech Controlled Web Desktop</title>
      <dc:creator>jzombie</dc:creator>
      <pubDate>Tue, 08 Mar 2022 23:48:49 +0000</pubDate>
      <link>https://dev.to/jzombie/azure-trial-hackathon-speech-controlled-web-desktop-2391</link>
      <guid>https://dev.to/jzombie/azure-trial-hackathon-speech-controlled-web-desktop-2391</guid>
      <description>&lt;h3&gt;
  
  
  Overview of My Submission
&lt;/h3&gt;

&lt;p&gt;A web-based desktop, called "ReShell", which responds to your voice.&lt;/p&gt;

&lt;p&gt;ReShell is a web-based desktop &amp;amp; mobile user interface featuring individual "portals," or collections of apps.&lt;/p&gt;

&lt;p&gt;ReShell extends &lt;a href="https://create-react-app.dev/"&gt;Create React App&lt;/a&gt; with a window management system, multiple portal handling, some core applications and utilities, and utilizes &lt;a href="https://github.com/google/zx"&gt;Google's zx JavaScript Bash replacement utility&lt;/a&gt; to do some file system management.&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Wacky Wildcards&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Code on GitHub
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/zenOSmosis"&gt;
        zenOSmosis
      &lt;/a&gt; / &lt;a href="https://github.com/zenOSmosis/reshell"&gt;
        reshell
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      ReShell  is a web-based desktop &amp;amp; mobile user interface featuring individual "portals," or collections of apps, based on the PhantomCore library.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;a href="https://raw.githubusercontent.com/zenOSmosis/reshell/main/LICENSE.txt" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/a11f39ae4c152b0d58cd1ef1abc7601a3c9e480c6e61084a8a4baa982ba97b8b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f7a656e6f736d6f7369732f72657368656c6c" alt="MIT License"&gt;&lt;/a&gt;
&lt;a href="https://github.com/zenOSmosis/reshell/blob/main/package.json#L3"&gt;&lt;img src="https://camo.githubusercontent.com/2f4a9ea176239c3aac56244bd28e420cfa3174db40e466c457f6aa1cf282173f/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f7061636b6167652d6a736f6e2f762f7a656e6f736d6f7369732f72657368656c6c" alt="version"&gt;&lt;/a&gt;
&lt;a href="https://reshell.org" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/6793e00b40b1748bf52092c83db5ce16de51adc9477f6156273b7fa936c8b284/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f776562736974652d72657368656c6c2e6f72672d626c7565" alt="reshell.org"&gt;&lt;/a&gt;
&lt;a href="https://www.codefactor.io/repository/github/zenOSmosis/reshell" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/b10fc2f6c72de18ddfaa7eabebce34428751cc1d00327f820ae0665557e4981b/68747470733a2f2f7777772e636f6465666163746f722e696f2f7265706f7369746f72792f6769746875622f7a656e4f536d6f7369732f72657368656c6c2f6261646765" alt="CodeFactor"&gt;&lt;/a&gt;
&lt;a href="https://prettier.io/" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/bd4532f32ea59bf1b368dfec6e9a1c10210725a43e36a9e38162c051f40f79df/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f64655f7374796c652d70726574746965722d6666363962342e7376673f7374796c653d666c6174" alt="Style Status"&gt;&lt;/a&gt;
&lt;a href="https://github.com/zenosmosis/phantom-core"&gt;&lt;img src="https://camo.githubusercontent.com/3aad762c49846b30fa83145865568b67c21c25f35e9859f33a916be03cd4f561/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6172636869746563747572652d7068616e746f6d2d2d636f72652d726564" alt="phantom-core-architecture"&gt;&lt;/a&gt;
&lt;a href="https://www.buymeacoffee.com/Kg8VCULYI" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/612938871bde60fc2ad59917dc958c4b6d087dc8ba04ebc0b0c3c6d4025a66c9/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f73706f6e736f722d6275796d6561636f666665652d677265656e" alt="buy-me-a-coffee"&gt;&lt;/a&gt;
&lt;a href="https://www.paypal.com/paypalme/zenOSmosis" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/eeb472188d8c183e75559459dd51f006902105c04b72c86954aaf296d4c81c99/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f73706f6e736f722d70617970616c2e6d652d626c7565" alt="paypal-me"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
ReShell - Web Desktop and UI Service Engine&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;This is a work in progress, subject to many API updates and feature regressions in a short amount of time, as it is used for development and prototyping of several applications at once.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;ReShell is a web-based desktop &amp;amp; mobile user interface featuring individual "portals," or collections of apps, based on the &lt;a href="https://github.com/zenOSmosis/phantom-core"&gt;PhantomCore&lt;/a&gt; library.&lt;/p&gt;
&lt;p&gt;ReShell extends &lt;a href="https://create-react-app.dev/" rel="nofollow"&gt;Create React App&lt;/a&gt; with a window management system, multiple portal handling, some core applications and utilities, and utilizes &lt;a href="https://github.com/google/zx"&gt;Google's zx JavaScript Bash replacement utility&lt;/a&gt; to do some file system management.&lt;/p&gt;
&lt;h1&gt;
Project Goals&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Stable and efficient on desktop and mobile&lt;/li&gt;
&lt;li&gt;Base portal UI should never require a backend to be present (specific portals may require one as necessary); should be easily distributable across multiple channels for a variety of frontend-related needs, from small to large projects&lt;/li&gt;
&lt;li&gt;Try not to break &lt;a href="https://create-react-app.dev/" rel="nofollow"&gt;Create React App&lt;/a&gt; nor get too clever&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/zenOSmosis/reshell"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Additional Resources / Info
&lt;/h3&gt;

&lt;p&gt;Video demonstrating speech control - &lt;br&gt;
&lt;a href="https://user-images.githubusercontent.com/1139657/157443171-d35decb7-5fd2-460d-b95e-cae7d7b28a80.mov"&gt;https://user-images.githubusercontent.com/1139657/157443171-d35decb7-5fd2-460d-b95e-cae7d7b28a80.mov&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j1e99b-E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/1139657/157346532-a62db462-292c-4d5d-91d0-17904646d58a.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j1e99b-E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/1139657/157346532-a62db462-292c-4d5d-91d0-17904646d58a.jpeg" alt="ReShell Web Desktop" width="800" height="592"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/zenOSmosis/reshell"&gt;Source Code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://reshell.org/speech-commander"&gt;Demo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>azuretrialhack</category>
      <category>webdev</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>A WebRTC server in your browser (virtual server; private audio)</title>
      <dc:creator>jzombie</dc:creator>
      <pubDate>Thu, 30 Sep 2021 15:10:07 +0000</pubDate>
      <link>https://dev.to/jzombie/a-webrtc-server-in-your-web-browser-for-group-communications-5c6l</link>
      <guid>https://dev.to/jzombie/a-webrtc-server-in-your-web-browser-for-group-communications-5c6l</guid>
      <description>&lt;p&gt;&lt;a href="https://twitter.com/intent/tweet?text=Private%20audio%20chat%20rooms%20using%20your%20browser%20as%20a%20virtual%20server&amp;amp;url=https://github.com/zenOSmosis/speaker.app&amp;amp;hashtags=webrtc,audio,screensharing,virtual-server,group-chat,communications,private" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimg.shields.io%2Ftwitter%2Furl%2Fhttp%2Fshields.io.svg%3Fstyle%3Dsocial" alt="tweet-url"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Speaker.app / zenRTC / Phantom Server
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/zenOSmosis/speaker.app" rel="noopener noreferrer"&gt;Source Code available on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://speaker.app" rel="noopener noreferrer"&gt;Speaker.app&lt;/a&gt; is a batteries-included, quasi-decentralized, alternative free speech audio platform that is compatible on any device that supports a modern web browser.&lt;/p&gt;

&lt;p&gt;Rather than a centralized server providing proxying of streams from each participant to other participants (i.e. an MCU / SFU), one can choose to host a network (or "room") where others can connect to, either publicly or privately.  The network hosting participant's web browser acts as the "server" for the other participants to connect to on the given network, and all proxying is done, including message storage and relaying, through that browser.&lt;/p&gt;

&lt;p&gt;Public networks are visible in a "network discovery" view, which serves as the default homepage for the application.&lt;/p&gt;

&lt;p&gt;No user accounts or passwords are required to join a public network, and user identities are generated using Ethereum, with a randomized user profile, by default.  Users can change their user profile to their liking, while their profile information is stored locally via local storage.&lt;/p&gt;

&lt;p&gt;To see it live, navigate to &lt;a href="https://speaker.app" rel="noopener noreferrer"&gt;https://speaker.app&lt;/a&gt;.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
Speaker.app / zenRTC / Phantom Server

&lt;ul&gt;
&lt;li&gt;Table of Contents&lt;/li&gt;
&lt;li&gt;Browser Support Matrix&lt;/li&gt;
&lt;li&gt;What's in the Box&lt;/li&gt;
&lt;li&gt;Architecture Overview&lt;/li&gt;
&lt;li&gt;Conventional WebRTC Network Topologies&lt;/li&gt;
&lt;li&gt;Speaker.app Peer-Based Network Topology&lt;/li&gt;
&lt;li&gt;Inspiration to Create this Project&lt;/li&gt;
&lt;li&gt;Getting Started&lt;/li&gt;
&lt;li&gt;Dependencies / System Requirements&lt;/li&gt;
&lt;li&gt;Building and Running&lt;/li&gt;
&lt;li&gt;Public Network Discovery / Private Networks&lt;/li&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;li&gt;Contributing / Forking&lt;/li&gt;
&lt;li&gt;Troubleshooting / Miscellaneous&lt;/li&gt;
&lt;li&gt;Invalid MongoDB Permissions (or some other missing environment variable)&lt;/li&gt;
&lt;li&gt;Invalid Elf header (farmhash)&lt;/li&gt;
&lt;li&gt;Error: ENOSPC: System limit for number of file watchers reached&lt;/li&gt;
&lt;li&gt;Linux check CPU speed&lt;/li&gt;
&lt;li&gt;Auto-Generate Markdown Table of Contents&lt;/li&gt;
&lt;li&gt;Motto&lt;/li&gt;
&lt;li&gt;Help Us Continue Writing Free Software&lt;/li&gt;
&lt;li&gt;License&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Browser Support Matrix
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Chrome&lt;/th&gt;
&lt;th&gt;Edge (Chromium)&lt;/th&gt;
&lt;th&gt;Firefox&lt;/th&gt;
&lt;th&gt;Safari&lt;/th&gt;
&lt;th&gt;IE&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Android&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;iOS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;[transcoder host only]&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Linux&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;macOS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Windows&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Note, on every OS except iOS, Chrome is the recommended browser;  On iOS, Safari should be used.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in the Box
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Frontend&lt;/strong&gt;:  Built with &lt;a href="https://github.com/facebook/create-react-app" rel="noopener noreferrer"&gt;create-react-app&lt;/a&gt;; state is managed with multiple Providers and accessible via useContext hooks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backend:&lt;/strong&gt; Node.js app, using &lt;a href="https://github.com/socketio/socket.io" rel="noopener noreferrer"&gt;Socket.io&lt;/a&gt; and &lt;a href="https://github.com/expressjs/express" rel="noopener noreferrer"&gt;Express&lt;/a&gt;.  Cluster module is utilized to utilize multiple CPUs and a Redis store is utilize to scale Socket.io across the CPUs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Redis&lt;/strong&gt;: Utilized with &lt;a href="https://socket.io/docs/v4/redis-adapter" rel="noopener noreferrer"&gt;Socket.io's Redis adapter&lt;/a&gt; to provide scalability of Socket.io across a cluster of Node.js running in different processes or servers, so they can all communicate, broadcast, and emit events to and from one another.  &lt;em&gt;This is mostly used in conjunction with the signaling layer to initiate WebRTC sessions &amp;amp; media, and most private communication happens over WebRTC data channels.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MongoDB&lt;/strong&gt;: Network details (name, host, number of participants) are stored in &lt;a href="https://github.com/mongodb/mongo" rel="noopener noreferrer"&gt;MongoDB&lt;/a&gt;.  When in development mode, &lt;a href="https://github.com/mongo-express/mongo-express" rel="noopener noreferrer"&gt;Mongo Express&lt;/a&gt; is available at &lt;a href="http://localhost:8081" rel="noopener noreferrer"&gt;http://localhost:8081&lt;/a&gt;, and provides a web-based administrative interface.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's Encrypt&lt;/strong&gt;: Free SSL certificates are managed via the &lt;a href="https://github.com/linuxserver/docker-swag" rel="noopener noreferrer"&gt;linuxserver.io/docker-swag Docker&lt;/a&gt; image.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;dev-ssl-proxy&lt;/strong&gt;: In development, a &lt;a href="https://github.com/zenOSmosis/docker-dev-ssl-proxy" rel="noopener noreferrer"&gt;self-signed SSL proxy&lt;/a&gt; is utilized in replacement of Let's Encrypt, to enable local development with SSL turned on (cam / mic / other HTML5-related APIs which require SSL by default).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Coturn&lt;/strong&gt;: A &lt;a href="https://github.com/zenOSmosis/docker-coturn" rel="noopener noreferrer"&gt;STUN / TURN server&lt;/a&gt; for WebRTC NAT traversal is included in the Docker Compose configuration, but is not enabled by default.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Included WebRTC Experiments&lt;/strong&gt;: Within the source code are some previous real-time, shared experience experiments  such as a drum looper, a sound sampler (play piano / electric guitar w/ keyboard), text-to-speech, TensorFlow-based skeletal tracker, and a game emulator.&lt;/p&gt;

&lt;p&gt;These experiments are mostly dormant and commented-out, but have made for some interesting demos in the past and may be re-enabled in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Conventional WebRTC Network Topologies
&lt;/h3&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%2Fraw.githubusercontent.com%2FzenOSmosis%2Fspeaker.app%2Fmain%2Ffrontend.web%2Fpublic%2Fassets%2Fnetwork%2Fmesh.svg" 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%2Fraw.githubusercontent.com%2FzenOSmosis%2Fspeaker.app%2Fmain%2Ffrontend.web%2Fpublic%2Fassets%2Fnetwork%2Fmesh.svg" alt="Mesh Network"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Mesh network example. (Illustration borrowed from &lt;a href="https://www.npmjs.com/package/simple-peer" rel="noopener noreferrer"&gt;simple-peer&lt;/a&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Most group-based WebRTC calls, which don't have a centralized MCU /  SFU rely on each peer to send out an extra stream to multiple peer.  This is not very efficient as for every participant added, every device connected must send out additional streams.&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%2Fraw.githubusercontent.com%2FzenOSmosis%2Fspeaker.app%2Fmain%2Ffrontend.web%2Fpublic%2Fassets%2Fnetwork%2Fsfu.svg" 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%2Fraw.githubusercontent.com%2FzenOSmosis%2Fspeaker.app%2Fmain%2Ffrontend.web%2Fpublic%2Fassets%2Fnetwork%2Fsfu.svg" alt="SFU"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Centralized MCU / SFU example.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;More advanced calling platforms utilize a centralized MCU / SFU.  While this is more efficient in terms of the network, additional considerations, and money, are needed in order to scale out the backend infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Speaker.app Peer-Based Network Topology
&lt;/h3&gt;

&lt;p&gt;Using a topology similar to the MCU / SFU example above, Speaker.app attempts to solve the scalability issue without throwing a lot of extra money into hosting fees, by enabling individual participants to host their own networks, on their own hardware, using their own bandwidth, while at the same time providing greater privacy and flexibility.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;zenRTC&lt;/strong&gt; (built with simple-peer) is based on WebRTC, adding additional functionality such as user-level network strength indication, events over data channels, and P2P-based shared state syncing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phantom Server&lt;/strong&gt; is a network host which runs in your web browser, and acts as the host, shared state manager, proxy, and transcoder for all connected participants within a WebRTC network.&lt;/p&gt;

&lt;p&gt;Every participant connects to the Phantom Server via a P2P connection and Phantom Server handles the stream negotiations / network programming with the other peers.&lt;/p&gt;

&lt;p&gt;Speaker.app is able to provide a quasi-decentralized MCU / SFU by enabling clients to run them in their own browsers, as a virtual machine.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;At the time of writing the Chrome on the Apple M1 processor is by far the most efficient for doing browser-based streaming transcoding, compared to a variety of Intel processors which have been tested on, though development has mostly been done on Intel processors / Linux.  ARM is the future, it seems.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Network hosting has also been tested on non-optimal hardware (i.e. 2018 Samsung J2; Intel i3) with adequate results for streaming 4K video streams to 4 participants.  Good hardware such as the new Apple M1 processor allows much greater yields, and better scalability.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration to Create this Project
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;TLDR; Experimentation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I was faced with a task for building a WebRTC bridge between two third party services in the virtual healthcare industry and after trying some various approaches, discovered that using a headless Chrome instance on the server was the path of least effort and less bugs to squash, though not necessarily being greatly efficient on its own.&lt;/p&gt;

&lt;p&gt;Running a headless Chrome instance on the server is very versatile, in being that you've got a really solid WebRTC implementation baked in, with the ability to mix audio and video streams using JavaScript and the real DOM.&lt;/p&gt;

&lt;p&gt;Wanting to continue pursuing the effort of a script-able WebRTC bridge using a web browser, and thinking of ways to potentially scale such a system, I made the decision to allow client-side devices to host these sessions, now no longer utilizing the headless Chrome instances as the main method of hosting sessions.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;NOTE: If you wish to host your own network (or room) you DO NOT HAVE TO DO this, and can instead go &lt;a href="https://speaker.app/setup/network/create" rel="noopener noreferrer"&gt;https://speaker.app/setup/network/create&lt;/a&gt; and create your own network!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The following is ONLY if you wish to host the entire infrastructure yourself.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependencies / System Requirements
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;All environments require&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bash (Unix shell) &lt;em&gt;If running the included Bash build scripts&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;Docker Compose&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Development environments require&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js 12+&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Recommended system requirements&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The following should get the system up and running, though additional resources may be required for higher traffic environments.  Presumably, these minimum requirements should host at least several dozen people concurrently before needing to add more RAM.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2048 MB RAM &lt;em&gt;(1048 MAY work if Coturn server is hosted separately)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Two CPU cores &lt;em&gt;(one should work just fine for low traffic environments)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Building and Running
&lt;/h3&gt;

&lt;p&gt;Some Bash scripts have been provided to help facilitate the starting and stopping of the respective environments. It is recommended to use these scripts instead of calling the Docker commands directly, as they will provide supplemental environment variables as well as any additional build instructions.&lt;/p&gt;

&lt;p&gt;In development environments, most of the container volumes have a mount directly to the host so that the source code can be updated in the containers without rebuilding.  See the respective docker.compose*.yml configurations and corresponding Dockerfile files for more details.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Set up the environment&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Copy the sample environment.&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;$ &lt;/span&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; .env.sample .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then populate .env with the configuration relevant to your environment.&lt;/p&gt;

&lt;p&gt;Note that other environment variables are set within the docker-compose*.yml files and are intended to be considered static.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To build the Docker containers&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Note that development environments may require additional dependencies to be installed. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;IMPORTANT: If you are using a shell other than Bash, the following scripts should be proceeded with the "bash" command (i.e. "bash ./build.prod.sh").&lt;/em&gt;&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;$ &lt;/span&gt;./build.prod.sh &lt;span class="c"&gt;# Or ./build.dev.sh, depending on environment&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;To start the containers&lt;/em&gt;&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;$ &lt;/span&gt;./start.prod.sh &lt;span class="c"&gt;# Or ./start.dev.sh, depending on environment&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;To stop the containers&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This stops the containers and tears down their temporary storage.&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;$ &lt;/span&gt;./stop.sh &lt;span class="c"&gt;# Stops any environment&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Public Network Discovery / Private Networks
&lt;/h2&gt;

&lt;p&gt;Public networks can be discovered on the default home page.  Private networks do not appear in the public network discovery but can be accessed via URL or QR code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Testing can be performed 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;&lt;span class="nv"&gt;$ &lt;/span&gt;./test.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note, development packages will be automatically installed locally when testing.&lt;/p&gt;

&lt;p&gt;At this time, testing is not fully automated.  Several internal utilities are tested using Jest (via the above command), while device-specific testing is performed manually using &lt;a href="https://www.browserstack.com" rel="noopener noreferrer"&gt;BrowserStack&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.browserstack.com" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FzenOSmosis%2Fjs-shell%2Fraw%2Fmaster%2Fassets%2FBrowserStack-logo.svg" alt="BrowserStack"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Contributing / Forking
&lt;/h2&gt;

&lt;p&gt;Source-code contributions and forks are welcome!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/zenOSmosis/speaker.app/issues" rel="noopener noreferrer"&gt;Open an issue&lt;/a&gt; if you find something that needs to be addressed that you aren't going to address yourself.&lt;/p&gt;

&lt;p&gt;For ideas of what to contribute, take a look at our &lt;a href="https://github.com/zenOSmosis/speaker.app/issues" rel="noopener noreferrer"&gt;open issues&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To contribute, fork the repository, create a new branch, add some code or documentation updates, then submit a PR.&lt;/p&gt;

&lt;h2&gt;
  
  
  Motto
&lt;/h2&gt;

&lt;p&gt;To contribute, however slightly, to the commonwealth of all human innovation and experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Help Us Continue Writing Free Software
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;PayPal&lt;/strong&gt;: &lt;a href="https://www.paypal.com/paypalme/zenOSmosis" rel="noopener noreferrer"&gt;https://www.paypal.com/paypalme/zenOSmosis&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Buy Me a Coffee&lt;/strong&gt;:  &lt;a href="https://www.buymeacoffee.com/Kg8VCULYI" rel="noopener noreferrer"&gt;https://www.buymeacoffee.com/Kg8VCULYI&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  License
&lt;/h2&gt;

&lt;p&gt;&lt;a href="//LICENSE.txt"&gt;GNU GENERAL PUBLIC LICENSE&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Source Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/zenOSmosis/speaker.app" rel="noopener noreferrer"&gt;Source Code available on GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>docker</category>
      <category>webrtc</category>
      <category>node</category>
    </item>
    <item>
      <title>Using Docker for a local HTTPS proxy</title>
      <dc:creator>jzombie</dc:creator>
      <pubDate>Sat, 07 Aug 2021 17:58:24 +0000</pubDate>
      <link>https://dev.to/jzombie/local-ssl-a-docker-based-local-https-server-47hi</link>
      <guid>https://dev.to/jzombie/local-ssl-a-docker-based-local-https-server-47hi</guid>
      <description>&lt;p&gt;Sometimes when you're developing locally, you might need to use HTTPS, and might not have that tooling available in your framework of choice.&lt;/p&gt;

&lt;p&gt;So I created this small Docker container which essentially creates a self-signed SSL certificate and uses nginx as a reverse proxy to pipe your request to whatever address you want to.&lt;/p&gt;

&lt;h2&gt;
  
  
  To use:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;clone the repo (&lt;a href="https://github.com/zenOSmosis/docker-dev-ssl-proxy"&gt;https://github.com/zenOSmosis/docker-dev-ssl-proxy&lt;/a&gt;)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://github.com/zenOSmosis/docker-dev-ssl-proxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;enter the repo directory
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;docker-dev-ssl-proxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;run the following (replacing "&lt;a href="http://localhost:8080"&gt;http://localhost:8080&lt;/a&gt;" with your desired proxy-to address)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--net&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;host &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;PROXY_ADDRESS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8080"&lt;/span&gt; docker-dev-ssl-proxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Then navigate to &lt;a href="https://localhost"&gt;https://localhost&lt;/a&gt; in your browser&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(The address you've defined in PROXY_ADDRESS will be proxied through to &lt;a href="https://localhost"&gt;https://localhost&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Note: For production usage, you might want to check out: &lt;a href="https://github.com/linuxserver/docker-swag"&gt;https://github.com/linuxserver/docker-swag&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ssl</category>
      <category>docker</category>
      <category>proxy</category>
    </item>
  </channel>
</rss>
