<?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>Forem: Bogdan Covrig</title>
    <description>The latest articles on Forem by Bogdan Covrig (@bogdaaamn).</description>
    <link>https://forem.com/bogdaaamn</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%2F36984%2Fe4f5fc0c-de89-4984-a2c2-1d3f65a5ca88.jpg</url>
      <title>Forem: Bogdan Covrig</title>
      <link>https://forem.com/bogdaaamn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/bogdaaamn"/>
    <language>en</language>
    <item>
      <title>Code of Conduct Notifier Action: 2021 GitHub Actions Hackathon</title>
      <dc:creator>Bogdan Covrig</dc:creator>
      <pubDate>Mon, 06 Dec 2021 19:03:36 +0000</pubDate>
      <link>https://forem.com/bogdaaamn/code-of-conduct-notifier-action-2021-github-actions-hackathon-567n</link>
      <guid>https://forem.com/bogdaaamn/code-of-conduct-notifier-action-2021-github-actions-hackathon-567n</guid>
      <description>&lt;p&gt;The challenge of managing online communities is continuously growing. Often times the members are spread across multiple platforms, making it harder to get a complete snapshot of its members' interactions and behavior. While platforms employ different tools and methods to moderate (potentially harmful) conversations, the moderators' priority will always be to create a safe and positive community experience for everybody. &lt;/p&gt;

&lt;p&gt;This Action aims to help just a little bit the GitHub communities moderators into enforcing their Code of Conduct.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;For this year's 2021 GitHub Actions Hackathon, I have built a simple GitHub Action that notifies the members of the community of their Code of Conduct document when this is mentioned. The Action will reply to issues and pull requests comments when the keywords &lt;em&gt;code of conduct&lt;/em&gt; are mentioned, helping the maintainers to quickly share the Code of Conduct document without going back and forth copy-pasting URLs. The Action will take care of this part. &lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Maintainer Must-Haves&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;

&lt;p&gt;The action is a composite action built on tope of the &lt;code&gt;github-script@v5&lt;/code&gt; action, using its functionality to retrieve and post comments in the GitHub issues and pull requests. The YAML file of the action is available in the repository under &lt;a href="https://github.com/BogDAAAMN/code-of-conduct-notifier-action/blob/main/action.yml" rel="noopener noreferrer"&gt;&lt;code&gt;action.yml&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More &lt;a href="https://github.com/BogDAAAMN/code-of-conduct-notifier-action#description" rel="noopener noreferrer"&gt;information&lt;/a&gt; and &lt;a href="https://github.com/BogDAAAMN/code-of-conduct-notifier-action#workflows" rel="noopener noreferrer"&gt;examples&lt;/a&gt; are available in the repository of the action &lt;a href="https://github.com/BogDAAAMN/code-of-conduct-notifier-action" rel="noopener noreferrer"&gt;BogDAAAMN/code-of-conduct-notifier-action&lt;/a&gt;. If you want to get started and use the action, you can visit the GitHub Marketplace page: &lt;a href="https://github.com/marketplace/actions/code-of-conduct-notifier" rel="noopener noreferrer"&gt;Code of Conduct Notifier&lt;/a&gt;.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/bogdaaamn" rel="noopener noreferrer"&gt;
        bogdaaamn
      &lt;/a&gt; / &lt;a href="https://github.com/bogdaaamn/code-of-conduct-notifier-action" rel="noopener noreferrer"&gt;
        code-of-conduct-notifier-action
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Simple Action that reminds the members of your community about the Code of Conduct
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


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

&lt;p&gt;The information presented in the description of the action, the inspiration, and the default messages used by the action are shaped from the following sources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://orbit.love/constellation-report-state-of-community-tools-2021" rel="noopener noreferrer"&gt;Constellation Report&lt;/a&gt;: State of Community Tools 2021 by &lt;a href="https://dev.to/orbit"&gt;@Orbit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.mozilla.org/en-US/about/governance/policies/participation/" rel="noopener noreferrer"&gt;Mozilla Community Participation Guidelines&lt;/a&gt; by &lt;a href="https://www.mozilla.org/en-US/about/" rel="noopener noreferrer"&gt;Mozilla Corporation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Feedback and conversations with &lt;a href="https://dev.to/virtualcoffee"&gt;@VirtualCoffee&lt;/a&gt; friends&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>actionshackathon21</category>
      <category>showdev</category>
      <category>github</category>
      <category>community</category>
    </item>
    <item>
      <title>Content Sentiment Analysis: Explore the emotion score of your content with Google API</title>
      <dc:creator>Bogdan Covrig</dc:creator>
      <pubDate>Sat, 22 Aug 2020 16:32:22 +0000</pubDate>
      <link>https://forem.com/bogdaaamn/content-sentiment-analysis-explore-the-emotion-score-of-your-content-with-google-api-2dg0</link>
      <guid>https://forem.com/bogdaaamn/content-sentiment-analysis-explore-the-emotion-score-of-your-content-with-google-api-2dg0</guid>
      <description>&lt;h3&gt;
  
  
  My Workflow
&lt;/h3&gt;

&lt;p&gt;I spent a few nights wrapping Google's &lt;a href="https://cloud.google.com/natural-language/docs/analyzing-sentiment#language-sentiment-string-protocol" rel="noopener noreferrer"&gt;analyzeSentiment API&lt;/a&gt; into a GitHub Action. The Action runs Sentiment Analysis over the content of HTML files and provides an overview of the overall emotion of all (the selected) pages in your project.&lt;/p&gt;

&lt;p&gt;The API returns values from -1 to 1, indicating how strong a certain emotion – positive or negative – is. After running the Action, a table with the score per each page is printed in its logs. Read more about &lt;a href="https://cloud.google.com/natural-language/docs/basics#interpreting_sentiment_analysis_values" rel="noopener noreferrer"&gt;Interpreting sentiment analysis values&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Along with other content analysis tools, it might come in handy to maintainers who want to understand the text that is pushed to the project every day. See it in action 🚀&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbc2b8c3f99o4w8jm6fxd.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbc2b8c3f99o4w8jm6fxd.gif" alt="Usage demo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⚠️ Now I got really excited about this and will continue developing along with other automation ideas that I have. This being an early release of the Action, please take a look at the &lt;a href="https://github.com/BogDAAAMN/copy-sentiment-analysis#-known-issues-and-limitations" rel="noopener noreferrer"&gt;roadmap&lt;/a&gt; and submit issues with what kind of features you would like to see in future releases.  &lt;/p&gt;

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

&lt;p&gt;Maintainer Must-Haves&lt;/p&gt;

&lt;h3&gt;
  
  
  Yaml File or Link to Code
&lt;/h3&gt;

&lt;p&gt;Here is an example of how to use the Action on public &lt;code&gt;.html&lt;/code&gt; files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Sentiment analysis on public&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;push&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;analysis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt; &lt;span class="c1"&gt;#Be sure you checkout the files beforehand&lt;/span&gt;
    &lt;span class="pi"&gt;-&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;Run sentiment analysis on HTML files&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bogdaaamn/copy-sentiment-analysis@v0.6.1&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
        &lt;span class="na"&gt;gcp_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GCP_KEY }}&lt;/span&gt; &lt;span class="c1"&gt;#Google Cloud Platform API key. Read the README for instructions &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Along with the code – more &lt;a href="https://github.com/BogDAAAMN/copy-sentiment-analysis#-usage" rel="noopener noreferrer"&gt;examples&lt;/a&gt;, &lt;a href="https://github.com/BogDAAAMN/copy-sentiment-analysis#-usage" rel="noopener noreferrer"&gt;requirements&lt;/a&gt; and a &lt;a href="https://github.com/BogDAAAMN/copy-sentiment-analysis#-known-issues-and-limitations" rel="noopener noreferrer"&gt;known issues roadmap&lt;/a&gt; are available in the &lt;a href="https://github.com/BogDAAAMN/copy-sentiment-analysis" rel="noopener noreferrer"&gt;bogdaaamn/copy-sentiment-analysis&lt;/a&gt; repository (view it on &lt;a href="https://github.com/marketplace/actions/content-sentiment-analysis" rel="noopener noreferrer"&gt;Marketplace&lt;/a&gt;). &lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/bogdaaamn" rel="noopener noreferrer"&gt;
        bogdaaamn
      &lt;/a&gt; / &lt;a href="https://github.com/bogdaaamn/copy-sentiment-analysis" rel="noopener noreferrer"&gt;
        copy-sentiment-analysis
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Run sentiment analysis over the text of your website using Google API. 
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Copy Sentiment Analysis&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;
  &lt;a href="https://github.com/BogDAAAMN/copy-sentiment-analysis/actions" rel="noopener noreferrer"&gt;&lt;img alt="javscript-action status" src="https://github.com/BogDAAAMN/copy-sentiment-analysis/workflows/sentiment-analysis/badge.svg"&gt;&lt;/a&gt; &lt;a href="https://snyk.io/test/github/BogDAAAMN/copy-sentiment-analysis?targetFile=package.json" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/99a250d9438e2d68259c85cb43a97b3e8056d5b0f92ea3fea887940532637ac4/68747470733a2f2f736e796b2e696f2f746573742f6769746875622f426f67444141414d4e2f636f70792d73656e74696d656e742d616e616c797369732f62616467652e7376673f74617267657446696c653d7061636b6167652e6a736f6e" alt="Known Vulnerabilities"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;This GitHub Action runs Sentiment Analysis over the &lt;strong&gt;built&lt;/strong&gt; text of your GitHub project. It uses Google's &lt;a href="https://cloud.google.com/natural-language/docs/analyzing-sentiment#language-sentiment-string-protocol" rel="nofollow noopener noreferrer"&gt;analyzeSentiment API&lt;/a&gt;, evaluating the overall emotion score (from positive to negative) of a page. The Action provides an overview of the scores of all the pages from your project (more on &lt;a href="https://cloud.google.com/natural-language/docs/basics#interpreting_sentiment_analysis_values" rel="nofollow noopener noreferrer"&gt;interpreting the scores&lt;/a&gt;).&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🚀 Usage&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/BogDAAAMN/copy-sentiment-analysis/blob/v0.6.1/_static/gif/usage.gif"&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%2FBogDAAAMN%2Fcopy-sentiment-analysis%2Fraw%2Fv0.6.1%2F_static%2Fgif%2Fusage.gif" alt="Usage example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a workflow example of using the Action on plain &lt;code&gt;.html&lt;/code&gt; files from the &lt;code&gt;public&lt;/code&gt; folder (by default).&lt;/p&gt;

&lt;div class="highlight highlight-source-yaml notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;name&lt;/span&gt;: &lt;span class="pl-s"&gt;Sentiment analysis on public&lt;/span&gt;

&lt;span class="pl-ent"&gt;on&lt;/span&gt;: &lt;span class="pl-s"&gt;push&lt;/span&gt;

&lt;span class="pl-ent"&gt;jobs&lt;/span&gt;:
  &lt;span class="pl-ent"&gt;analysis&lt;/span&gt;:
    &lt;span class="pl-ent"&gt;runs-on&lt;/span&gt;: &lt;span class="pl-s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="pl-ent"&gt;steps&lt;/span&gt;:
    - &lt;span class="pl-ent"&gt;uses&lt;/span&gt;: &lt;span class="pl-s"&gt;actions/checkout@v2 &lt;/span&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt;Be sure you checkout the files beforehand&lt;/span&gt;
    - &lt;span class="pl-ent"&gt;name&lt;/span&gt;: &lt;span class="pl-s"&gt;Run sentiment analysis on HTML files&lt;/span&gt;
      &lt;span class="pl-ent"&gt;uses&lt;/span&gt;: &lt;span class="pl-s"&gt;bogdaaamn/copy-sentiment-analysis@v0.6.1&lt;/span&gt;
      &lt;span class="pl-ent"&gt;with&lt;/span&gt;: 
        &lt;span class="pl-ent"&gt;gcp_key&lt;/span&gt;: &lt;span class="pl-s"&gt;${{ secrets.GCP_KEY }} &lt;/span&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt;Google Cloud Platform API key. Read the README for instructions &lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Although, if you project needs to be built beforehand, be sure you place…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/bogdaaamn/copy-sentiment-analysis" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



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

&lt;h4&gt;
  
  
  Open source use cases
&lt;/h4&gt;

&lt;p&gt;At the moment, the overview table is printed in the Actions tab, after the code is running. But it seems counter-intuitive and having too much friction in between. &lt;/p&gt;

&lt;p&gt;I am curious about what the community thinks: &lt;strong&gt;How would you see this Action printing the results? A comment to the PR? A table in Action's log? Failing if there are too many negative results?&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  ⚠️ GCP's bias in sentiment analysis
&lt;/h4&gt;

&lt;p&gt;A few years ago, Google API was criticized in the media for producing bias results towards race, gender, and religion. So I had mixed feelings about using a pre-trained model in this Action.&lt;/p&gt;

&lt;p&gt;Now, it is hard to understand what is going on with Google's proprietary algorithm and how they fight unwanted bias, but more recent research (see &lt;a href="https://data.blog/2019/08/21/gender-and-racial-bias-in-cloud-nlp-sentiment-apis/" rel="noopener noreferrer"&gt;charlescearl, 2019&lt;/a&gt;) concluded that GCP &lt;em&gt;seems to be less sensitive to the race or gender of participants&lt;/em&gt; than other competitor platforms. The same article recommends that users should proceed with caution and conduct evaluations on their own. The tests that I've done had neutral results, but I am ready to expand my research and pull the plug if needed.&lt;/p&gt;

&lt;p&gt;Moreover, there is extraordinary research done towards identifying, analyzing, and diminishing bias in data (see &lt;a href="https://research.google/pubs/pub46743/" rel="noopener noreferrer"&gt;Dixon et al., 2018&lt;/a&gt; from Google Research or &lt;a href="https://arxiv.org/abs/1608.07187" rel="noopener noreferrer"&gt;Caliskan et al., 2016&lt;/a&gt; and &lt;a href="https://arxiv.org/abs/1903.10561" rel="noopener noreferrer"&gt;May et al., 2019&lt;/a&gt;) and all I hope is that Google (or really any cloud provider out there) is doing better and better. I believe it is really important to enable and support bias and fairness research – especially now, after the recent upbringing of GPT-3 (see &lt;a href="https://towardsdatascience.com/the-un-ethical-story-of-gpt-3-openais-million-dollar-model-213d7d06bbf1" rel="noopener noreferrer"&gt;Burus, 2020&lt;/a&gt;) when the society gets exposed more and more to technology. &lt;/p&gt;

&lt;h4&gt;
  
  
  Sources
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.vice.com/en_us/article/j5jmj8/google-artificial-intelligence-bias" rel="noopener noreferrer"&gt;Vice: Google’s Sentiment Analyzer Thinks Being Gay Is Bad&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.engadget.com/2017-10-25-googles-sentiment-analysis-api-is-just-as-biased-as-humans.html" rel="noopener noreferrer"&gt;Engadget: Google's sentiment analysis API is just as biased as humans&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.techleer.com/articles/387-google-sentiment-analysis-api-gives-a-biased-output" rel="noopener noreferrer"&gt;Techleer: Google Sentiment Analysis API gives a biased output&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://data.blog/2019/08/21/gender-and-racial-bias-in-cloud-nlp-sentiment-apis" rel="noopener noreferrer"&gt;Gender and Racial Bias in Cloud NLP Sentiment APIs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://research.google/pubs/pub46743" rel="noopener noreferrer"&gt;Measuring and Mitigating Unintended Bias in Text Classification&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://arxiv.org/abs/1608.07187" rel="noopener noreferrer"&gt;Semantics derived automatically from language corpora contain human-like biases&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://arxiv.org/abs/1903.10561" rel="noopener noreferrer"&gt;On Measuring Social Biases in Sentence Encoders&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://towardsdatascience.com/the-un-ethical-story-of-gpt-3-openais-million-dollar-model-213d7d06bbf1" rel="noopener noreferrer"&gt;The (Un)ethical Story of GPT-3: OpenAI’s Million Dollar Model&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>actionshackathon</category>
      <category>github</category>
      <category>googlecloud</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Contribute to Forem 🌱 in Gitpod on your own fork</title>
      <dc:creator>Bogdan Covrig</dc:creator>
      <pubDate>Mon, 27 Jul 2020 13:34:30 +0000</pubDate>
      <link>https://forem.com/bogdaaamn/contribute-to-forem-in-gitpod-on-your-own-fork-1g1o</link>
      <guid>https://forem.com/bogdaaamn/contribute-to-forem-in-gitpod-on-your-own-fork-1g1o</guid>
      <description>&lt;p&gt;To follow-up on &lt;a class="mentioned-user" href="https://dev.to/ben"&gt;@ben&lt;/a&gt;'s &lt;a href="https://dev.to/ben/spin-up-a-local-instance-of-dev-in-the-cloud-with-gitpod-it-s-incredibly-simple-pij"&gt;post&lt;/a&gt;, Gitpod allows you to spin up &lt;a href="https://github.com/forem/forem" rel="noopener noreferrer"&gt;Forem&lt;/a&gt;'s codebase on the cloud and makes it available to you in the browser. Really, a fully working local instance in your browser. Within minutes.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/ben" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1%2Ff451a206-11c8-4e3d-8936-143d0a7e65bb.png" alt="ben"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/ben/spin-up-a-local-instance-of-dev-in-the-cloud-with-gitpod-it-s-incredibly-simple-pij" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Spin up a "local" instance of DEV in the cloud with GitPod (It's incredibly simple)&lt;/h2&gt;
      &lt;h3&gt;Ben Halpern ・ Apr 8 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#contributorswanted&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#gitpod&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#docker&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;If you already tried to spin up Forem on Gitpod as the &lt;a href="https://docs.forem.com/installation/gitpod/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; describes, most probably you couldn't push the changes. That is perfectly normal; contributors are not allowed to (and they shouldn't) push changes directly into the original repo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;remote: Permission to forem/forem.git denied to BogDAAAMN.
fatal: unable to access &lt;span class="s1"&gt;'https://github.com/forem/forem/'&lt;/span&gt;: The requested URL returned error: 403
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The solution is to push the changes to &lt;em&gt;your&lt;/em&gt; Forem fork instead. The fastest way to do that is to change the &lt;code&gt;origin&lt;/code&gt; of the project. Gitpod allows that in a bunch of ways.&lt;/p&gt;
&lt;h1&gt;
  
  
  Option 1. Good old &lt;code&gt;git remote&lt;/code&gt;
&lt;/h1&gt;

&lt;p&gt;If you take a quick look at the remote right after Gitpod's initialization, the &lt;code&gt;origin&lt;/code&gt; is pointing to the Forem repository. If you push now, naturally, the changes go to the &lt;code&gt;origin&lt;/code&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;git remote &lt;span class="nt"&gt;-v&lt;/span&gt;
origin  https://github.com/forem/forem.git &lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
origin  https://github.com/forem/forem.git &lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To work this out, fire up a terminal in Gitpod and set the &lt;code&gt;origin&lt;/code&gt; to your Forem fork (assuming you already have one).&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;git remote set-url origin https://github.com/&amp;lt;YOUR_USERNAME&amp;gt;/forem
&lt;span class="nv"&gt;$ &lt;/span&gt;git remote &lt;span class="nt"&gt;-v&lt;/span&gt;
origin  https://github.com/&amp;lt;YOUR_USERNAME&amp;gt;/forem.git &lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
origin  https://github.com/&amp;lt;YOUR_USERNAME&amp;gt;/forem.git &lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Cool, from now on you will push your commits to the new &lt;code&gt;origin&lt;/code&gt; – your fork.&lt;/p&gt;

&lt;p&gt;You still need to add the Forem repository as &lt;code&gt;upstream&lt;/code&gt; because you will need to pull and fetch the latest changes from &lt;code&gt;forem/forem&lt;/code&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;git remote add upstream https://github.com/forem/forem
&lt;span class="nv"&gt;$ &lt;/span&gt;git remote &lt;span class="nt"&gt;-v&lt;/span&gt;
origin    https://github.com/&amp;lt;YOUR_USERNAME&amp;gt;/forem.git &lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
origin    https://github.com/&amp;lt;YOUR_USERNAME&amp;gt;/forem.git &lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;
upstream  https://github.com/forem/forem.git &lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
upstream  https://github.com/forem/forem.git &lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Option 2. Gitpod UI
&lt;/h1&gt;

&lt;p&gt;A visual approach to changing the &lt;code&gt;origin&lt;/code&gt; to your fork is to use the Gitpod UI Git panel (left side toolbar). Click on the Git button. If the remote repository is set to &lt;code&gt;forem/forem&lt;/code&gt; and you don't have the right to push changes, a yellow warning will appear stating that &lt;em&gt;You don't have push permissions for &lt;code&gt;forem/forem&lt;/code&gt;&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;A quick fix is to click on the &lt;code&gt;Fork&lt;/code&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fv2xzl808z724o9305ars.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fv2xzl808z724o9305ars.gif" alt="Gitpod Git panel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gitpod's command palette will pop up, asking you to &lt;em&gt;Switch to existing fork&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;If you didn't fork the Forem repo yet, you will have to provide access to Gitpod to create one. Then you will be able to switch to the freshly created one. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwo2n5ttplkw56oal78y5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwo2n5ttplkw56oal78y5.gif" alt="Gitpod Command Pallete"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cool, now wait for confirmation. Once the prompt (bottom right-hand side) says that the remote was successfully changed to &lt;em&gt;your fork&lt;/em&gt;, you are good to go! Gitpod took care of changing the remote of the repo for you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Facv5tucqk2c9f5l6w47i.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Facv5tucqk2c9f5l6w47i.gif" alt="Gitpod Confirmation Prompt"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h1&gt;
  
  
  Option 3. Your fork instance on Gitpod
&lt;/h1&gt;

&lt;p&gt;As explained in the &lt;a href="https://community.gitpod.io/t/how-to-specify-users-fork-instead-of-main-repository/639/3" rel="noopener noreferrer"&gt;community forum&lt;/a&gt;, Gitpod will fire up any repository URL you provide. &lt;/p&gt;

&lt;p&gt;If you already forked Forem, you can simply paste your repo URL into &lt;code&gt;https://gitpod.io/#&amp;lt;URL&amp;gt;&lt;/code&gt;. Gitpod will clone your fork and spin up the Forem local instance in your browser.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://gitpod.io/#https://github.com/&amp;lt;YOUR_USERNAME&amp;gt;/forem
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Finale
&lt;/h1&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/forem/forem/pull/2321#issuecomment-480614021" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Comment for
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#2321&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/benhalpern" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars0.githubusercontent.com%2Fu%2F3102842%3Fu%3D9dfdf168b1efd5a1ea509a6f733a4a65f2f69908%26v%3D4" alt="benhalpern avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/benhalpern" rel="noopener noreferrer"&gt;benhalpern&lt;/a&gt;
        &lt;/strong&gt; commented on &lt;a href="https://github.com/forem/forem/pull/2321#issuecomment-480614021" rel="noopener noreferrer"&gt;&lt;time&gt;Apr 07, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;This is absolutely amazing, I've been dreaming of making this happen.&lt;/p&gt;
&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/jankeromnes"&gt;@jankeromnes&lt;/a&gt; just sign the CLA and this is good to go.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/forem/forem/pull/2321#issuecomment-480614021" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;I absolutely love Gitpod for removing a lot of friction from running Forem on my machine. Pretty awesome how it makes it possible to fiddle with the code within minutes. It helps a lot if you always mess up trying to install the right Ruby version locally :)&lt;/p&gt;

&lt;p&gt;However, there are still issues and bugs that the community encountered while trying to work on Gitpod. Fell free to Pull Request along! &lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/forem/forem/issues/9195" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        continue button on ¨onboarding welcome message¨ is not working
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#9195&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/akhil-naidu" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars0.githubusercontent.com%2Fu%2F11688537%3Fv%3D4" alt="akhil-naidu avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/akhil-naidu" rel="noopener noreferrer"&gt;akhil-naidu&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/forem/forem/issues/9195" rel="noopener noreferrer"&gt;&lt;time&gt;Jul 08, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Issue: continue button on ¨onboarding welcome message¨ is not working&lt;/p&gt;
&lt;p&gt;Platform: Gitpod
Oauth: Github&lt;/p&gt;
&lt;p&gt;Did I miss configuring something?&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/forem/forem/issues/9195" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/forem/forem/issues/8849" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Incorrect node version used in GitPod
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#8849&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/Amorpheuz" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars3.githubusercontent.com%2Fu%2F22113778%3Fv%3D4" alt="Amorpheuz avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/Amorpheuz" rel="noopener noreferrer"&gt;Amorpheuz&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/forem/forem/issues/8849" rel="noopener noreferrer"&gt;&lt;time&gt;Jun 23, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      

&lt;p&gt;&lt;strong&gt;Describe the bug&lt;/strong&gt;
Creating a new GitPod instance leads to a bug where under &lt;code&gt;gem install solargraph; bin/setup &amp;amp;&amp;amp; bin/startup&lt;/code&gt; the &lt;code&gt;bin/setup&lt;/code&gt; script fails at &lt;code&gt;yarn install&lt;/code&gt; due to incorrect node version being used (which is 12.18.x).&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://github.com/thepracticaldev/dev.to/blob/master/.gitpod.dockerfile"&gt;GitPod Dockerfile&lt;/a&gt; does handle the installation of nvm and correct node version, but forgets to switch to the correct node version (12.16.3).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To Reproduce&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a GitPod Workspace with &lt;a href="https://gitpod.io/#https://github.com/thepracticaldev/dev.to" rel="nofollow"&gt;https://gitpod.io/#https://github.com/thepracticaldev/dev.to&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Wait till &lt;code&gt;bundle install&lt;/code&gt; finishes in the third &lt;code&gt;workspace/dev.to&lt;/code&gt; tab completes.&lt;/li&gt;
&lt;li&gt;Yarn throws the error as indicated in screenshot below.&lt;/li&gt;
&lt;/ol&gt;





&lt;p&gt;&lt;strong&gt;Expected behavior&lt;/strong&gt;
Correct node version is selected in nvm, which allows the &lt;code&gt;yarn install&lt;/code&gt; command to complete successfully.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Screenshots&lt;/strong&gt;
&lt;a href="https://user-images.githubusercontent.com/22113778/85383294-6b990d80-b55d-11ea-92ff-a74d807c917b.png" rel="nofollow 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%2Fuser-images.githubusercontent.com%2F22113778%2F85383294-6b990d80-b55d-11ea-92ff-a74d807c917b.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Desktop (please complete the following information):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OS: Windows 10&lt;/li&gt;
&lt;li&gt;Browser: Edge&lt;/li&gt;
&lt;li&gt;Version: 83&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Additional context&lt;/strong&gt;
The &lt;code&gt;nvm use&lt;/code&gt; command can be of help.&lt;/p&gt;


    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/forem/forem/issues/8849" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Love 🌱🌱&lt;/p&gt;

</description>
      <category>forem</category>
      <category>gitpod</category>
      <category>opensource</category>
      <category>contributorswanted</category>
    </item>
    <item>
      <title>Getting started with Google Cloud Functions on Firebase</title>
      <dc:creator>Bogdan Covrig</dc:creator>
      <pubDate>Tue, 26 Feb 2019 00:11:05 +0000</pubDate>
      <link>https://forem.com/bogdaaamn/getting-started-with-google-cloud-functions-on-firebase-3g29</link>
      <guid>https://forem.com/bogdaaamn/getting-started-with-google-cloud-functions-on-firebase-3g29</guid>
      <description>&lt;p&gt;You know what they say. &lt;em&gt;In a world full of serverless, deploy... serverless.&lt;/em&gt; So, of course, I will do my part. Working on a small project that requires &lt;em&gt;only&lt;/em&gt; static pages, the biggest struggle was to find a way to gather feedback from the users (through a static form). My first thought was to build a small API that gets the data from the form and stores it in a database. But the traffic on the website is not that heavy, so I didn't see a point to serve an API for 24/7 just for a few requests per week.&lt;/p&gt;

&lt;p&gt;The most popular solution that I encountered was, of course, serverless. There are plenty of approaches with &lt;a href="https://medium.com/calyx/serverless-contact-forms-with-aws-lambda-79959cd1a6cd" rel="noopener noreferrer"&gt;AWS Lambda&lt;/a&gt; or &lt;a href="https://medium.com/@marcmintel/how-to-submit-forms-on-a-static-website-with-vuejs-and-netlify-functions-b901f40f0627" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt;. But my static pages were already deployed on &lt;a href="https://firebase.google.com/docs/hosting/" rel="noopener noreferrer"&gt;Firebase Hosting&lt;/a&gt;, so &lt;strong&gt;I had to&lt;/strong&gt; give a try to the &lt;a href="https://firebase.google.com/docs/functions/" rel="noopener noreferrer"&gt;Google Cloud Functions&lt;/a&gt; for Firebase.&lt;/p&gt;

&lt;h1&gt;
  
  
  Advantages
&lt;/h1&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/adnanrahic"&gt;@adnanrahic&lt;/a&gt; does a great job explaining serverless pros and cons (&lt;strong&gt;bonus&lt;/strong&gt; a comparison with containers).&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/adnanrahic" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F11252%2F57b23301-aa8e-4cb7-83a1-5bedfdc663bd.png" alt="adnanrahic"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/adnanrahic/containers-vs-serverless-from-a-devops-standpoint-e4n" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Containers vs. Serverless from a DevOps standpoint&lt;/h2&gt;
      &lt;h3&gt;Adnan Rahić ・ Sep 8 '18&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#serverless&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#kubernetes&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#aws&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;For this specific project, a serverless architecture is a perfect match: easy to write, deploy and maintain. There is no infrastructure to care about, I can write them in my favorite language using my favorite packages and I can even test them locally. Convenient.&lt;/p&gt;

&lt;h1&gt;
  
  
  Getting started
&lt;/h1&gt;

&lt;p&gt;There is no need to set up or scale a server, we will just write the functions and deploy them to Firebase. They will be triggered only when the requests are called.&lt;/p&gt;

&lt;p&gt;At this very moment, Google Cloud Functions can be written in &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; (v6 or v8), &lt;a href="https://python.org/" rel="noopener noreferrer"&gt;Python&lt;/a&gt; (beta) or &lt;a href="https://golang.org/" rel="noopener noreferrer"&gt;Go&lt;/a&gt; (beta). I will proceed further with Node.js and some additional resources such as &lt;a href="https://www.npmjs.com/package/express" rel="noopener noreferrer"&gt;Express&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/cors" rel="noopener noreferrer"&gt;CORS&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Install Node.js
&lt;/h2&gt;

&lt;p&gt;Make sure that you have &lt;a href="https://nodejs.org/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; and &lt;a href="https://www.npmjs.com/get-npm" rel="noopener noreferrer"&gt;npm&lt;/a&gt; properly configured before you start because we will write the functions in Node.js.&lt;/p&gt;

&lt;p&gt;Some people will recommend you &lt;a href="https://github.com/creationix/nvm" rel="noopener noreferrer"&gt;nvm&lt;/a&gt; to install and managed Node.js versions.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/nvm-sh" rel="noopener noreferrer"&gt;
        nvm-sh
      &lt;/a&gt; / &lt;a href="https://github.com/nvm-sh/nvm" rel="noopener noreferrer"&gt;
        nvm
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;a href="https://github.com/nvm-sh/logos" 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%2Fraw.githubusercontent.com%2Fnvm-sh%2Flogos%2FHEAD%2Fnvm-logo-color.svg" height="50" alt="nvm project logo"&gt;
  
&lt;/a&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Node Version Manager &lt;a href="https://app.travis-ci.com/nvm-sh/nvm" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8a042189204d0a496b06c9c51d54b87f8912d907d5ddefcaa801e017548158ab/68747470733a2f2f6170702e7472617669732d63692e636f6d2f6e766d2d73682f6e766d2e7376673f6272616e63683d6d6173746572" alt="Build Status"&gt;&lt;/a&gt; &lt;a href="https://github.com/nvm-sh/nvm/releases/tag/v0.40.1" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/de6573c38240e5f97ed87110df3fafa87444b1240ef46cbc72e1a2d0eead1bff/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f76657273696f6e2d76302e34302e312d79656c6c6f772e737667" alt="nvm version"&gt;&lt;/a&gt; &lt;a href="https://bestpractices.dev/projects/684" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/56e71f5e731bbb02144c4bb3e8c964e653046aa94e20f2e654569b7b1fe2d99b/68747470733a2f2f626573747072616374696365732e6465762f70726f6a656374732f3638342f6261646765" alt="CII Best Practices"&gt;&lt;/a&gt;
&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Table of Contents&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#intro" rel="noopener noreferrer"&gt;Intro&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#about" rel="noopener noreferrer"&gt;About&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/nvm-sh/nvm#installing-and-updating" rel="noopener noreferrer"&gt;Installing and Updating&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/nvm-sh/nvm#install--update-script" rel="noopener noreferrer"&gt;Install &amp;amp; Update Script&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#additional-notes" rel="noopener noreferrer"&gt;Additional Notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#troubleshooting-on-linux" rel="noopener noreferrer"&gt;Troubleshooting on Linux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#troubleshooting-on-macos" rel="noopener noreferrer"&gt;Troubleshooting on macOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#ansible" rel="noopener noreferrer"&gt;Ansible&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#verify-installation" rel="noopener noreferrer"&gt;Verify Installation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#important-notes" rel="noopener noreferrer"&gt;Important Notes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#git-install" rel="noopener noreferrer"&gt;Git Install&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#manual-install" rel="noopener noreferrer"&gt;Manual Install&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#manual-upgrade" rel="noopener noreferrer"&gt;Manual Upgrade&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/nvm-sh/nvm#usage" rel="noopener noreferrer"&gt;Usage&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#long-term-support" rel="noopener noreferrer"&gt;Long-term Support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#migrating-global-packages-while-installing" rel="noopener noreferrer"&gt;Migrating Global Packages While Installing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#default-global-packages-from-file-while-installing" rel="noopener noreferrer"&gt;Default Global Packages From File While Installing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#iojs" rel="noopener noreferrer"&gt;io.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#system-version-of-node" rel="noopener noreferrer"&gt;System Version of Node&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#listing-versions" rel="noopener noreferrer"&gt;Listing Versions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/nvm-sh/nvm#setting-custom-colors" rel="noopener noreferrer"&gt;Setting Custom Colors&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#persisting-custom-colors" rel="noopener noreferrer"&gt;Persisting custom colors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#suppressing-colorized-output" rel="noopener noreferrer"&gt;Suppressing colorized output&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#restoring-path" rel="noopener noreferrer"&gt;Restoring PATH&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#set-default-node-version" rel="noopener noreferrer"&gt;Set default node version&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/nvm-sh/nvm#use-a-mirror-of-node-binaries" rel="noopener noreferrer"&gt;Use a mirror of node binaries&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#pass-authorization-header-to-mirror" rel="noopener noreferrer"&gt;Pass Authorization header to mirror&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#nvmrc" rel="noopener noreferrer"&gt;.nvmrc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/nvm-sh/nvm#deeper-shell-integration" rel="noopener noreferrer"&gt;Deeper Shell Integration&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/nvm-sh/nvm#calling-nvm-use-automatically-in-a-directory-with-a-nvmrc-file" rel="noopener noreferrer"&gt;Calling &lt;code&gt;nvm use&lt;/code&gt; automatically in a directory with a &lt;code&gt;.nvmrc&lt;/code&gt; file&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#bash" rel="noopener noreferrer"&gt;bash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#zsh" rel="noopener noreferrer"&gt;zsh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#fish" rel="noopener noreferrer"&gt;fish&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#running-tests" rel="noopener noreferrer"&gt;Running Tests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#environment-variables" rel="noopener noreferrer"&gt;Environment variables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/nvm-sh/nvm#bash-completion" rel="noopener noreferrer"&gt;Bash Completion&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#usage-1" rel="noopener noreferrer"&gt;Usage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#compatibility-issues" rel="noopener noreferrer"&gt;Compatibility Issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/nvm-sh/nvm#installing-nvm-on-alpine-linux" rel="noopener noreferrer"&gt;Installing nvm on Alpine Linux&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#alpine-linux-313" rel="noopener noreferrer"&gt;Alpine Linux 3.13+&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#alpine-linux-35---312" rel="noopener noreferrer"&gt;Alpine Linux 3.5 - 3.12&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/nvm-sh/nvm#uninstalling--removal" rel="noopener noreferrer"&gt;Uninstalling / Removal&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#manual-uninstall" rel="noopener noreferrer"&gt;Manual Uninstall&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#docker-for-development-environment" rel="noopener noreferrer"&gt;Docker For Development Environment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#problems" rel="noopener noreferrer"&gt;Problems&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#macos-troubleshooting" rel="noopener noreferrer"&gt;macOS Troubleshooting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#wsl-troubleshooting" rel="noopener noreferrer"&gt;WSL Troubleshooting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#maintainers" rel="noopener noreferrer"&gt;Maintainers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#project-support" rel="noopener noreferrer"&gt;Project Support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#enterprise-support" rel="noopener noreferrer"&gt;Enterprise Support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#license" rel="noopener noreferrer"&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/nvm-sh/nvm#copyright-notice" rel="noopener noreferrer"&gt;Copyright notice&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Intro&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;nvm&lt;/code&gt; allows you to quickly…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/nvm-sh/nvm" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;But if you can use the &lt;a href="https://nodejs.org/en/download/" rel="noopener noreferrer"&gt;graphical instructions&lt;/a&gt; as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Configure Firebase
&lt;/h2&gt;

&lt;p&gt;Sign up or sign in to the &lt;a href="https://console.firebase.google.com/" rel="noopener noreferrer"&gt;Firebase console&lt;/a&gt; and create a new project. Doesn't really matter, but I called mine &lt;code&gt;dev-form-entries&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, setup your project locally.&lt;/p&gt;

&lt;p&gt;First, install globally &lt;a href="https://github.com/firebase/firebase-tools" rel="noopener noreferrer"&gt;Firebase CLI&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g firebase-tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now create a local folder for your project.&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="nb"&gt;mkdir &lt;/span&gt;dev-form-entries
&lt;span class="nb"&gt;cd &lt;/span&gt;dev-form-entries
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;While in the project folder, login to Firebase.&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;firebase login
Success! Logged &lt;span class="k"&gt;in &lt;/span&gt;as me@tld.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let's initialize our first Firebase project (you can actually run &lt;code&gt;firebase init&lt;/code&gt; and add the functions later).&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firebase init functions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhldyi23bq2madaj4xl3k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhldyi23bq2madaj4xl3k.png" alt="Your first Firebase project!!!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Select a default Firebase project for this directory:&lt;/strong&gt; &lt;code&gt;dev-form-entries&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What language would you like to use?&lt;/strong&gt; &lt;code&gt;JavaScript&lt;/code&gt;&lt;br&gt;
We will use Javascript now. Typescript will work too.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Do you want to use ESLint to catch probable bugs?&lt;/strong&gt; &lt;code&gt;No&lt;/code&gt;&lt;br&gt;
Neat option, but not needed right now.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Do you want to install dependencies with npm now?&lt;/strong&gt; &lt;code&gt;Yes&lt;/code&gt;&lt;br&gt;
Run that &lt;code&gt;npm install&lt;/code&gt; to install &lt;code&gt;firebase-functions&lt;/code&gt; and &lt;code&gt;firebase-admin&lt;/code&gt; for you.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ok, so let's see what we've got&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;firebase.json&lt;/code&gt; for configuring &lt;a href="https://firebase.google.com/docs/hosting/full-config" rel="noopener noreferrer"&gt;Firebase Hosting&lt;/a&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.firebaserc&lt;/code&gt; for configuring multiple projects,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;functions/index.js&lt;/code&gt; is the boilerplate provided by Firebase. We will get back to that soon.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  3. Configure Realtime Database
&lt;/h2&gt;

&lt;p&gt;Not too much to configure here, because it will be initialized programmatically. But I want to mention them before it's too late.&lt;/p&gt;

&lt;p&gt;As I mentioned before, I wanted to store all the data in a database. Firebase has two great out-of-the-box databases that you can use, &lt;a href="https://firebase.google.com/docs/database/" rel="noopener noreferrer"&gt;Realtime Database&lt;/a&gt; and &lt;a href="https://firebase.google.com/docs/firestore/" rel="noopener noreferrer"&gt;Cloud Firestore&lt;/a&gt;. Both of them are highly scalable and flexible (I will get to this later) but I choose to use Realtime Database because it doesn't need any sort of pre-configuration, we will just reference it from the code.&lt;/p&gt;

&lt;p&gt;&lt;a class="mentioned-user" href="https://dev.to/aurelkurtula"&gt;@aurelkurtula&lt;/a&gt; might give you a glimpse of the Realtime Database's greatness.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/aurelkurtula" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F39325%2F588d853b-9210-468f-983e-c8a353a52f78.png" alt="aurelkurtula"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/aurelkurtula/introduction-to-firebases-real-time-database-89l" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Introduction to firebase's real-time database &lt;/h2&gt;
      &lt;h3&gt;aurel kurtula ・ Dec 9 '17&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#firebase&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#database&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;h1&gt;
  
  
  Deploying to Firebase
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Hello from Firebase
&lt;/h2&gt;

&lt;p&gt;Let's start with Firebase's hello world. Edit &lt;code&gt;functions/index.js&lt;/code&gt; and keep their example.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-functions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Create and Deploy Your First Cloud Functions&lt;/span&gt;
&lt;span class="c1"&gt;// https://firebase.google.com/docs/functions/write-firebase-functions&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helloWorld&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onRequest&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello from Firebase!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This function will create a route &lt;code&gt;/helloWorld&lt;/code&gt; and it will respond with &lt;code&gt;Hello from Firebase!&lt;/code&gt; on each request.&lt;/p&gt;
&lt;h2&gt;
  
  
  Deploy it
&lt;/h2&gt;

&lt;p&gt;Now, your first deployment.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firebase deploy &lt;span class="nt"&gt;--only&lt;/span&gt; functions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or you can run just &lt;code&gt;firebase deploy&lt;/code&gt; since the project contains only one function at this moment.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=== Deploying to 'dev-form-entries'...

i  deploying functions
i  functions: ensuring necessary APIs are enabled...
✔  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (42.53 KB) for uploading
✔  functions: functions folder uploaded successfully
i  functions: updating Node.js 6 function helloWorld(us-central1)...
✔  functions[helloWorld(us-central1)]: Successful update operation. 

✔  Deploy complete!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now that your deployment is complete, you can go to your &lt;a href="https://console.firebase.google.com/" rel="noopener noreferrer"&gt;Firebase console&lt;/a&gt; and find your function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa4qr9zifzuwaey9h27h5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa4qr9zifzuwaey9h27h5.png" alt="My Google Cloud Functions in the Firebase Console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's a neat Dashboard. You can check the health and read the logs of your functions. You can get redirected to Google Cloud Platform to see the full details and quotas.&lt;/p&gt;
&lt;h2&gt;
  
  
  Test it
&lt;/h2&gt;

&lt;p&gt;I will use &lt;a href="https://www.getpostman.com/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt; to test the functions. Postman is a nice tool to test your APIs, I will cover only the super basics today, but you check &lt;a class="mentioned-user" href="https://dev.to/harshitrathod"&gt;@harshitrathod&lt;/a&gt;'s beginner guide or take a deep look into it, by &lt;a href="https://dev.to/ebanx/going-beyond-with-postman-522f"&gt;Going beyond with Postman&lt;/a&gt; with &lt;a class="mentioned-user" href="https://dev.to/jlozovei"&gt;@jlozovei&lt;/a&gt;.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/harshitrathod" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F40234%2F04409a9e-1e74-42bc-a8ae-fc3dcf9ec6fa.jpeg" alt="harshitrathod"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/harshitrathod/introduction-to-postman-rest-client-748" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Introduction to Postman REST client&lt;/h2&gt;
      &lt;h3&gt;Harshit rathod ・ Nov 13 '17&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#tutorial&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;p&gt;As seen in the dashboard, my function's route is &lt;code&gt;https://us-central1-dev-form-entries.cloudfunctions.net/helloWorld&lt;/code&gt;. I will paste it in Postman and make a &lt;code&gt;GET&lt;/code&gt; request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0mfzhs8dx0yr6xtnrqz3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0mfzhs8dx0yr6xtnrqz3.png" alt="Successful response got in Postman"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Writing the API
&lt;/h1&gt;

&lt;p&gt;Ok, so now you know where to write, deploy and test the code. Let's try to do something real.&lt;/p&gt;

&lt;h2&gt;
  
  
  Warming up
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Express and CORS
&lt;/h3&gt;

&lt;p&gt;As little helpers for our great goal, we will use &lt;a href="https://www.npmjs.com/package/express" rel="noopener noreferrer"&gt;Express&lt;/a&gt; (for the middleware and nicer routes writing) and &lt;a href="https://www.npmjs.com/package/cors" rel="noopener noreferrer"&gt;CORS&lt;/a&gt; (for enabling all CORS requests, if you're not familiar with it, take a look at some of the @effingkay's CORS concepts).&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;div class="ltag__link__content"&gt;
    &lt;div class="missing"&gt;
      &lt;h2&gt;Article No Longer Available&lt;/h2&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;First, you will need to install them, so pop into your terminal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save&lt;/span&gt; express cors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;and add them at the top of your &lt;code&gt;index.js&lt;/code&gt; file.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Right after, create an instance of Express and write the middleware that will accept all the CORS requests.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;cors&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You will use the &lt;code&gt;app&lt;/code&gt; instance to write the routes and you will export it as a Google Cloud Function, as you did with the &lt;code&gt;helloWorld&lt;/code&gt; one. So write the new one right after the &lt;code&gt;helloWorld&lt;/code&gt; exports.&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="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will create an &lt;code&gt;/entries&lt;/code&gt; function. All the routes that we will write for the &lt;code&gt;app&lt;/code&gt; instance will be available in the &lt;code&gt;entries&lt;/code&gt; function.&lt;/p&gt;
&lt;h3&gt;
  
  
  Realtime Database
&lt;/h3&gt;

&lt;p&gt;In order to use the Realtime Databases, you will need to import and initialize it.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initializeApp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  POST entries
&lt;/h2&gt;

&lt;p&gt;I would normally start with the &lt;code&gt;GET&lt;/code&gt; route, but we need the entries before we can get them. So you will write the &lt;code&gt;POST&lt;/code&gt; route to push data to the database.&lt;/p&gt;

&lt;p&gt;A basic example of an Express &lt;code&gt;POST /&lt;/code&gt; route is&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// send stuff...&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The fun thing about Realtime Database is that it is fully flexible, so you don't need to design a whole structure beforehand. Since it stores the data as one JSON tree, we can push a JSON structure and it will be enough. Of course, there needs to be validation involved if all the fields are pushed to the database, but this a nice talk for another time.&lt;/p&gt;

&lt;p&gt;So the entry that will be stored in the database will be the body of the request itself.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The way data is pushed to the database is&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;return&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;database&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/entries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;/entries&lt;/code&gt; being the path to the database reference.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;push&lt;/code&gt; function returns a promise that we will use to validate and send the response. On fulfilled, we will return the entry pushed and &lt;code&gt;200&lt;/code&gt; status code. Otherwise, catch and send the error as an &lt;code&gt;Internal Server Error&lt;/code&gt;.&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;return&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;database&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/entries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Oh no! Error: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;error&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;At the very core of it, that's it!&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;After a quick deploy, I take it in Postman and make a POST request to &lt;code&gt;/entries&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name:John Doe
subject:dev.to
message:Hello dev.to!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgfcgx0n1tehqtdzvvy2h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgfcgx0n1tehqtdzvvy2h.png" alt="Postman's expected response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you browse to your &lt;a href="https://console.firebase.google.com/" rel="noopener noreferrer"&gt;Firebase console&lt;/a&gt;, under &lt;strong&gt;Database&lt;/strong&gt; you will be able to see all the entries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqdwtyq68xow6kjnvknv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqdwtyq68xow6kjnvknv.png" alt="Realtime Database entries in my Firebase Console"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  GET entries
&lt;/h2&gt;

&lt;p&gt;To get all the data for the database, we will use&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="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;database&lt;/span&gt;&lt;span class="p"&gt;(...).&lt;/span&gt;&lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(...).&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;that will return through a callback all the entries that exist.&lt;/p&gt;

&lt;p&gt;This is actually a listener function, so each time there is a new entry in the database, it will be called (cool if you have a static page to monitor those entries).&lt;/p&gt;

&lt;p&gt;No promises this time, just a callback that returns the value in a &lt;code&gt;snapshot&lt;/code&gt;.&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="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;database&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/entries&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;snapshot&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;val&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;error&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Oh no! Error: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;error&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;Calling it in Postman I got a JSON with all the entries.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"-LZadZujD5Qb1MrQvAd_"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello, dev.to!!!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John Doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"subject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dev.to"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"-LZaeMZYJjQ2weey6k7H"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello dev.to!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jess Doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"subject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dev.to"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"-LZaeQc8DAOn0A6B1Gzc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello dev.to!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jane Doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"subject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dev.to"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Sticking everything together
&lt;/h2&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;If you deploy them, you can monitor the functions from the dashboard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi86dharm4v7iia07z7f8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi86dharm4v7iia07z7f8.png" alt="All the Google Cloud Functions in the Firebase Console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But note that you will not be able to see the quotas for each route if you write them for the same instance of an Express app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the functions locally
&lt;/h2&gt;

&lt;p&gt;It would be a pain in the ass to deploy to Firebase all the small changes just to test them. Firebase allows you to test all these functions locally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firebase serve &lt;span class="nt"&gt;--only&lt;/span&gt; functions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will serve your functions locally, just use the links generated in your terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✔  functions: entries: http://localhost:5000/dev-form-entries/us-central1/entries
✔  functions: helloWorld: http://localhost:5000/dev-form-entries/us-central1/helloWorld
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Finale
&lt;/h1&gt;

&lt;p&gt;That's really not much at all. This is just a glimpse of the greatness of Serverless APIs, Google Cloud Functions and Realtime Databases on Firebase. There are other ways to deal with data (such as deleting or updating it). There is a lot of validation and security layers that &lt;strong&gt;you should&lt;/strong&gt; add on top of these.&lt;/p&gt;

&lt;p&gt;That's the basics that I want to share, I am actually considering writing a whole series about Serverless APIs on Firebase, while I document myself on the topic. Please let me know how are you using Firebase and what fancy stuff are you doing with all the features.&lt;/p&gt;

&lt;p&gt;Love!&lt;/p&gt;

</description>
      <category>node</category>
      <category>serverless</category>
      <category>firebase</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Run your Node.js application on a headless Raspberry Pi</title>
      <dc:creator>Bogdan Covrig</dc:creator>
      <pubDate>Sun, 17 Feb 2019 18:41:48 +0000</pubDate>
      <link>https://forem.com/bogdaaamn/run-your-nodejs-application-on-a-headless-raspberry-pi-4jnn</link>
      <guid>https://forem.com/bogdaaamn/run-your-nodejs-application-on-a-headless-raspberry-pi-4jnn</guid>
      <description>&lt;p&gt;Recently I've got a little piece of hardware (&lt;a href="https://www.raspberrypi.org/products/raspberry-pi-2-model-b/" rel="noopener noreferrer"&gt;Raspberry Pi 2 Model B&lt;/a&gt;) on my desk. Rather than have it sit on its ass all day, I got a little Node.js application up and running through Nginx.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get that Raspberry Pi up and running
&lt;/h2&gt;

&lt;p&gt;A headless install doesn't require any kind of extra hardware (such as screens or keyboard), so everything that you need is the Raspberry Pi itself, a microSD (or SD, depending on your hardware) card and an internet connection (wired or wireless, again depending on your Raspberry).&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Get the &lt;a href="https://www.raspbian.org/" rel="noopener noreferrer"&gt;Raspbian Stretch&lt;/a&gt; image
&lt;/h3&gt;

&lt;p&gt;Raspbian is the most optimized OS for Raspberries and I use it when I need a minimum and fast setup. Just go the &lt;a href="https://www.raspberrypi.org/downloads/raspbian/" rel="noopener noreferrer"&gt;official website&lt;/a&gt; and download the latest version of &lt;strong&gt;Raspbian Stretch Lite&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqo3ux97zqak2t0fmmrq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faqo3ux97zqak2t0fmmrq.png" alt="Download Raspbian Stretch Lite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Burn that image
&lt;/h3&gt;

&lt;p&gt;Insert your card in your PC and burn the Raspbian image on it.&lt;/p&gt;

&lt;p&gt;I followed &lt;a href="https://www.raspberrypi.org/documentation/installation/installing-images/mac.md" rel="noopener noreferrer"&gt;these instructions&lt;/a&gt; (&lt;a href="https://www.raspberrypi.org/documentation/installation/installing-images/linux.md" rel="noopener noreferrer"&gt;&lt;strong&gt;Linux&lt;/strong&gt;&lt;/a&gt;/&lt;a href="https://www.raspberrypi.org/documentation/installation/installing-images/windows.md" rel="noopener noreferrer"&gt;&lt;strong&gt;Windows&lt;/strong&gt;&lt;/a&gt; also available) because I prefer using my terminal, but &lt;a href="https://www.balena.io/etcher/" rel="noopener noreferrer"&gt;Etcher&lt;/a&gt; (a graphical alternative on steroids) is also available on all platforms.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Enable headless SSH connections
&lt;/h3&gt;

&lt;p&gt;SSH is not enabled by default in Raspbian, so you will have to do it before you boot the card for the first time.&lt;/p&gt;

&lt;p&gt;After the installation, go to &lt;code&gt;boot/&lt;/code&gt; and create a file called &lt;code&gt;ssh&lt;/code&gt; (no extension).&lt;/p&gt;

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

&lt;span class="nb"&gt;touch &lt;/span&gt;ssh


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  4. Boot that Raspberry Pi
&lt;/h3&gt;

&lt;p&gt;Insert the card, the power source, and the network cable. After the green LEDs stop blinking, your Raspberry Pi is good to go!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fapxnvzmp42n4dru60p55.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fapxnvzmp42n4dru60p55.jpg" alt="My Raspberry Pi good to go!"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  5. Find that Raspberry Pi
&lt;/h3&gt;

&lt;p&gt;So you have power, network and an OS, no keyboard, no screen. How do you connect to the Raspberry Pi?&lt;/p&gt;

&lt;p&gt;In order to SSH into it, you will have to find it in your network first. Supposing that you connected the Raspberry to your home network, you can see all the devices (MAC and IP addresses) in your LAN from the ARP table. Simply run in your terminal (working on all platforms)&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

arp &lt;span class="nt"&gt;-a&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;and you will find your Raspberry Pi right there.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

fritz.box (192.168.178.1) on en1 ifscope [ethernet]
raspberrypi.fritz.box (192.168.178.73) on en1 ifscope [ethernet]


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

&lt;/div&gt;
&lt;p&gt;In my case, &lt;code&gt;fritz.box&lt;/code&gt; is my router and right after is my Raspberry Pi. So from now on, I will connect to it through &lt;code&gt;192.168.178.73&lt;/code&gt; address.&lt;/p&gt;

&lt;p&gt;More about ARP tables and how you should find your devices there.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/onmyway133" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F20120%2Ff6355e24-68e5-42a1-bf8f-07dcb87e14b5.jpeg" alt="onmyway133"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/onmyway133/understanding-arp-at-the-mac-layer-2a14" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Understanding ARP at the MAC layer&lt;/h2&gt;
      &lt;h3&gt;Khoa Pham ・ Sep 21 '18&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#arp&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#mac&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#ip&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  6. &lt;em&gt;Finally&lt;/em&gt; SSH into that Raspberry Pi
&lt;/h3&gt;

&lt;p&gt;The default credentials are&lt;/p&gt;

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

username: pi
password: raspberry


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

&lt;/div&gt;
&lt;p&gt;SSH into the Raspberry Pi. On &lt;strong&gt;Mac&lt;/strong&gt; or &lt;strong&gt;Linux&lt;/strong&gt; you can just simply run&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 bash
ssh pi@192.168.178.73


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

&lt;/div&gt;
&lt;p&gt;while on &lt;strong&gt;Windows&lt;/strong&gt; are a few alternatives such as &lt;a href="https://www.putty.org/" rel="noopener noreferrer"&gt;Putty&lt;/a&gt; or the default config on &lt;a href="http://cmder.net/" rel="noopener noreferrer"&gt;Cmder&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Get your Node.js application up and running
&lt;/h2&gt;

&lt;p&gt;You are in! You should get your Node.js application up, so the following steps are run through SSH, on your Raspberry Pi.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Install Node.js on Raspbian
&lt;/h3&gt;

&lt;p&gt;There are a lot of ways to install &lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; on a Linux machine, but I always follow &lt;a href="https://github.com/nodesource" rel="noopener noreferrer"&gt;NodeSource&lt;/a&gt;'s instructions, being the safest way I ever did.&lt;/p&gt;

&lt;p&gt;For Node.js v11.x I ran&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
curl &lt;span class="nt"&gt;-sL&lt;/span&gt; https://deb.nodesource.com/setup_11.x | bash -
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; nodejs


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

&lt;/div&gt;
&lt;p&gt;Anyways, &lt;code&gt;curl -sL https://deb.nodesource.com/setup_11.x | bash -&lt;/code&gt; will provide more instructions if you need more tools or add-ons.&lt;/p&gt;

&lt;p&gt;Check if Node.js and &lt;code&gt;npm&lt;/code&gt; are installed properly.&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;node &lt;span class="nt"&gt;-v&lt;/span&gt;
v11.10.0

&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nt"&gt;-v&lt;/span&gt;
6.7.0


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

&lt;/div&gt;
&lt;p&gt;For other versions or troubleshooting take a look to &lt;a href="https://github.com/nodesource" rel="noopener noreferrer"&gt;NodeSource&lt;/a&gt;'s comprehensive docs. Raspbian is a Debian based OS, so look for Debian instructions.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/nodesource" rel="noopener noreferrer"&gt;
        nodesource
      &lt;/a&gt; / &lt;a href="https://github.com/nodesource/distributions" rel="noopener noreferrer"&gt;
        distributions
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      NodeSource Node.js Binary Distributions
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;
&lt;a href="https://nodesource.com" rel="nofollow noopener noreferrer"&gt;NodeSource&lt;/a&gt; N|Solid &amp;amp; Node.js Binary Distributions&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://nodesource.com" rel="nofollow 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%2Fnodesource%2Fdistributionsimages%2Fns-linux-distributions.svg" alt="NodeSource"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://circleci.com/gh/nodesource/distributions/tree/master" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/77cbd0010402463e7a4dbd5a02b76010ca80939a50ddbb2e7bb4466e700914c2/68747470733a2f2f636972636c6563692e636f6d2f67682f6e6f6465736f757263652f646973747269627574696f6e732f747265652f6d61737465722e7376673f7374796c653d737667" alt="CircleCI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/nodesource/distributions/actions/workflows/ci.yaml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/nodesource/distributions/actions/workflows/ci.yaml/badge.svg" alt="Github Actions Test"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This repository contains the instructions to install the &lt;strong&gt;&lt;a href="https://nodesource.com/products/runtime" rel="nofollow noopener noreferrer"&gt;NodeSource N|solid&lt;/a&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;a href="http://nodejs.org" rel="nofollow noopener noreferrer"&gt;Node.js&lt;/a&gt;&lt;/strong&gt; Binary Distributions via .rpm and .deb as well as their setup and support scripts.&lt;/p&gt;

&lt;p&gt;If you're looking for more information on NodeSource's low-impact Node.js performance monitoring platform, &lt;strong&gt;&lt;a href="https://nodesource.com/products/nsolid" rel="nofollow noopener noreferrer"&gt;Learn more here&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;&lt;strong&gt;New Update ⚠️&lt;/strong&gt;&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;We'd like to inform you of important changes to our distribution repository &lt;a href="https://github.com/nodesource/distributions" rel="noopener noreferrer"&gt;nodesource/distributions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's New:&lt;/strong&gt;&lt;/p&gt;


&lt;ul&gt;

&lt;li&gt;&lt;em&gt;&lt;strong&gt;Package Changes:&lt;/strong&gt; DEB and RPM packages are now available under the &lt;code&gt;nodistro&lt;/code&gt; codename. We no longer package the installer coupled to specific versions. This means you can install Node.js on almost any distro that meets the minimum requirements.&lt;/em&gt;&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Installation Scripts:&lt;/strong&gt; Back by popular demand, the installation scripts have returned and are better than ever. See the installation instructions below for details on how to use them.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;RPM Package Signing Key:&lt;/strong&gt; The key used to sign RPM packages has changed. We now sign…&lt;/li&gt;

&lt;/ul&gt;
&lt;/div&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/nodesource/distributions" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;If you choose to write or paste the code, quickly install &lt;code&gt;vim&lt;/code&gt;, it will make our lives easier and later I will walk you through, don't worry.&lt;/p&gt;

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

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;vim &lt;span class="nt"&gt;-y&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  2. Get your Node.js app
&lt;/h3&gt;

&lt;p&gt;Write, copy-paste or &lt;a href="https://github.com/BogDAAAMN/nodejs-hello-world" rel="noopener noreferrer"&gt;clone&lt;/a&gt; the Node.js application. For testing purposes, I created &lt;code&gt;app.js&lt;/code&gt; file.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; ~
vim app.js


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

&lt;/div&gt;
&lt;p&gt;I pasted the following boilerplate&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/plain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello dev.to!&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PORT&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server running on port &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;If &lt;code&gt;vim&lt;/code&gt; is too overwhelming you can try to use other ways as &lt;code&gt;nano&lt;/code&gt;. But just to be sure, this is a &lt;em&gt;really quick&lt;/em&gt; follow-up:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open (or create) the file with &lt;code&gt;vim app.js&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now, &lt;code&gt;vim&lt;/code&gt; is in the &lt;strong&gt;normal mode&lt;/strong&gt; and it's waiting for your command. Press &lt;code&gt;i&lt;/code&gt; to go in the &lt;strong&gt;insert mode&lt;/strong&gt;, this will allow you write code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Type or paste your code now, exactly how you'd do it in your editor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you're done writing, press &lt;code&gt;esc&lt;/code&gt; so you go back to the &lt;strong&gt;normal mode&lt;/strong&gt; so you can command &lt;code&gt;vim&lt;/code&gt; to save and exit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Usually, &lt;code&gt;vim&lt;/code&gt; commands start with &lt;code&gt;:&lt;/code&gt;. Gently press &lt;code&gt;:&lt;/code&gt; followed by &lt;code&gt;w&lt;/code&gt; for &lt;strong&gt;w&lt;/strong&gt;riting and &lt;code&gt;q&lt;/code&gt; for &lt;strong&gt;q&lt;/strong&gt;uitting. You can actually see the commands that you're typing on the bottom of your terminal. Press enter to acknowledge the commands.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Taa-daaaaa. &lt;code&gt;app.js&lt;/code&gt; is saved.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want to do more crazy tricks with &lt;code&gt;vim&lt;/code&gt;, follow-up this beginner guide and you will see that &lt;code&gt;vim&lt;/code&gt; is not &lt;strong&gt;that&lt;/strong&gt; bad.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/hamza" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F50687%2F03827052-2382-44b8-adbb-2315f8d649ee.png" alt="hamza"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/hamza/vim-for-starters---the-minimum-you-need-to-know-3ob" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Vim for starters - the minimum you need to know&lt;/h2&gt;
      &lt;h3&gt;Hamza Tamenaoul ・ Dec 25 '17&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#vim&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#linux&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#terminal&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  3. &lt;em&gt;Finally&lt;/em&gt; run the Node.js application
&lt;/h3&gt;

&lt;p&gt;Run&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;node app
Server running at 127.0.0.1 on port 3000.


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

&lt;/div&gt;
&lt;p&gt;and your Node.js app will run on &lt;code&gt;localhost:3000/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Because none of the ports are opened by default, you can test the app only from your Raspberry Pi. Open a new tab of the SSH connection and run&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

curl localhost:3000


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

&lt;/div&gt;
&lt;p&gt;and you should get&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Hello dev.to!


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  4. Install PM2
&lt;/h3&gt;

&lt;p&gt;Of course that you want your application daemonized (in &lt;em&gt;background&lt;/em&gt;) and of course that you want your application to start when the system is restarting. &lt;a href="https://github.com/Unitech/pm2" rel="noopener noreferrer"&gt;PM2&lt;/a&gt; will provide all of this.&lt;/p&gt;

&lt;p&gt;Stop your Node.js application (&lt;code&gt;ctrl + C&lt;/code&gt;) and proceed to installation.&lt;/p&gt;

&lt;p&gt;We will use &lt;code&gt;npm&lt;/code&gt; to install PM2 globally &lt;code&gt;-g&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;sudo &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; pm2


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

&lt;/div&gt;
&lt;h4&gt;
  
  
  Start the application with PM2
&lt;/h4&gt;

&lt;p&gt;To start &lt;code&gt;app.js&lt;/code&gt; with PM2 run&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 bash
pm2 start app.js


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

&lt;/div&gt;
&lt;p&gt;and you should see&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

[PM2] Starting /home/pi/app.js in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬─────────┬──────┬─────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐
│ App name │ id │ version │ mode │ pid │ status │ restart │ uptime │ cpu │ mem       │ user │ watching │
├──────────┼────┼─────────┼──────┼─────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤
│ app      │ 0  │ N/A     │ fork │ 738 │ online │ 0       │ 0s     │ 0%  │ 21.8 MB   │ pi   │ disabled │
└──────────┴────┴─────────┴──────┴─────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘


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

&lt;/div&gt;
&lt;p&gt;Now &lt;code&gt;app.js&lt;/code&gt; is daemonized running. You can test it as we did before with &lt;code&gt;curl localhost:3000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bonus&lt;/strong&gt;:  if the app crashes, PM2 will restart it.&lt;/p&gt;
&lt;h4&gt;
  
  
  PM2 startup
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;pm2 startup&lt;/code&gt; command will generate a script that will lunch PM2 on boot together with the applications that you configure to start.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

pm2 startup systemd


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

&lt;/div&gt;
&lt;p&gt;will generate&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

[PM2] Init System found: systemd
[PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u pi --hp /home/pi


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

&lt;/div&gt;
&lt;p&gt;Copy the generated command and run it.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;sudo env &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd &lt;span class="nt"&gt;-u&lt;/span&gt; pi &lt;span class="nt"&gt;--hp&lt;/span&gt; /home/p


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

&lt;/div&gt;
&lt;p&gt;This created a system unit that will start PM2 on boot. When the system will boot PM2 will resurrect from a dump file that is not created yet. To create it run&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

pm2 save


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

&lt;/div&gt;
&lt;p&gt;This will save the current state of PM2 (with &lt;code&gt;app.js&lt;/code&gt; running) in a dump file that will be used when resurrecting PM2.&lt;/p&gt;

&lt;p&gt;That's it! Your application is currently running and in case of a restart, it will start when the system boots.&lt;/p&gt;
&lt;h4&gt;
  
  
  PM2 daemon
&lt;/h4&gt;

&lt;p&gt;You will be able to check anytime the status of your application with &lt;code&gt;pm2 list&lt;/code&gt;, &lt;code&gt;pm2 status&lt;/code&gt; or &lt;code&gt;pm2 show&lt;/code&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;pm2 list
┌──────────┬────┬─────────┬──────┬─────┬────────┬─────────┬────────┬──────┬───────────┬──────┬──────────┐
│ App name │ &lt;span class="nb"&gt;id&lt;/span&gt; │ version │ mode │ pid │ status │ restart │ &lt;span class="nb"&gt;uptime&lt;/span&gt; │ cpu  │ mem       │ user │ watching │
├──────────┼────┼─────────┼──────┼─────┼────────┼─────────┼────────┼──────┼───────────┼──────┼──────────┤
│ app      │ 0  │ N/A     │ fork │ 451 │ online │ 0       │ 96m    │ 0.2% │ 31.8 MB   │ pi   │ disabled │
└──────────┴────┴─────────┴──────┴─────┴────────┴─────────┴────────┴──────┴───────────┴──────┴──────────┘


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

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

$ pm2 show app
┌───────────────────┬──────────────────────────────────┐
│ status            │ online                           │
│ name              │ app                              │
│ version           │ N/A                              │
│ restarts          │ 0                                │
│ uptime            │ 97m                              │
│ script path       │ /home/pi/app.js                  │
│ script args       │ N/A                              │
│ error log path    │ /home/pi/.pm2/logs/app-error.log │
│ out log path      │ /home/pi/.pm2/logs/app-out.log   │
│ pid path          │ /home/pi/.pm2/pids/app-0.pid     │
│ interpreter       │ node                             │
│ interpreter args  │ N/A                              │
│ script id         │ 0                                │
│ exec cwd          │ /home/pi                         │
│ exec mode         │ fork_mode                        │
│ node.js version   │ 11.10.0                          │
│ node env          │ N/A                              │
│ watch &amp;amp; reload    │ ✘                                │
│ unstable restarts │ 0                                │
│ created at        │ 2019-02-17T14:14:35.027Z         │
└───────────────────┴──────────────────────────────────┘


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

&lt;/div&gt;
&lt;p&gt;There is a lot of greatness within PM2 that you can use, read more about logs and processes below.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/nickparsons" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F23591%2Faff7eabf-f28f-4520-a8a4-77c13fd8a3ef.png" alt="nickparsons"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/nickparsons/running-pm2--nodejs-in-production-environments-23i5" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Running PM2 &amp;amp; Node.js in Production Environments&lt;/h2&gt;
      &lt;h3&gt;Nick Parsons ・ Aug 6 '18&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#pm2&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#processmanagement&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Make use of a Reverse Proxy
&lt;/h2&gt;

&lt;p&gt;As I mentioned before, none of the ports on your devices are publicly open yet, so you cannot access your Raspberry Pi from the outer world. There are &lt;a href="https://www.reddit.com/r/node/comments/6b3voh/why_would_you_use_a_reverse_proxy_for_node/" rel="noopener noreferrer"&gt;a ton of reason&lt;/a&gt; why you should or shouldn't use a reverse proxy for your Node.js application. Because of scalability and security reasons (and also is really simple to setup and manage), I will use Nginx as a Reverse Proxy Server for this application.&lt;/p&gt;

&lt;h3&gt;
  
  
  0. Don't use a Reverse Proxy :(
&lt;/h3&gt;

&lt;p&gt;If you plan to use a Reverse Proxy don't follow this step otherwise you will mess up the ports (like having 80 and 3000 opened at the same time).&lt;/p&gt;

&lt;p&gt;An uncomplicated way to go without a Reverse Proxy is to use &lt;a href="https://help.ubuntu.com/community/UFW" rel="noopener noreferrer"&gt;&lt;code&gt;ufw&lt;/code&gt;&lt;/a&gt; to allow some of the ports to allow incoming traffic. But note that this might be a big security flaw.&lt;/p&gt;

&lt;p&gt;Install it by running&lt;/p&gt;

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

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt-get &lt;span class="nb"&gt;install &lt;/span&gt;ufw


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

&lt;/div&gt;
&lt;p&gt;A quick &lt;code&gt;sudo ufw status verbose&lt;/code&gt; will show us that &lt;code&gt;ufw&lt;/code&gt; is currently inactive. Before you enable it, you should allow all the SSH traffic to your device, so the connection is not disturbed.&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;sudo &lt;/span&gt;ufw allow ssh
Rules updated
Rules updated &lt;span class="o"&gt;(&lt;/span&gt;v6&lt;span class="o"&gt;)&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Now you can enable it.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw &lt;span class="nb"&gt;enable&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Another quick &lt;code&gt;sudo ufw status verbose&lt;/code&gt; will show that all incoming SSH traffic is allowed. All the outgoing traffic is allowed, so don't worry about it. Now just go on and allow connections on &lt;code&gt;3000&lt;/code&gt;, the port of your application.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow 3000


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

&lt;/div&gt;
&lt;p&gt;Now you can access from the outside of the world! You can type your device's address followed by the port in your browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93sh85a36ouaa1c9zg3g.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93sh85a36ouaa1c9zg3g.jpg" alt="Outer world"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Install NGINX
&lt;/h3&gt;

&lt;p&gt;I used Nginx as a Reverse Proxy Server to redirect all the traffic to/from port &lt;code&gt;80&lt;/code&gt; to my application, on port &lt;code&gt;3000&lt;/code&gt;. Install Nginx running&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;nginx


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

&lt;/div&gt;
&lt;p&gt;After the installation, Nginx will be running right away. The default port opened is &lt;code&gt;80&lt;/code&gt; and you can test it by browsing to your Raspberry's address.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Filr5iiu2wm1bpir29tyi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Filr5iiu2wm1bpir29tyi.png" alt="Welcome to Nginx, dev.to"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Configure the Reverse Proxy Server
&lt;/h3&gt;

&lt;p&gt;There is a lot to say about Reverse Proxies, but we will stick to basics now.&lt;/p&gt;

&lt;p&gt;You will edit the default configuration (that serves the HTML page that you saw in your browser) to make the proper redirects.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;sudo &lt;/span&gt;vim /etc/nginx/sites-available/default


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

&lt;/div&gt;
&lt;p&gt;If you are not familiar to Nginx, &lt;code&gt;/etc/nginx/sites-available/default&lt;/code&gt; is a long, confusing file. I will get rid of all the comments so you can see it better.&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;80&lt;/span&gt; &lt;span class="s"&gt;default_server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:80&lt;/span&gt; &lt;span class="s"&gt;default_server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.html&lt;/span&gt; &lt;span class="s"&gt;index.htm&lt;/span&gt; &lt;span class="s"&gt;index.nginx-debian.html&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;_&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="c1"&gt;# First attempt to serve request as file, then&lt;/span&gt;
            &lt;span class="c1"&gt;# as directory, then fall back to displaying a 404.&lt;/span&gt;
            &lt;span class="kn"&gt;try_files&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt; &lt;span class="nv"&gt;$uri&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="c1"&gt;# proxy_pass http://localhost:8080;&lt;/span&gt;
            &lt;span class="c1"&gt;# proxy_http_version 1.1;&lt;/span&gt;
            &lt;span class="c1"&gt;# proxy_set_header Upgrade $http_upgrade;&lt;/span&gt;
            &lt;span class="c1"&gt;# proxy_set_header Connection 'upgrade';&lt;/span&gt;
            &lt;span class="c1"&gt;# proxy_set_header Host $host;&lt;/span&gt;
            &lt;span class="c1"&gt;# proxy_cache_bypass $http_upgrade;&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;You will need the basic configuration, therefore leave it be. You will make changes to &lt;code&gt;location / {&lt;/code&gt; block.&lt;/p&gt;

&lt;p&gt;Uncomment the commented section inside that block, change the port to &lt;code&gt;3000&lt;/code&gt;, get rid of the first lines and that exact configuration is a Reverse Proxy (or just copy the following code).&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;80&lt;/span&gt; &lt;span class="s"&gt;default_server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="s"&gt;[::]:80&lt;/span&gt; &lt;span class="s"&gt;default_server&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;root&lt;/span&gt; &lt;span class="n"&gt;/var/www/html&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;index&lt;/span&gt; &lt;span class="s"&gt;index.html&lt;/span&gt; &lt;span class="s"&gt;index.htm&lt;/span&gt; &lt;span class="s"&gt;index.nginx-debian.html&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;_&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="kn"&gt;proxy_cache_bypass&lt;/span&gt; &lt;span class="nv"&gt;$http_upgrade&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;Check for syntax errors in Nginx with&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;sudo &lt;/span&gt;nginx &lt;span class="nt"&gt;-t&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;and &lt;em&gt;finally&lt;/em&gt; restart the Nginx server.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nginx


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

&lt;/div&gt;
&lt;p&gt;Test it out by browsing to your Raspberry's address.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvyoguw76yosplkltiu0t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvyoguw76yosplkltiu0t.png" alt="Finally the needed outer world"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Done! All the requests to your Raspberry's address will be redirected to your Node.js application.&lt;/p&gt;

&lt;p&gt;Note that this is a basic configuration of Nginx, you can discover more about other features here.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/legobox" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__org__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F225%2F82a803f4-5759-4cc7-892a-2cf5e74dada8.png" alt="Legobox"&gt;
      &lt;div class="ltag__link__user__pic"&gt;
        &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F22851%2Fc1e857d6-6ad3-46af-88d0-933d3078611c.jpg" alt=""&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/legobox/understanding-nginx-proxying-reverse-proxying-load-balancing-1pjd" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Understanding nginx (proxying, reverse proxying, load balancing)&lt;/h2&gt;
      &lt;h3&gt;Osita Chibuike for Legobox ・ May 23 '18&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#showdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#linux&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#learning&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Finale
&lt;/h2&gt;

&lt;p&gt;Now you are done! So you got a Node.js application running (daemonized) on a headless Raspberry Pi that deals with requests through an Nginx Reverse Proxy Server.&lt;/p&gt;

&lt;p&gt;Hopefully, this was a comprehensive enough guide, but I am open to discussions and questions below. Let us know what you've experienced or what other alternatives you found on the way.&lt;/p&gt;

</description>
      <category>raspberrypi</category>
      <category>node</category>
      <category>nginx</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
