<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Laura buns</title>
    <description>The latest articles on Forem by Laura buns (@walaura).</description>
    <link>https://forem.com/walaura</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%2F178067%2Faa32363c-44eb-45b1-9f89-127258b99825.jpg</url>
      <title>Forem: Laura buns</title>
      <link>https://forem.com/walaura</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/walaura"/>
    <language>en</language>
    <item>
      <title>So you want to make a Twitter bot (2.5/3)</title>
      <dc:creator>Laura buns</dc:creator>
      <pubDate>Sun, 22 Dec 2019 15:51:45 +0000</pubDate>
      <link>https://forem.com/walaura/so-you-want-to-make-a-twitter-bot-2-5-3-2a8k</link>
      <guid>https://forem.com/walaura/so-you-want-to-make-a-twitter-bot-2-5-3-2a8k</guid>
      <description>&lt;p&gt;Sorry for going final harry potter movie on you. Anyway&lt;/p&gt;

&lt;p&gt;OMG OMG it's ALMOST part 3 it's THE FUN PART TODAY – up until now all the steps we have made (see &lt;a href="https://dev.to/walaura/so-you-want-to-make-a-twitter-bot-1-3-4nj2"&gt;part 1&lt;/a&gt; and &lt;a href="https://dev.to/walaura/so-you-want-to-make-a-twitter-bot-2-3-9ba"&gt;part 2&lt;/a&gt;) are mostly plumbing, you gotta do these for each bot (there are a couple tricks to automate this. You can duplicate repos and heroku apps, and you can get all your keys using a single app &lt;a href="https://twitter.com/freezydorito/status/1196414820255440896" rel="noopener noreferrer"&gt;like this&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;However our actual posts leave a lot to be desired. i can't teach you to be funny (if i knew the secrets to that I'd be funny myself). In &lt;a href="https://github.com/cool-robot-pals" rel="noopener noreferrer"&gt;my own bots&lt;/a&gt; I use a &lt;em&gt;lot&lt;/em&gt; of images to accomplish this. In cases like &lt;a href="https://twitter.com/readyforspoons" rel="noopener noreferrer"&gt;@readyforspoons&lt;/a&gt; or &lt;a href="https://twitter.com/fakefantas" rel="noopener noreferrer"&gt;@fakefantas&lt;/a&gt; they are the whole point of the tweet. the dirty little secret here is that they are webpages:&lt;/p&gt;

&lt;p&gt;There's a tool called &lt;a href="https://www.npmjs.com/package/puppeteer" rel="noopener noreferrer"&gt;puppeteer&lt;/a&gt; that i never know how to spell and that more serious people than me use for actual purposes that lets you automate spinning up Chrome (okay it's Chromium. Who cares, not the point), taking a screenshot of certain dimensions, and saving it to a file. This is a very neat closed loop, it means we can develop this in isolation* and then from our tweeting app, pick up the image and tweet it. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;okay, almost isolation. In most cases you are gonna get some more stuff back from the page, like the text for the tweet or whatevers. More on this later&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'm sitting on a mcdonalds listening to fall out boy massively hungover thinking about deep stuff so let's make an aesthetics bot that makes these poster things you see on tumblr but it's lyrics from smash mouths 'all star' instead. (This is a terrible bot idea don't do this there's v little variation)&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjeg1bi8itr7gbp21ks2r.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%2Fjeg1bi8itr7gbp21ks2r.png" alt="Tumblr aesthetics"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, research is always an important first step, there's a lot of different aesthetic quotes and we gotta figure out how much variation we want. Do we wanna cycle through images or just have one? (we are gonna have just 2 bc im lazy). If we are using random images, where are we gonna credit the authors? (i mostly riff of brands and for this I'll just use photos I took, you too can use VSCO on your phone). How do we wanna show the text? italic arial is a classic but if you want a challenge, doing chat bubbles is a cool idea. (we aren't)&lt;/p&gt;

&lt;p&gt;I had a play around in sketch and much to my despair this looks exactly like a normal aesthetic post. there's no joke here, no clever subversion. Just teenage angst. I don't care. We are doing this anyway, you find a way to make the content work on your own:&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F66tsi6tbaherl92v0n5x.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%2F66tsi6tbaherl92v0n5x.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Websites
&lt;/h2&gt;

&lt;p&gt;I have a bit of a confession to make, I got not clue how to make a webpage from scratch, the script and css tags elude me, so let's just copypaste some boilerplate from w3schools into a glitch sandbox because why not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Okay this works&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"/style.css"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/script.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And throw in some CSS for styles:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/*
so we cant actually use real arial! this 
is bc your computer probably has it 
but the remote computer running this doesn't.

what this means is that I went to 
google fonts and picked a look-alike. Close enough!
*/&lt;/span&gt;

&lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="sx"&gt;url('https://fonts.googleapis.com/css?family=Archivo:600i&amp;amp;display=swap')&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/*
  worlds barebonest css reset
  */&lt;/span&gt;
  &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c"&gt;/*this centers our heading*/&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url(https://cdn.glitch.com/15a843df-5327-4b8b-b3ef-ca56f7e35e5e%2F46653054781_f96753b868_o.jpg?v=1576936807505)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;cover&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c"&gt;/*
  vw and vh are viewport units, 
  they are 1/100th the size of the 
  browser window, so using 100 means
  we tell body to fill everything.
  */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#AF9C3E&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"Archivo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;600&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;italic&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c"&gt;/*
  this is a design thing
  */&lt;/span&gt;
  &lt;span class="nl"&gt;text-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;blur&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;.1vw&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c"&gt;/*
  we can use viewport units 
  for font sizes too and this will 
  make them scale with the window!
  */&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5vw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;10vmax&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;And we got something that looks like this (I started this from scratch on glitch. At this point all we really care about is making a stand-alone webpage, we'll 'integrate' it into our 'pipeline' later:&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fnm22jhdnmmenknahzbsy.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%2Fnm22jhdnmmenknahzbsy.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's actually plug some quotes into our JS (&lt;a href="https://gist.github.com/walaura/e046801f71620c8cdbf8097d9169175f" rel="noopener noreferrer"&gt;Get them here&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ALL_STAR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s2"&gt;`Somebody once told me the world is gonna roll me`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;`I ain't the sharpest tool in the shed`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;`...`&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;quote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ALL_STAR&lt;/span&gt;&lt;span class="p"&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;floor&lt;/span&gt;&lt;span class="p"&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;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;ALL_STAR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;quote&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the console.log is actually working let's plug the quote into our heading and see if that works out okay&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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;quote&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;Fun fact!&lt;/em&gt; We can use this oneliner because our script tag is at the end of our &lt;code&gt;index.html&lt;/code&gt;, so the script is not gonna run until the browser has parsed the whole document, meaning at this point it already knows what our elements are.&lt;/p&gt;

&lt;p&gt;Do you know what would be, like, real cool, right now? let's randomise the text color, i'm sick of that yellow already. I'm sure we can do &lt;code&gt;npm i random-color-or-whatever&lt;/code&gt; but let's &lt;em&gt;not&lt;/em&gt; do that because css is awesome when you are only doing websites for the last version of Chrome&lt;/p&gt;

&lt;p&gt;In our CSS, let's switch our color up to use HSL. HSL rules, it stands for hue, saturation, and luminosity and what this means is that if we mess with the hue we get a whole rainbow of colors that all match the mood we are going for, and we can plug the hue as a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties" rel="noopener noreferrer"&gt;css variable&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;...&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--hue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;80%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;53%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="err"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That we then set from our javascript like madmen:&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;$h1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;h1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;$h1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;$h1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--hue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&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;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(The second argument in var(), where we got a 0, is a &lt;em&gt;fallback&lt;/em&gt;. if the CSS parser can't find a variable named &lt;code&gt;--hue&lt;/code&gt; it'll use that value. For this use case it doesn't really matter because this is a closed loop and we know this variable is gonna be put in, but picking up good practices doesn't hurt.&lt;/p&gt;

&lt;p&gt;Let's clean this up and do another for the text transform because omg this is FUN&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;const&lt;/span&gt; &lt;span class="nt"&gt;hue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;Math&lt;/span&gt;&lt;span class="nc"&gt;.random&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="err"&gt;360&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;const&lt;/span&gt; &lt;span class="nt"&gt;textTransform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;Math&lt;/span&gt;&lt;span class="nc"&gt;.random&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;0&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="err"&gt;5&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;"lowercase"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"uppercase"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="nc"&gt;.style.setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;"--hue"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;hue&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="nc"&gt;.style.setProperty&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;"--text-transform"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;textTransform&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might have noticed that our hue thing is mostly working but also we got a problem, when the hue is on the blue range it kinda blends with our background. What's really cool about HSL is that we can sorta fix it? we know that when our hue is around a certain value (i fiddled with the devtools to find out which, if you don't wanna do it, it's 200-300) the luminosity is not enough and it just so happens that we have a luminosity value and it's another number we can mess with.&lt;/p&gt;

&lt;p&gt;We can make something far nicer and maths based here but i don't have paper at hand and also i'm not a fucking nerd so I did this and it works out fine:&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;hue&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;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;360&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;textTransform&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;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lowercase&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;uppercase&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;$h1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--hue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;$h1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--text-transform&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;textTransform&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;hue&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;hue&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;$h1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--lumi&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;80%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And plugged the &lt;code&gt;--lumi&lt;/code&gt; variable in the css&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;...&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--hue&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;80%&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--lumi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;63%&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="err"&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's like a lot you can do with just HTML and CSS to generate images for bots. &lt;a href="https://glitch.com/edit/#!/bot-tutorial-part-3" rel="noopener noreferrer"&gt;Here's what I ended up with&lt;/a&gt;. Try out randomizing other values! If you wanna move your text flexbox is fantastic for that. Other things I've done myself is use 3D transforms or &lt;a href="https://github.com/cool-robot-pals/dril-is-strange/blob/master/web/fetch.js" rel="noopener noreferrer"&gt;play a youtube video in the background to capture stills of it&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's deploy
&lt;/h2&gt;

&lt;p&gt;This is gonna move on to a final fourth part because i'm running out of weekend but let's get this integrated into our bot anyway,&lt;br&gt;
One last thing! Because of annoying things like 'security', or 'progress', or 'chrome being a little bitch' having some static HTML website locally just doesn't cut it for a lot of things, including screenshotting it. You might also wanna scale up your JS to import multiple files or use SASS. Three very straightforward ways to take what we've got and put it on a real URL instead of a file URL:&lt;/p&gt;

&lt;h3&gt;
  
  
  We keep it on glitch and do nothing else
&lt;/h3&gt;

&lt;p&gt;It &lt;em&gt;does&lt;/em&gt; have a URL and this is gonna work - only thing is this is all a bit fragile, normally you want your code yo be a closed system.&lt;/p&gt;

&lt;h3&gt;
  
  
  If it's only static like this we can use &lt;code&gt;serve&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;If you download this stuff as a zip and open a terminal and type &lt;code&gt;npx serve&lt;/code&gt; you will immediately get a localhost url pointing to this folder. This is powered by the &lt;a href="https://www.npmjs.com/package/serve" rel="noopener noreferrer"&gt;serve&lt;/a&gt; NPM package&lt;/p&gt;

&lt;h3&gt;
  
  
  If it's a bit fancy and you want SASS or babel or whatever
&lt;/h3&gt;

&lt;p&gt;Use &lt;a href="https://parceljs.org/" rel="noopener noreferrer"&gt;parcel&lt;/a&gt;. use it like serve (&lt;code&gt;npx parcel watch index.html&lt;/code&gt;). This will also serve your website on a local URL but behind the scenes it's compiling your js and css. You can read the docs to get an idea of the plugins you can use. &lt;a href="https://github.com/cool-robot-pals/getreadyfor" rel="noopener noreferrer"&gt;This is what I do with most of my (newer) bots&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  All set!
&lt;/h2&gt;

&lt;p&gt;Next week we'll use &lt;a href="https://www.npmjs.com/package/puppeteer" rel="noopener noreferrer"&gt;puppeteer&lt;/a&gt; to take an image out of this and link it with the bot. have a good one!&lt;/p&gt;

&lt;p&gt;#twitter&lt;/p&gt;

</description>
      <category>twitter</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>So you want to make a Twitter bot (2/3)</title>
      <dc:creator>Laura buns</dc:creator>
      <pubDate>Sat, 14 Dec 2019 15:03:41 +0000</pubDate>
      <link>https://forem.com/walaura/so-you-want-to-make-a-twitter-bot-2-3-9ba</link>
      <guid>https://forem.com/walaura/so-you-want-to-make-a-twitter-bot-2-3-9ba</guid>
      <description>&lt;p&gt;Hi! You might wanna check &lt;a href="https://dev.to/walaura/so-you-want-to-make-a-twitter-bot-1-3-4nj2"&gt;part 1&lt;/a&gt; first. If you are back from it we left with a bot in a folder in your computer (did you already set up a repo? pls do, if you have skip ahead). We have a working twitter bot and really we could just put it on a timer and that's it, we are good. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kDYxx6b8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--64gi-PTX--/c_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_880/https://thepracticaldev.s3.amazonaws.com/i/odh7h4syaditkb8t20sx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kDYxx6b8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--64gi-PTX--/c_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_880/https://thepracticaldev.s3.amazonaws.com/i/odh7h4syaditkb8t20sx.png" alt='""'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, and you will have had this problem already if you started torrenting movies back in the 2Mb broadband days, you will also wanna turn off your computer at some point. And have the bot still running. The surprisingly uncontrived solution for this is just put it in somebody else's computer (like a website!)&lt;/p&gt;

&lt;p&gt;Doing this is kinda cool because we are still doing a pointless shitposting exercise but we are using industry standard tools for this, which means this is a fantastic way to learn about fancy-ass things like &lt;em&gt;CI&lt;/em&gt; or &lt;em&gt;devops&lt;/em&gt;, or &lt;em&gt;servers&lt;/em&gt;, or &lt;em&gt;deployments&lt;/em&gt;, or &lt;em&gt;containers&lt;/em&gt; all without actually doing any of the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  First things first let's get this into a repository
&lt;/h2&gt;

&lt;p&gt;So, the way code works most of the time is that you will have a &lt;em&gt;repository&lt;/em&gt; (this is like dropbox but for nerds) and then from there services can &lt;em&gt;deploy&lt;/em&gt; it to a &lt;em&gt;server&lt;/em&gt; (this is moving the code to somebody else's computer and getting it to a state where it can run). Sometimes you run it on a different computer first to test it and if that's okay you then deploy it. &lt;br&gt;
In most cases this is all automatic. When your code changes, the repo lets the testing computer know – it will then kick off the tests, and if they all pass then it'll let the deploy computer know to do it's thing. This is called &lt;em&gt;CI&lt;/em&gt; and we are gonna do a very basic version of it (without testing bc we are lazy)&lt;/p&gt;

&lt;p&gt;For this guide we'll be using &lt;a href="https://www.github.com"&gt;GitHub&lt;/a&gt; as a repo and &lt;a href="https://www.heroku.com"&gt;Heroku&lt;/a&gt; as a server. GitHub because it's super popular, and Heroku because it's free. Sign up for both if you haven't. &lt;/p&gt;
&lt;h2&gt;
  
  
  Getting our code ready for open source
&lt;/h2&gt;

&lt;p&gt;So I forgot this on part 1!! You will need a &lt;code&gt;package.json&lt;/code&gt; file to continue. When you were installing &lt;code&gt;twitter&lt;/code&gt; in part 1 you might have gotten an error and a &lt;code&gt;package-lock.json&lt;/code&gt; file was created. This is all good! Think of &lt;code&gt;package.json&lt;/code&gt; as some basic info about your app. What it is, what it does, what dependencies does it have, etc. When we deploy the app we will install it and this file is how the other computer figures out what modules your app needs.&lt;/p&gt;

&lt;p&gt;You can run &lt;code&gt;npm init -y&lt;/code&gt; in the same folder your app is to generate one. Make sure it's adding twitter as a dependency! If it's not, you can run &lt;code&gt;npm i twitter&lt;/code&gt; again to add it.&lt;/p&gt;

&lt;p&gt;Now, as you might remember your code has &lt;em&gt;secrets&lt;/em&gt; in it, the tokens and whatnot.&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Twitter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;consumer_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;314gvas...12kjbh31n2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;consumer_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bd129u...21hjbv3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;access_token_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;89xzcyh...ads&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;access_token_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;98217...gyve98&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;While you can store them on a private repository and call it a day this is a bit limiting. You can also just delete them and add them manually whenever you wanna run the bot? but this is not gonna fly when hosting it on a server, and it's a pain in the ass.&lt;/p&gt;

&lt;p&gt;Like most problems you run in computer science, this is a problem many people have had before and we have a lovely industry standard way to handle secrets called &lt;em&gt;environment variables&lt;/em&gt;.&lt;br&gt;
The gist of it is that most operating systems have this concept of OS-level text-based key-value variables that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the entire computer has access to&lt;/li&gt;
&lt;li&gt;live &lt;em&gt;outside&lt;/em&gt; of your code&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can set these via the terminal, but there's &lt;a href="https://www.npmjs.com/package/dotenv"&gt;this handy little package&lt;/a&gt; on NPM that lets you set them in a file, the idea here is that you don't commit this file, and instead every computer that runs the code (every environment) has its own private and personal copy of these variables.&lt;/p&gt;

&lt;p&gt;Let's try this! Install &lt;a href="https://www.npmjs.com/package/dotenv"&gt;dotenv&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And now let's update our code.&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;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="cm"&gt;/*put this up top*/&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Twitter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;consumer_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;consumer_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;consumer_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;consumer_secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;access_token_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;access_token_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;access_token_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;access_token_secret&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and put our secrets in a &lt;code&gt;.env&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;consumer_key=314gvas...12kjbh31n2
consumer_secret=bd129u...21hjbv3
access_token_key=89xzcyh...ads
access_token_secret=98217...gyve98
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Give tweeting (&lt;code&gt;node index.js&lt;/code&gt;) a go just to make sure everything still works!&lt;/p&gt;

&lt;p&gt;if it doesn't (shit happens, it's okay) try &lt;code&gt;console.log(process.env)&lt;/code&gt; to check if your variables are in there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Okay, now back to git
&lt;/h2&gt;

&lt;p&gt;GitHub has an amazing &lt;a href="https://desktop.github.com/"&gt;desktop app&lt;/a&gt; that lets you get away with not using the command line and makes the dropbox comparison very fair. use it and create a repository.&lt;/p&gt;

&lt;p&gt;You may be asked about creating a &lt;code&gt;.gitignore&lt;/code&gt;. This file lists directories and files you don't wanna commit to source control. it's where you can put stuff like &lt;code&gt;node_modules&lt;/code&gt; or &lt;code&gt;.env&lt;/code&gt;. Files here will be effectively invisible to git.&lt;/p&gt;

&lt;p&gt;If you are asked to create one choose &lt;code&gt;node&lt;/code&gt;, if you aren't, let's make one. in both cases, let's make sure to add our &lt;code&gt;.env&lt;/code&gt; to it:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;And now you wanna &lt;em&gt;commit&lt;/em&gt; and &lt;em&gt;push&lt;/em&gt; your code. There's this concept of &lt;em&gt;branches&lt;/em&gt; that we are not gonna get into. &lt;code&gt;master&lt;/code&gt; is considered the &lt;em&gt;main&lt;/em&gt; branch (v problematic, sorry) and you can branch out if you wanna do some work that is gonna take a while and it's not ready to just go into the prime time. you can then &lt;em&gt;merge&lt;/em&gt; your branch back to &lt;code&gt;master&lt;/code&gt;. In any case, push to &lt;code&gt;master&lt;/code&gt; for now.&lt;/p&gt;

&lt;p&gt;You wanna end up with something like &lt;a href="https://github.com/cool-robot-pals/british-wourds"&gt;this&lt;/a&gt;, if you see a &lt;code&gt;package.json&lt;/code&gt; at the top level you got this!&lt;/p&gt;

&lt;h2&gt;
  
  
  Coffee break
&lt;/h2&gt;

&lt;p&gt;Not for &lt;em&gt;you&lt;/em&gt; lol for me, i've been hiding in an office corner typing this for the last hour, gonna go replenish. I'm not actually having coffee, i have this whole thing about not drinking calories, not the point. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Okay&lt;/strong&gt; So at this point we got our code at a point where it's &lt;em&gt;deployable&lt;/em&gt;. This means that we can automate the steps required to get it to download and run in a fresh computer, which is what we are gonna be up to next.&lt;/p&gt;

&lt;h2&gt;
  
  
  Heroku time!
&lt;/h2&gt;

&lt;p&gt;let's get into the Heroku dashboard and just like with the twitter API, we gotta create an &lt;em&gt;app&lt;/em&gt; here. After doing that you'll notice there's a bunch of stuff (by the way, if you are skimming through, you can sync Heroku with dropbox instead of github! You can do that instead of everything in the previous steps)&lt;/p&gt;

&lt;p&gt;The steps here are straightforward too, get our app into Heroku, put the environment variables in, give it a try, then finally set a timer to tweet for us and forget about it.&lt;br&gt;
(We can also put the environment variables first but where's the fun in THAT)&lt;/p&gt;

&lt;p&gt;At the time of writing the top navigation bar should have a literal 'deployments' button, and going there will get you to a page where you can sync with a GitHub repo. Connect yours and you are done. Just one more thing! there's a checkbox that lets you redeploy every time you push changes, you probably wanna tick this too. It's good practice to have your master branch in your repo in sync with the deployed code.&lt;/p&gt;

&lt;p&gt;Now heroku is downloading our code and trying to install it in the background. Exciting! You can check the progress in the "Activity" tab.&lt;/p&gt;

&lt;p&gt;While that's going let's throw in some variables! Again at the time of writing you can find 'em on settings, and you'll see that they follow the same key=value structure that we have in our &lt;code&gt;.env&lt;/code&gt; file. Add all of them and save.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H7Vxt7B2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/uq4qagmzw1do1xttkiu0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H7Vxt7B2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/uq4qagmzw1do1xttkiu0.png" alt="The Heroku console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Buildpacks lol
&lt;/h3&gt;

&lt;p&gt;If you have been keeping an eye on your deploy you'll have notice it has failed. That's because we are using node, and Heroku just gives us a barebones OS. To fix it you can add 'buildpacks' they call them in the Settings page. This is just a collection of preinstalled software. Add the one for &lt;code&gt;nodejs&lt;/code&gt; and try deploying again. This one should work!!!&lt;/p&gt;

&lt;p&gt;to quickly test if everything is in order you can open a console from the 'more' menu. This lets you run terminal commands on the remote computer, so you can do &lt;code&gt;node index.js&lt;/code&gt; just like you did in yours. Except this time it's all in the cloud. Did you get a tweet out? Please tell me you got a tweet out.&lt;/p&gt;

&lt;p&gt;If all is good this is pretty cool because this is how you deploy &lt;em&gt;anything&lt;/em&gt; not just twitter bots. You could make a website on &lt;a href="https://netlify.com"&gt;Netlify&lt;/a&gt; or dip your toes in CI with &lt;a href="https://travis-ci.org/"&gt;Travis&lt;/a&gt; if you wanted.&lt;/p&gt;

&lt;h3&gt;
  
  
  A fancy egg timer
&lt;/h3&gt;

&lt;p&gt;Now, we sure have wasted a lot of time but we haven't fixed the problem we were trying to fix where we want the thing to run on its own lol. Heroku has this concept of &lt;a href="https://elements.heroku.com/addons"&gt;addons&lt;/a&gt; and what you can do is install the &lt;a href="https://elements.heroku.com/addons/scheduler"&gt;scheduler&lt;/a&gt;, which runs console commands at set times.&lt;/p&gt;

&lt;p&gt;After adding it to your app all that's left to do is configuring it to post &lt;code&gt;node tweet.js&lt;/code&gt; as much as you wanna. if you have trust issues (like me) you can also install &lt;a href="https://elements.heroku.com/addons/papertrail"&gt;papertrail&lt;/a&gt;. This will let you see the logs for what your scheduler is doing and in the case your bot isn't posting, help you figure out why!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HwiCs5FD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/blrjsgt1tv8wo5trvm3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HwiCs5FD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/blrjsgt1tv8wo5trvm3w.png" alt='""'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Woo!!
&lt;/h2&gt;

&lt;p&gt;In the next part we are gonna make the bot actually funny. or not, but we are gonna go over some of the tools I use myself to make the actual bots. We'll be going through stuff like randomising posts as well as doing PICTURES.&lt;/p&gt;

&lt;h1&gt;
  
  
  twitter
&lt;/h1&gt;

</description>
      <category>twitter</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>So you want to make a Twitter bot (1/3)</title>
      <dc:creator>Laura buns</dc:creator>
      <pubDate>Sat, 07 Dec 2019 12:01:24 +0000</pubDate>
      <link>https://forem.com/walaura/so-you-want-to-make-a-twitter-bot-1-3-4nj2</link>
      <guid>https://forem.com/walaura/so-you-want-to-make-a-twitter-bot-1-3-4nj2</guid>
      <description>&lt;p&gt;One of my hobbies is creating twitter bots, you might be familiar with &lt;a href="https://twitter.com/fakefantas"&gt;@fakefantas&lt;/a&gt; for example? if you aren't that's okay that's not the point. The point is that sometimes people ask me how to do these, and I love talking about this because on paper there's a lot of complexity involved but when you break it down into parts it's pretty manageable!&lt;/p&gt;

&lt;p&gt;(Most of my bots just tweet random stuff on a timer, this means they don't listen to replies or know what they posted before. This helps a lot with complexity but hopefully by the end of this series you'll be able to work out how to add this)&lt;/p&gt;

&lt;p&gt;Bots are a cool 'problem' to solve because they sound daunting at first, it's a lot to take in! However when you break the problem into smaller problems now you got a lot to take in but also you gotta take it in 3 times. PROGRESS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--64gi-PTX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/odh7h4syaditkb8t20sx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--64gi-PTX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/odh7h4syaditkb8t20sx.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When it comes to bots, you have a part that's creating the content. This part takes thin air and produces content. This is hard because you gotta be funny but also sometimes you'll want images or even video, and we gotta automate THAT somehow I normally use I normally use &lt;a href="https://www.npmjs.com/package/puppeteer"&gt;puppeteer&lt;/a&gt;. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You then have a second part that takes your content and turns it into a tweet that shows up on twitter.com. This is hard because backend development and API keys are b🔥ll👎sh🙅‍♀️t but thankfully what we are doing is a pretty textbook example. &lt;/li&gt;
&lt;li&gt;There's a third part where we deploy this to somebody else's computer and have it run automatically, instead of us doing the work I use &lt;a href="https://www.heroku.com"&gt;Heroku&lt;/a&gt;. for this but something like Glitch can work out fine too!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On this first tutorial I wanna focus on the second part. (bc i can't count) We are gonna create our app on &lt;a href="https://glitch.com/create"&gt;Glitch&lt;/a&gt;and by the end of this we are gonna be able to type &lt;code&gt;npm run tweet&lt;/code&gt; and see the thing pop on our screenies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A thing!&lt;/strong&gt; We are using Glitch to avoid setting up Node locally, but it effectively hosts and deploys our code so it can do a lot of the third step for us. I personally use GitHub+Heroku because they give me more robust tools around collaboration and scheduling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tweeting &lt;em&gt;something&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Let's start with the basics, let's make a JS function that gives us the day of the week, we are gonna ignore timezones because thats not the point today and not make it any more complicated than it has to be.&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="cm"&gt;/*tweet.js*/&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;weekdays&lt;/span&gt; &lt;span class="o"&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;Sunday&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/*america wtf*/&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Monday&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;Tuesday&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;Wednesday&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;Thursday&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;Friday&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;Saturday&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;tweet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&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="s2"&gt;`Wooo todays a &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;weekdays&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;getDay&lt;/span&gt;&lt;span class="p"&gt;()]}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tweet&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if you run &lt;code&gt;node ./tweet.js&lt;/code&gt; (and it's a Saturday) you'll now get &lt;code&gt;Wooo todays a 6&lt;/code&gt;. Once you're happy, one final thing is that console logging rules for debugging while we make a file but when we are done this will have to be part of a larger system, so let's export &lt;code&gt;tweet&lt;/code&gt; instead! We'll import it later. Feel free to make any changes, all we really care about here is that calling &lt;code&gt;tweet()&lt;/code&gt; gives us a text under 280 characters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- console.log(tweet());
&lt;/span&gt;&lt;span class="gi"&gt;+ module.exports = tweet;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;leave that to sit in your kitchen counter (or wherever you code) and let's focus our attention on becoming a Twitter developer:&lt;/p&gt;

&lt;h2&gt;
  
  
  Making a Twitter app
&lt;/h2&gt;

&lt;p&gt;We will wanna create an 'app' in &lt;a href="https://dev.twitter.com"&gt;dev.twitter.com&lt;/a&gt; If you click around you will see that Twitter has really lost its cool over time about this. Now luckily our use case is still covered.&lt;/p&gt;

&lt;p&gt;The developer console is always changing over time as Twitter becomes less of a quirky website and more and more of a soul crushing direct competitor to NBCUniversal but the core concept is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aZEPSW7D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/b1qvmzrzyb6g6lsr97x1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aZEPSW7D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/b1qvmzrzyb6g6lsr97x1.png" alt="Screenshot of the twitter developer site showing a roadblock"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need an 'access token' (and secret). These tell twitter what user is posting to it (instead of a username/password combo)&lt;/li&gt;
&lt;li&gt;To get the access token you need to make an app that will have a 'consumer key' (and secret). This tells twitter what 'app' is posting to it (instead of a users browser). Four keys total. All good things come in pairs. &lt;/li&gt;
&lt;li&gt;To obtain your consumer key/secret you wanna create a 'twitter app'. As of the time of writing, after creating an app twitter will conveniently give you the access token/keys for your current account which is hella nice&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Find that 'create app button', click through and fill out the form. Do whatever song and dance Twitter requires you to do and by the end you should be able to find a page with your tokens:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rhxya44C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/q92v9h9ic04gsqswo19r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rhxya44C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/q92v9h9ic04gsqswo19r.png" alt="Screenshot of the page with the tokens. In this case they are on the app settings under the 'keys and tokens' section."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt; These tokens are like your password and grant anybody with all four of them access to your Twitter account. Treat them carefully!!&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's go back to coding
&lt;/h2&gt;

&lt;p&gt;If you had a bit of a wander around the twitter developers site you'll see there's hella detailed documentation for how to post to twitter and make authenticated requests and a bunch of other stuff. Now, something I love about using node (and that my ex that was more into reinventing wheels than into driving hated) is that somebody else has &lt;a href="https://www.npmjs.com/package/twitter"&gt;already done our job for us&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Have a read through the page for the &lt;code&gt;twitter&lt;/code&gt; package and you'll see that we already got authentication (our 4 tokens!) covered all the way at the top and tweeting a bit below, will it work? let's &lt;code&gt;npm i twitter&lt;/code&gt; and find out!&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="cm"&gt;/*index.js*/&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Twitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;twitter&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Twitter&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;consumer_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;314gvas...12kjbh31n2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;consumer_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bd129u...21hjbv3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;access_token_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;89xzcyh...ads&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;access_token_secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;98217...gyve98&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;statuses/update&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="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bananas lol&lt;/span&gt;&lt;span class="dl"&gt;"&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;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;tweet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;yay!&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We aren't using our &lt;code&gt;tweet()&lt;/code&gt; function yet because it's always good to test parts in isolation first. Imagine this didn't work. is the problem here or in &lt;code&gt;tweet.js&lt;/code&gt;? Nobody knows, it's chaos. Making things as small as possible helps you find bugs faster.&lt;/p&gt;

&lt;p&gt;Having that said, in this case we will hopefully get lucky and this is gonna work out of the box! Try running &lt;code&gt;node index.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lcPMo7Qa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/5r6fsaiz7dp384ytfycm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lcPMo7Qa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/5r6fsaiz7dp384ytfycm.png" alt="'Bananas lol' posted on Twitter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This got 2 likes before i deleted it i shit you not. Okay, time for a trial by fire! let's plug in our &lt;code&gt;tweet()&lt;/code&gt; function&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="cm"&gt;/*don't forget to import this at the top!!*/&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tweet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./tweet.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/*and keep the authentication stuff in the middle the same*/&lt;/span&gt;
&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;statuses/update&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="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tweet&lt;/span&gt;&lt;span class="p"&gt;()&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;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;tweet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;response&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;yay!&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LqtMpnk7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/o1w8e82p50iez6akjh3l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LqtMpnk7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/o1w8e82p50iez6akjh3l.png" alt="'Woooo its a Saturday posted on Twitter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(Goes without saying, you will wanna use your bot account, not your own account) but the larger point is &lt;strong&gt;we did it&lt;/strong&gt;!!!!!&lt;br&gt;
In part 2 we will be moving this from our computer to &lt;a href="https://www.heroku.com"&gt;Heroku&lt;/a&gt; and setting it up so it tweets every hour or whatever. In the meantime, why not come up with a funnier &lt;code&gt;tweet()&lt;/code&gt; function?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V5GRwR_4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/874l65epmjsted0rg8zj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V5GRwR_4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/874l65epmjsted0rg8zj.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lost?&lt;/strong&gt; here's what we've got so far &lt;a href="https://glitch.com/edit/#!/bot-tutorial-part-1"&gt;on glitch&lt;/a&gt;. You'll notice that instead of using the tokens straight up I'm using this thing called &lt;code&gt;process.env&lt;/code&gt;. As I said before you don't wanna reveal your tokens! Not even in code!! &lt;/p&gt;

&lt;p&gt;We'll go into detail about this in &lt;a href="https://dev.to/walaura/so-you-want-to-make-a-twitter-bot-2-3-9ba"&gt;part 2&lt;/a&gt; too but for now either don't let your code leave your computer or use something like &lt;a href="https://www.npmjs.com/package/dotenv"&gt;dotenv&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>twitter</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The web without the web</title>
      <dc:creator>Laura buns</dc:creator>
      <pubDate>Thu, 01 Aug 2019 12:43:56 +0000</pubDate>
      <link>https://forem.com/walaura/the-web-without-the-web-aeo</link>
      <guid>https://forem.com/walaura/the-web-without-the-web-aeo</guid>
      <description>&lt;h1&gt;
  
  
  1.
&lt;/h1&gt;

&lt;p&gt;I built my first website when I was 14? It was a fansite for the Sims. It used tables and the colours wouldn't pass any accessibility (or aesthetics, for that matter) checklist. If I remember correctly it was a combination of making the visuals in dreamweaver to then copy/paste the generated HTML and CSS into a PHP backend that I made myself (you can imagine how that looked on the inside).&lt;/p&gt;

&lt;p&gt;This was a very important website not just because it somehow got relatively popular but it was also important for me as it became my personal playground. I taught myself CSS to make the layout nicer, and in the process I picked up enough design skills to be employed as a designer for 4 years. I started doing banners and animations using Flash (from macromedia back then!). &lt;/p&gt;

&lt;p&gt;The web 2.0 era arrived shortly after and I started hacking together mooFx scripts to make things move and be cool. I wasn't entirely sure about what was going on in my code and I missed to PHP standard library dearly but I powered through. Eventually picked up jQuery and for a buncha years that was all my understanding of the DOM really. &lt;/p&gt;

&lt;p&gt;I learned more about HTML and CSS. I learned how to write semantic and accessible code. I learned how to scale up CSS architectures to prevent spaghetti code.&lt;/p&gt;

&lt;p&gt;For a while I had this personal website that was like a Mario World stage and everything moved and it used CSS animation and some JS sprinkles to add infinite clouds and stuff.&lt;/p&gt;

&lt;p&gt;I fell in love with all the cool shit I could build. &lt;/p&gt;

&lt;center&gt;

![](https://thepracticaldev.s3.amazonaws.com/i/ha6dim4gjonlx8ed3g6m.gif)

&lt;/center&gt;

&lt;h1&gt;
  
  
  2.
&lt;/h1&gt;

&lt;p&gt;I eventually became a somewhat respected frontend 'engineer'. I do talks and stuff. LinkedIn recruiters actually put effort in their greeting messages. It rules. I'm just bragging at this point. Stop me.&lt;/p&gt;

&lt;p&gt;Now, despite all this you may have noticed I'm missing a lot of things from my intro to an engineering career. &lt;/p&gt;

&lt;p&gt;I'm not really sure how functions map to mathematical constructs. I actually dropped out of maths when we started doing that algebra where instead of equality you deal with stuff like &lt;code&gt;2*n &amp;gt; x/3&lt;/code&gt; and you have to find out what range &lt;code&gt;n&lt;/code&gt; and &lt;code&gt;x&lt;/code&gt; are (I have no idea if this particular one is solvable, I just came up with it)&lt;/p&gt;

&lt;p&gt;I'm still just wrapping my head around the more complicated types you can do in stuff like typescript. For what is worth I don't use types in personal projects. I think they are good for making code self documenting and thus, good for teams. Too abstract though.&lt;/p&gt;

&lt;p&gt;For a long time I never used any real frameworks for web development. I totally slid past the angular and ember era because I considered unacceptable to have a site not work without JS enabled. Writing your entire frontend in javascript felt incredibly unnecessary when we have semantic HTML.&lt;/p&gt;

&lt;center&gt;

![](https://thepracticaldev.s3.amazonaws.com/i/l2ejqlhzv58drpkmu5ep.jpg)

&lt;/center&gt;

&lt;h1&gt;
  
  
  3.
&lt;/h1&gt;

&lt;p&gt;I love React. I love React because I know enough about scaling up HTML and CSS that I understand the value of single file components. I like the way CSS-in-JS gives you the enough abstraction to still use tricks like blind owl selectors while also giving you the full power of using JS to do stuff like container queries. I love how server side rendering React apps is trivial because it all compiles down to vanilla HTML rather than web components, effectively turning it into a kickass template engine that can come alive. I love the way you can very effectively still do progressive enhancement by using completely semantic markup and then letting hydration do more to it.&lt;/p&gt;

&lt;p&gt;I also hate React. I hate React because these behaviours are not defaults. React is not gonna warn you if you make a form using divs and unlabelled textboxes and send the whole thing to a server. I hate React because CSS-in-JS approaches by default encourage you to write completely self contained one off components rather than trying to build a website UI up as a whole. I hate the way server side rendering and progressive enhancement are not defaults, but rather things you have to go out of your way to do.&lt;/p&gt;

&lt;p&gt;But what I hate the most about React is that it paves over the land of HTML, CSS, and JS progressively layering on top of each other and replaces it with 'efficient' and 'clean' code.&lt;br&gt;
Compared to vanilla HTML it's very easy to add type checking to a React app to really make sure you can't accidentally add &lt;code&gt;"12" + "8"&lt;/code&gt; because how else would you know you aren't getting 20 here. By running your app? Absurd. It's also very easy to automate tests by taking component snapshots and effectively freezing them in time, evolving CSS layouts be dammed. With CSS-in-JS you can ignore those pesky CSS behaviours like the cascade. It's not like it's the first letter in the name or anything.&lt;br&gt;
Not having that much first class DOM manipulation and a mandatory build step anyway means engineers can finally start paving over the ugly duckling and liability that is javascript for other languages, based on the purity and elegance of mathematics, like Elm or Reason.&lt;/p&gt;

&lt;p&gt;Some people think these are good things. Other people think they are a masturbatory exercise in service of nerds finding actually coding websites too boring and needing to spice it up.&lt;/p&gt;

&lt;center&gt;

![](https://thepracticaldev.s3.amazonaws.com/i/4d74ecz0wvl2qx4fiu1x.jpg)

&lt;/center&gt;

&lt;h1&gt;
  
  
  4.
&lt;/h1&gt;

&lt;p&gt;I'm a surprisingly fast learner. I have caught up. I know my stuff around all this shit. I'm also a bit of a rarity. The best frontend developers I know are at a complete loss right now. &lt;/p&gt;

&lt;p&gt;Most modern frontend codebases are no longer about HTML and CSS. In fact they are so far removed from it that the idk 20? people total who still care about HTML and CSS and can code websites and haven't become product designers or whatever have no clue where to even start.&lt;/p&gt;

&lt;p&gt;Our 'clean' and 'elegant' frontends are now often more clean in the back than in the front now. Our perfectly typed 20 file redux store supporting a form that doesn't work with javascript off. Our CSS-in-JS modules with typed props hiding spaghetti CSS with completely static props as an implementation detail. &lt;/p&gt;

&lt;p&gt;We are building toilets with world-class plumbing that people can't then sit on. And the people who know how to fix the toilets have no clue how to fit a toilet into our plumbing.&lt;/p&gt;

&lt;p&gt;The designer that knows CSS can't update some colours in GitHub without breaking half of the tests. The Product manager can't replace a bunch of words in a page without figuring out the PropTypes of the map component. The accessibility expert can't replace &lt;code&gt;divs&lt;/code&gt; with &lt;code&gt;buttons&lt;/code&gt; because the visual regression testing says that Opera mini in Windows Phone 6.5 renders a border about them and we can't merge changes until it all goes green. The frontend dev can't implement an accordion (honestly, that one might be for the best) because the guy who's super into types won't let her store state outside of redux.&lt;/p&gt;

&lt;p&gt;In elevating frontend to the land of Serious Code we have not just made things incredibly over-engineered but we have also set fire to all the ladders that we used to get up here in the first place.&lt;/p&gt;

&lt;center&gt;

![](https://thepracticaldev.s3.amazonaws.com/i/j9bo057dlq3hm1t189a9.png)

&lt;/center&gt;

&lt;h1&gt;
  
  
  5
&lt;/h1&gt;

&lt;p&gt;I think a lot about how I started coding. About how I developed an understanding of the web. It was wild. I didn't touch code for ages while still making cool websites. We just made things work. &lt;br&gt;
The web, by design, always has had a bit of 'best effort' sprinkled all over it. You would make your HTML accessible and semantic and then write your CSS in a resilient way so when it inevitably breaks in a different/older browser the page still works. And then you sprinkle your javascript on top and if it doesn't work? That's fine because it's not required to function. It's icing on the cake.&lt;/p&gt;

&lt;p&gt;I love React because it lets me do my best work faster and more easily. I hate React because the culture around it more than the library itself actively prevents other people from doing their best work.&lt;/p&gt;

&lt;center&gt;

![](https://thepracticaldev.s3.amazonaws.com/i/pmbz29o37bmccm191j67.png)

&lt;/center&gt;

</description>
    </item>
    <item>
      <title>I picked up React Native as a web developer and here's what I've learned</title>
      <dc:creator>Laura buns</dc:creator>
      <pubDate>Sun, 09 Jun 2019 13:43:09 +0000</pubDate>
      <link>https://forem.com/walaura/i-picked-up-react-native-as-a-web-developer-and-here-s-what-i-ve-learned-59h6</link>
      <guid>https://forem.com/walaura/i-picked-up-react-native-as-a-web-developer-and-here-s-what-i-ve-learned-59h6</guid>
      <description>&lt;p&gt;For the last couple weeks, I've been building a React native app at &lt;a href="https://gu.com" rel="noopener noreferrer"&gt;work&lt;/a&gt;. It's a news reader (duh) and a bit of a monster at that, with filesystem access, background downloads, and push notifications. &lt;/p&gt;

&lt;p&gt;This wasn't my first time using React but!! It was my first time using RN. Which is scary because new things are scary. It's been a great experience though, and I'm kinda waiting for an 'OH S**T' moment where something unexpected goes horribly wrong – but so far it's been ridiculously fun.&lt;/p&gt;

&lt;p&gt;Why React native? Well, my team originally wanted a web app! (a PWA, they are all the rage now) We changed course for three key reasons: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Despite web being a 'nice to have' our first market was app stores&lt;/li&gt;
&lt;li&gt;We wanted it to have very elaborate offline &amp;amp; background functionality. This is very early &amp;amp; experimental on web but a solved issue on mobile apps since day one.&lt;/li&gt;
&lt;li&gt;We wanted to deliver a native-like experience. Think 60fps animations, multiple stacked views, the works. These are solved problems in the app world too but on the web we are on our own.&lt;/li&gt;
&lt;li&gt;With &lt;code&gt;react-native-web&lt;/code&gt; &lt;a href="https://github.com/necolas/react-native-web" rel="noopener noreferrer"&gt;we have a path&lt;/a&gt; to turn this back into a PWA if needed&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  It's not the web
&lt;/h2&gt;

&lt;p&gt;On the web, plain React eventually generates an HTML-based website. This is how you can use CSS and directly call DOM functions on your components.&lt;/p&gt;

&lt;p&gt;Native is a bit of a different beast. Despite using React's syntax – and unlike libraries like Cordova – RN never gives you HTML, or DOM Elements or CSS, but rather orchestrates native views directly on your mobile OS. This is pretty awesome because it means your UI is truly native. Sure, it's being assembled on the fly using javascript but it's using the same set of blocks the rest of apps are using.&lt;/p&gt;

&lt;p&gt;How different is this from standard React? Not a lot to be honest. The primitives are &lt;a href="https://facebook.github.io/react-native/docs/getting-started.html" rel="noopener noreferrer"&gt;pretty similar&lt;/a&gt;!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="cm"&gt;/*react web*/&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nc"&gt;Counter &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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'row'&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Add number&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="cm"&gt;/*react native*/&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nc"&gt;Counter &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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;row&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Add number&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Using native UI not only makes your app a better citizen but also it's, like, &lt;em&gt;fast&lt;/em&gt;. If you are used to struggling to get 60 fps animations on the web this is a whole new world where you just &lt;em&gt;get that&lt;/em&gt;. For free! even on old as heck devices! (More on performance in a second part)&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%2Fmedia0.giphy.com%2Fmedia%2FDjEysmrFX7S8w%2Fgiphy.gif%3Fcid%3D790b76115cfba11a516c764845cde8a3%26rid%3Dgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmedia0.giphy.com%2Fmedia%2FDjEysmrFX7S8w%2Fgiphy.gif%3Fcid%3D790b76115cfba11a516c764845cde8a3%26rid%3Dgiphy.gif" alt="aladdin scene with the carpet and the whole new world song"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By the way! You don't get all the semantic element niceness from HTML5 in here either. Almost everything in RN is a &lt;code&gt;View&lt;/code&gt;. This means it's &lt;a href="https://facebook.github.io/react-native/docs/accessibility" rel="noopener noreferrer"&gt;super important&lt;/a&gt; to mark up the semantic purpose of your views for a11y purposes. You can use &lt;code&gt;accessibilityRole&lt;/code&gt; to do that. If you need alt text, &lt;code&gt;accessibilityLabel&lt;/code&gt; has you covered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;I had some incredibly basic Xcode experience from doing prototypes eons ago (back then xcode looked like itunes? it was a weird time) but anyway I kinda knew what to expect compared to the web – faster apps, but a slower dev cycle with harder to use devtools.&lt;/p&gt;

&lt;p&gt;_&lt;br&gt;
i &lt;br&gt;
was&lt;br&gt;
so &lt;br&gt;
wrong&lt;br&gt;
_&lt;/p&gt;

&lt;p&gt;First of all, if you just wanna dip your toes in the native waters you don't need any of this, you can use &lt;a href="https://expo.io" rel="noopener noreferrer"&gt;expo&lt;/a&gt; to run your javascript and handle all the app-y bits. This gives you significantly less control over the app bits on your app but what's pretty cool is that all your code is still vanilla React. If you ever need that control you can just &lt;code&gt;expo eject&lt;/code&gt; at any point and get your raw Xcode and android studio projects.&lt;/p&gt;

&lt;p&gt;Even after you eject, you still won't be using Xcode or Android studio for the most part (unless you wanna). &lt;code&gt;react-native run-ios&lt;/code&gt; will fire up a simulated iPhone X and run your app, and &lt;code&gt;react-native run-android&lt;/code&gt; will install it directly to your phone that you only meant to charge but it's fine I guess now you've got an app on your phone.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://facebook.github.io/react-native/docs/getting-started.html" rel="noopener noreferrer"&gt;react docs on setting up Android Studio&lt;/a&gt; are pretty good. When it comes to iOS, code signing your app is a &lt;a href="https://facebook.github.io/react-native/docs/running-on-device" rel="noopener noreferrer"&gt;bit of a pain&lt;/a&gt; – you need to do this before running it on a iOS device. You don't need to be a paid member of the apple developer program to do this but you need to be signed in into Xcode. What i normally do is try to compile it, click on everything red, and click the 'Fix issue' buttons until there are no more issues.&lt;/p&gt;

&lt;p&gt;Finally, when running your app you can shake your device or simulator to get a pretty cool debug menu. You can hot reload code just like on the web, run the chrome devtools to hunt for bugs, or even open up the worlds cutest little inspector:&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fcehwgjjo5v5hebg25igf.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%2Fcehwgjjo5v5hebg25igf.png" alt="inspector screenshot. it's tiny"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Styling
&lt;/h2&gt;

&lt;p&gt;You will probably want to style your app. Unless you are making a todo list or whatever you will probably want to style your app &lt;em&gt;a lot&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;React native comes with a built in &lt;code&gt;StyleSheet&lt;/code&gt; module. it handles styling for you. This rules because you don't have to argue ever again about what css-in-js solution to use. It's also bad because &lt;code&gt;StyleSheet&lt;/code&gt; is &lt;em&gt;so similar&lt;/em&gt; to CSS you might think you are writing CSS but the similarities are only surface deep.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&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="nx"&gt;StyleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;button&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;999&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tomato&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;paddingHorizontal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;textTransform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uppercase&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Touchable&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;button&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Touchable&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The built in documentation on how to style things is &lt;a href="https://facebook.github.io/react-native/docs/0.59/flexbox" rel="noopener noreferrer"&gt;very good&lt;/a&gt; but I wanna get into the big changes first&lt;/p&gt;

&lt;h3&gt;
  
  
  It's pretty much like css-in-js
&lt;/h3&gt;

&lt;p&gt;Your styles are a javascript object with camelcase properties. If you have used &lt;code&gt;emotion&lt;/code&gt; or &lt;code&gt;styled-components&lt;/code&gt; you'll feel right at home with this way of working&lt;/p&gt;

&lt;h3&gt;
  
  
  Chonky pixels
&lt;/h3&gt;

&lt;p&gt;Most phone screens are pretty dense and scale up their UI so, as a unit, &lt;code&gt;1px&lt;/code&gt; is &lt;em&gt;a lot&lt;/em&gt; and pretty big looking for borders. You can use &lt;code&gt;StyleSheet.hairlineWidth&lt;/code&gt; to get the size of 1 screen pixel across devices. &lt;/p&gt;

&lt;h3&gt;
  
  
  But everything is a flexbox
&lt;/h3&gt;

&lt;p&gt;Since all &lt;code&gt;StyleSheet&lt;/code&gt; does is talk to the underlying OS you are restricted in ways you can layout compared to CSS. If you want to float something (For example to wrap an image to the side of some text) you are completely out of luck. Same goes for using CSS grid!&lt;/p&gt;

&lt;p&gt;You have a magical &lt;code&gt;flex&lt;/code&gt; property that consolidates &lt;code&gt;flexGrow&lt;/code&gt;, &lt;code&gt;flexShrink&lt;/code&gt; and &lt;code&gt;flexBasis&lt;/code&gt; into a single number. I have no idea how to use this. &lt;a href="https://mobile.twitter.com/nikkitaftw" rel="noopener noreferrer"&gt;@NikkitaFTW&lt;/a&gt; calls it 'backwards flex'. She has no idea how to use it either.&lt;/p&gt;

&lt;h3&gt;
  
  
  So you can't float things
&lt;/h3&gt;

&lt;p&gt;Ours is quite a special case but since our app had to render very type-heavy articles. To fix this we decided to render the body of the article in a webview and put that inside our React native app. This felt wrong and counter intuitive since "it's all javascript anyway" but it's important to always use the best tool for the job and the web was built to render documents!&lt;/p&gt;

&lt;h3&gt;
  
  
  Or debug layouts 😰
&lt;/h3&gt;

&lt;p&gt;Remember when you had to start coloring divs red to see where your layout had issues? Get ready for some NOSTALGIA. RN does offer a built in inspector but because it's inside the simulator (or inside your phone) it's kind of a hassle to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  And there's no cascade or selectors
&lt;/h3&gt;

&lt;p&gt;You apply your styles directly to your components. You can't style children based on their type or have things like &lt;code&gt;hover&lt;/code&gt; or &lt;code&gt;disabled&lt;/code&gt; states or &lt;code&gt;:before / :after&lt;/code&gt; pseuds.&lt;/p&gt;

&lt;p&gt;This sounds super limiting but in reality having a well architected and modular app with small components will take care of &lt;em&gt;a lot&lt;/em&gt; of this for you. &lt;/p&gt;

&lt;p&gt;None of your styles cascade, this can make your CSS more predictable but also a bit of a pain. We remediated this by using react context to encapsulate style properties we wanted to cascade down like theme colors. Context is ideal for this because you can have multiple contexts in the same screen for different nodes, almost working like css variables.&lt;/p&gt;

&lt;p&gt;This is a bit of an oversimplification (we've got a useAppearance() hook that returns the values directly) but you get the idea:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="cm"&gt;/*
in your appearance file
*/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appearances&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fff&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="na"&gt;light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#000&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AppearanceContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;- that's the default!&lt;/span&gt;


&lt;span class="cm"&gt;/*
in your view
*/&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AppearanceContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;I'm dark!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="na"&gt;AppearanceContext&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="na"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AppearanceContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;I'm light!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;AppearanceContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;


/*
in your component
*/
(...) =&amp;gt; &lt;span class="si"&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;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;appearances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;AppearanceContext&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;View&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="si"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The loss of the cascade is not that big of a deal as it might seem except for a single but very important use case:&lt;/p&gt;

&lt;h3&gt;
  
  
  Text
&lt;/h3&gt;

&lt;p&gt;All text you want to render in React native has to be &lt;code&gt;&amp;lt;Text&amp;gt;Wrapped in a text tag&amp;lt;/Text&amp;gt;&lt;/code&gt; and it will display in the system font at 16px.&lt;/p&gt;

&lt;p&gt;You can of course style your text to have any font and size you wanna, but text comes so many shapes and sizes that you should be prepared to have a ton of variations. In our app we ended up having a single file for all our styled text elements but I'm not sure this is the best structure.&lt;/p&gt;

&lt;p&gt;When it comes to fonts you'll probably wanna use custom fonts! Especially now that all apps are white on black with a bunch of lines and there is literally no other way than type to tell them apart. Good news first, you don't have to deal with &lt;code&gt;@font-face&lt;/code&gt; rules which is pretty neat!&lt;/p&gt;

&lt;p&gt;Sadly everything else &lt;a href="https://medium.com/@mehran.khan/ultimate-guide-to-use-custom-fonts-in-react-native-77fcdf859cf4" rel="noopener noreferrer"&gt;is pain&lt;/a&gt;. Your fonts will live duplicated inside your Android and iOS projects and here's where it gets hairy: To use a font in Android you will reference its filename, to use it on iOS you will reference its Postscript name. Don't know what that is? Don't worry, I didn't either. It's this thing:&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftorryqbnknreppob1w93.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%2Ftorryqbnknreppob1w93.png" alt="font book on mac referencing the postscript name"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Images &amp;amp; icons
&lt;/h2&gt;

&lt;p&gt;If you are following modern design trends most of your images by now will be flat vector images, probably inline SVGs and boy do I have bad news for you: You don't get to use normal SVGs in React native. They are not supported by the &lt;code&gt;&amp;lt;Image/&amp;gt;&lt;/code&gt; element. This is bad especially for icons and such. How do you load images then? There's a couple strategies:&lt;/p&gt;

&lt;p&gt;For complex shapes and such you can convert them into bitmaps, 90s style. You'll probably wanna set up a build pipeline to churn them out for you. All the assets in your app will be downloaded upfront so file size is not as big of a critical consideration as it is on web (but don't go bananas!) To make sure bitmaps are crispy you will want to export them at &lt;code&gt;@3x&lt;/code&gt; their intended size on screen.&lt;/p&gt;

&lt;p&gt;If you want to remotely import SVG that's a bit trickier but not impossible! There are &lt;a href="https://www.npmjs.com/package/react-native-remote-svg" rel="noopener noreferrer"&gt;several libraries&lt;/a&gt; that will do this for you by essentially chucking them in a webview. &lt;/p&gt;

&lt;p&gt;For everything else (I'm doing this!) You can use &lt;code&gt;react-native svg&lt;/code&gt; to use SVGs inside your code. The way this works is it exports React native versions of everything in an svg and you can use these and it draws the proper views for you&lt;/p&gt;

&lt;p&gt;Having SVGs be first class citizens in React with props and animation and everything has changed the way i see all SVGs. i always knew they were markup but having to directly adjust them myself now has given me lots of ideas for cool things I can do with them.&lt;/p&gt;

&lt;p&gt;At the end of the day &lt;code&gt;react-native svg&lt;/code&gt; is a very elaborate hack that gives you views so it can also be used as a low level drawing library for things like lines and circles and whatnot! Your imagination is the limit!&lt;/p&gt;

&lt;p&gt;A good way to assess what image loading strategy to use is by asking yourself &lt;em&gt;how messed up will things be if this doesn't load?&lt;/em&gt; so for example you might want icons to be inline SVGs but big hero images to be remotely downloaded. Be aware that some things will &lt;em&gt;always&lt;/em&gt; be messed up and that some of your users will never see images anyway because they use screen readers or have poor eyesight or they just can't figure out what an arrow coming out of a box in a circle is supposed to mean.&lt;/p&gt;

&lt;p&gt;Always make sure you have proper accessible descriptors for all your images! And provide sensible fallbacks if an image can't load (For example, in a hero, code in a background color that gives the text enough contrast)&lt;/p&gt;

&lt;h2&gt;
  
  
  Navigation
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;react-navigation&lt;/code&gt; kinda sounds like the &lt;code&gt;react-router&lt;/code&gt; of this land. You might have noticed that mobile apps have more advanced navigation types than the web. You can't just replace things in place and call it a div, if you look at any mobile app, all your screens slide out and in and away. &lt;code&gt;react-navigation&lt;/code&gt; has a &lt;a href="https://reactnavigation.org/docs/en/modal.html" rel="noopener noreferrer"&gt;data model that is super linked to these transitions&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Each navigator is a flat list of screens with an entry point and each defines the transitions between its screens. For example you can use a single navigator for all your app and all your screens within it will do that thing where they progressively pile on top of each other from left to right.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RootNavigator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createAppContainer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;createStackNavigator&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HomeScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;Downloads&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DownloadScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SettingsScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But say you are doing a music player and you wanna add a card that can slide over any views with some "now playing" info. You can just create a new top level navigator that contains your original navigator and that lonesome card. You can even just use &lt;code&gt;{mode: 'modal'}&lt;/code&gt; on it to get a pre made animation and voila, now if you navigate to your now playing view it glides over the rest of your app!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;RootNavigator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createAppContainer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nf"&gt;createStackNavigator&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="nf"&gt;createStackNavigator&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HomeScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;Downloads&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DownloadScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SettingsScreen&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="na"&gt;NowPlaying&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NowPlayingScreen&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="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;modal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Something really cool is that even though your navigators are in a hierarchy your route names aren't. You can navigate from any route to any route without worrying about reaching out to the top level or something. It just works™.&lt;/p&gt;

&lt;p&gt;For accessibility reasons you will probably want to use &lt;code&gt;&amp;lt;Link /&amp;gt;&lt;/code&gt; like &lt;a href="https://reactnavigation.org/docs/en/web-support.html" rel="noopener noreferrer"&gt;this&lt;/a&gt;. This will make things neat and tidy if you ever make a website with &lt;code&gt;react-native-web&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Good to know!&lt;/em&gt; &lt;code&gt;react-navigation&lt;/code&gt; gives you a lot of control but in exchange it recreates a lot of the platform's native navigation views. If you have simpler needs you might wanna look at &lt;a href="https://github.com/wix/react-native-navigation" rel="noopener noreferrer"&gt;&lt;code&gt;react-native-navigation&lt;/code&gt;&lt;/a&gt; which implements the platform native navigation bars at the cost of flexibility.&lt;/p&gt;

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

&lt;p&gt;The only bad thing I can say about React native is that it's too good? As I said at first I'm still waiting for a major 'oh no' type moment where I rode a wrong assumption for far too long and half of the app is broken or something.&lt;/p&gt;

&lt;p&gt;Funnily enough this happened with my first React (web) app! We got a last minute requirement to make it work on Samsung Internet on low end phones and well, it was a Redux and websocket fueled beast, best we could do was getting it to crash at the signin screen instead of at the splash page.&lt;/p&gt;

&lt;p&gt;IMO RN is pretty good and I feel sometimes it can get a bit of unfair flak. Web developers fear it because it's not the web and app developers fear it because it's an unnecessary abstraction. Personally I'm hella impressed at how elegant it is as a solution to write multi platform apps that feel like they belong on each platform. I'm also super excited about eventually using &lt;code&gt;react-native-web&lt;/code&gt; to go full circle and get a PWA!&lt;/p&gt;

&lt;p&gt;🥳&lt;/p&gt;

&lt;p&gt;Crossing fingers this was interesting to read! There are parts of this that I feel I could turn into a full blown book!! I'd love to hear your thoughts on what you found odd or funny in React native and I hope this post inspires you to start making apps! &lt;/p&gt;

&lt;p&gt;Did you enjoy this post? Pls let me know! I wanna publish a followup with even more things like animation and perf but I don't wanna bore the world with my React native ramblings.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;psss. you can follow me on twitter &lt;a href="https://twitter.com/freezydorito" rel="noopener noreferrer"&gt;@freezydorito&lt;/a&gt;&lt;/em&gt; &lt;/p&gt;

</description>
      <category>react</category>
      <category>reactnative</category>
      <category>ios</category>
      <category>android</category>
    </item>
  </channel>
</rss>
