<?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: Sdu</title>
    <description>The latest articles on DEV Community by Sdu (@sduduzog).</description>
    <link>https://dev.to/sduduzog</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%2F86317%2Fe8658a7e-0e1b-4463-beff-49f974146b1d.jpg</url>
      <title>DEV Community: Sdu</title>
      <link>https://dev.to/sduduzog</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sduduzog"/>
    <language>en</language>
    <item>
      <title>null vs undefined? What to choose? What to use?</title>
      <dc:creator>Sdu</dc:creator>
      <pubDate>Wed, 23 Aug 2023 09:32:50 +0000</pubDate>
      <link>https://dev.to/sduduzog/null-vs-undefined-what-to-choose-what-to-use-11g</link>
      <guid>https://dev.to/sduduzog/null-vs-undefined-what-to-choose-what-to-use-11g</guid>
      <description>&lt;p&gt;If you have experience with writing JavaScript, you might have a preference of using undefined in place of null, and even go to an extent of casting null values to undefined instead. If you were any wiser, you'd have known that null and undefined are not supposed to be interchangeable.&lt;/p&gt;

&lt;p&gt;Of course, the caveat of choosing one over the other, and/or switching between them isn't much of a conversation starter as it rarely causes any head turning issues in production...rarely! I say this because I'm certain that the use of a wrong type has caused issues which were solved without being fully understood.&lt;/p&gt;

&lt;p&gt;Okay let's look at specifics.&lt;/p&gt;

&lt;h2&gt;
  
  
  null
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;null&lt;/code&gt; is a primitive value that represents the intentional absence of any object value. Probably the most common keyword across a lot of programming languages and with a common definition too. Other languages get fancy and use &lt;code&gt;nil&lt;/code&gt; instead. I'm not quiet sure yet if that's also an exact equivalent to null, but it's worth checking out.&lt;/p&gt;

&lt;h2&gt;
  
  
  undefined
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;undefined&lt;/code&gt; is a primitive value used when a variable has not been assigned a value. This is just a JavaScript thing. With JavaScript you can travel back in time to make a variable not assigned a value.&lt;/p&gt;

&lt;p&gt;"&lt;em&gt;But black dynamite, assigning null to a variable does the same thing&lt;/em&gt;" see that's where you'd be wrong. Here's an analogy for you. We can say null is like loading a webpage and just getting a blank screen, but undefined is a '404 not found' error.&lt;/p&gt;

&lt;p&gt;The two keywords do have some common traits though. Ones that I can think from the top of my head is, they're both falsy values. This means that if you have a Boolean expression like &lt;code&gt;if (null || undefined)&lt;/code&gt; you'll always get false from it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to choose? What to use?
&lt;/h2&gt;

&lt;p&gt;Let me get this out the way first. You shouldn't really have to choose. Your circumstances have to either choose for you or you make the choice depending on the solution for the problem you're solving. This is the answer to almost every 'vs' question in programming, but no one likes it as it ends arguments too early.&lt;/p&gt;

&lt;p&gt;Speaking of circumstances choosing for you. In most cases, if not all, variables that hold data moving to/from the user to some data store, even via http requests, you must have at some point dealt with transforming it or the form of it to JSON. JSON is an open standard file format and data interchange format. &lt;/p&gt;

&lt;p&gt;When consuming APIs through some library or dealing with databases, notice how your favorite library hints to giving you either the data of some property or null? Why don't your orm or database connector thingie mabob give you back a property as undefined? Because at that point it would be extremely difficult to tell whether the property in the structure you're dealing with even exists. Getting &lt;code&gt;{"foo": null}&lt;/code&gt; is better than &lt;code&gt;{}&lt;/code&gt; because I know that 'foo' does exist in some other condition. When you get a chance, open a javascript console and run the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
  &lt;span class="na"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Typescript particularly makes these choices very loud, as when you're defining your types, you need to specify whether a property of an object or a variable can hold either null, undefined or some type.&lt;/p&gt;

&lt;p&gt;Let's make a scenario to conclude this mini rant.&lt;/p&gt;

&lt;p&gt;You're writing a form with your favorite framework, that when a user types, a request to update the data is made to the backend and your backend should only update the fields that have been changed. Let's also assume we're using RESTful apis to further pin down the scope. How does your frontend communicate this? Lets say the form is for user details and the fields are "name", "age", "height".&lt;/p&gt;

&lt;p&gt;If the request payload from the client is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The backend can interpret this payload as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Property 'age' exists and has number. Update age with provided integer&lt;/li&gt;
&lt;li&gt;Property 'name' is not defined. Do nothing&lt;/li&gt;
&lt;li&gt;Property 'height' is null. Clear its field in the data store.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How does the backend figure out that the property 'name' is not defined? Because it isn't.&lt;br&gt;
That payload is equivalent to the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where the inclusion of 'name' is redundant. Misuse of 'undefined' in such cases is a common place for bugs too. When this object is used to create URL search parameters, it will interpret the keyword 'undefined' as a string, which hopefully if your favorite http client omits undefined properties for you in requests, you're lucky, but some serialize it incorrectly.&lt;/p&gt;

&lt;p&gt;I even resort to having a helper function to create query parameters from an object to avoid this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createUrlSearchParamsFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;safePayload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;safePayload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a javascript object is being serialized, all undefined properties are discarded, remember 'undefined' means a property is yet to be assigned a value. But null on the other hand is known by JSON as its a valid JSON data type&lt;/p&gt;

&lt;p&gt;That's it. Hope you learned something.&lt;/p&gt;

&lt;p&gt;If you spot any interesting bits or tweaks to be done on this post, let's discuss it here or reach out on twitter&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>learning</category>
    </item>
    <item>
      <title>Firebase authentication you can eject, used with any backend</title>
      <dc:creator>Sdu</dc:creator>
      <pubDate>Wed, 17 Feb 2021 08:07:45 +0000</pubDate>
      <link>https://dev.to/sduduzog/firebase-authentication-you-can-eject-used-with-any-backend-5b4p</link>
      <guid>https://dev.to/sduduzog/firebase-authentication-you-can-eject-used-with-any-backend-5b4p</guid>
      <description>&lt;p&gt;Firebase is great for prototyping projects, especially when you really want to focus on your frontend or mobile app. Plus getting a server up and running from scratch is tedious. So with a couple of clicks, you have a database, a way to authenticate your app and storage, all for free.&lt;/p&gt;

&lt;p&gt;But that, still, comes at a cost. The trade-off of how easy and readily available firebase features are is that it locks you in to their ecosystem. I mean, it doesn't matter the type of project, its really uncomfortable adding features to a project that you know at the back of you mind, will be a pain to move to another infrastructure. Like for instance, firebase SDKs make is sooo easy to store stuff into their database solution, you don't need to worry about schema and what not, but rather how the data maps with objects in your app. But it being so easy, means that how you think about you data structure should adhere to their document object model. And for some solutions, data relativity gets very complex where using a relational database would have been ideal.&lt;/p&gt;

&lt;p&gt;Take for instance, you come up with a revolutionary to-do application that probably can add tasks before you even think you need to do them. Great idea isn't it. You don't want to spend too much time reinventing the wheel with chores like logging in, registration and a solution like firebase comes in very handy here. That being said, you want to write your server code in python, to leverage some AI library you just read about online, and you really really want to use MySQL. Conflicting I know! You can pretty much plug and play with a buttload of services available out there but choosing which corners to cut and where to put in the effort is a bit tough. And its your responsibility as the millionaire to be. I will however help you cut one corner with this post.&lt;/p&gt;

&lt;p&gt;Lets stick to the theme, &lt;strong&gt;authentication&lt;/strong&gt;. We'll use &lt;strong&gt;firebase&lt;/strong&gt; for our client. Either web or native app, it doesn't matter. But for our backend? Anything. I was using(learning) Nestjs at the time I stumbled onto this solution so bare with my code samples. So you client will use any firebase sdk for authentication and your server should be expecting and verifying a Json Web Token (JWT).&lt;/p&gt;

&lt;h2&gt;
  
  
  Why firebase?
&lt;/h2&gt;

&lt;p&gt;"Why not I just write all the authentication logic by myself?" Fair question to ask. Especially given the amount of online resources available online for implementing this. But authentication is not just logging in, or registering a new account or the funky access token validation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;There's account or email verification,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There's account reset or password retrieval,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There's single sign on solutions i.e. logging in via Google or Twitter and,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There's making sure that multiple sign on options still work together,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There's access token management. The big ol question of storing the token in memory, local storage or as a cookie.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All this could take up half or more of the time you could have spent perfecting your project idea. Firebase already solves all of this, so we'll use that instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Yea nah. You don't need firebase on your server.
&lt;/h2&gt;

&lt;p&gt;Again, sticking to the theme. We're building our own backend, or have build our own backend and we only want to tie up authentication. Here's the beauty, there's a section in the &lt;a href="https://firebase.google.com/docs/auth/admin/verify-id-tokens#verify_id_tokens_using_the_firebase_admin_sdk" rel="noopener noreferrer"&gt;firebase docs&lt;/a&gt; that goes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If your backend is in a language not supported by the Firebase Admin SDK, you can still verify ID tokens. First, find a third-party JWT library for your language. Then, verify the header, payload, and signature of the ID token.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We strike gold here. Conventionally, you would have to install the firebase admin sdk to manage how your users are authorized in the backend. For simpler nodejs projects, this is no issue, but I started to struggle trying to use that admin sdk when working with a very opinionated framework, Nestjs. And getting to these docs you realise:...&lt;/p&gt;

&lt;h2&gt;
  
  
  How it all works
&lt;/h2&gt;

&lt;p&gt;Lets start with the client app. Honestly I don't think it's necessary for me to elaborate on how to setup firebase authentication for your app. There's plenty of tutorials online for that, and their docs are pretty comprehensive. But given enough reasons, I might edit this to include some example or something. When your user signs in, or signs up i.e.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="c1"&gt;// This is what some method looks like inside my nuxtjs application to log me in :)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$fire&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signInWithEmailAndPassword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upon success, you'll be able to retrieve the token from wherever within your app to make server requests with, along with other properties your app has been granted access to by the user i.e. email, name etc. by listening to firebase events like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;firebase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;onAuthStateChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// User is signed in. Get what you need here&lt;/span&gt;
        &lt;span class="c1"&gt;// you can call user.getIdToken() from here and store it anywhere you want&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now requests from there will look something like below. It really doesn't matter how you get your token to the database, whether as authorization header or you pass it as a query parameter with your API url as long as it follows the OAuth standard or it is what your server is expecting. A simple authorized request should look something like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://some-api.herokuapp.com/users/me&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;headers&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;authorization&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;Bearer &amp;lt;your token here&amp;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="s2"&gt;referrer&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;http://some-app.herokuapp.com/&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;referrerPolicy&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;strict-origin-when-cross-origin&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;body&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;method&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;GET&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;mode&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;cors&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;credentials&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;include&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, firebase stores a cookie in the users browser to persist the session. I advise that you don't persist the access token but rather keep it in memory, and get a fresh one if you loose it. This is because the access token is very short lived &lt;strong&gt;as it should&lt;/strong&gt;, you expose some security vulnerabilities by doing so, and one of the reasons for using firebase in the first place is to have that all handled for us.&lt;/p&gt;

&lt;p&gt;That string token you get from firebase is an actual valid JWT, so &lt;em&gt;"thank you firebase but we'll take it from here".&lt;/em&gt; Here's how things will essentially work&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fa.storyblok.com%2Ff%2F95997%2F937x423%2F121a70a202%2Fscreenshot-2021-02-16-182547.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fa.storyblok.com%2Ff%2F95997%2F937x423%2F121a70a202%2Fscreenshot-2021-02-16-182547.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When a request is sent to your server, you need to follow a couple of steps to validate the firebase token.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Ensure that the signing algorithm is "RS256" and that the signature is valid.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate the token payload claims&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  1. Ensuring that the the signature is valid
&lt;/h3&gt;

&lt;p&gt;There are many ways to achieve this, depending on the choice of your server stack. Here's how you'd typically do it if you were using an npm package like &lt;a href="https://www.npmjs.com/package/jsonwebtoken#jwtverifytoken-secretorpublickey-options-callback" rel="noopener noreferrer"&gt;jsonwebtoken&lt;/a&gt; :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decoded&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// bar&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where the verify function takes in 1) the token to verify, 2) the public signing key and your options as an object. Follow the link to learn more about this. More on public keys in a moment. You should be able to pass in the required signing algorithm within you options.&lt;/p&gt;

&lt;p&gt;For ASP.NET Core users alike, the &lt;code&gt;System.IdentityModel.Tokens.Jwt&lt;/code&gt; package should be sufficient enough to achieve similar results if not the very same. I'd love to provide an example here but I don't think I have a fitting one as I'm still a bit fuzzy on the platform. I do however have a .NET Core &lt;a href="https://github.com/sduduzog/yAuth" rel="noopener noreferrer"&gt;public repo with a working jwt example&lt;/a&gt; which can be modified to fit this use case for the hopeless looking for a starting point.&lt;/p&gt;

&lt;p&gt;Now, the tricky part, and the most important. Getting the public key used to verify the token's signature. Firebase public keys are actually available and accessible from the link &lt;a href="https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com" rel="noopener noreferrer"&gt;https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com&lt;/a&gt; as a json object. This json object usually carries two keys as I've seemed to notice, and to get the one that will work for you, you need to use a key ID or (kid) found in you token's header when decoded. Now you'll use the key ID (kid) you get from your decoded token's header to get the public key as you would with any other json object, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getPublicKeysFromGoogle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;publicKeys&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;header64&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rawJwtToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&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="c1"&gt;// refer to the structure of a jwt&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;header64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ascii&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;thePublicKeyIWant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;publicKeys&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kid&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a refresher, a jwt is made up of 3 parts when encoded, seperated by dots ( . ). The header, payload and the verify signature part. The snippet above merely splits the token and only grabs the encoded header, decodes it to then grab the kid (the key id). From there, it extracts the public key from the object returned by my helper function &lt;code&gt;getPublicKeysFromGoogle()&lt;/code&gt; which looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getPublicKeysFromGoogle&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AxiosResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;httpService&lt;/span&gt; &lt;span class="c1"&gt;// httpService comes from nextjs, you can use fetch or axios for this&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="s1"&gt;https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toPromise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are two problems with my helper function for now. These public keys expire so we can't fetch them once and save them somewhere but you can refresh them by using the value from the max-age in the Cache-Control header of the response from this endpoint. Secondly, we don't want to send a request every time any of our endpoints are hit, it would slow us down for probably 200ms-350ms depending on where you're hosting your server and that is baaaaaad because this is just for verifying a token, excluding the time you will incur as you satisfy the request. To solve this, employ a cache mechanism and modify the little snippet above.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getPublicKeysFromGoogle&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AxiosResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;keys&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;cacheManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;jwtConstants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicTokenCacheKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;httpService&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="s1"&gt;https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toPromise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cache-control&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cacheControl&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[,&lt;/span&gt; &lt;span class="nx"&gt;maxAgeString&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cacheControl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[,&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;maxAgeString&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ageInt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cacheManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jwtConstants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicTokenCacheKey&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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ageInt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what's different here; I first check the cache for the keys and return those if I find them, if not, continue fetching them from the endpoint. Now from the response headers, I extract the time remaining, in seconds until these keys expire, and set the keys in cache with the same expiry date I got from my headers. This ensures that I only have to re-fetch the keys once they have expired. Now with this, we have verified our signature.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Validate the token payload claims
&lt;/h3&gt;

&lt;p&gt;So apart from the signature verification which ensures that the jwt used with the request is issues by Google for real, we need to also validate claims that are in the payload. This ensures that the request isn't being sent with a possibly hijacked token or something. There's a comprehensive list of claims to check listed &lt;a href="https://firebase.google.com/docs/auth/admin/verify-id-tokens" rel="noopener noreferrer"&gt;here&lt;/a&gt; at the bottom of the page, under "ID Token Payload Claims" to which I won't bore you with relisting them again.&lt;/p&gt;

&lt;h2&gt;
  
  
  To sum up
&lt;/h2&gt;

&lt;p&gt;By the time your app has grown to have so many users that you now need to leave firebase and you can focus on reimplementing authentication on your own, you will only need to change a very small part of your servers logic. How token verification is done, as you won't be using Google's public keys anymore, and I guess which claims to validate. and that's rarely any more of a chore compared to the refactor you will need for your front end. But that's one less part of your system you don't need to worry about anymore.&lt;/p&gt;

&lt;p&gt;I wrote this because I once spent hours trying to figure it out and with one or two php solutions online which are older than my own knowledge of php lol. I hope this helps at least one person, and if it's more, that'll be great. I generalised most things here hoping to have this piece less technical as possible but it ended up not turning out that way. If there are any additions, suggestions or any clarifications that you need added here please drop me an email at &lt;a href="//mailto:bs.gumede@outlook.com"&gt;bs.gumede@outlook.com&lt;/a&gt; or inbox me on twitter &lt;a href="https://twitter.com/sduduzo_g" rel="noopener noreferrer"&gt;@sduduzo_g&lt;/a&gt; . Neutral to positive criticism is very welcome, and will most likely drive edits to better improve the article and my writting too.  &lt;/p&gt;

&lt;p&gt;I used &lt;a href="https://carbon.now.sh/" rel="noopener noreferrer"&gt;carbon.now.sh&lt;/a&gt; for the cover image&lt;br&gt;&lt;br&gt;
and I used &lt;a href="https://www.umletino.com/" rel="noopener noreferrer"&gt;umletino&lt;/a&gt; for the diagram.&lt;/p&gt;

</description>
      <category>firebase</category>
      <category>javascript</category>
      <category>jwt</category>
      <category>oauth</category>
    </item>
    <item>
      <title>Introducing purgitory. My first npm package :)</title>
      <dc:creator>Sdu</dc:creator>
      <pubDate>Sat, 12 Sep 2020 18:38:40 +0000</pubDate>
      <link>https://dev.to/sduduzog/introducing-purgitory-my-first-npm-package-pn0</link>
      <guid>https://dev.to/sduduzog/introducing-purgitory-my-first-npm-package-pn0</guid>
      <description>&lt;h1&gt;
  
  
  Introducing purgitory. My first npm package :)
&lt;/h1&gt;

&lt;p&gt;So purgitory is an npm tool to An npm tool to purge local branches that have been merged and deleted to the main branch in remote.&lt;/p&gt;

&lt;p&gt;Working in a fast paced project and/or projects basically means I'll be creating, checking out and reviewing around a dozen of git branches per week, and from this, I found myself with a bunch of stale branches locally to which most have been merged into master as the work has been deployed.&lt;/p&gt;

&lt;p&gt;I needed something to clean my local repositories, many people do. So while I was pair programming with my teammate this past week he asked me "Hey man, what do you use to remove merged branches locally?" and my answer was "there's a way, google search 'git purge local merged branches' and you'll definitely find some bash script on stackoverflow" not a good answer, I know. But then that's what I always do. I surf the internet until I forget what I was looking for in the first place. Now because there's no easy way to do this, the number of branches locally kept on growing. Clearly we need a solution for this.... and it hit me&lt;/p&gt;

&lt;p&gt;"Fine, I'll do it myself" - This phrase, every time I fail to find a tool for something, it hits me, and then another side project is born&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%2Fi%2Fwzk3lvy1jklw1kv6floo.gif" 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%2Fi%2Fwzk3lvy1jklw1kv6floo.gif" title="Gif of thanos taking the gauntlet and with caption \" alt="Gif of thanos taking the gauntlet and with caption " width="498" height="239"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So immediately after work on Friday. I took a nap, or at least tried to, but I couldn't because I was trying to figure out &lt;em&gt;"how do I make this super simple?"&lt;/em&gt;, &lt;em&gt;"how do I make it easy for myself to accomplish this?"&lt;/em&gt; and &lt;em&gt;"what would I consider a complete project"&lt;/em&gt; and while asking myself those questions I jotted a couple of notes down and went to work.&lt;/p&gt;

&lt;p&gt;This how how &lt;a href="https://www.npmjs.com/package/purgitory" rel="noopener noreferrer"&gt;purgitory&lt;/a&gt; was born.&lt;/p&gt;

&lt;p&gt;The name is like a combination of "purge" and "git". I asked my colleague "what do you think of this name?" and he was like "I just want to use the thing, the name sounds cool" and well.... so if the name doesn't make sense, that's because the focus was on getting this thing to work.&lt;/p&gt;

&lt;p&gt;I had a choice to write this in either c# or javascript, but because of the npm ecosystem, it was easier to lean more towards javascript just so that the tool is easily accessible to a wider audience easier and there are packages for interactive command line tools I can use from npm to make this easier for me.&lt;/p&gt;

&lt;p&gt;This was written 24hrs after the first version "0.0.1" literally had a '&lt;a href="https://github.com/sduduzog/purgitory/blob/2790ee88c303efc0ce90b2138dbd085a144f76b2/bin/index.js" rel="noopener noreferrer"&gt;console.log("foo")&lt;/a&gt;' which didn't work obviously as I learned. But that was the whole point. I heard a quote today from Stefan Mischook "You wanna learn how to fight, you fight" which I resonated with greatly as it's been how I've probably learned everything I know today, or most of it. By diving head first into a challenge.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>javascript</category>
      <category>git</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Hacktoberfest is coming!</title>
      <dc:creator>Sdu</dc:creator>
      <pubDate>Thu, 20 Aug 2020 14:41:18 +0000</pubDate>
      <link>https://dev.to/sduduzog/hacktoberfest-is-coming-h72</link>
      <guid>https://dev.to/sduduzog/hacktoberfest-is-coming-h72</guid>
      <description>&lt;h1&gt;
  
  
  Hacktoberfest is coming!
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;cover image &lt;a href="https://dev.to/ankit986/hactoberfest-2k19-4206"&gt;source&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;TL;DR;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Do open source stuff on the internet, get free stuff.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So What's Hacktoberfest?
&lt;/h2&gt;

&lt;p&gt;It's not a month long beer festival, I first thought it was, but no 😒. It is a month long festival of code organized by DigitalOcean where you participate by simply opening a pull request and contributing to any open source project. All backgrounds and skill levels are encouraged to complete the challenge. In every year, you're given instructions in how to complete the challenge, last year, it was to submit at least four pull requests to any public repository on Github and you're done. Last year, the first 50 000 contributors received limited edition T-shirts and a bunch of cool stickers. This year though, the first 75 000 participants can earn a T-shirt.&lt;/p&gt;

&lt;p&gt;Now to be fully immersed in the experience I really recommend you to follow the &lt;a href="https://dev.to/t/hacktoberfest"&gt;#hacktoberfest tag&lt;/a&gt; on &lt;a href="https://dev.to"&gt;dev.to&lt;/a&gt; and don't be shy to share you journey with the world there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;"I've never contributed to open source before, I don't even know where to start"&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have I got news for you. That alone makes you the perfect participant all on its own. Many people believe that contributing to open source means writing super complex code and/or fixing issues the author of the project could have never figured out. Which, in so many lengths, is &lt;strong&gt;not&lt;/strong&gt; true.&lt;/p&gt;

&lt;p&gt;To put this simply, with a quick example. One of the pull requests I submitted for the 2019 hacktoberfest challenge was editing a README for just explaining steps to setup firebase on an android app. Just that one page, and I had contributed to open source, 3 more similar pull requests sent out and I had completed the challenge thus receiving my 2019 hacktoberfest swag.&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%2Fi%2Fa2jqg1jrsgnscthwm8hr.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%2Fi%2Fa2jqg1jrsgnscthwm8hr.png" title="One of the pull requests submitted" alt="A screenshot from a merged pull request showing edits on a readme file on github" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A few tips on how to find projects to contribute to
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Search for the keyword hacktoberfest on Github&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A trick to get contributors on board by project maintainers is that they label some github issues with 'hacktoberfest', especially during these times of the festival which makes it very easy to filter down to repositories who are looking for help or looking to help you contribute. Other labels to look out for are 'good first issue' and 'beginner' which imply that you do not need to be an expert or super skilled and even versed on a certain project to take a jab in solving that issue.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask around your circles if anyone needs an extra hand in their public projects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes it's the people who are close to you who could also use a helping hand with their projects. You might be also working in a company or a team that maintains some open source repositories, that's your chance to also deal with some minor typos in their documentation here and there, adding some tests or just organizing their file structure for easier consumption.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be on a lookout for online tools used to search for projects on github&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tools like &lt;a href="http://issuehub.io/" rel="noopener noreferrer"&gt;http://issuehub.io/&lt;/a&gt; &lt;a href="https://gauger.io/contrib" rel="noopener noreferrer"&gt;https://gauger.io/contrib&lt;/a&gt; and &lt;a href="https://www.codetriage.com/" rel="noopener noreferrer"&gt;https://www.codetriage.com/&lt;/a&gt; make it so easy to scan through the many projects out there to tackle. I personally like &lt;a href="http://issuehub.io/" rel="noopener noreferrer"&gt;http://issuehub.io/&lt;/a&gt; because it's pretty intuitive and I think it's the one I've been using even way after the festival had passed&lt;/p&gt;

&lt;p&gt;For more detailed information (because I'm writing this out of excitement) please see &lt;a href="https://hacktoberfest.digitalocean.com" rel="noopener noreferrer"&gt;https://hacktoberfest.digitalocean.com&lt;/a&gt; for more details.&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
    </item>
    <item>
      <title>Creating an auto resizing textarea with Vue Composition API in 4 easy steps. I can't wait for Vue v3</title>
      <dc:creator>Sdu</dc:creator>
      <pubDate>Fri, 07 Feb 2020 23:30:57 +0000</pubDate>
      <link>https://dev.to/sduduzog/creating-an-auto-resizing-textarea-with-vue-composition-api-in-4-easy-steps-i-can-t-wait-for-vuejs-v3-3n8l</link>
      <guid>https://dev.to/sduduzog/creating-an-auto-resizing-textarea-with-vue-composition-api-in-4-easy-steps-i-can-t-wait-for-vuejs-v3-3n8l</guid>
      <description>&lt;p&gt;I'm assuming you now know how to add &lt;a href="https://github.com/vuejs/composition-api" rel="noopener noreferrer"&gt;@vue/composition-api&lt;/a&gt; to your project so I won't waste any more time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;Where ever you need to, in your template, just add the textarea element like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!-- anything else you probably had --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;textarea&lt;/span&gt; &lt;span class="na"&gt;ref=&lt;/span&gt;&lt;span class="s"&gt;"myTextArea"&lt;/span&gt; &lt;span class="na"&gt;v-model=&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice we added a &lt;code&gt;ref&lt;/code&gt; attribute. name it whatever you like. Don't forget the v-model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;Create the composition function. I created mine inside the same component file I created the textarea in. You can even create a separate file for it if you like.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useTextArea&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;myTextArea&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLTextAreaElement&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;// remove &amp;lt;...&amp;gt; if JS&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;myTextArea&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;If not done automatically by your editor, add the following import statement&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;createComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;watch&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;@vue/composition-api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// remember 'createComponent' is not needed/used in javascript&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3
&lt;/h3&gt;

&lt;p&gt;Expose these properties to your Vue template. We do that in the setup function's return statement&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;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;createComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="c1"&gt;// ... other things you did.&lt;/span&gt;
  &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ... some other stuff&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;myTextArea&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTextArea&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// ... maybe some more stuff, I don't know&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// ... maybe other things are here too, your things&lt;/span&gt;
      &lt;span class="nx"&gt;myTextArea&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;content&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&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;VueConstructor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I usually add &lt;code&gt;as VueContructor&lt;/code&gt; just to stop the noise from eslint and vue-router complaining about the component's expected type. Not really a requirement.&lt;/p&gt;

&lt;p&gt;Ok everything is neat now, there should be no errors but nothing works yet. We do however have a &lt;a href="https://vuejs.org/v2/api/#ref" rel="noopener noreferrer"&gt;reference&lt;/a&gt; without having to use &lt;code&gt;this.$refs&lt;/code&gt; bacause obviously we don't have access to &lt;code&gt;this&lt;/code&gt; in our setup function. But through the magic of the composition api, the concept of refs is unified.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4
&lt;/h3&gt;

&lt;p&gt;Making it work. We go back to the &lt;code&gt;useTextArea&lt;/code&gt; function to add a couple of lines to watch for changes in the textarea's content and calculate the element's new height after that.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useTextArea&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
  &lt;span class="c1"&gt;// ... after variable declarations&lt;/span&gt;
  &lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;myTextArea&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// depends on what you want initially&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getComputedStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myTextArea&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paddingTop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paddingTop&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paddingBottom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;paddingBottom&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;padding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;paddingTop&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;paddingBottom&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;myTextArea&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scrollHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;myTextArea&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollHeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newRows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scrollHeight&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;initialHeight&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;textArea&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;newRows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// ... before the return statement&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aaand done. You now have a textarea that adds or removes rows if there are any changes with it's value. You don't have to know off hand, the height of your element or the font size of the content, which can change anytime.&lt;/p&gt;

&lt;p&gt;One concern I have is just the performance of the code inside the &lt;code&gt;watch&lt;/code&gt; function. If you have a better implementation please link it in the comments, I'd love to see different ideas around this. I've never enjoyed writing VueJS like this ever before.&lt;/p&gt;

</description>
      <category>vue</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>typescript</category>
    </item>
    <item>
      <title>C# and .NET Core Appreciation Post. The most beautiful piece of code I have ever seen... this month!</title>
      <dc:creator>Sdu</dc:creator>
      <pubDate>Mon, 09 Dec 2019 13:24:19 +0000</pubDate>
      <link>https://dev.to/sduduzog/c-and-net-core-appreciation-post-the-most-beautiful-piece-of-code-i-have-ever-seen-this-month-49gf</link>
      <guid>https://dev.to/sduduzog/c-and-net-core-appreciation-post-the-most-beautiful-piece-of-code-i-have-ever-seen-this-month-49gf</guid>
      <description>&lt;h3&gt;
  
  
  Disclaimer!
&lt;/h3&gt;

&lt;p&gt;This post is a little bit ridiculous and over the top but I'd be doing injustice if I do not share my thoughts on how the journey of learning something new feels like. But if you're in a rush, just scroll to the snippet at the bottom&lt;/p&gt;

&lt;p&gt;So here's the thing. Years ago, when I had just started programming, as part of my degree, I hated C#. I didn't want anything to do with any project related to Microsoft related tech. Here's the rationale behind this (it's a dumb rationale) &lt;em&gt;&lt;strong&gt;Why does C# have a 'C' in its name but looks almost exactly like Java?&lt;/strong&gt;&lt;/em&gt;  I also believed that a good programmer must know Java, C/C++, PHP for server programming, and Python just to prove you're smart. I swear this is a phase that I literally went through.&lt;/p&gt;

&lt;p&gt;This was because when you've just started coding, for some reason there's this notion of being defined by the programming languages you know and the libraries you use. I'm sure that was greatly influenced by the "&lt;strong&gt;Top 10 best languages to learn in 201X&lt;/strong&gt;" or "&lt;strong&gt;Language X is dead, here's why&lt;/strong&gt;", even "&lt;strong&gt;Programming languages used by Facebook&lt;/strong&gt;" articles that &lt;strong&gt;I actively looked for!&lt;/strong&gt; just so that I don't get left behind in the industry.&lt;/p&gt;

&lt;p&gt;Of course, a lot changed in the way I view tech and my career but what I felt about C# or anything related to it never changed, until about 6-7 months ago. See, at work, they use a shit ton of .NET (or dotnet. I'm still getting the hang of this) so I'm learning it now. A few months ago, I completed a 'Basics for beginners' udemy course. It was fine I guess🙄 but learned a lot of cool stuff 🤗&lt;/p&gt;

&lt;p&gt;Now I'm creating a project so that I learn more of this freaky stuff. &lt;strong&gt;Enter .NET Core 3!&lt;/strong&gt; The most overwhelming piece of framework I've ever encountered (this year. I have to be clear on this). I have never given up so many times but come back to try again, in just a single week, ever for any project that I ever started to learn. When I finally got my thingie to give me a token for authentication, after days and nights of struggle, I ran the most satisfyingly powerful git command known to mankind&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;git commit -m 'Initial commit'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I was happy. Then I had my supper while rereading up on what I've implemented and that's when I saw it&lt;/p&gt;

&lt;h4&gt;
  
  
  The masterpiece
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;GetUserByToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Users&lt;/span&gt;
        &lt;span class="k"&gt;join&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tokens&lt;/span&gt;
            &lt;span class="k"&gt;on&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="k"&gt;equals&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserId&lt;/span&gt;
        &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;
        &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;SingleOrDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;It's beautiful isn't it? I thought so too&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
I mean do you understand that the last time I saw something this cool was when I saw JSX for the first time, which looked so confusing but really not so trivial after some time of use. My brain doesn't have to context switch between application code and database scripts but the thing just works seamlessly. And the syntax highlighting plus the IntelliSense! I am stunned.&lt;/p&gt;

&lt;p&gt;If you're reading this and you do not understand WTF is going on here, it's okay, it's not your time yet. But later on in your life, you will see what I saw and you'll say "shit, that dude on dev.to wrote a weird post about this feeling I'm feeling right now".&lt;/p&gt;

&lt;h3&gt;
  
  
  Not convinced? Look again
&lt;/h3&gt;

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

</description>
      <category>dotnet</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Ok I knew contributing to open source was fun but no one told me it would be this easy :satisfied:</title>
      <dc:creator>Sdu</dc:creator>
      <pubDate>Sat, 12 Oct 2019 22:24:08 +0000</pubDate>
      <link>https://dev.to/sduduzog/ok-i-knew-contributing-to-open-source-was-fun-but-no-one-told-me-it-would-be-this-easy-satisfied-5aek</link>
      <guid>https://dev.to/sduduzog/ok-i-knew-contributing-to-open-source-was-fun-but-no-one-told-me-it-would-be-this-easy-satisfied-5aek</guid>
      <description>&lt;p&gt;I honestly didn't think I would be able to finish the hacktoberfest challenge, let alone in such short amount of time. Still I feel like I am not done participating.&lt;/p&gt;

&lt;p&gt;I first heard of hacktoberfest last year when I had been a member of Dev.to for just a couple of months and struggling with getting my open source app off the ground. I focused on working on my own project because I believed to contribute to another person's or organisation's codebase you have to be super skilled. While asking for help with my own issues I was facing, another community member &lt;a href="https://dev.to/subbramanil"&gt;subbramanil&lt;/a&gt; opened a PR just for a single unit test file and took me through what the contribution was and why he was doing it, as confused and excited as I was. Here's one inspiring piece: &lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/subbramanil" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F18587%2Fca1b8a36-25ff-4939-9a0f-0a43d8c586e4.JPG" alt="subbramanil"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/subbramanil/hactoberfest-challenge-completed-e49" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;HactoberFest Challenge: Completed&lt;/h2&gt;
      &lt;h3&gt;Subbu Lakshmanan ・ Oct 30 '18&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#hacktoberfest&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#android&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#opensource&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;A year later. Still I didn't want to contribute to anything because I felt I wasn't going to be good enough. I read so many posts everywhere about how people contributed even it was just a single line of documentation in a README.md and that really pumped me up to actually doing something. (I still didn't)&lt;/p&gt;

&lt;p&gt;What got me to stop procrastinating about participating is the fact that everyone in my office was either already participating or being encouraged to. Plus I wouldn't want to see a bunch of beautiful hacktoberfest T-shirts at work knowing that I could've gotten one too but didn't do anything about it.&lt;/p&gt;

&lt;p&gt;This past Friday, I found easy prey. I saw this&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/LBBO/node-netflix2/issues/27" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Add JSDoc comments for better IDE support
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#27&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/LBBO" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--qlBVS7MG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://avatars0.githubusercontent.com/u/8076094%3Fv%3D4" alt="LBBO avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/LBBO" rel="noopener noreferrer"&gt;LBBO&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/LBBO/node-netflix2/issues/27" rel="noopener noreferrer"&gt;&lt;time&gt;Oct 11, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;JSDoc comments can be added to most methods to clarify not only their purpose and usage, but also their parameter's expected types. Since this project is not written in TypeScript, IDEs could use these comments instead in order to provide useful code completion etc.&lt;/p&gt;
&lt;p&gt;Please direct any PR towards the &lt;code&gt;refactor-everything&lt;/code&gt; branch and only work on &lt;code&gt;lib/netflix2.class.js&lt;/code&gt; as this is soon going to replace &lt;code&gt;lib/netflix2.js&lt;/code&gt;.&lt;/p&gt;

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


&lt;p&gt;The thing is, I've been writting comments all my live (minus the years I didn't know about programming) I mean how hard can it be?&lt;br&gt;
I submitted a pull request, then BOOM!! 1/4 PRs for hacktoberfest was done. I was so exited that I submitted 2 more pull requests to other repos in one day.&lt;/p&gt;

&lt;p&gt;As a bonus to myself, I submitted a pull request to the Dev.to android project.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/forem" rel="noopener noreferrer"&gt;
        forem
      &lt;/a&gt; / &lt;a href="https://github.com/forem/DEV-Android" rel="noopener noreferrer"&gt;
        DEV-Android
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      DEV Community Android App
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;DEV Android 💝&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://codeclimate.com/github/thepracticaldev/DEV-Android/maintainability" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/e4f7e7644a835c3781bcd5f709e3856f3f0bb9760179b75ee0336285b03b57c9/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f61643331623861323637613337343735653134632f6d61696e7461696e6162696c697479"&gt;&lt;/a&gt;
&lt;a href="https://codeclimate.com/github/thepracticaldev/DEV-Android/test_coverage" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/2a1ba52d7b907d4b219b2084ef277d14d4e96a7476573ded6d466e762646d581/68747470733a2f2f6170692e636f6465636c696d6174652e636f6d2f76312f6261646765732f61643331623861323637613337343735653134632f746573745f636f766572616765"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is the official repository for the &lt;a href="https://dev.to/" rel="nofollow"&gt;dev.to&lt;/a&gt;'s Android app.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://play.google.com/store/apps/details?id=to.dev.dev_android&amp;amp;pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1" rel="nofollow noopener noreferrer"&gt;&lt;img width="150px" alt="Get it on Google Play" src="https://camo.githubusercontent.com/24e5a047a2a2617f40b69cb9ada90e7c11e94d7cad428bc6107275e507e0688f/68747470733a2f2f706c61792e676f6f676c652e636f6d2f696e746c2f656e5f75732f6261646765732f696d616765732f67656e657269632f656e5f62616467655f7765625f67656e657269632e706e67"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Design ethos&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;DEV Android is an &lt;a href="https://developer.android.com/guide/webapps/webview" rel="nofollow noopener noreferrer"&gt;WebView&lt;/a&gt; based application. This application is inspired by &lt;a href="https://m.signalvnoise.com/basecamp-3-for-ios-hybrid-architecture-afc071589c25" rel="nofollow noopener noreferrer"&gt;Basecamp's approach&lt;/a&gt;. We will grow to include more native code over time.&lt;/p&gt;
&lt;p&gt;By leveraging webviews as much as possible, we can smoothly sync up with our web dev work. And where it makes sense, we can re-implement certain things fully native, or build entirely native features. Life's a journey, not a destination.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Contributions&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;We expect contributors to abide by our underlying &lt;a href="https://github.com/forem/DEV-Android./CODE_OF_CONDUCT.md" rel="noopener noreferrer"&gt;code of conduct&lt;/a&gt;. All conversations and discussions on GitHub (issues, pull requests) and across dev.to must be respectful and harassment-free.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;System Requirements&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;You will need to have Android Studio 3.5 or up installed.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Usage&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;$ ./gradlew tasks --group=custom
------------------------------------------------------------
Tasks runnable from root project
------------------------------------------------------------

Custom tasks
------------
androidTest - Run android instrumentation tests
hello - Hello World task&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/forem/DEV-Android" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


</description>
      <category>hacktoberfest</category>
    </item>
    <item>
      <title>Flutter Dependency Injection</title>
      <dc:creator>Sdu</dc:creator>
      <pubDate>Sat, 07 Sep 2019 09:41:21 +0000</pubDate>
      <link>https://dev.to/sduduzog/flutter-dependency-injection-1aj6</link>
      <guid>https://dev.to/sduduzog/flutter-dependency-injection-1aj6</guid>
      <description>&lt;p&gt;&lt;em&gt;cover image &lt;a href="https://medium.com/apparence/use-dependency-injection-with-flutter-9c3ee7bf4d16" rel="noopener noreferrer"&gt;source&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Lately I've been fascinated with code sharing between web and mobile. Obviously there are many ways one can write code to be shared among platform and the phrase 'code sharing' can imply quite a number of things. The one that intrigued me the most was with Flutter, AngularDart (I'll continue referring to this as ngDart) and the BLoC pattern. &lt;/p&gt;

&lt;p&gt;To demonstrate my findings I took the flutter pre built counter app and implemented it in ngDart. I did try to make it as identical as possible but I'm lazy and I wasn't very much focused on the aesthetics. &lt;a href="https://github.com/sduduzog/counter_example" rel="noopener noreferrer"&gt;Check out the repo here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To run the flutter app, open the flutter project folder and either use your IDE shortcut or in the terminal, do &lt;br&gt;
&lt;code&gt;&amp;gt; flutter run&lt;/code&gt;&lt;br&gt;
To run the angular app, it's almost same thing, but the command is &lt;br&gt;
&lt;code&gt;&amp;gt; webdev serve&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You'll see that with ngDart, dependency injection framework is no issue as it's built in but with Flutter, I had to shop around for the solution that looks like it fits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution 1
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://pub.dev/packages/flutter_simple_dependency_injection" rel="noopener noreferrer"&gt;flutter_simple_dependency_injection&lt;/a&gt;&lt;br&gt;
I found  this package from &lt;a href="https://www.toptal.com/cross-platform/code-sharing-angular-dart-flutter-bloc" rel="noopener noreferrer"&gt;the article&lt;/a&gt; I used to start off my code sharing example. I wouldn't have made the project if I didn't think that article although very informative it was rather complex when it came to the example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution 2
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/google/inject.dart" rel="noopener noreferrer"&gt;Googles inject.dart repo&lt;/a&gt;&lt;br&gt;
This seemed like the go to solution. Their README mentions charming fancy words like&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Compile-time dependency injection for Dart and Flutter, similar to Dagger.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I was hooked, especially because I had just ported my &lt;a href="https://github.com/sduduzog/slim-launcher" rel="noopener noreferrer"&gt;open source android app&lt;/a&gt; to Dagger.&lt;br&gt;
I immediately ported my example to use it instead, while doing so I couldn't throw off the bad feeling that came with using this package.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It isn't on the dart package registry &lt;a href="https://pub.dev" rel="noopener noreferrer"&gt;pub.dev&lt;/a&gt; so there's a funky way you must use to add it to your project.&lt;/li&gt;
&lt;li&gt;Their README has a note stating **&lt;em&gt;This is not an official Google or Dart team project.&lt;/em&gt; while the repo is literally hosted by the Google org on github.&lt;/li&gt;
&lt;li&gt;The issue tracker is disabled.
That was all enough for me to look for another solution. I didn't even get to see this in action. I stopped in the middle of configuring it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Solution 3
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://pub.dev/packages/dependencies_flutter" rel="noopener noreferrer"&gt;dependecies_flutter&lt;/a&gt;&lt;br&gt;
While porting to this, I immediately felt comfortable. It was modular and felt native to the flutter Widget system. The author's examples we're also very easy to follow, I didn't have to google for a medium article just to understand how to use it.&lt;/p&gt;

&lt;p&gt;I hope I don't get to Solution 4 because Solution 3 chased me away but rather because of what benefits my projects will be getting from the migration instead.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>dart</category>
      <category>flutter</category>
      <category>android</category>
    </item>
    <item>
      <title>I got the job 💃</title>
      <dc:creator>Sdu</dc:creator>
      <pubDate>Thu, 21 Mar 2019 09:29:15 +0000</pubDate>
      <link>https://dev.to/sduduzog/i-got-the-job--5bod</link>
      <guid>https://dev.to/sduduzog/i-got-the-job--5bod</guid>
      <description>&lt;p&gt;This is just a follow-up to the post I wrote a while back.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/sduduzog" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F86317%2Fe8658a7e-0e1b-4463-beff-49f974146b1d.jpg" alt="sduduzog"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/sduduzog/i-went-to-my-first-interview-it-was-terrifying-dpe" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;I went to my first interview! It was terrifying.&lt;/h2&gt;
      &lt;h3&gt;Sdu ・ Feb 12 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#beginners&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#career&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#discuss&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;After that first interview, I went to another a few days later and got an offer from the second company on the spot. What I immediately got from that was, an interview goes both ways. As much as they are assessing you, you also have to be assessing them. Anyway, I declined an offer to be a front-end developer from this other company and came back to codeo to complete the recruitment process, that being a full day spent at their offices with the team and a second interview.&lt;/p&gt;

&lt;p&gt;I started work officially on the 1st of March and I couldn't be more happier. If I were to tag each and everyone who posted here, the content that helped me prep, I wouldn't even know where to start. Thanks to everyone who is a part of dev.to and those that are always lending a helping hand to career toddlers like me. You know, I've even received emails of people pointing out typos in my resume that I'd overlooked.&lt;/p&gt;

&lt;p&gt;I mean check this out&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/ice_lenor" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F17692%2F0c1e08f1-cb6c-4ae7-be0b-3fd5ce00f174.jpg" alt="ice_lenor"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/ice_lenor/do-i-want-to-work-in-this-company-or-what-questions-to-ask-on-an-interview-7po" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Do I Want To Work In This Company, or What Questions To Ask On An Interview&lt;/h2&gt;
      &lt;h3&gt;Elena ・ Nov 8 '17&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#career&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#interview&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#job&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;I don't know how many times I read these questions, days before both my interviews at codeo. When they finally asked me "Alright, do you have any questions to ask us?" I was blank! This happened twice, when I was trying to recall questions that they haven't answered indirectly or that I haven't figured out already. At most I'd just say "No I don't have any, question 1, 2 and 3 were answered by this, that and such and such but thank you for the opportunity" as I said that, a funny question clouds my mind, it was so silly that I'd giggle while I was trying to speak, like an inner voice kept on shouting "ASK THEM &lt;strong&gt;WHERE DO I SIGN?&lt;/strong&gt;"&lt;/p&gt;

&lt;p&gt;Anyway, I'd talk about this forever, I just wanted to let you all know that I'm good now. I'm jobbing 🎉🎉🎉 (if that's a word)&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>discuss</category>
      <category>career</category>
    </item>
    <item>
      <title>I redid my portfolio site for the third time, this year alone!</title>
      <dc:creator>Sdu</dc:creator>
      <pubDate>Fri, 22 Feb 2019 00:32:09 +0000</pubDate>
      <link>https://dev.to/sduduzog/i-redid-my-portfolio-site-for-the-third-time-this-year-alone-25ee</link>
      <guid>https://dev.to/sduduzog/i-redid-my-portfolio-site-for-the-third-time-this-year-alone-25ee</guid>
      <description>&lt;p&gt;The last quarter of 2018 was the year dev.to was most influential in my career. More so great because I was doing my last year in varsity. I was inspired to start a &lt;a href="https://github.com/sduduzog/slim-launcher" rel="noopener noreferrer"&gt;project&lt;/a&gt; &lt;strong&gt;and actually finish it&lt;/strong&gt; while following advice for projects to show off on my portfolio.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Vue.js to a Jekyll generated 'noscript' site
&lt;/h2&gt;

&lt;p&gt;I entered a year with a portfolio that had some fun animations powered by Vue.js, but as part of my resolutions this year, I wanted to start blogging. I took down my site, recreated it now with Jekyll and its default theme. No javascript whatsoever.&lt;/p&gt;

&lt;h2&gt;
  
  
  From default minima theme to more custom design
&lt;/h2&gt;

&lt;p&gt;Ok, I think it is great that Jekyll provides minima as their entry theme, not too heavy and not too complicated to customize. I changed the home page to something I felt represented me the most. &lt;em&gt;At some point, my portfolio site was opened on one job interview that I was in on a projector&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Now this!
&lt;/h1&gt;

&lt;p&gt;I created a new branch just for the redesign. I deleted everything on my repo and started with a new index.html file and worked my way up from there. And being unemployed 🤣, I've been in front of my laptop for more than 10 hours updating my site, and now writing this post minutes after pushing the changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sduduzog.github.io/" rel="noopener noreferrer"&gt;View my incomplete portfolio here&lt;/a&gt; and tell me what you think. Of course, it's not complete yet, I need to add a section for my projects and a link to my resume. I also have to redesign pages for my blog posts. I would use any Jekyll theme but I feel that takes away my personality from the site.&lt;/p&gt;

&lt;p&gt;What makes this even more fun is that I'm doing this while learning vim. People really need to check this article out, for beginners like me who were lowkey scared of taking that leap because of the "&lt;em&gt;Exiting vim&lt;/em&gt;" jokes, exiting vim is actually wayyy easier than I thought 😳&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/vintharas" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F93147%2F09d69d89-7e27-4285-86cc-d620dfcd20ec.jpg" alt="vintharas"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/vintharas/boost-your-coding-fu-with-visual-studio-code-and-vimboost-your-coding-fu-with-visual-studio-code-and-vim-502h" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Boost Your Coding Fu With Visual Studio Code and Vim&lt;/h2&gt;
      &lt;h3&gt;Jaime González García ・ Feb 10 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#vscode&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#vim&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#productivity&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;h1&gt;
  
  
  I almost forgot to mention the logo!
&lt;/h1&gt;

&lt;p&gt;I made it with gimp. using material colors of course. Do you guys know about this &lt;a href="https://github.com/harnerdesigns/material-color" rel="noopener noreferrer"&gt;material color picker?&lt;/a&gt; I use it all the time! Even with my portfolio design and graphics. I then exported my logo as a big &lt;code&gt;.bmp&lt;/code&gt; file to trace with Inkscape for a smaller SVG.&lt;/p&gt;

&lt;h1&gt;
  
  
  Links
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I use &lt;a href="http://forestry.io" rel="noopener noreferrer"&gt;Forestry.io&lt;/a&gt; to build my site automatically when I push to origin. I initially used it as my CMS but I needed more flexibility.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I use &lt;a href="https://github.com/ashmaroli/jekyll-manager" rel="noopener noreferrer"&gt;jekyll-manager&lt;/a&gt; as my GUI for creating and editing posts. The rest I edit in vscode.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Badges on the bottom of the page, I got from &lt;a href="https://simpleicons.org/" rel="noopener noreferrer"&gt;simpleicons.org&lt;/a&gt;. They have EVERYTHING! OK maybe they don't but I didn't check.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>showdev</category>
      <category>beginners</category>
      <category>portfolio</category>
      <category>career</category>
    </item>
    <item>
      <title>I went to my first interview! It was terrifying.</title>
      <dc:creator>Sdu</dc:creator>
      <pubDate>Tue, 12 Feb 2019 13:56:25 +0000</pubDate>
      <link>https://dev.to/sduduzog/i-went-to-my-first-interview-it-was-terrifying-dpe</link>
      <guid>https://dev.to/sduduzog/i-went-to-my-first-interview-it-was-terrifying-dpe</guid>
      <description>&lt;p&gt;Terrifying in a good way. I've never been in an interview aligned with my career and I'm still a fresh graduate. The post is for a Junior QA Engineer, of course it's not development but I read up on the role thoroughly and I feel it's really important that I start with it. Its gonna teach me so much about ensuring code quality and maintaining standards of the organisation, which at some point developers tend to overlook.&lt;/p&gt;

&lt;p&gt;I also want to get into a hobby of Test Driven Development. Which I feel would be inline with the culture of quality assurance. I'm highly interested in taking up the responsibility of the role so much that my nerves during the interview were intertwined with excitement.&lt;/p&gt;

&lt;p&gt;By the way, I just completed my degree in Computer Science, so job hunting season kicked off in the beginning of this year. I'm constantly sending out applications and hoping for the best. Regardless of the decision that will be taken by my interviewers today, I learned a lot. My first experience of a cultural interview was awesome. I also found out that I'm quite good with office humour,&lt;em&gt;apparently&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I took a lot of advice from posts here on dev.to and it helped that I'm a talkative person so the interview felt more like a conversation about me, more than anything else. A treasure that helped me through the process is a post by @emmawedekind&lt;/p&gt;


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


&lt;blockquote&gt;
&lt;p&gt;Although typically cultural interviews aren’t as terrifying as coding interviews, interviewers can make or break your application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I swear to God, half of my confidence came from it. In as much as I was beginning this journey, I felt prepared. Also being honest actually worked very well in my favour. I'm just still not sure how they received my humour 😑&lt;/p&gt;

&lt;p&gt;Here's one thing that terrified me. I misread the time on my calendar by mistake, I thought I was coming in an hour early but turns out, I was JUST IN TIME. So already I was thrown off a bit. Props to being punctual 🤞. Also I don't think anyone likes seeing a whiteboard where an interview is to be conducted. Luckily not required at the time, but those few minutes of waiting for my interviewers to join me in the boardroom, I couldn't help but wonder which "searching algorithm" were they gonna ask for, just nerves messing me up I guess.&lt;/p&gt;

&lt;p&gt;Anyway, I can't wait to get my first job in tech 🤞&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>SDP - A scalable size unit... To the rescue 😁</title>
      <dc:creator>Sdu</dc:creator>
      <pubDate>Sun, 13 Jan 2019 00:14:11 +0000</pubDate>
      <link>https://dev.to/sduduzog/sdp---a-scalable-size-unit-to-the-rescue--4nh3</link>
      <guid>https://dev.to/sduduzog/sdp---a-scalable-size-unit-to-the-rescue--4nh3</guid>
      <description>&lt;p&gt;&lt;em&gt;My first 2019 post here on dev.to so happy new year and you're awesome&lt;/em&gt; 😎&lt;/p&gt;

&lt;p&gt;I wrote an article here about &lt;a href="https://dev.to/sduduzog/side-project-success--2i3k"&gt;my side project&lt;/a&gt; last year and the side effects were amazing 🙌 Downloads picked up a lot and I've been receiving great reviews.&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/sduduzog" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F86317%2Fe8658a7e-0e1b-4463-beff-49f974146b1d.jpg" alt="sduduzog"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/sduduzog/side-project-success--2i3k" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Side project success 🎉&lt;/h2&gt;
      &lt;h3&gt;Sdu ・ Dec 15 '18&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#showdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#android&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#kotlin&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;From the feedback the app was received on google play and emails, one issue  stood out the most.&lt;/p&gt;

&lt;p&gt;This is used as the cover image also 😐&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fq888pkulz9n2fidrsnro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fq888pkulz9n2fidrsnro.png" alt="google play review screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another review 🤨&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff78ahfz5p5kgesg0ufm9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff78ahfz5p5kgesg0ufm9.png" alt="another google play screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Last screenshot, I swear 😑&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F59z0o3fuvqr3a7bez5an.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F59z0o3fuvqr3a7bez5an.png" alt="screenshot of an email review"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I tinted the images to differentiate from the site background&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Basically more and more people noticed the "little thing" I thought was "not an issue" &lt;strong&gt;text size on different screen sizes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I can't really recall how many requests I received about text size issues on smaller screen devices but it got me paranoid.&lt;/p&gt;

&lt;p&gt;See, the app is a minimalist launcher that allows you to choose 5 apps to appear on your home screen and only displays a clock plus your selection. &lt;strong&gt;The problem is&lt;/strong&gt; on smaller screens, app text would overlap with the clock 😫&lt;/p&gt;

&lt;p&gt;I tried creating different &lt;code&gt;dimens&lt;/code&gt; resources to target different densities but that was a disaster. I knew I would never cover every use case smoothly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Until I came across&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/intuit" rel="noopener noreferrer"&gt;
        intuit
      &lt;/a&gt; / &lt;a href="https://github.com/intuit/sdp" rel="noopener noreferrer"&gt;
        sdp
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An Android lib that provides a new size unit - sdp (scalable dp). This size unit scales with the screen size.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/45fb57a2440ff7b090af1ac9b857cbf74a1406799fc450676c7fba2f86624919/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f696e747569742f736470"&gt;&lt;img src="https://camo.githubusercontent.com/45fb57a2440ff7b090af1ac9b857cbf74a1406799fc450676c7fba2f86624919/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f696e747569742f736470" alt="issues"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/b202b4dca09a67a724d849b4e17101a5c14bd54dc23001cd2892b0c4c970b45a/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f726b732f696e747569742f736470"&gt;&lt;img src="https://camo.githubusercontent.com/b202b4dca09a67a724d849b4e17101a5c14bd54dc23001cd2892b0c4c970b45a/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f726b732f696e747569742f736470" alt="Forks"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/6cec0e132dbcecaa468ed6102b8a07c598e190848982a5bb8854af6977693030/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f696e747569742f736470"&gt;&lt;img src="https://camo.githubusercontent.com/6cec0e132dbcecaa468ed6102b8a07c598e190848982a5bb8854af6977693030/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f696e747569742f736470" alt="Stars"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/8888adf3e5c4027aa38fa3957d9b9d1199ee54dbeb83c095d1554c203aab0145/68747470733a2f2f696d672e736869656c64732e696f2f6d6176656e2d63656e7472616c2f762f636f6d2e696e747569742e7364702f7364702d616e64726f6964"&gt;&lt;img src="https://camo.githubusercontent.com/8888adf3e5c4027aa38fa3957d9b9d1199ee54dbeb83c095d1554c203aab0145/68747470733a2f2f696d672e736869656c64732e696f2f6d6176656e2d63656e7472616c2f762f636f6d2e696e747569742e7364702f7364702d616e64726f6964" alt="Maven Central"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/07d9e54ef9a66e5f89b1400720b14eca874acb5c6fc7c734ca34fc4bc893a430/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f696e747569742f736470"&gt;&lt;img src="https://camo.githubusercontent.com/07d9e54ef9a66e5f89b1400720b14eca874acb5c6fc7c734ca34fc4bc893a430/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f696e747569742f736470" alt="License"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;SDP - a scalable size unit&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;An android lib that provides a new size unit - sdp (scalable dp). This size unit scales with the screen size. It can help Android developers with supporting multiple screens.&lt;/p&gt;
&lt;p&gt;for text views please refer to &lt;a href="https://github.com/intuit/ssp" rel="noopener noreferrer"&gt;ssp&lt;/a&gt; which is based on the sp size unit for texts.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Attention&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Use it carefully! for example, in most cases you still need to design a different layout for tablets.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Example&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/intuit/sdp/blob/master/sdp-android/src/main/res/layout/sdp_example.xml" rel="noopener noreferrer"&gt;Here&lt;/a&gt; is a single layout built using sdp:&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/intuit/sdp/blob/master/sdp_example.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fintuit%2Fsdp%2Fraw%2Fmaster%2Fsdp_example.png" alt="sdp example"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And &lt;a href="https://github.com/intuit/sdp/blob/master/sdp-android/src/main/res/layout/dp_example.xml" rel="noopener noreferrer"&gt;here&lt;/a&gt; is the same layout built using dp:&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/intuit/sdp/blob/master/dp_example.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fintuit%2Fsdp%2Fraw%2Fmaster%2Fdp_example.png" alt="dp example"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can see that sdp scales with the screen size and the dp stays with the same size on all screen sizes.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Getting Started&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;To add sdp to your project (Using Android Studio and Gradle):&lt;/p&gt;
&lt;p&gt;add implementation 'com.intuit.sdp:sdp-android:1.1.1' to your build.gradle dependencies block.&lt;/p&gt;
&lt;p&gt;for example:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;dependencies {
  implementation 'com.intuit.sdp:sdp-android:1.1.1'
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See the &lt;a href="https://github.com/intuit/sdp/blob/master/sdp-android/src/main/res/layout/sdp_example.xml" rel="noopener noreferrer"&gt;sdp_example.xml&lt;/a&gt; to see how to use to the…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/intuit/sdp" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  And
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/intuit" rel="noopener noreferrer"&gt;
        intuit
      &lt;/a&gt; / &lt;a href="https://github.com/intuit/ssp" rel="noopener noreferrer"&gt;
        ssp
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Variant of sdp project based on the sp size unit.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/6eeef07f5fc1e923f96abf365293c8caaddcd3f2378e2df54b5538fe4f683e69/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f696e747569742f737370"&gt;&lt;img src="https://camo.githubusercontent.com/6eeef07f5fc1e923f96abf365293c8caaddcd3f2378e2df54b5538fe4f683e69/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f696e747569742f737370" alt="issues"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/0458449d5e67605c422a0dfb3aa6938d2af0d4354d99c48a8ee307587c7587ca/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f726b732f696e747569742f737370"&gt;&lt;img src="https://camo.githubusercontent.com/0458449d5e67605c422a0dfb3aa6938d2af0d4354d99c48a8ee307587c7587ca/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f726b732f696e747569742f737370" alt="Forks"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/7e9d58366b2ceeb6c97775103c2353a67a342e614ad5ee3c5fed8473a27f4132/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f696e747569742f737370"&gt;&lt;img src="https://camo.githubusercontent.com/7e9d58366b2ceeb6c97775103c2353a67a342e614ad5ee3c5fed8473a27f4132/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f696e747569742f737370" alt="Stars"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/6b2ee83ba21364edc14825f90db7c8e342915a7e745810ab918902b7a27c03b0/68747470733a2f2f696d672e736869656c64732e696f2f6d6176656e2d63656e7472616c2f762f636f6d2e696e747569742e7373702f7373702d616e64726f6964"&gt;&lt;img src="https://camo.githubusercontent.com/6b2ee83ba21364edc14825f90db7c8e342915a7e745810ab918902b7a27c03b0/68747470733a2f2f696d672e736869656c64732e696f2f6d6176656e2d63656e7472616c2f762f636f6d2e696e747569742e7373702f7373702d616e64726f6964" alt="Maven Central"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/a18a9d057530a20fcba7353a4c19f976585ef5897b537cecc65f8153815635d0/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f696e747569742f737370"&gt;&lt;img src="https://camo.githubusercontent.com/a18a9d057530a20fcba7353a4c19f976585ef5897b537cecc65f8153815635d0/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f696e747569742f737370" alt="License"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;SSP - a scalable size unit for texts&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;An android lib that provides a new size unit - ssp (scalable sp). This size unit scales with the screen size based on the sp size unit (for texts). It can help Android developers with supporting multiple screens.&lt;/p&gt;
&lt;p&gt;This is the sibling of the &lt;a href="https://github.com/intuit/sdp" rel="noopener noreferrer"&gt;sdp&lt;/a&gt; size unit that should be used for non text views.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Attention&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Use it carefully! for example, in most cases you still need to design a different layout for tablets.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Example&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/intuit/ssp/blob/master/ssp-android/src/main/res/layout/ssp_example.xml" rel="noopener noreferrer"&gt;Here&lt;/a&gt; is a single layout built using ssp:&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/intuit/ssp/blob/master/ssp_example.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fintuit%2Fssp%2Fraw%2Fmaster%2Fssp_example.png" alt="ssp example"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And &lt;a href="https://github.com/intuit/ssp/blob/master/ssp-android/src/main/res/layout/sp_example.xml" rel="noopener noreferrer"&gt;here&lt;/a&gt; is the same layout built using sp:&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/intuit/ssp/blob/master/sp_example.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fintuit%2Fssp%2Fraw%2Fmaster%2Fsp_example.png" alt="sp example"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can see that ssp scales with the screen size and the sp stays with the same size on all screen sizes.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Getting Started&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;To add ssp to your Android Studio project:&lt;/p&gt;
&lt;p&gt;add implementation 'com.intuit.ssp:ssp-android:1.1.1’ to your build.gradle dependencies block.&lt;/p&gt;
&lt;p&gt;for example:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;dependencies {
  implementation 'com.intuit.ssp:ssp-android:1.1.1'
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;See the &lt;a href="https://github.com/intuit/ssp/blob/master/ssp-android/src/main/res/layout/ssp_example.xml" rel="noopener noreferrer"&gt;ssp_example.xml&lt;/a&gt;…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/intuit/ssp" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I trusted these libraries for delivering a consistent ui in all homescreens of the hundreds of users who downloaded my app.&lt;/p&gt;

&lt;p&gt;I truly design just one layout, use probably &lt;code&gt;@dimen/_64sdp&lt;/code&gt; for a margin or text size and something like &lt;code&gt;@dimen/_12ssp&lt;/code&gt; for an &lt;code&gt;android:textSize&lt;/code&gt; that I want consistent across a lot of screen sizes.&lt;/p&gt;

&lt;p&gt;It supports minimum sdk version 16, and I'll be testing for tablets too.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be careful&lt;/strong&gt; not to forget that the &lt;em&gt;all screen sizes&lt;/em&gt; approach is not a solution for most ui design solutions.&lt;/p&gt;

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

</description>
      <category>githunt</category>
      <category>discuss</category>
      <category>kotlin</category>
      <category>android</category>
    </item>
  </channel>
</rss>
