<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bernardo Cassina</title>
    <description>The latest articles on DEV Community by Bernardo Cassina (@cassina).</description>
    <link>https://dev.to/cassina</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%2F1213124%2F074efc9a-fe73-49e3-a873-fb04e0a34027.png</url>
      <title>DEV Community: Bernardo Cassina</title>
      <link>https://dev.to/cassina</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cassina"/>
    <language>en</language>
    <item>
      <title>Firebase Functions Express Typescript Project Guide Part 2</title>
      <dc:creator>Bernardo Cassina</dc:creator>
      <pubDate>Tue, 14 May 2024 14:45:53 +0000</pubDate>
      <link>https://dev.to/cassina/firebase-functions-express-typescript-project-guide-part-2-3jhg</link>
      <guid>https://dev.to/cassina/firebase-functions-express-typescript-project-guide-part-2-3jhg</guid>
      <description>&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Understanding about Promises and &lt;a href="https://www.freecodecamp.org/news/javascript-async-await/"&gt;async/await in Javascript&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this part we will create a &lt;strong&gt;REST API&lt;/strong&gt;  to perform &lt;strong&gt;CRUD&lt;/strong&gt; operations in a &lt;strong&gt;Pets&lt;/strong&gt; resource. We will be able to use this &lt;strong&gt;API&lt;/strong&gt; to interact with our &lt;strong&gt;Pets Firestore Collection&lt;/strong&gt; like dogs or cats.&lt;/p&gt;

&lt;p&gt;First it is important to understand the Best Practices of REST API Design, please &lt;a href="https://stackoverflow.blog/2020/03/02/best-practices-for-rest-api-design/"&gt;read this article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note: Remember to build the Functions project every time you make a new change with &lt;code&gt;npm run buil&lt;/code&gt; this will recreate the &lt;code&gt;lib&lt;/code&gt; directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  0. Design First Path
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Now, that you have read about the best practices let’s design our paths. Let’s say that our default URL will be &lt;code&gt;http://127.0.0.1:5001/my-project/us-central1/api&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;First we want to create &lt;strong&gt;Pets&lt;/strong&gt;, so our first path should be &lt;code&gt;/pets&lt;/code&gt; . This endpoint will create a brand new pet and it should return the new resource created along with its database ID, so we can identify it later.&lt;/li&gt;
&lt;li&gt;The HTTP method we use to create a new resource is &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST"&gt;POST&lt;/a&gt;&lt;/strong&gt; so we will create a new function that accepts a &lt;code&gt;POST&lt;/code&gt; request and creates a new &lt;code&gt;Pet&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It will look something like this:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&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="s2"&gt;/pets&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;req&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;res&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="c1"&gt;// create a new pet );&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Create Pet Model
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Now that we created our first &lt;strong&gt;POST&lt;/strong&gt; path, we now we want to create &lt;strong&gt;Pets,&lt;/strong&gt; but how would a pet look like, what properties should it have? Let’s use a simple example, let’s say a pet has these properties:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Pet
&lt;span class="p"&gt;    -&lt;/span&gt; id
&lt;span class="p"&gt;  -&lt;/span&gt; category
&lt;span class="p"&gt;  -&lt;/span&gt; name
&lt;span class="p"&gt;  -&lt;/span&gt; tags
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now all of this properties need a &lt;a href="https://firebase.google.com/docs/firestore/data-model#:~:text=Note%3A%20Cloud%20Firestore%20supports%20a,structure%20data%20within%20a%20document.&amp;amp;text=You%20may%20notice%20that%20documents,In%20fact%2C%20they%20basically%20are."&gt;Firestore Type&lt;/a&gt; like boolean, string or number. Let’s define them:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Pet
&lt;span class="p"&gt;    -&lt;/span&gt; id: string;
&lt;span class="p"&gt;  -&lt;/span&gt; category: string;
&lt;span class="p"&gt;  -&lt;/span&gt; name: string;
&lt;span class="p"&gt;  -&lt;/span&gt; tags: Array of strings;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now we have the properties for our &lt;strong&gt;Pet&lt;/strong&gt; model, we need to use the power of Typescript to define this model in our code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;First let’s define what Typescript uses interfaces and types for [GPT complete this part]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now that we now how interfaces and types work, let’s create our Pet interface:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// Array of strings&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now, probably we want to have explicit categories, so we don’t pets without a valid category, we can do that with a Type:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PetCategory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bird&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;And the we update our &lt;strong&gt;Pet&lt;/strong&gt; interface:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PetCategory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// Array of strings&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This way we will make sure only strings of those values can be passed to a &lt;code&gt;Pet&lt;/code&gt; interface and if not, the TS compiler will throw an error.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now that we have our type and interfaces, let’s add them to our code. The good practice is to create separate files for them an import them as necessary. Let’s create an &lt;code&gt;interfaces.ts&lt;/code&gt; and &lt;code&gt;types.ts&lt;/code&gt; inside the &lt;code&gt;src&lt;/code&gt; directory next to the &lt;code&gt;index.ts&lt;/code&gt; file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The content of the types file should be:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PetCategory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dog&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bird&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;/li&gt;
&lt;li&gt;
&lt;p&gt;And the interfaces file should look like this:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// We create a relative import to use the PetCategory type in our interface&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;PetCategory&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PetCategory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// Array of strings&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Great! Now we have a new &lt;code&gt;Pet&lt;/code&gt; model.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Initialize Firestore
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;First let’s add the Firestore emulator, otherwise all calls will be added to your Firebase Project’s Firestore Database you created un part 1 and we want to test in our local environment first.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Let’s modify the &lt;code&gt;serve&lt;/code&gt; script in package.json file to add Firestore emulators:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;serve&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="s2"&gt;npm run build &amp;amp;&amp;amp; firebase emulators:start --only=functions,firestore&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Let’s run &lt;code&gt;npm serve&lt;/code&gt; and you should see something like this:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;i&lt;/span&gt;  &lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Firestore&lt;/span&gt; &lt;span class="nx"&gt;Emulator&lt;/span&gt; &lt;span class="nx"&gt;logging&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;
&lt;span class="err"&gt;✔&lt;/span&gt;  &lt;span class="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Firestore&lt;/span&gt; &lt;span class="nx"&gt;Emulator&lt;/span&gt; &lt;span class="nx"&gt;UI&lt;/span&gt; &lt;span class="nx"&gt;websocket&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;running&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="mi"&gt;9150&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="err"&gt;┌───────────┬────────────────┬─────────────────────────────────┐&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="nx"&gt;Emulator&lt;/span&gt;  &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="nx"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;Port&lt;/span&gt;      &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="nx"&gt;View&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;Emulator&lt;/span&gt; &lt;span class="nx"&gt;UI&lt;/span&gt;             &lt;span class="err"&gt;│&lt;/span&gt;
&lt;span class="err"&gt;├───────────┼────────────────┼─────────────────────────────────┤&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="nx"&gt;Functions&lt;/span&gt; &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="mf"&gt;127.0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5001&lt;/span&gt; &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//127.0.0.1:4000/functions │&lt;/span&gt;
&lt;span class="err"&gt;├───────────┼────────────────┼─────────────────────────────────┤&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="nx"&gt;Firestore&lt;/span&gt; &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="mf"&gt;127.0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt; &lt;span class="err"&gt;│&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//127.0.0.1:4000/firestore │&lt;/span&gt;
&lt;span class="err"&gt;└───────────┴────────────────┴─────────────────────────────────┘&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now let’s initialize Firestore in the &lt;code&gt;main.ts&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;other&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt;

&lt;span class="c1"&gt;// Import Firebase admin to use Firestore&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;admin&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firebase-admin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Import the Pet interface&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./interfaces&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Initialize Firebase Admin SDK&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;span class="c1"&gt;// Firestore database reference&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&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;firestore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Let’s also use &lt;code&gt;express.json&lt;/code&gt; in our express app to parse requests:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;
&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;other&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&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="c1"&gt;// Middleware to parse JSON requests&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="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now build the project to update the emulators server&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Create new Pet
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Let’s write a function to create the new &lt;code&gt;Pet&lt;/code&gt;, but first &lt;a href="https://firebase.google.com/docs/firestore/manage-data/add-data"&gt;read this&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Define a POST route for creating new pets&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;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/pets&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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;res&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="c1"&gt;// Extract the new pet data from the request body&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;newPet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CreatePetBody&lt;/span&gt; &lt;span class="o"&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;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Add the new pet to the "pets" collection in Firestore&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;docRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pets&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newPet&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Create a pet document with the generated ID and pet data&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;petDocument&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PetDocument&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;docRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;newPet&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// Send the created pet document as the response with status 201&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&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;petDocument&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="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Send an error response with status 500 if something goes wrong&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;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="s2"&gt;Error creating new pet: &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;/li&gt;
&lt;li&gt;&lt;p&gt;Now build the project to update the emulators server&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open postman, create a new &lt;code&gt;POST&lt;/code&gt; request to the default URL and the path &lt;code&gt;/pets&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the &lt;strong&gt;Body,&lt;/strong&gt; then select &lt;strong&gt;Raw&lt;/strong&gt; and &lt;strong&gt;JSON&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now add the following:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;category&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="s2"&gt;dog&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="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Buddy&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="s2"&gt;tags&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;friendly&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="s2"&gt;playful&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;/li&gt;
&lt;li&gt;
&lt;p&gt;If it worked, the Postman response should look like this:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&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="s2"&gt;Jth82AgC7CIMxxXQKPEF&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="s2"&gt;category&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="s2"&gt;dog&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="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Buddy&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="s2"&gt;tags&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;friendly&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="s2"&gt;playful&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;/li&gt;
&lt;li&gt;&lt;p&gt;Now we can use that id to retrieve that specific pet in the future and if you go to &lt;code&gt;http://localhost:4000/firestore&lt;/code&gt; you should see the new data in the emulator&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. What if some parameters are missing?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;So what happens if someone tries to create a Pet without a name? We will create a Document that looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&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="s2"&gt;Jth82AgC7CIMxxXQKPEF&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="s2"&gt;category&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="s2"&gt;dog&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="s2"&gt;tags&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;friendly&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="s2"&gt;playful&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;/li&gt;
&lt;li&gt;
&lt;p&gt;This is not correct and can lead to data corruption, we need to make sure we are persisting the data following our interfaces and type models. So let’s add a check:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;newPet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&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;400&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;Bad request: missing name&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;/li&gt;
&lt;li&gt;
&lt;p&gt;Also we should check that the &lt;code&gt;category&lt;/code&gt; is passed as an argument:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;newPet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&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;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&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;Bad request: missing category&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;/li&gt;
&lt;li&gt;&lt;p&gt;Try to create a pet without category or name, you should receive  a &lt;code&gt;Bad request: missing name&lt;/code&gt; response&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;What about the tags? The tags is an array of strings, we can either set it as an empty array or as an optional property. Let’s add it as optional, modify the interface to add a &lt;code&gt;?&lt;/code&gt; that tells typescript this is an optional property:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;PetCategory&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./types&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PetCategory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt; &lt;span class="c1"&gt;// Optional ? Array of strings&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cool. Now we can create Pets.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. GET Pets and filter by category and tag
&lt;/h2&gt;

&lt;p&gt;After creating the Pets, it’s time to read those Pets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://firebase.google.com/docs/firestore/query-data/get-data"&gt;Read this first&lt;/a&gt; to learn how to get data from Firestore&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now let’s get all our pets:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&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;/pets&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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;res&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;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Reference to the pets collection&lt;/span&gt;
    &lt;span class="c1"&gt;// CollectionReference: https://firebase.google.com/docs/reference/node/firebase.firestore.CollectionReference&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;petsRef&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="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pets&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Fetch pets from Firestore&lt;/span&gt;
    &lt;span class="c1"&gt;// This declaration returns a Firestore QuerySnapshot:&lt;/span&gt;
    &lt;span class="c1"&gt;// https://firebase.google.com/docs/reference/node/firebase.firestore.QuerySnapshot&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;snapshot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;petsRef&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="c1"&gt;// Why do we need to iterate over docs? We need to iterate&lt;/span&gt;
    &lt;span class="c1"&gt;// over docs to convert each document into a usable object&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PetResponse&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;docs&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;docSnapshot&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="nx"&gt;firestore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;QueryDocumentSnapshot&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="c1"&gt;// What is "as"? "as" is a TypeScript type assertion,&lt;/span&gt;
        &lt;span class="c1"&gt;// telling the compiler that docSnapshot.data() is of type Pet&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;docSnapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;Pet&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Return the data along with the Document ID&lt;/span&gt;
        &lt;span class="c1"&gt;// Combining the document ID with the pet data into one object&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;docSnapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Send the processed and filtered pets as the response&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;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;pets&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="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Send an error response with status 500 if something goes wrong&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;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="s2"&gt;Error reading pets: &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;/li&gt;
&lt;li&gt;
&lt;p&gt;So what if we want to search for pets that have only the &lt;code&gt;dog&lt;/code&gt; category. In REST API design, we can do that with query parameters added to our path like so:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;dog&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We can other queries as well:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;pets&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;dog&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;intelligent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;This way we can tell Firestore to filter the results like this:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pets&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;category&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;==&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;dog&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;/li&gt;
&lt;li&gt;&lt;p&gt;So the final code should look like this:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.get("/pets", async (req: Request, res: Response) =&amp;gt; {
  try {
    // Get query parameters
    const {category, tag} = req.query;

    // Reference to the pets collection
    // CollectionReference: https://firebase.google.com/docs/reference/node/firebase.firestore.CollectionReference)
    let petsRef: admin.firestore.Query = db.collection("pets");

    // Apply category filter if provided
    if (category) {
      petsRef = petsRef.where("category", "==", category);
    }

    // Apply category filter if provided
    if (tag) {
      petsRef = petsRef.where("tag", "==", tag);
    }

    // Fetch pets from Firestore
    // This declaration returns a Firestore QuerySnapshot:
    // https://firebase.google.com/docs/reference/node/firebase.firestore.QuerySnapshot
    const snapshot = await petsRef.get();

    // What's going on? Why do we need to iterate over docs?
    const pets: PetResponse[] = snapshot.docs
      .map((docSnapshot: admin.firestore.QueryDocumentSnapshot) =&amp;gt; {
        // What's going on here? What is "as"?
        const pet: Pet = docSnapshot.data() as Pet;

        // Return the data along with the Document ID
        return {
          id: docSnapshot.id,
          data: pet,
        };
      });

    // Send the processed and filtered pets as the response
    res.status(200).send(pets);
  } catch (error) {
    // Send an error response with status 500 if something goes wrong
    res.status(500).send("Error reading pets: " + error);
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hell yeah! Now we have created and filtered virtual animals.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>express</category>
      <category>firebase</category>
    </item>
    <item>
      <title>Firebase Functions Express Typescript Project Guide Part 1</title>
      <dc:creator>Bernardo Cassina</dc:creator>
      <pubDate>Tue, 14 May 2024 01:16:20 +0000</pubDate>
      <link>https://dev.to/cassina/firebase-functions-express-typescript-project-guide-3ji4</link>
      <guid>https://dev.to/cassina/firebase-functions-express-typescript-project-guide-3ji4</guid>
      <description>&lt;p&gt;This guide will walk you through setting up your Mac for development with Node.js, Firebase, and Firestore, including creating a simple Express app within a Firebase Functions project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Basic command line knowledge&lt;/li&gt;
&lt;li&gt;Mac computer with admin access&lt;/li&gt;
&lt;li&gt;Mac with &lt;strong&gt;&lt;a href="https://forums.developer.apple.com/forums/thread/677124"&gt;XCode&lt;/a&gt;&lt;/strong&gt; installed&lt;/li&gt;
&lt;li&gt;Postman Installed&lt;/li&gt;
&lt;li&gt;Create a Firebase Project before hand&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;h3&gt;
  
  
  0. Create a Firebase Project
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Login into your google account&lt;/li&gt;
&lt;li&gt;Go to the &lt;a href="https://console.firebase.google.com/"&gt;Firebase Console&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Create a new project and name it however you like, we’ll use the name &lt;code&gt;my-project&lt;/code&gt; for this example.&lt;/li&gt;
&lt;li&gt;Don’t set Google Analytics, not necessary&lt;/li&gt;
&lt;li&gt;After your Project is ready, you’ll be redirected to the project overview page&lt;/li&gt;
&lt;li&gt;On the left Sidenav, click the settings icon, select Project settings&lt;/li&gt;
&lt;li&gt;Look for your Project ID&lt;/li&gt;
&lt;li&gt;Now go to the &lt;a href="https://console.firebase.google.com"&gt;Firestore page here&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Select the default location&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Start in test mode&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;After the DB has been created,  you’ll see an empty Database 😬&lt;/li&gt;
&lt;li&gt;That’s all we need to know now, well come back to the console later&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1. &lt;a href="https://brew.sh/"&gt;Install Homebrew&lt;/a&gt; and Java
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://brew.sh/"&gt;Homebrew&lt;/a&gt; is a package manager for macOS. It simplifies the installation of software on macOS.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After installation, verify it by running:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;brew&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tu use the Firebase Emulators, we need to install the &lt;strong&gt;Java JDK&lt;/strong&gt;, you can do it with &lt;a href="https://formulae.brew.sh/formula/openjdk"&gt;homebrew&lt;/a&gt;, although there are other methods.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;a href="https://medium.com/@priscillashamin/how-to-install-and-configure-nvm-on-mac-os-43e3366c75a6"&gt;Install Node.js 18 Using nvm&lt;/a&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/@priscillashamin/how-to-install-and-configure-nvm-on-mac-os-43e3366c75a6"&gt;Install Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Note: the example is for Node 16 although you should install Node 18 &lt;code&gt;nvm&lt;/code&gt;, although with &lt;code&gt;nvm&lt;/code&gt; you can have multiple node versions and choose between them 😉&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nvm&lt;/code&gt; allows you to manage multiple installations of Node.js.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After installing &lt;code&gt;nvm&lt;/code&gt; and Node 18 , verify installation by running:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Make sure &lt;code&gt;npm&lt;/code&gt; is installed
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Verify by running:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Install Firebase CLI
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The firebase CLI is…&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install it &lt;strong&gt;globally&lt;/strong&gt; by runnning:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;g&lt;/span&gt; &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;tools&lt;/span&gt;

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

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Verify the installation:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;firebase &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Create a New Firebase Functions TypeScript Project
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;To use Firebase products like Functions, Firestore, Auth, and others, we need to create a new Firebase project.&lt;/li&gt;
&lt;li&gt;Note: this project is different from your Firebase Console Project where we will deploy this Typescript project. To be clear: one is the code project and the other, a container in Firebase Console to deploy our code project.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Initialize your project:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# In a terminal, change to your existing Develop directory:&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;my-dev-directory
&lt;span class="c"&gt;# Create a new directory to store the project&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-firebase-project
&lt;span class="c"&gt;# Move into the new directory&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;my-firebase-project
&lt;span class="c"&gt;# Login into Firebase&lt;/span&gt;
firebase login

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

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;That command will prompt a URL or open your browser so you can login with your google account.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After successful login, Initialize the Firebase project&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Initialize&lt;/span&gt; &lt;span class="nx"&gt;Firebase&lt;/span&gt;
&lt;span class="nx"&gt;firebase&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;This will prompt different &lt;strong&gt;Firebase&lt;/strong&gt; &lt;strong&gt;features&lt;/strong&gt; to start the project, read the instructions thoroughly and then choose these options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select to use &lt;strong&gt;Firestore&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select to use &lt;strong&gt;Functions&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select to use &lt;strong&gt;Emulators&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Leave all others features disabled&lt;/li&gt;
&lt;li&gt;When prompted to select a project, choose the one you first created from the list&lt;/li&gt;
&lt;li&gt;When prompted, select all defaults for the &lt;strong&gt;Firestore Setup&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;For the &lt;strong&gt;Functions Setup&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select TypeScript when prompted&lt;/li&gt;
&lt;li&gt;Choose to use ESLint when prompted&lt;/li&gt;
&lt;li&gt;Choose to install dependencies with npm, this will run &lt;code&gt;npm install&lt;/code&gt; in the project and create the &lt;code&gt;node_modules&lt;/code&gt; directory&lt;/li&gt;
&lt;li&gt;For the &lt;strong&gt;Emulators Setup&lt;/strong&gt; choose the &lt;strong&gt;Functions&lt;/strong&gt; and &lt;strong&gt;Firestore&lt;/strong&gt; emulators&lt;/li&gt;
&lt;li&gt;Leave all defaults for the next options&lt;/li&gt;
&lt;li&gt;Choose to download the emulators now ( this is what you need the &lt;strong&gt;Java SDK&lt;/strong&gt; for)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Verify your project directory running:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt;
&lt;span class="c"&gt;# The output should look like this&lt;/span&gt;
total 40
drwxr-xr-x   8   staff   256 May 13 15:33 &lt;span class="nb"&gt;.&lt;/span&gt;
drwxr-xr-x   7   staff   224 May 13 15:07 ..
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;   1   staff    68 May 13 15:33 .firebaserc
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;   1   staff  1166 May 13 15:33 .gitignore
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;   1   staff   650 May 13 15:33 firebase.json
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;   1   staff    44 May 13 15:31 firestore.indexes.json
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt;   1   staff   755 May 13 15:30 firestore.rules
drwxr-xr-x  10   staff   320 May 13 15:32 functions

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

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now you have installed a new Firebase Functions Project!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installing Project Dependencies
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Open the project in your Code Editor&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The directory structure should look like this:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Project Structure Overview&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; &lt;span class="sb"&gt;`functions-express-ts-project-guide`&lt;/span&gt;
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="sb"&gt;`functions`&lt;/span&gt;
&lt;span class="p"&gt;    -&lt;/span&gt; &lt;span class="sb"&gt;`node_modules`&lt;/span&gt;
&lt;span class="p"&gt;    -&lt;/span&gt; &lt;span class="sb"&gt;`src`&lt;/span&gt;
&lt;span class="p"&gt;      -&lt;/span&gt; &lt;span class="sb"&gt;`index.ts`&lt;/span&gt;
&lt;span class="p"&gt;      -&lt;/span&gt; &lt;span class="sb"&gt;`.eslintrc.js`&lt;/span&gt;
&lt;span class="p"&gt;      -&lt;/span&gt; &lt;span class="sb"&gt;`.gitignore`&lt;/span&gt;
&lt;span class="p"&gt;      -&lt;/span&gt; &lt;span class="sb"&gt;`package.json`&lt;/span&gt;
&lt;span class="p"&gt;      -&lt;/span&gt; &lt;span class="sb"&gt;`package-lock.json`&lt;/span&gt;
&lt;span class="p"&gt;      -&lt;/span&gt; &lt;span class="sb"&gt;`tsconfig.dev.json`&lt;/span&gt;
&lt;span class="p"&gt;      -&lt;/span&gt; &lt;span class="sb"&gt;`tsconfig.json`&lt;/span&gt;
&lt;span class="p"&gt;    -&lt;/span&gt; &lt;span class="sb"&gt;`.firebaserc`&lt;/span&gt;
&lt;span class="p"&gt;    -&lt;/span&gt; &lt;span class="sb"&gt;`.gitignore`&lt;/span&gt;
&lt;span class="p"&gt;    -&lt;/span&gt; &lt;span class="sb"&gt;`firebase.json`&lt;/span&gt;
&lt;span class="p"&gt;    -&lt;/span&gt; &lt;span class="sb"&gt;`firestore.indexes.json`&lt;/span&gt;
&lt;span class="p"&gt;    -&lt;/span&gt; &lt;span class="sb"&gt;`firestore.rules`&lt;/span&gt;

&lt;span class="gu"&gt;### functions&lt;/span&gt;
This directory contains all the source code and configuration for Firebase Functions.

&lt;span class="gu"&gt;#### node_modules&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Purpose:**&lt;/span&gt; Contains all the npm packages that are installed as dependencies for the project. Managed by npm.

&lt;span class="gu"&gt;#### src&lt;/span&gt;
This directory holds the TypeScript source files for the Firebase Functions.

&lt;span class="gu"&gt;##### index.ts&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Purpose:**&lt;/span&gt; The main entry point for Firebase Functions, contains the TypeScript code for defining cloud functions.

&lt;span class="gu"&gt;##### .eslintrc.js&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Purpose:**&lt;/span&gt; Configuration file for ESLint, a tool for identifying and reporting on patterns found in ECMAScript/JavaScript code, aiming to make code more consistent and avoiding bugs.

&lt;span class="gu"&gt;##### .gitignore&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Purpose:**&lt;/span&gt; Specifies intentionally untracked files that Git should ignore. Files already tracked by Git are not affected.

&lt;span class="gu"&gt;##### package.json&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Purpose:**&lt;/span&gt; Defines npm package dependencies for the project, as well as build scripts and project metadata.

&lt;span class="gu"&gt;##### package-lock.json&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Purpose:**&lt;/span&gt; Automatically generated file which specifies the exact versions of all npm dependencies that were installed for the project. Ensures a consistent environment for all installations of the dependencies.

&lt;span class="gu"&gt;##### tsconfig.dev.json&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Purpose:**&lt;/span&gt; The TypeScript compiler configuration file for development environments, may differ slightly in settings from production to enable better debugging or more verbose logging.

&lt;span class="gu"&gt;##### tsconfig.json&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Purpose:**&lt;/span&gt; The TypeScript compiler configuration file for the project. Defines options required to compile the project.

&lt;span class="gu"&gt;#### .firebaserc&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Purpose:**&lt;/span&gt; Firebase CLI runtime configuration file. Stores aliases and project specific settings used by Firebase.

&lt;span class="gu"&gt;#### .gitignore (in functions directory)&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Purpose:**&lt;/span&gt; Similar to the src .gitignore, but for the entire functions directory.

&lt;span class="gu"&gt;#### firebase.json&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Purpose:**&lt;/span&gt; Firebase configuration file which defines rules and settings for your Firebase project, like hosting behavior and cloud functions paths.

&lt;span class="gu"&gt;#### firestore.indexes.json&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Purpose:**&lt;/span&gt; Configuration file for defining indexes in Firestore. Helps improve query performance.

&lt;span class="gu"&gt;#### firestore.rules&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Purpose:**&lt;/span&gt; Security rules file for Firestore. Defines what data can be accessed by whom, securing your Firestore data based on authentication and authorization.

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

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open the &lt;code&gt;index.ts&lt;/code&gt; file&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You should see an auto generated code, let’s remove all the code for now&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This will be our entry file and we need to create a new Express application&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1. Install Express
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Let’s firs install express by running:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Important: First, move into the functions directory, this is where the package.json file lives.&lt;/span&gt;
&lt;span class="c"&gt;# We will run all our commands from this directory.&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;functions
&lt;span class="c"&gt;# Install Express&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;express
&lt;span class="c"&gt;# You should see express on your package.json file dependencies&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you take a look at the &lt;code&gt;package.json&lt;/code&gt; there’s auto generated content by the Firebase CLI, there are already some scripts, dependencies, and all we need to start developing&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Do some code
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Add the following to the &lt;code&gt;index.ts&lt;/code&gt; file and read it carefull:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// For our API we will use the Functions 2nd Gen HTTP Request trigger&lt;/span&gt;
&lt;span class="c1"&gt;// See this: https://firebase.google.com/docs/functions/http-events?gen=2nd&lt;/span&gt;
&lt;span class="c1"&gt;// Import onRequest from firebase-functions for HTTP triggers.&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onRequest&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firebase-functions/v2/https&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Import the entire Express module. This allows us to use its&lt;/span&gt;
&lt;span class="c1"&gt;// functionalities to create and manage the server.&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Import the Request and Response types from the 'express' module.&lt;/span&gt;
&lt;span class="c1"&gt;// These types are used to type the request and response objects in&lt;/span&gt;
&lt;span class="c1"&gt;// route handlers, providing type checking and IntelliSense features in the IDE.&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&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 a new Express application by calling `express()`.&lt;/span&gt;
&lt;span class="c1"&gt;// This `app` object encapsulates all the functionalities of an&lt;/span&gt;
&lt;span class="c1"&gt;// Express application.&lt;/span&gt;
&lt;span class="c1"&gt;// It's used to configure routes, middleware, and to start the server.&lt;/span&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="c1"&gt;// Define a route handler for HTTP GET requests to the root URL ("/").&lt;/span&gt;
&lt;span class="c1"&gt;// This sets up the server to respond to GET requests at the&lt;/span&gt;
&lt;span class="c1"&gt;// specified path. Here, the path is the root URL.&lt;/span&gt;
&lt;span class="c1"&gt;// eslint-disable max-len&lt;/span&gt;
&lt;span class="c1"&gt;// `req` (request) and `res` (response) are parameters typed with&lt;/span&gt;
&lt;span class="c1"&gt;// `Request` and `Response` to enhance type safety and tooling support.&lt;/span&gt;
&lt;span class="c1"&gt;// The handler function sends the text "Hello World!" back to the&lt;/span&gt;
&lt;span class="c1"&gt;// client when the root URL is accessed.&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;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;req&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;res&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="nx"&gt;res&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 World!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// Export the `app` instance as `api`. This exported `api` can be used&lt;/span&gt;
&lt;span class="c1"&gt;// elsewhere, particularly in Firebase Functions, to handle&lt;/span&gt;
&lt;span class="c1"&gt;// HTTP requests. This allows the `api` to act as a&lt;/span&gt;
&lt;span class="c1"&gt;// serverless function in the Firebase ecosystem.&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;api&lt;/span&gt; &lt;span class="o"&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;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Now build the project to update the emulators server with npm run build this will create a lib directory which will be the one to actually deploy to the Cloud Functions.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Start the Emulators
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Now, go back the &lt;code&gt;package.json&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;See the command &lt;code&gt;serve&lt;/code&gt; , run it with &lt;code&gt;npm run serve&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You’ll see something like this:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;✔  functions: Loaded functions definitions from &lt;span class="nb"&gt;source&lt;/span&gt;: api.
&lt;span class="c"&gt;# Important: this is the URL you will use to call the API&lt;/span&gt;
✔  functions[us-central1-api]: http &lt;span class="k"&gt;function &lt;/span&gt;initialized &lt;span class="o"&gt;(&lt;/span&gt;http://127.0.0.1:5001/my-project/us-central1/api&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

┌─────────────────────────────────────────────────────────────┐
│ ✔  All emulators ready! It is now safe to connect your app. │
│ i  View Emulator UI at http://127.0.0.1:4000/               │
└─────────────────────────────────────────────────────────────┘

┌───────────┬────────────────┬─────────────────────────────────┐
│ Emulator  │ Host:Port      │ View &lt;span class="k"&gt;in &lt;/span&gt;Emulator UI             │
├───────────┼────────────────┼─────────────────────────────────┤
│ Functions │ 127.0.0.1:5001 │ http://127.0.0.1:4000/functions │

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

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to &lt;a href="http://localhost:4000/"&gt;http://localhost:4000/&lt;/a&gt; and you should see the Emulators interface, although only the &lt;strong&gt;Functions&lt;/strong&gt; emulator is running for now in the URL: &lt;code&gt;http://127.0.0.1:5001/my-project/us-central1/api&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Open Postman&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a new Request and do a GET to the URL&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Response should be &lt;code&gt;"Hello World!"&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it! you have now created a Hello World with Firebase Functions, Express and Typescript. In part 2 we will cover initializing Firestore and performing the CRUD operations for a Pets REST API.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>express</category>
      <category>typescript</category>
      <category>firebase</category>
    </item>
    <item>
      <title>Keep it cool and secure: do's and don'ts for managing Web App secrets</title>
      <dc:creator>Bernardo Cassina</dc:creator>
      <pubDate>Sat, 06 Jan 2024 17:54:38 +0000</pubDate>
      <link>https://dev.to/cassina/keep-it-cool-and-secure-dos-and-donts-for-managing-web-app-secrets-4daa</link>
      <guid>https://dev.to/cassina/keep-it-cool-and-secure-dos-and-donts-for-managing-web-app-secrets-4daa</guid>
      <description>&lt;p&gt;The security of your web application abides by the strength of your secrets. &lt;/p&gt;

&lt;p&gt;Severe data breaches and systems that got totally hijacked for cryptocurrency mining aren't just tales from the tech-crypt, they're real, heavy, and far too prevalent. &lt;/p&gt;

&lt;p&gt;Every other day we're hearing about some massive data breach or a bunch of servers turned into crypto-mining zombies. These aren't just wake-up calls; they're blaring alarms telling us to keep our digital house locked down tight. &lt;/p&gt;

&lt;p&gt;Forget about the headache of cleaning up after an attack; it's the trust you lose, the customers that give you the side-eye, and the reputation you've built up taking a major hit. So yeah, staying on top of our security game is more than a good idea; it's essential to keeping everything we've worked for safe and sound.&lt;/p&gt;

&lt;p&gt;Keeping your API keys, passwords, and other sensitive intel secure isn't just about playing defense, it's about preserving your cool reputation, your customers' privacy, and the trust of your team.&lt;/p&gt;

&lt;p&gt;As we roll into the do's and don'ts of managing these crucial secrets, let's stay open-minded and remember that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Adopting the right practices isn't just a laid-back suggestion; it's the key to maintaining a robust and trustworthy application.&lt;/li&gt;
&lt;li&gt;There are likely more insights and strategies beyond what I've shared. So, I warmly invite you to contribute your thoughts and additional do's and don'ts in the comments.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Do's
&lt;/h2&gt;

&lt;p&gt;Store your secrets like you’d keep your most precious item - in a cool, safe place, away from prying eyes.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Use Environment Variables
&lt;/h3&gt;

&lt;p&gt;Environment are a way of keeping your info out of the codebase and reducing the risk of a bummer exposure. &lt;/p&gt;

&lt;p&gt;Consider using tools like &lt;a href="https://docs.gitlab.com/ee/ci/variables/"&gt;Gitlab CI/CD&lt;/a&gt; variables or &lt;a href="https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions"&gt;Github secrets&lt;/a&gt; to fortify their security and seamlessly integrate them during the build process, tailored to your specific environment.&lt;/p&gt;

&lt;p&gt;While environment variables are a common method for storing secrets, it's important to be aware of their potential risks, as highlighted in &lt;a href="https://www.trendmicro.com/en_se/research/22/h/analyzing-hidden-danger-of-environment-variables-for-keeping-secrets.html"&gt;this Trend Micro article&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Environment variables are not inherently secure, as they are not encrypted and can be exposed to unauthorized access. Before using them, ensure that your deployment environment is secure and consider additional protective measures like access controls. Regularly review and audit your use of environment variables to prevent unintended exposure of sensitive information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Employ a Secret Management Tool
&lt;/h3&gt;

&lt;p&gt;For a more comprehensive and robust secret management solution, get your hands on tools like &lt;a href="https://cloud.google.com/security/products/secret-manager"&gt;GCP Secret Manager&lt;/a&gt;, or &lt;a href="https://www.vaultproject.io/"&gt;HashiCorp Vault&lt;/a&gt;. They're like the security guards of your secrets, providing a safe house, access control, and keeping logs of who’s been snooping around.&lt;/p&gt;

&lt;p&gt;I think this is a better alternative to using plain environment variables for storing API keys or secrets since they will be treated as encrypted secrets in a vault.&lt;/p&gt;

&lt;h4&gt;
  
  
  Environment Variables vs Secret Management Tool example
&lt;/h4&gt;

&lt;p&gt;With Firebase Functions you can use Google Secret Manager and have a Parameterized configuration for both secrets and environment variables.&lt;/p&gt;

&lt;h5&gt;
  
  
  Environment Variables
&lt;/h5&gt;

&lt;p&gt;You can create an env variable via an .env file or via deployment runtime or emulators. The following is a basic example, please see the &lt;a href="https://firebase.google.com/docs/functions/config-env?gen=2nd"&gt;Firebase Docs&lt;/a&gt; for a full example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineString&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-functions/params&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseStripeAPIURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ConfigParameter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defineString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BASE_STRIPE_API_URL&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;h5&gt;
  
  
  Secrets
&lt;/h5&gt;

&lt;p&gt;You can create a secret using the firebase SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
firebase functions:secrets:set STRIPE_KEY

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

&lt;/div&gt;



&lt;p&gt;And then access the secret like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineSecret&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firebase-functions/params&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stripeKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ConfigParameter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defineSecret&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;STRIPE_KEY&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;h3&gt;
  
  
  Encrypt secrets
&lt;/h3&gt;

&lt;p&gt;Make sure your secrets are as unreadable as ancient hieroglyphs to those not in the know. Encryption is the magic spell here, with &lt;a href="https://en.wikipedia.org/wiki/Advanced_Encryption_Standard"&gt;AES-256&lt;/a&gt; being the incantation of choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rotate secrets regularly
&lt;/h3&gt;

&lt;p&gt;Rotate secrets at industry-recommended intervals, such as every 3-6 months, based on your application's threat model. &lt;/p&gt;

&lt;p&gt;Regularly switching things up minimizes the fallout from any leaks. You can create a calendar and notifications to remind you when to change your secrets, this can be simplified with a Secret Management Tool as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implement Least Privilege Access
&lt;/h3&gt;

&lt;p&gt;Granting access to your system is like handing out backstage passes to a concert; you should only give them to those who absolutely need to be there. This approach minimizes the potential chaos if things go south. &lt;/p&gt;

&lt;p&gt;Begin by assigning the bare minimum level of privilege necessary, then cautiously elevate permissions if additional access is required for specific tasks. &lt;/p&gt;

&lt;p&gt;Consider also the temporal aspect of access—some may only need certain privileges for a limited period. Once their task is complete, or the time expires, revoke those privileges promptly. This way, you maintain a tight, secure environment, just as you would ensure only the essential crew is backstage during the show&lt;/p&gt;

&lt;h3&gt;
  
  
  Audit and monitor access to your secrets
&lt;/h3&gt;

&lt;p&gt;Regularly check who's got the backstage pass to your secrets and keep a watchful eye on access logs. Stay alert for any oddball activity that could spell trouble, like an uninvited guest at your chill gathering. You can use tools like &lt;a href="https://cloud.google.com/logging/docs/audit"&gt;Cloud Audit Logs&lt;/a&gt; or &lt;a href="https://cloud.google.com/security/products/armor?hl=en"&gt;Cloud Armor&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Secure your deployment pipeline
&lt;/h3&gt;

&lt;p&gt;Ensure the path to rolling out your application is as secure as a locked diary. Use CI/CD tools that vibe with secret management and put up a "No Trespassing" sign to restrict access to the deployment process. You can use a tool like &lt;a href="https://docs.gitlab.com/ee/ci/variables/"&gt;Gitlab CI/CD&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Use environment-specific secrets
&lt;/h3&gt;

&lt;p&gt;Divide your secrets: one for development, testing, and production. This way, you prevent an accidental leak during a soundcheck from ruining the main show.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ensure backup security
&lt;/h3&gt;

&lt;p&gt;Ensuring the security of your backups is as important as securing your primary data. Encrypting backup data protects it even if accessed by unauthorized parties. &lt;/p&gt;

&lt;p&gt;Regularly test and update your backup security measures to ensure they provide strong protection, making them an integral part of your data security strategy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Educate your team
&lt;/h3&gt;

&lt;p&gt;Gather your band members and make sure they're in tune with the importance of secret management. It's like teaching them the chords to a complex song – they need to understand and follow the best practices to hit the right notes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Informed employees are a company's first and most effective line of defense.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's important that they don't perceive this as a burdensome task. Providing informative and engaging learning content can help motivate your team about cybersecurity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implement MFA
&lt;/h3&gt;

&lt;p&gt;Implement Multi Factor Authentication as an essential layer of security for accessing secrets, significantly reducing the risk of unauthorized access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don'ts
&lt;/h2&gt;

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

&lt;h3&gt;
  
  
  Don't hardcode secrets
&lt;/h3&gt;

&lt;p&gt;Never embed your secrets directly into your source code or configuration files. &lt;/p&gt;

&lt;p&gt;This practice, while convenient, is similar to leaving personal notes open in public spaces — it can inadvertently expose sensitive information. Instead, securely manage your secrets using environment variables or secret management tools to keep them protected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't share secrets unnecessarily
&lt;/h3&gt;

&lt;p&gt;Avoid passing around your secrets like a hot potato unless it's absolutely necessary. Each service should have its own private stash to minimize the drama if something goes sideways.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't use predictable secrets
&lt;/h3&gt;

&lt;p&gt;Steer clear of secrets that are as predictable as a broken record. Always opt for strong, randomly generated passwords and keys that no one can guess.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't ignore alerts
&lt;/h3&gt;

&lt;p&gt;Heed the call when your security system sounds the alarm. Swiftly investigate any unusual activity or unauthorized alterations to your secrets – they might be signaling a problem you can't afford to ignore.&lt;/p&gt;

&lt;p&gt;These alerts act as an early warning system, helping to prevent potential breaches and maintain the integrity of your security measures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't neglect regular audits
&lt;/h3&gt;

&lt;p&gt;Regularly reviewing your secret management practices ensures they remain effective and up-to-date. Stay hip to the latest security trends and tweak your strategies to stay ahead of the curve.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't overlook API limits
&lt;/h3&gt;

&lt;p&gt;Be mindful of the rate limits of any APIs you're using. Exceeding these limits can disrupt service and potentially lead to security vulnerabilities, so it's important to stay within the prescribed boundaries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't store secrets in client-side code
&lt;/h3&gt;

&lt;p&gt;Storing secrets in the client-side of your application can make them easily accessible to others. Instead, keep secrets server-side where they can be more securely managed and controlled, reducing the risk of exposure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't rely on obscurity
&lt;/h3&gt;

&lt;p&gt;Relying solely on hiding information is not a secure strategy. Adopt a comprehensive approach that includes encrypting data, enforcing strict access controls, and regularly monitoring for suspicious activities. A proactive and layered security strategy offers far more protection than simply hoping secrets remain undiscovered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't neglect code reviews
&lt;/h3&gt;

&lt;p&gt;Ensure code containing secret access or usage undergoes thorough code reviews to identify and mitigate potential vulnerabilities.&lt;/p&gt;

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

&lt;p&gt;By abiding by these do's and don'ts, you're not just throwing a security blanket over your application; you're actively engaging in a righteous quest to protect your digital realm. &lt;/p&gt;

&lt;p&gt;Security isn't a one-and-done deal. It's a continuous journey, a vibe you maintain. So, stay informed, stay cool, and most importantly, keep those secrets safe. Your application, your team, and your customers will thank you. &lt;/p&gt;

&lt;p&gt;There are likely more insights and strategies beyond what I've shared. So, I warmly invite you to contribute your thoughts and additional do's and don'ts in the comments. &lt;/p&gt;

&lt;p&gt;Let's learn and grow together in our quest for better security.&lt;/p&gt;

&lt;p&gt;Thank you for reading ✌️😬&lt;/p&gt;

</description>
      <category>cybersecurity</category>
      <category>webdev</category>
      <category>security</category>
      <category>devops</category>
    </item>
    <item>
      <title>Understanding Stock Options: A Guide to Employee Equity</title>
      <dc:creator>Bernardo Cassina</dc:creator>
      <pubDate>Tue, 28 Nov 2023 12:40:17 +0000</pubDate>
      <link>https://dev.to/cassina/understanding-stock-options-a-guide-to-employee-equity-2a0a</link>
      <guid>https://dev.to/cassina/understanding-stock-options-a-guide-to-employee-equity-2a0a</guid>
      <description>&lt;p&gt;As a software developer in the tech industry, you've likely come across job offers that feature stock options as part of the compensation package. But what exactly are these "options," and more importantly, how do they translate into real-world financial benefits for you? &lt;/p&gt;

&lt;p&gt;We go uncover not only the benefits but also the critical aspects to scrutinize stock options. These warnings are key to ensuring that a seemingly lucrative offer doesn’t lead you astray. It's essential, whether you're evaluating a new job offer or charting your tech career path, to understand the full spectrum of stock options. This insight is vital for making decisions that truly benefit your career and financial future.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What on earth are Stock Options?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Stock Options are not equivalent to owning shares in a company, at least not immediately. They represent a right, but not an obligation, to purchase shares of the company at a predetermined price at a later date. This purchase is called &lt;strong&gt;exercising&lt;/strong&gt; your options. Think of it as a promise that you may buy a part of the company in the future, at a price set today.&lt;/p&gt;

&lt;p&gt;In the realm of stock options, you'll encounter primarily two types: incentive stock options (&lt;a href="https://carta.com/blog/what-are-incentive-stock-options/"&gt;ISOs&lt;/a&gt;) and non-qualified stock options (&lt;a href="https://carta.com/blog/what-are-non-qualified-stock-options/"&gt;NSOs&lt;/a&gt;). The key distinction between them lies in their tax treatment and timing. For an in-depth exploration of these differences, &lt;a href="https://carta.com/blog/equity-101-stock-option-basics/#what-are-the-different-types-of-stock-options/"&gt;Carta offers a detailed blog post&lt;/a&gt; which delves into these nuances. We won't cover these specifics extensively here, but this external resource can provide you with a deeper understanding.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How Stock Options Work&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Setting The Stage&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When a company is either starting up or hiring, it often creates an Employee Stock Options Pool (ESOP). This pool is like a reserved section for the potential high performers the company wishes to attract. However, establishing this pool requires approval from the company's Board of Directors and shareholders.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;The Golden Ticket Offer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Consider this scenario: &lt;em&gt;XYZ Technologies&lt;/em&gt; offers you a position and includes Stock Options in your compensation package. The number of options you receive might depend on your role, salary, and other factors. For example, if your yearly salary is $120K and the Stock Options value is calculated using a 0.5 multiplier, you would receive Stock Options valued at $60K.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Sample Offer&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Yearly Salary: $120K&lt;/li&gt;
&lt;li&gt;Stock Options Value: $60K&lt;/li&gt;
&lt;li&gt;Vesting Period: 4 years (with a 1-year cliff)&lt;/li&gt;
&lt;li&gt;Vesting Start Date: 01/01/2023&lt;/li&gt;
&lt;li&gt;Fully Vested Date: 01/01/2027&lt;/li&gt;
&lt;li&gt;Post Termination Exercise Period: 6 months&lt;/li&gt;
&lt;li&gt;Stock Option Price: $2.00&lt;/li&gt;
&lt;li&gt;Total Stock Options: 30,000&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Understanding Vesting and Exercise&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1 Year Cliff&lt;/strong&gt;: If you leave the company before completing a year, you forfeit all options.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4 Year Vesting Period&lt;/strong&gt;: After the 1-year cliff, 25% of your options become eligible for conversion to company shares each year. So you would vest 25% or 7,500 options each year.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Post Termination Exercise Period&lt;/strong&gt;: If you leave the company, you have a set period, in this case, 6 months, to &lt;strong&gt;exercise&lt;/strong&gt; your options. And if you don’t, &lt;strong&gt;you will lose them forever&lt;/strong&gt;. So be aware of any notifications and verify with your company about the Post Termination Exercise Period before leaving.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Red Flags
&lt;/h2&gt;

&lt;p&gt;A founder I once advised responded dismissively when I suggested explaining equity to their employees, saying, ‘There’s no need to explain equity; they wouldn’t understand it anyway.’ This attitude is a major red flag. Be vigilant for such warning signs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lack of Transparency&lt;/strong&gt;: Hidden details about the company's financial status.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lack of Clarity&lt;/strong&gt;: Unclear Stock Options plans.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failure to Vest&lt;/strong&gt;: Delayed vesting without legitimate reasons.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unfavorable Terms Upon Exit&lt;/strong&gt;: Disadvantageous terms for employees.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inadequate Documentation&lt;/strong&gt;: Missing or incomplete documentation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unwillingness to Discuss Valuation&lt;/strong&gt;: Founders reluctant to talk about the company's valuation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overly Complex Structures&lt;/strong&gt;: Complicated Stock Options plans.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Changes in Plan Without Notification&lt;/strong&gt;: Unannounced alterations to the Stock Options plan.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unrealistic Vesting Schedules&lt;/strong&gt;: Non-standard vesting timelines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Legal Counsel&lt;/strong&gt;: Discouragement from seeking legal advice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High Turnover Rates&lt;/strong&gt;: Frequent changes in key personnel.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dilution Concerns&lt;/strong&gt;: Unclear policies on share dilution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Absence of an Exit Strategy&lt;/strong&gt;: No clear plan for liquidity events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Excessive Control and Restrictions&lt;/strong&gt;: Overly restrictive Stock Options agreements.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Exercising Stock Options&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Four years later, let's assume your options' value has increased significantly. If the per-option value rises to $5.00, your 30,000 options now represent a $150,000 value, a substantial increase from the initial $60,000.&lt;/p&gt;

&lt;p&gt;Exercising Stock Options can be a financially rewarding decision, but it comes with its own set of complexities, particularly regarding tax implications. &lt;/p&gt;

&lt;p&gt;It's important to note that each company may have its own set of rules and conditions for exercising stock options. These can include specific timelines, procedures, and restrictions that you need to be aware of. Always thoroughly review your company’s stock option plan and seek clarification on any points you don't fully understand. This due diligence is vital to ensure you're fully informed and can make the most of your stock options without any unwelcome surprises. Here's what you need to know:&lt;/p&gt;

&lt;h3&gt;
  
  
  Tax Implications of Exercising Options
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Immediate Tax Consequences&lt;/strong&gt;: When you exercise Stock Options, especially Non-Qualified Stock Options (NSOs), the difference between the exercise price and the fair market value of the stock is treated as ordinary income and is subject to income tax.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alternative Minimum Tax (AMT)&lt;/strong&gt;: For Incentive Stock Options (ISOs), the spread on exercise can trigger the Alternative Minimum Tax, which could significantly impact your tax liability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capital Gains Tax&lt;/strong&gt;: If you hold the shares after exercising and sell them later, any appreciation since the exercise date is subject to capital gains tax. The rate depends on how long you've held the shares before selling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Timing of Exercise and Sale
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Holding Period&lt;/strong&gt;: The decision of when to exercise and sell can greatly affect your tax situation. For ISOs, if you hold the shares for at least one year after exercise and two years after the grant date, you may qualify for long-term capital gains tax rates on any further appreciation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Market Considerations&lt;/strong&gt;: Timing can also be influenced by market conditions and your perception of the company's future prospects.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Financial Planning Considerations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Diversification&lt;/strong&gt;: Owning a significant portion of your wealth in a single company's stock can be risky. Consider the role of these shares within your broader investment portfolio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Liquidity Needs&lt;/strong&gt;: Exercising options requires paying the exercise price, and you may need liquidity to cover this cost and potential taxes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Personal Financial Goals&lt;/strong&gt;: Align your decision to exercise options with your overall financial goals and life events, such as purchasing a home or planning for retirement.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Seek Professional Advice
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tax Advisor Consultation&lt;/strong&gt;: A tax professional can help you understand the implications of exercising your options and plan for the tax consequences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Financial Planner&lt;/strong&gt;: A financial planner can assist in integrating this decision into your broader financial strategy, considering your personal circumstances and market conditions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Benefits of Stock Options&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Stock options can be a pivotal part of your compensation, offering more than just monetary value. Here’s how they enhance your package:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Growth and Wealth Accumulation&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Company Success&lt;/strong&gt;: As your company flourishes, the value of your stock options can soar, positioning you for significant financial gains.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long-Term Benefits&lt;/strong&gt;: They're not just immediate rewards; stock options are tools for future wealth, potentially outpacing standard salary increments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Alignment and Flexibility&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Personal Investment&lt;/strong&gt;: Holding stock options aligns your success with the company’s, deepening your engagement and potentially boosting motivation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control&lt;/strong&gt;: You have the flexibility to exercise these options based on your financial strategy, market conditions, and personal goals.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Tax Advantages&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;For ISOs&lt;/strong&gt;: They may offer favorable tax treatment, with potential savings if you meet specific holding requirements.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While stock options can be lucrative, it's crucial to weigh them within the broader context of your career and financial planning.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Path to Cashing In&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;There are several avenues for employees to cash in on their Stock Options, each with its specificities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Secondary Markets&lt;/strong&gt;: Platforms like SharesPost or EquityZen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buybacks by the Company&lt;/strong&gt;: Company-initiated share repurchase programs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Selling to Other Employees or Insiders&lt;/strong&gt;: Internal transactions within the company.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;External Private Investors&lt;/strong&gt;: Sales to venture capitalists or private investors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Acquisition&lt;/strong&gt;: Share sales during a company acquisition.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IPO&lt;/strong&gt;: Public share sales post-IPO.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tender Offers&lt;/strong&gt;: Buyout offers from investors or the company.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Merger or Business Combination&lt;/strong&gt;: Stock conversions in case of a merger.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stock Option Loan Programs&lt;/strong&gt;: Loans using Stock Options as collateral.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stock Swap with Another Company&lt;/strong&gt;: Exchanging stocks between companies.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Years later, if the company goes public or its valuation increases significantly, the financial benefits can be substantial. However, it's crucial to understand the terms and conditions associated with Stock Options and seek professional advice when necessary.&lt;/p&gt;

&lt;p&gt;Remember, both founders and employees play a role in the effective management of Stock Options. &lt;/p&gt;

&lt;p&gt;Founders must educate their employees on the nuances and be transparent about it, while employees must proactively understand the terms and conditions, or ask the right questions if you notice any red flags.&lt;/p&gt;

&lt;p&gt;Thank you for reading ✌️😬&lt;/p&gt;

&lt;h2&gt;
  
  
  External links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.investopedia.com/terms/s/stockoption.asp"&gt;https://www.investopedia.com/terms/s/stockoption.asp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://secfi.com/learn/stock-option-starter-guide"&gt;https://secfi.com/learn/stock-option-starter-guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://carta.com/blog/2022-employee-stock-options-report/"&gt;https://carta.com/blog/2022-employee-stock-options-report/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://carta.com/blog/equity-101-stock-option-basics/#what-are-the-different-types-of-stock-options/"&gt;https://carta.com/blog/equity-101-stock-option-basics/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://carta.com/blog/what-are-incentive-stock-options/"&gt;https://carta.com/blog/what-are-incentive-stock-options/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://carta.com/blog/what-are-non-qualified-stock-options/"&gt;https://carta.com/blog/what-are-non-qualified-stock-options/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://carta.com/blog/equity-101-exercising-and-taxes/"&gt;https://carta.com/blog/equity-101-exercising-and-taxes/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;small&gt;&lt;br&gt;
&lt;strong&gt;Disclaimer&lt;/strong&gt;: The information provided in this blog post, including all examples and scenarios, is for illustrative and educational purposes only. It should not be construed as financial or legal advice. Stock Options and related financial decisions can be complex and vary greatly depending on individual circumstances and the specific details of each company's Stock Options plan. We strongly recommend consulting with qualified financial advisors, tax professionals, and legal counsel before making any decisions based on the information provided in this blog post. The author and publisher of this blog post are not responsible for any financial losses or legal issues arising from the use of the information contained herein. Always do your own due diligence and seek professional advice tailored to your specific situation.&lt;br&gt;
&lt;/small&gt;&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>startup</category>
    </item>
    <item>
      <title>API Checklist: Are You Production-Ready?</title>
      <dc:creator>Bernardo Cassina</dc:creator>
      <pubDate>Mon, 27 Nov 2023 20:44:23 +0000</pubDate>
      <link>https://dev.to/cassina/api-tude-checklist-are-you-production-ready-f3e</link>
      <guid>https://dev.to/cassina/api-tude-checklist-are-you-production-ready-f3e</guid>
      <description>&lt;h3&gt;
  
  
  &lt;strong&gt;Ensuring your APIs are production-ready&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;APIs (Application Programming Interfaces) have emerged as the backbone of modern software development. From small-scale apps to enterprise-level solutions, APIs drive the interconnectedness of our digital ecosystem. But, with great power comes great responsibility. As developers, it's not enough to just create an API; it must be robust, reliable, and truly production-ready. Enter the API Checklist, a guide for helping your APIs stand tall and proud in the production landscape.&lt;/p&gt;

&lt;h3&gt;
  
  
  API Checklist
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;&lt;a href="https://github.com/cassina/barnaldus-checklists/blob/main/api-checklist.md"&gt;API Checklist&lt;/a&gt;&lt;/strong&gt; was born out of a desire to streamline and enhance developer teams processes. I am a fan of well written documentation and recognized that having a step-by-step guide could significantly elevate the quality of the APIs a team delivers. Instead of getting lost in the details or sidetracked by tight timelines, this checklist serves as a roadmap, ensuring that every essential aspect of API development is addressed. It's a tool that helps us maintain high standards, promotes consistency across projects, and ultimately leads to more reliable and robust APIs, well-suited for the demands of real-world applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Focus on Production Readiness?
&lt;/h3&gt;

&lt;p&gt;A well-structured, thoroughly tested, and secure API is a foundational pillar of any successful software application. Production readiness transcends basic functionality; it encompasses scalability, security, documentation, and maintainability. Here’s why it’s crucial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reliability:&lt;/strong&gt; A production-ready API can handle peak loads and unexpected traffic spikes without buckling, ensuring consistent service to users.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security:&lt;/strong&gt; In an era where data breaches are rampant, a secure API is non-negotiable. It’s about safeguarding your data and your users' trust.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Experience:&lt;/strong&gt; An API that seamlessly integrates and operates smoothly enhances the overall user experience of your application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Future Scalability:&lt;/strong&gt; Building with production in mind means your API can grow with your user base and feature set, avoiding costly overhauls down the line.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What's in the API Checklist?
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;&lt;a href="https://github.com/cassina/barnaldus-checklists/blob/main/api-checklist.md"&gt;API Checklist&lt;/a&gt;&lt;/strong&gt; spans various critical areas, from design consistency and error handling to security and performance. Each point in the checklist prompts you to scrutinize aspects of your API you might not have considered. Here’s a sneak peek:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Design &amp;amp; Consistency:&lt;/strong&gt; Is your API in harmony with your existing ecosystem? Does it follow RESTful principles?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security:&lt;/strong&gt; Have you armored your API against common vulnerabilities?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation:&lt;/strong&gt; Is your API’s documentation clear, thorough, and accessible?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring &amp;amp; Logging:&lt;/strong&gt; Can you efficiently track your API’s health and performance?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Got ideas to make our &lt;strong&gt;&lt;a href="https://github.com/cassina/barnaldus-checklists/blob/main/api-checklist.md"&gt;API Checklist&lt;/a&gt;&lt;/strong&gt; even cooler? I’m all ears. Shoot your suggestions for improvement or any nifty tips you've got up your sleeve in this &lt;a href="https://github.com/cassina/barnaldus-checklists"&gt;&lt;strong&gt;repo&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thank you for reading ✌️😬&lt;/p&gt;

</description>
      <category>api</category>
      <category>programming</category>
      <category>documentation</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
