<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Seth Alexander</title>
	<atom:link href="https://sethaalexander.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://sethaalexander.com/</link>
	<description>Father - Dev - Hustler</description>
	<lastBuildDate>Wed, 11 Sep 2024 21:23:47 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6.2</generator>
	<item>
		<title>2023 Recap</title>
		<link>https://sethaalexander.com/2023-recap/</link>
					<comments>https://sethaalexander.com/2023-recap/#respond</comments>
		
		<dc:creator><![CDATA[Seth Alexander]]></dc:creator>
		<pubDate>Tue, 02 Jan 2024 00:55:25 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">https://sethaalexander.com/?p=3126</guid>

					<description><![CDATA[<p>hey peeps. Long time since I&#8217;ve posted anything here. Figured with a new year I&#8217;d let you know where I disappeared to. Somewhere along the way in 2023 I decided to be much more intentional with my time which meant very little time on social media. One way I replaced that time is with reading,&#8230; <a class="more-link" href="https://sethaalexander.com/2023-recap/">Continue reading <span class="screen-reader-text">2023 Recap</span> <span class="meta-nav" aria-hidden="true">&#8594;</span></a></p>
<p>The post <a href="https://sethaalexander.com/2023-recap/">2023 Recap</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><img decoding="async" height="16" width="16" alt="&#x1f44b;" src="https://static.xx.fbcdn.net/images/emoji.php/v9/t99/2/16/1f44b.png"> hey peeps. Long time since I&#8217;ve posted anything here. Figured with a new year I&#8217;d let you know where I disappeared to. Somewhere along the way in 2023 I decided to be much more intentional with my time which meant very little time on social media. One way I replaced that time is with reading, among other things, and managed to complete these books this year (hit me up if you want to know my take on any of them):</p>



<p>&#8211; The Ruthless Elimination of Hurry: How to Stay Emotionally <a></a>Healthy and Spiritually Alive in the Chaos of the Modern World by Mark Comer <a href="https://l.facebook.com/l.php?u=https%3A%2F%2Famzn.to%2F3ttTGsx%3Ffbclid%3DIwZXh0bgNhZW0CMTAAAR3YCmm-57S8ly4BP5vY9rhmzXvHqaJ4MKs93NZgi7DMKngvc7jf-nASDM8_aem_bEwx2XqoRfh9GArX0jEjUw&amp;h=AT258cmjwW4YHNr8folGbfRIt2efeDlWBwE-QaWXK2rv4RgZQUSA63hyfCFrKos8sXUTLAKzOobef9QKmAoeAXDTgUIIzjwfBZJyw3P-X1JcZvwaqjZEVSqAUGozlV-RZF70cg&amp;__tn__=-UK-R&amp;c[0]=AT1XGphhNJwt-viSl3ea9FlJIzLPP1ygm2euNzbR9O5fO7nRZcXu0XJcE9B9g8NIVEHkkZ0zvky5n8lMYd1380zNvoiZuvBweZabl57ralDIZ8Y6fdYbm-c1Q928kR9PBKk5XRTUW7szdJ1iDBEaAGjGrRor91gvxOeTcQ4or5ukRYY1tzfzXQ" rel="noreferrer noopener" target="_blank">https://amzn.to/3ttTGsx</a></p>



<p>&#8211; Jesus and John Wayne: How White Evangelicals Corrupted a Faith and Fractured a Nation by Kristin Kobes Du Mez <a href="https://l.facebook.com/l.php?u=https%3A%2F%2Famzn.to%2F41F490R%3Ffbclid%3DIwZXh0bgNhZW0CMTAAAR15Wn1bTBKEhw5B8jCTPSG0keoQDkZKWjubDjjSEsX7XrZtAa5-r8hsHNs_aem_cAmQFr1mzNAUeBE8xsJtmA&amp;h=AT1Kxgnsk_rP8G4vuXmytQS3ypfA3ORiRO-vkNa7yVRcYW-g6woHpaCEhM4Od-ZMZLgR5weYVi9PdCKXmK9b4wXrO_x5vQLw0OVABfMO3bEEBrofVN7VtxpwNfdRSO6MNQOjjA&amp;__tn__=-UK-R&amp;c[0]=AT1XGphhNJwt-viSl3ea9FlJIzLPP1ygm2euNzbR9O5fO7nRZcXu0XJcE9B9g8NIVEHkkZ0zvky5n8lMYd1380zNvoiZuvBweZabl57ralDIZ8Y6fdYbm-c1Q928kR9PBKk5XRTUW7szdJ1iDBEaAGjGrRor91gvxOeTcQ4or5ukRYY1tzfzXQ" rel="noreferrer noopener" target="_blank">https://amzn.to/41F490R</a></p>



<p>&#8211; Robert E. Lee and Me: A Southerner&#8217;s Reckoning with the Myth of the Lost Cause by Ty Seidule <a href="https://amzn.to/3H5ahWO?fbclid=IwZXh0bgNhZW0CMTAAAR2kH7XitN8Tu6H5ZY0WTyVmtjTk_206ZEXnYuPKWvIK94XOkhCZgwsl5Qk_aem_Zjqw75pFQkGd4UJ6n4N-2w" rel="noreferrer noopener" target="_blank">https://amzn.to/3H5ahWO</a></p>



<p>&#8211; Deep Work: Rules for Focused Success in a Distracted World by Cal Newport <a href="https://l.facebook.com/l.php?u=https%3A%2F%2Famzn.to%2F41GGSeS%3Ffbclid%3DIwZXh0bgNhZW0CMTAAAR0YdCAcoPAtxLNLzoeFcmdu6DdDjJAguIoZLxuQJa_g-VDy4FZuzmvJqlk_aem_F9CSgaDzmjzNr7JY9xi8tA&amp;h=AT2RtzWOJZovE0Vi0eTEC0qU-Mz8TpRFzlq0AL0xw4r4OB4tyAy6fJmF8Sakwyh672EPcNcK_FBYpED9tfbnCp57jmh9Bc0VqFpTPIWosiJGLBWV2kc3TPfGxCTbJzdrhBOwfA&amp;__tn__=-UK-R&amp;c[0]=AT1XGphhNJwt-viSl3ea9FlJIzLPP1ygm2euNzbR9O5fO7nRZcXu0XJcE9B9g8NIVEHkkZ0zvky5n8lMYd1380zNvoiZuvBweZabl57ralDIZ8Y6fdYbm-c1Q928kR9PBKk5XRTUW7szdJ1iDBEaAGjGrRor91gvxOeTcQ4or5ukRYY1tzfzXQ" rel="noreferrer noopener" target="_blank">https://amzn.to/41GGSeS</a></p>



<p>&#8211; So Good They Can&#8217;t Ignore You: Why Skills Trump Passion in the Quest for Work You Love by Cal Newport <a href="https://amzn.to/3vohBu4?fbclid=IwZXh0bgNhZW0CMTAAAR2Bb08BrOT02krDps8y8Ald3SGILVxsSC6TPWdVFEdXSocxw5i8d5g_638_aem_LAJB0_JLjT4g_3IgIi4_4g" rel="noreferrer noopener" target="_blank">https://amzn.to/3vohBu4</a></p>



<p>&#8211; Never Split the Difference: Negotiating As If Your Life Depended On It by Chris Voss <a href="https://l.facebook.com/l.php?u=https%3A%2F%2Famzn.to%2F47sjmnm%3Ffbclid%3DIwZXh0bgNhZW0CMTAAAR1Sfu01bFGaaBfDOIClRYPwfHyZR1z9JrWpn3cvwGxrgDAEm-P3R9AM3tc_aem_ApIHi8sRm_Fv1v2p8DUHvw&amp;h=AT0ScR_ZixqOHj1KIZxKYA8G03y_QWcKD182wAysELM-UzyyVQlhaPratnjMOlanJ8d53hxvfinYHo742IsuHjV-Te8bw6QiBD0UimwacbimiR1sklx1IE65a8u4jBzsLvoxMw&amp;__tn__=-UK-R&amp;c[0]=AT1XGphhNJwt-viSl3ea9FlJIzLPP1ygm2euNzbR9O5fO7nRZcXu0XJcE9B9g8NIVEHkkZ0zvky5n8lMYd1380zNvoiZuvBweZabl57ralDIZ8Y6fdYbm-c1Q928kR9PBKk5XRTUW7szdJ1iDBEaAGjGrRor91gvxOeTcQ4or5ukRYY1tzfzXQ" rel="noreferrer noopener" target="_blank">https://amzn.to/47sjmnm</a></p>



<p>&#8211; Amazing Grace: William Wilberforce and the Heroic Campaign to End Slavery by Eric Metaxas <a href="https://amzn.to/3NRrhn1?fbclid=IwZXh0bgNhZW0CMTAAAR05eQMULES6U8KIjm76mSscd6K_AwO3VpPHv92MUYBABK-PENDxJ8XJPvQ_aem_JenJWLwhn6RrxxPcOyKyAA" rel="noreferrer noopener" target="_blank">https://amzn.to/3NRrhn1</a></p>



<p>&#8211; The Reason for God: Belief in an Age of Skepticism by Timothy Keller <a href="https://l.facebook.com/l.php?u=https%3A%2F%2Famzn.to%2F3NHZrcH%3Ffbclid%3DIwZXh0bgNhZW0CMTAAAR3hPhbbX59-gS6lGK2c70sA_IWYan-KNY-Vdhe40ZBDEMWyrhNarP9ABxk_aem_pCuNVjENzsbRB0ElUOxkJw&amp;h=AT22zwIyufg8xh9qS0fZISAZWllL23TvBkNuZKxJp9x3WDQKaLTklzAGM_tE6Tivnicv9rytHjW8swOhRhKSMhBXTm0qrlgDZziqF4LVlKLr813TUwU93ixFC90qP5NoinQLeQ&amp;__tn__=-UK-R&amp;c[0]=AT1XGphhNJwt-viSl3ea9FlJIzLPP1ygm2euNzbR9O5fO7nRZcXu0XJcE9B9g8NIVEHkkZ0zvky5n8lMYd1380zNvoiZuvBweZabl57ralDIZ8Y6fdYbm-c1Q928kR9PBKk5XRTUW7szdJ1iDBEaAGjGrRor91gvxOeTcQ4or5ukRYY1tzfzXQ" rel="noreferrer noopener" target="_blank">https://amzn.to/3NHZrcH</a></p>



<p>&#8211; Defending Your Faith: An Introduction to Apologetics by R.C. Sproul <a href="https://l.facebook.com/l.php?u=https%3A%2F%2Famzn.to%2F48Baug6%3Ffbclid%3DIwZXh0bgNhZW0CMTAAAR07c1W_hA1_GppGkLppkAcWYMHwdkm8-zuQXKPCleWtjUl9FRieTCHyik4_aem_5WuqqFdabvhCbTD_-iGifg&amp;h=AT1t91TBh1tfpvn8hwx7xnD37AdOn_ngUq5OLGlD4-m2AWRQyS393jbwepkeAT7plmT1aifUVPuTp0OCq3pPxnofftPNIun2Zs2oPFJSRgs6dJ6Xj4CeY2HXJZ3Nbc8bFVzUKw&amp;__tn__=-UK-R&amp;c[0]=AT1XGphhNJwt-viSl3ea9FlJIzLPP1ygm2euNzbR9O5fO7nRZcXu0XJcE9B9g8NIVEHkkZ0zvky5n8lMYd1380zNvoiZuvBweZabl57ralDIZ8Y6fdYbm-c1Q928kR9PBKk5XRTUW7szdJ1iDBEaAGjGrRor91gvxOeTcQ4or5ukRYY1tzfzXQ" rel="noreferrer noopener" target="_blank">https://amzn.to/48Baug6</a></p>



<p>&#8211; The Righteous Mind: Why Good People Are Divided by Politics and Religion by Jonathan Haidt <a href="https://amzn.to/3S2bkNe?fbclid=IwZXh0bgNhZW0CMTAAAR1Sfu01bFGaaBfDOIClRYPwfHyZR1z9JrWpn3cvwGxrgDAEm-P3R9AM3tc_aem_ApIHi8sRm_Fv1v2p8DUHvw" rel="noreferrer noopener" target="_blank">https://amzn.to/3S2bkNe</a></p>



<p>&#8211; Digital Minimalism: Choosing a Focused Life in a Noisy World by Cal Newport (not pictured) <a href="https://l.facebook.com/l.php?u=https%3A%2F%2Famzn.to%2F3S2Nz7Q%3Ffbclid%3DIwZXh0bgNhZW0CMTAAAR2KGSd3PVw6gb5_Bb7y_3ZjSBSB7G01sXB4Rga18CX44KSz880mrk_F0-0_aem_ismcLSzrb6FfCnHnVlwo5g&amp;h=AT3qIjNoa7q814PCR5WA0L5_aAESEQBlPqqzN-oxuXTNYOYrf2war0dFdbjfz4aqfFNXszGMjj9_uZJznG_HgdWCotli-xr87yIt_Ih34EQabpAJwXijPZ64uFLwYsDgkPJpmA&amp;__tn__=-UK-R&amp;c[0]=AT1XGphhNJwt-viSl3ea9FlJIzLPP1ygm2euNzbR9O5fO7nRZcXu0XJcE9B9g8NIVEHkkZ0zvky5n8lMYd1380zNvoiZuvBweZabl57ralDIZ8Y6fdYbm-c1Q928kR9PBKk5XRTUW7szdJ1iDBEaAGjGrRor91gvxOeTcQ4or5ukRYY1tzfzXQ" rel="noreferrer noopener" target="_blank">https://amzn.to/3S2Nz7Q</a></p>



<p>&#8211; The Screwtape Letters by C.S. Lewis (not pictured) <a href="https://amzn.to/3Tr4LV3">https://amzn.to/3Tr4LV3</a></p>



<p>&#8211; The Bible (ESV) <a href="https://www.esv.org/?fbclid=IwZXh0bgNhZW0CMTAAAR2-p7tOkAr9SZarflk4abZeoWpruPkogc8hwKB3Dcpkc4_v0OyykYlYdqU_aem_ry5-L3dfsJqQarXW2x3PuQ" rel="noreferrer noopener" target="_blank">https://www.esv.org/</a></p>



<p>I can say that for me, my life is much richer having read these books than having spent the equivalent amount of time scrolling. I&#8217;m definitely not spending much time writing blogs, though I&#8217;d love to share more long form content.</p>



<p>See you in 2025 most likely <img decoding="async" height="16" width="16" alt="&#x1f601;" src="https://static.xx.fbcdn.net/images/emoji.php/v9/tee/2/16/1f601.png">.</p>
<p>The post <a href="https://sethaalexander.com/2023-recap/">2023 Recap</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sethaalexander.com/2023-recap/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Rails Direct Upload to AWS S3 from React Native</title>
		<link>https://sethaalexander.com/rails-direct-upload-aws-s3-react-native/</link>
					<comments>https://sethaalexander.com/rails-direct-upload-aws-s3-react-native/#respond</comments>
		
		<dc:creator><![CDATA[Seth Alexander]]></dc:creator>
		<pubDate>Tue, 24 Sep 2019 02:19:42 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[react native]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[s3]]></category>
		<guid isPermaLink="false">https://sethaalexander.com/?p=3001</guid>

					<description><![CDATA[<p>I recently took on the task of allowing a user of a React Native app I&#8217;m helping build upload a custom profile picture. It sounded like a relatively simple task when I was estimating it in our sprint planning. However, I still allowed myself some grace since I&#8217;d never done such a thing before and&#8230; <a class="more-link" href="https://sethaalexander.com/rails-direct-upload-aws-s3-react-native/">Continue reading <span class="screen-reader-text">Rails Direct Upload to AWS S3 from React Native</span> <span class="meta-nav" aria-hidden="true">&#8594;</span></a></p>
<p>The post <a href="https://sethaalexander.com/rails-direct-upload-aws-s3-react-native/">Rails Direct Upload to AWS S3 from React Native</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>I recently took on the task of allowing a user of a <a href="http://facebook.github.io/react-native/">React Native</a> app I&#8217;m helping build upload a custom profile picture. It sounded like a relatively simple task when I was estimating it in our sprint planning. However, I still allowed myself some grace since I&#8217;d never done such a thing before and put 8 hours on it. Little did I know what was to come.</p>



<p>See, I knew our backend was running <a href="https://rubyonrails.org">Ruby on Rails</a> (RoR) and I knew that <a href="https://guides.rubyonrails.org/active_storage_overview.html">Active Storage</a> is now the thing but I didn&#8217;t realize the issues I would run into when I threw <a href="https://aws.amazon.com/s3/">Amazon Web Services (AWS) S3</a> into the mix. I had heard good things bout Active Storage though I hadn&#8217;t worked with it any, I know RoR well enough to know that the things they add are intentional and typically well thought out, and I also knew my experience with S3 was while the configuration could be somewhat complex when it comes to IAM roles and things once it was running the way you wanted it <em>should</em> be pretty easy to use. Especially for something that was going to be public.</p>



<p>Early on in my work on this task I was informed by the back end engineer that Active Storage had this pretty neat way of allowing the client application to send files directly to S3 and just sending a reference string to the Rails server. This is preferred because instead of sending the data from the client to the Rails server to Amazon it goes directly from the client to Amazon. Bypassing one step speeds everything up and also saves some load on the server. I thought to myself this was pretty cool. We at <a href="https://teamairship.com">Airship</a> had done this before with a web app with solid results. I had that code to reference and base my work off of. </p>



<h4 class="wp-block-heading">Where things start to go wrong&#8230;</h4>



<p>This is where things start to splinter. I start to digest the code from the web app we created:</p>



<pre class="wp-block-prismatic-blocks"><code class="language-javascript">import axios from &quot;axios&quot;;
import SparkMD5 from &quot;spark-md5&quot;;
const getUploadInfo = async (file) =&gt; {
  const checksum = await createFileChecksum(file);
  return axios.post(
    `${process.env.BASE_URL}/rails/active_storage/direct_uploads`,
    {
      blob: {
        filename: file.name,
        content_type: file.type,
        byte_size: file.size,
        checksum: checksum
      }
    }
  );
};
export const createFileChecksum = async (file) =&gt; {
  return new Promise((resolve, reject) =&gt; {
    const chunkSize = 2097152; // 2MB
    const chunkCount = Math.ceil(file.size / chunkSize);
    var chunkIndex = 0;
    const md5Buffer = new SparkMD5.ArrayBuffer();
    const fileReader = new FileReader();
    const readNextChunk = () =&gt; {
      if (chunkIndex &lt; chunkCount || (chunkIndex === 0 &amp;&amp; chunkCount === 0)) {
        const start = chunkIndex * chunkSize;
        const end = Math.min(start + chunkSize, file.size);
        const fileSlice =
          File.prototype.slice ||
          File.prototype.mozSlice ||
          File.prototype.webkitSlice;
        const bytes = fileSlice.call(file, start, end);
        fileReader.readAsArrayBuffer(bytes);
        chunkIndex++;
        return true;
      } else {
        return false;
      }
    };
    fileReader.addEventListener(&quot;load&quot;, event =&gt; {
      md5Buffer.append(event.target.result);
      if (!readNextChunk()) {
        const binaryDigest = md5Buffer.end(true);
        const base64digest = btoa(binaryDigest);
        resolve(base64digest);
      }
    });
    fileReader.addEventListener(&quot;error&quot;, () =&gt;
      reject(`Error reading ${file.name}`)
    );
    readNextChunk();
  });
};
export const uploadFile = async (file) =&gt; {
  const uploadInfo = await getUploadInfo(file);
  await axios.put(uploadInfo.data.direct_upload.url, file, {
    headers: uploadInfo.data.direct_upload.headers
  });
  return uploadInfo.data.signed_id;
};</code></pre>



<p>Real quick, <code>getUploadInfo()</code> sends the relevant info about the file the the Rails back end and returns what&#8217;s needed to direct upload to S3. <code>createFileChecksum()</code> is used by <code>getUploadInfo()</code> to calculate the base64 encoded md5 checksum of the file being sent. While Amazon does not require this Rails does. Lastly, <code>uploadFile()</code> uploads the file to AWS and then returns the <code>signed_id</code> that is then sent to Rails so it can associate that file with whatever it is in the back end.</p>



<p>I later realized most of this code came from somewhere else, maybe even the <a href="https://www.npmjs.com/package/@rails/activestorage">@rails/activestorage</a> package. I found similar code living in a <code>&lt;a href=&quot;https://github.com/rails/rails/blob/master/activestorage/app/javascript/activestorage/file_checksum.js&quot;&gt;file_checksum.js&lt;/a&gt;</code> file in the Rails repository on GitHub. No matter the source of the code, there was an issue. I don&#8217;t have access to the <code>FileReader</code> api on mobile. I&#8217;m working in React Native and not a browser. So now the search commences to doing this exact same thing in React Native.</p>



<h2 class="wp-block-heading">All the things that didn&#8217;t work</h2>



<p>Actually, I&#8217;m not going to bore you with everything that didn&#8217;t work. I honestly don&#8217;t think you care. You probably Googled how to do this and it&#8217;s <strong>NOWHERE TO BE FOUND</strong> on the internet. Yet, this direct upload has been a feature in Rails for a while. You might have even landed on the Rails issue <a href="https://github.com/rails/rails/issues/32208">Make ActiveStorage work for API only apps</a> and a comment there:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>For those on react native, I was able to get direct uploads working using&nbsp;<code>rn-fetch-blob</code>&nbsp;for md5 hashing (which is output in hex), then converting its hex output into base64 using&nbsp;<code>buffer</code>&nbsp;for calculating the checksum. To lookup the content_type, I used&nbsp;<code>react-native-mime-types</code>, and last but not least, used&nbsp;<code>rn-fetch-blob</code>&nbsp;again for calculating the size. Then, just follow the communication guidelines pointed out by&nbsp;@cbothner, and if the files are big, use&nbsp;<code>rn-fetch-blob</code> for efficiently uploading the file.</p>
<cite>&#8211; <a href="https://github.com/rails/rails/issues/32208#issuecomment-477688465">Samsinite</a></cite></blockquote>



<p>So, I tried to follow the above thread and I couldn&#8217;t get it to work. Granted, that comment is almost 6 months old and in JavaScript time that&#8217;s a lifetime ago. The main issue I ran into is I could not for the life of me get the checksum to match up with what Amazon calculated on their side. I kept getting responses of &#8220;The Content-MD5 you specified was invalid&#8221;. I tried <strong>MANY</strong> ways of generating the md5 checksum and they all ended up with the same Content-MD5 message being returned from AWS.</p>



<p>So here&#8217;s how I ended up getting it to work (why you&#8217;re really here):</p>



<pre class="wp-block-prismatic-blocks"><code class="language-javascript">import axios from &quot;axios&quot;;
import Config from &quot;react-native-config&quot;;
import RNFetchBlob from &quot;rn-fetch-blob&quot;;
import AWS from &quot;aws-sdk/dist/aws-sdk-react-native&quot;;
import { Platform } from &quot;react-native&quot;;
import { Buffer } from &quot;buffer&quot;;
const { fs } = RNFetchBlob;

AWS.config.update({
  accessKeyId: Config.AWS_ACCESS_KEY_ID,
  region: Config.AWS_REGION,
  secretAccessKey: Config.AWS_SECRET_ACCESS_KEY
});
const s3 = new AWS.S3({ apiVersion: &quot;2006-03-01&quot; });

const getUploadInfo = async (fileInfo, file) =&gt; {
  const params = {
    Bucket: Config.AWS_BUCKET,
    ContentType: fileInfo.type,
    Key: fileInfo.fileName,
    Body: file
  };
  const psUrl = s3.getSignedUrl(&quot;putObject&quot;, params);
  const checksum = unescape(psUrl.split(&quot;&amp;&quot;)[1].split(&quot;=&quot;)[1]);

  return axios.post(
    `${Config.API_UPLOAD_HOST}/rails/active_storage/direct_uploads`,
    {
      blob: {
        filename: fileInfo.fileName,
        content_type: fileInfo.type,
        byte_size: fileInfo.fileSize,
        checksum: checksum
      }
    }
  );
};

export const uploadFile = async (fileInfo) =&gt; {
  const uri =
    Platform.OS === &quot;ios&quot; ? fileInfo.uri.replace(&quot;file://&quot;, &quot;&quot;) : fileInfo.uri;
  const file = await fs
    .readFile(uri, &quot;base64&quot;)
    .then(data =&gt; new Buffer(data, &quot;base64&quot;));

  const uploadInfo = await getUploadInfo(fileInfo, file);
  const { headers, url } = uploadInfo.data.direct_upload;

  try {
    await axios.put(url, file, { headers: { ...headers } });
  } catch (e) {
    throw e;
  }

  return uploadInfo.data.signed_id;
};</code></pre>



<p>This is definitely not the most elegant solution. I haven&#8217;t refactored it at all yet either. However, it works. In the world of code that means something. So what in the world is going on here? I&#8217;ll walk through it, although, I&#8217;ll jump around the file some. First, I setup the <code>aws-sdk</code> and a new <code>s3</code> instance. I&#8217;m using <code>react-native-config</code> to manage environment variables here. I initially did this to see if I could get the <code>signed_id</code> I needed by just bypassing Rails and uploading directly to AWS, that didn&#8217;t work. However, what I noticed when I generated a pre-signed URL for uploading via the <code>aws-sdk</code> was that the URL contained and md5 checksum!</p>



<h4 class="wp-block-heading">Back to the code</h4>



<p>Okay, the code, walk through it, here we go. I call <code>uploadFile()</code> in the response from <code>react-native-image-picker</code> on my screen component. That&#8217;s where the <code>fileInfo</code> argument comes from. I then get the proper URI based on the OS, and read the file with <code>rn-fetch-blob</code>. I turn that data into a Buffer because the <code>aws-sdk</code> on accepts certain types of files when creating a pre-signed URL. I then pass the <code>fileInfo</code> and the <code>file</code> along the <code>getUploadInfo()</code>. <code>getUploadInfo()</code> then creates a pre-signed URL using the <code>s3</code> instance we setup earlier and does some hacky string manipulation (needs a refactor) to acquire the checksum. Now, I can use that checksum (which Amazon code created) to get the direct upload URL and headers from Rails. Lastly, I upload the file to AWS and return the <code>signed_id</code> which I send along to Rails elsewhere in my code.</p>



<p>Ultimately, this was a pretty frustrating problem to fight against. However, it felt so good when I uploaded a file and saw the user profile image change. I actually got up and ran around my home office with my hands in the air rejoicing. I&#8217;m also stoked that I can share this solution and see how others might improve on what I did or figure out better ways to go about this. I&#8217;m not convinced this is the best solution to this problem, however, it&#8217;s a solution that works.</p>



<p>From my <code>yarn.lock</code>:<br>&#8211; react-native v0.60.5<br>&#8211; react-native-image-picker v1.1.0<br>&#8211; rn-fetch-blob v0.10.16<br>&#8211; aws-sdk v2.532.0</p>
<p>The post <a href="https://sethaalexander.com/rails-direct-upload-aws-s3-react-native/">Rails Direct Upload to AWS S3 from React Native</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sethaalexander.com/rails-direct-upload-aws-s3-react-native/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Supercluster with @react-native-mapbox-gl/maps</title>
		<link>https://sethaalexander.com/supercluster-with-react-native-mapbox-gl-maps/</link>
					<comments>https://sethaalexander.com/supercluster-with-react-native-mapbox-gl-maps/#respond</comments>
		
		<dc:creator><![CDATA[Seth Alexander]]></dc:creator>
		<pubDate>Tue, 03 Sep 2019 19:31:59 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<category><![CDATA[mapbox]]></category>
		<category><![CDATA[react native]]></category>
		<category><![CDATA[supercluster]]></category>
		<guid isPermaLink="false">https://sethaalexander.com/?p=2992</guid>

					<description><![CDATA[<p>During a recent project in my work at Airship I had to stop using the built in cluster functionality that &#60;a href=&#34;https://github.com/react-native-mapbox-gl/maps&#34;&#62;@react-native-mapbox-gl/maps&#60;/a&#62; provides and utilize Supercluster instead. The reason is we need access to the points that make up the clusters. We had some items that never broke out of their clusters because they had&#8230; <a class="more-link" href="https://sethaalexander.com/supercluster-with-react-native-mapbox-gl-maps/">Continue reading <span class="screen-reader-text">Supercluster with @react-native-mapbox-gl/maps</span> <span class="meta-nav" aria-hidden="true">&#8594;</span></a></p>
<p>The post <a href="https://sethaalexander.com/supercluster-with-react-native-mapbox-gl-maps/">Supercluster with @react-native-mapbox-gl/maps</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image"><img fetchpriority="high" decoding="async" width="702" height="438" src="https://sethaalexander.com/wp-content/uploads/2019/09/43407b46-a40c-11e5-8662-e99ab1cd2cb7.gif" alt="" class="wp-image-2995"/></figure>



<p>During a recent project in my work at <a href="https://teamairship.com">Airship</a> I had to stop using the built in cluster functionality that <code>&lt;a href=&quot;https://github.com/react-native-mapbox-gl/maps&quot;&gt;@react-native-mapbox-gl/maps&lt;/a&gt;</code> provides and utilize <a href="https://github.com/mapbox/supercluster">Supercluster</a> instead. The reason is we need access to the points that make up the clusters. We had some items that never broke out of their clusters because they had the same exact longitude &amp; latitude combination. As well as wanting to show a slide up view of those locations in a list view. What started me down this path was an issue on the deprecated <code>&lt;a href=&quot;https://github.com/nitaliano/react-native-mapbox-gl&quot;&gt;react-native-mapbox-gl&lt;/a&gt;</code> library which shares a lot of functionality with the new library. You can view that issue <a href="https://github.com/nitaliano/react-native-mapbox-gl/issues/1122">here</a>. I&#8217;m honestly surprised that this functionality isn&#8217;t available in the library since it <em>is</em> supported in the Mapbox JS SDK as documented <a href="https://docs.mapbox.com/mapbox-gl-js/api/#geojsonsource">here</a> with the <code>getClusterLeaves()</code> function. I noticed people asking how to do this so when I nailed it down I knew a how-to was coming.</p>



<span id="more-2992"></span>



<h2 class="wp-block-heading">Without Supercluster</h2>



<p>I setup a code example <a href="https://snack.expo.io/@sethalexander/before-supercluster">here</a> to show a contrived starting state utilizing the built in clustering functionality. This is essentially where I started with the core Mapbox functionality. Let&#8217;s walk through this code some.</p>



<pre class="wp-block-prismatic-blocks"><code class="language-javascript">render() {
  return (
    &lt;View style={{ flex: 1 }}&gt;
      &lt;MapboxGL.MapView
        ref={c =&gt; (this._map = c)}
        zoomEnabled
        style={[{ flex: 1 }]}
      &gt;
        {this.renderPoints()}
      &lt;/MapboxGL.MapView&gt;
    &lt;/View&gt;
  );
}</code></pre>



<p>Here&#8217;s our MapboxGL container to setup our map. We then need to render all our points on the map and we handle that in a helper function <code>renderPoints()</code>.</p>



<pre class="wp-block-prismatic-blocks"><code class="language-javascript">renderPoints = () =&gt; {
  const { points } = this.state;

  return (
    &lt;MapboxGL.ShapeSource
      id=&quot;symbolLocationSource&quot;
      hitbox={{ width: 18, height: 18 }}
      onPress={this.onMarkerSelected}
      shape={points}
      cluster
    &gt;
      &lt;MapboxGL.SymbolLayer
        minZoomLevel={6}
        id=&quot;pointCount&quot;
        style={mapStyles.clusterCount}
      /&gt;

      &lt;MapboxGL.CircleLayer
        id=&quot;clusteredPoints&quot;
        minZoomLevel={6}
        belowLayerID=&quot;pointCount&quot;
        filter={[&quot;has&quot;, &quot;point_count&quot;]}
        style={mapStyles.clusteredPoints}
      /&gt;

      &lt;MapboxGL.SymbolLayer
        id=&quot;symbolLocationSymbols&quot;
        minZoomLevel={6}
        filter={[&quot;!has&quot;, &quot;point_count&quot;]}
        style={mapStyles.icon}
      /&gt;
    &lt;/MapboxGL.ShapeSource&gt;
  );
};</code></pre>



<p>So here we&#8217;re getting the list of groups from state and passing them into <code>MapboxGL.ShapeSource</code> and toggling the <code>cluster</code> functionality on. We have three layers inside there which I&#8217;ll refer to by ID values.<br>&#8211; <code>pointCount</code> is the actual numerical value of the number of items that make up the cluster.<br>&#8211; <code>clusteredPoints</code> is the cluster circle which we see is set to be below the <code>pointCount</code> layer.<br>&#8211; <code>symbolLocationSymbols</code> is the map marker for a single location on the map that isn&#8217;t being clustered.</p>



<p>When we click a marker, whether it&#8217;s a cluster or single point on the map we call <code>onMarkerSelected</code> which currently only has functionality implemented for non-clusters like so:</p>



<pre class="wp-block-prismatic-blocks"><code class="language-javascript">onMarkerSelected = event =&gt; {
  const point = event.nativeEvent.payload;
  const { name, cluster } = point.properties;
  const coordinates = point.geometry.coordinates;

  if (cluster) {
    console.log(cluster);
  } else {
    this.setState(
      {
        selectedPointName: name,
        selectedPointLat: coordinates[1],
        selectedPointLng: coordinates[0],
      },
      () =&gt; {
        this.map.flyTo(point.geometry.coordinates, 500);
      }
    );
  }
};</code></pre>



<p>The <code>if/else</code> statement is just logging the cluster if there is one otherwise it&#8217;s setting the state to the selected point and centering the map on that point. The idea of adding the point info to state is to do something with that info.</p>



<p>We decide if we&#8217;re going to render the circle or marker based on the <code>filter</code> criteria being passed into the <code>CircleLayer</code> and <code>SymbolLayer</code>.</p>



<pre class="wp-block-prismatic-blocks"><code class="language-javascript">const mapStyles = MapboxGL.StyleSheet.create({
  icon: {
    iconAllowOverlap: true,
    iconSize: 0.35
  },
  clusteredPoints: {
    circleColor: &quot;#004466&quot;,
    circleRadius: [
      &quot;interpolate&quot;,
      [&quot;exponential&quot;, 1.5],
      [&quot;get&quot;, &quot;point_count&quot;],
      15,
      15,
      20,
      30
    ],
    circleOpacity: 0.84
  },
  clusterCount: {
    textField: &quot;{point_count}&quot;,
    textSize: 12,
    textColor: &quot;#ffffff&quot;
  }
});</code></pre>



<p>This last piece provides some of the styling and actually won&#8217;t change when we swap out the clustering functionality.</p>



<h2 class="wp-block-heading">Implementing Supercluster</h2>



<p>So the idea of switching to Supercluster to to replace the built in clustering of the raw <code>FeatureCollection</code> data. Supercluster is not going to do anything with the actual rendering of that data. We need to initialize a cluster using Supercluster then update that cluster based on the bounds of the map and zoom level. I&#8217;m going to walk through the guts of this conversion.</p>



<p>Firstly, you&#8217;ll need the cluster which I decided to store in state. I think this makes the most sense and works well for me.</p>



<pre class="wp-block-prismatic-blocks"><code class="language-javascript">const collection = MapboxGL.geoUtils.makeFeatureCollection(groupFeatures);
const cluster = new Supercluster({ radius: 40, maxZoom: 16 });
cluster.load(collection.features);

this.setState({
  point: collection,
  loading: false,
  selectedPoints: [],
  superCluster: cluster,
  userFound: false
});</code></pre>



<p>So now I have the <code>FeatureCollection</code> as <code>state.groups</code> and the Supercluster cluster as <code>state.superCluster</code>. However, we will not be able to pass this <code>superCluster</code> into our <code>MapboxGL.ShapeSource</code> just yet. This cluster is immutable and essentially what we will now use to create the shape object we will pass into <code>ShapeSource</code>. Next let&#8217;s update our <code>MapView</code> like so:</p>



<pre class="wp-block-prismatic-blocks"><code class="language-javascript">&lt;MapboxGL.MapView
  ref={c =&gt; (this._map = c)}
  onRegionDidChange={this.updateClusters}
  zoomEnabled
  style={[{ flex: 1 }]}
&gt;
  {this.renderPoints()}
&lt;/MapboxGL.MapView&gt;</code></pre>



<p>Notice the added <code>onRegionDidChange</code> which takes a callback function. This prop I found works the best for me, however, as the <code>react-native-mapbox-gl/maps</code> library continues to evolve there may be a better solution. This calls <code>updateClusters</code> after the map has been moved. Now lets take a look at the <code>updateClusters</code> function:</p>



<pre class="wp-block-prismatic-blocks"><code class="language-javascript">updateClusters = async () =&gt; {
  const sc = this.state.superCluster;
  if (sc) {
    const bounds = await this._map.getVisibleBounds();
    const westLng = bounds[1][0];
    const southLat = bounds[1][1];
    const eastLng = bounds[0][0];
    const northLat = bounds[0][1];
    const zoom = Math.round(await this._map.getZoom());
    this.setState({
      superClusterClusters: sc.getClusters(
        [westLng, southLat, eastLng, northLat],
        zoom
      )
    });
  }
};</code></pre>



<p>So, I take the cluster that was created in my <code>componentDidMount()</code> and set that to a local variable. Just in case I check to ensure it exists before doing anything else. Next, I get the visible bounds from the <code>_map</code> ref that is setup on the <code>MapView</code>. I extract the four bounds into their own variables mostly for ease of knowing what they are. I then get the zoom and round it to a whole number (I found decimal zooms gave Supercluster issues). Finally, I take all that information and create the appropriate clusters for those bounds and zoom level and save them in state to <code>superClusterClusters</code>.</p>



<p>This <code>superClusterClusters</code> is what gets fed into the <code>ShapeSource</code> in <code>renderPoints</code> like so:</p>



<pre class="wp-block-prismatic-blocks"><code class="language-javascript">renderPoints = () =&gt; {
  const { superClusterClusters } = this.state;

  return (
    &lt;MapboxGL.ShapeSource
      id=&quot;symbolLocationSource&quot;
      hitbox={{ width: 18, height: 18 }}
      onPress={this.onMarkerSelected}
      shape={{ type: &quot;FeatureCollection&quot;, features: superClusterClusters }}
    &gt;
      &lt;MapboxGL.SymbolLayer
        id=&quot;pointCount&quot;
        minZoomLevel={6}
        style={mapStyles.clusterCount}
      /&gt;

      &lt;MapboxGL.CircleLayer
        id=&quot;clusteredPoints&quot;
        minZoomLevel={6}
        belowLayerID=&quot;pointCount&quot;
        filter={[&quot;&gt;&quot;, &quot;point_count&quot;, 1]}
        style={mapStyles.clusteredPoints}
      /&gt;

      &lt;MapboxGL.SymbolLayer
        id=&quot;symbolLocationSymbols&quot;
        minZoomLevel={6}
        filter={[&quot;!&quot;, [&quot;has&quot;, &quot;point_count&quot;]]}
        style={mapStyles.icon}
      /&gt;
    &lt;/MapboxGL.ShapeSource&gt;
  );
};</code></pre>



<p>Notice that the <code>shape</code> prop requires the creation of an object and I&#8217;m not passing in the <code>superClusterClusters</code> directly from the state. Also notice that the <code>cluster</code> prop is no longer included on <code>ShapeSource</code>. This is something I forgot about and caused me a lot of grief. The built in clustering was conflicting with my clustering. </p>



<p>Lastly we add in functionality for getting the info about each point out of the cluster when we touch it on the phone in our <code>onMarkerSelected()</code> like so:</p>



<pre class="wp-block-prismatic-blocks"><code class="language-javascript">onMarkerSelected = event =&gt; {
  const point = event.nativeEvent.payload;
  const { name, cluster } = point.properties;
  const coordinates = point.geometry.coordinates;

  if (cluster) {
    const sc = this.state.superCluster;
    if (sc) {
      const points = sc
        .getLeaves(point.properties.cluster_id, Infinity)
        .map(leaf =&gt; ({
          selectedPointName: leaf.properties.name,
          selectedPointLat: leaf.geometry.coordinates[1],
          selectedPointLng: leaf.geometry.coordinates[0],
        }));
      this.setState({ selectedPoints: points });
      console.log(points);
    } else {
      this.setState(
        {
          selectedPoints: [
            {
              selectedPointName: name,
              selectedPointLat: coordinates[1],
              selectedPointLng: coordinates[0],
            },
          ],
        },
        () =&gt; {
          this.camera.flyTo(point.geometry.coordinates, 500);
        }
      );
    }
  }
};</code></pre>



<p>By using Superclusters <code>getLeaves()</code> we map those to a new array and set our <code>selectedPoints</code> state to it. We can now use this new data in state to render something in the UI.</p>



<h3 class="wp-block-heading">Final Thoughts</h3>



<p>While there might seem like there are many steps involved in adding Supercluster to a <code>react-native-mapbox-gl/maps</code> map to access the underlying points of a cluster most of the code that I have shared can be reused as is to ease the transition.</p>



<p>For reference, the exact versions I&#8217;m using in this example are:<br><code>react-native-mapbox-gl/maps</code>: 7.0.1<br><code>supercluster</code>: 6.0.2<br>A final code sample is available <a href="https://snack.expo.io/@sethalexander/after-supercluster">here</a>.</p>



<p><strong>NOTE:</strong> The code samples WILL NOT WORK. Although, if you&#8217;re reading this article I&#8217;m making the assumption you already have Mapbox implemented. With that I also assume you have the library initialized with your access token.</p>



<p>I hope this saves people some headaches along the way and you build amazing things having access to the underlying data points that make up your clusters.</p>
<p>The post <a href="https://sethaalexander.com/supercluster-with-react-native-mapbox-gl-maps/">Supercluster with @react-native-mapbox-gl/maps</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sethaalexander.com/supercluster-with-react-native-mapbox-gl-maps/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>How-to Build Your Own React Boilerplate</title>
		<link>https://sethaalexander.com/how-to-build-your-own-react-boilerplate/</link>
					<comments>https://sethaalexander.com/how-to-build-your-own-react-boilerplate/#comments</comments>
		
		<dc:creator><![CDATA[Seth Alexander]]></dc:creator>
		<pubDate>Sat, 12 May 2018 03:47:05 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">https://sethaalexander.com/?p=2773</guid>

					<description><![CDATA[<p>So you&#8217;ve learned some React and built a few things. You&#8217;ve probably used create-react-app or react-slingshot to get off the ground quickly with minimal configuration. However, now you&#8217;re ready to venture out on your own with your very own React boilerplate. WHERE. TO. START??? I recently faced this same dilemma. It was a struggle but&#8230; <a class="more-link" href="https://sethaalexander.com/how-to-build-your-own-react-boilerplate/">Continue reading <span class="screen-reader-text">How-to Build Your Own React Boilerplate</span> <span class="meta-nav" aria-hidden="true">&#8594;</span></a></p>
<p>The post <a href="https://sethaalexander.com/how-to-build-your-own-react-boilerplate/">How-to Build Your Own React Boilerplate</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>So you&#8217;ve learned some <a href="https://reactjs.org/">React</a> and built a few things. You&#8217;ve probably used <a href="https://github.com/facebook/create-react-app">create-react-app</a> or <a href="https://github.com/coryhouse/react-slingshot">react-slingshot</a> to get off the ground quickly with minimal configuration. However, now you&#8217;re ready to venture out on your own with your very own React boilerplate.<br />
<img loading="lazy" decoding="async" class="alignnone size-full" src="https://media.giphy.com/media/aysBMSvOiagPm/giphy.gif" alt="react boilerplate freedom" width="500" height="380" /></p>
<h2>WHERE. TO. START???</h2>
<p><span id="more-2773"></span>I recently faced this same dilemma. It was a struggle but at the end of it, I had a solid repo that I could use as a basis for future React projects. I realized I wanted to use <a href="https://webpack.js.org/">webpack</a> because it&#8217;s the new hotness (well not so new) but I would have a lot of resources to pull from to figure it out. I have <strong>ZERO</strong> working knowledge of <a href="https://gruntjs.com/">Grunt</a> or <a href="https://gulpjs.com/">Gulp</a> although with the minimal amount I&#8217;ve looked at them they do some cools things in their own right. Also, I know the people I interact with who <em>know</em> more than me use webpack. I also had a reference React boilerplate webpack config I was going to use as a base (I quickly realized I was going to rewrite most of this config).</p>
<h2>Back to the Beginning</h2>
<p>Let&#8217;s take it back though. What really is a boilerplate? <a href="https://en.oxforddictionaries.com/definition/boilerplate">Dictionary.com</a> failed in getting me a definition that would work. <a href="https://en.oxforddictionaries.com/definition/boilerplate">Oxford Dictionaries</a> on the other hand landed the W with:</p>
<blockquote><p><strong>3.1</strong> Standardized pieces of text for use as clauses in contracts or as part of a computer program.</p></blockquote>
<p>This works. So something that&#8217;s standard across computer programs. As in some code that&#8217;s always the same at least in theory. So instead of having to run things like <code>npm i react react-dom webpack</code> etc&#8230; every time we start a project we can copy our boilerplate and be off to the races knowing all the essential pieces we want are ready to go. We&#8217;ll also know that everything is being maintained the way <em>we</em> want it to because it&#8217;s ours. We also will learn <strong>a lot</strong> during the process and possibly even decide to make decisions that differ from what others have instructed us to do.</p>
<h2>Get Git</h2>
<p>First let&#8217;s create a local folder and make this a Git repository.<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2793" src="https://sethaalexander.com/wp-content/uploads/2018/05/01.png" alt="git init" width="632" height="404" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/01.png 632w, https://sethaalexander.com/wp-content/uploads/2018/05/01-300x192.png 300w" sizes="(max-width: 632px) 100vw, 632px" /></p>
<h2>First things First</h2>
<p>Now, what type of project would this be without a <code>README.md</code>? Every repository should have a readme file. Even if it&#8217;s just to remind YOU about how things work. Trust me, it may seem like you&#8217;ll remember exactly what each script does and why right now. However, a year from now these readme&#8217;s come in handy! Trust me. So, create a <code>README.md</code> in the root of the project. Put something like this in there:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2794" src="https://sethaalexander.com/wp-content/uploads/2018/05/02.png" alt="readme" width="756" height="526" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/02.png 756w, https://sethaalexander.com/wp-content/uploads/2018/05/02-300x209.png 300w" sizes="(max-width: 756px) 100vw, 756px" /></p>
<p>Make sure to commit your files to Git after any changes you make:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2792" src="https://sethaalexander.com/wp-content/uploads/2018/05/03.png" alt="commit" width="696" height="364" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/03.png 696w, https://sethaalexander.com/wp-content/uploads/2018/05/03-300x157.png 300w" sizes="(max-width: 696px) 100vw, 696px" /></p>
<h2>Folder Structure</h2>
<p>This one is pretty straightforward. Make the following folder structure to house everything:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2796" src="https://sethaalexander.com/wp-content/uploads/2018/05/04.png" alt="folder structure" width="552" height="486" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/04.png 552w, https://sethaalexander.com/wp-content/uploads/2018/05/04-300x264.png 300w" sizes="(max-width: 552px) 100vw, 552px" /></p>
<p>You can accomplish this easily with this command:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2797" src="https://sethaalexander.com/wp-content/uploads/2018/05/05.png" alt="mkdir" width="840" height="322" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/05.png 840w, https://sethaalexander.com/wp-content/uploads/2018/05/05-300x115.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/05-768x294.png 768w" sizes="(max-width: 840px) 100vw, 840px" /></p>
<h2>.gitignore</h2>
<p>An essential part of any Git project is the <code>.gitignore</code> file. This tells git to not put certain files under version control. This is important for things like packages and other things that we will retrieve from repositories. Not only do we not need these in version control but it&#8217;s actually detrimental if we do include them in version control. At least I&#8217;m pretty sure it&#8217;s detrimental. Create a <code>.gitignore</code> file in the root of your project and add the following to it:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2798" src="https://sethaalexander.com/wp-content/uploads/2018/05/06.png" alt="gitignore" width="424" height="486" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/06.png 424w, https://sethaalexander.com/wp-content/uploads/2018/05/06-262x300.png 262w" sizes="(max-width: 424px) 100vw, 424px" /></p>
<p>There are generators for this file, like <a href="https://www.gitignore.io/">this one</a>, but this should be enough for what we&#8217;re doing today.</p>
<h2>npm</h2>
<p>All node projects must be initialized so we can use the package manager. This will create a <code>package.json</code> file for us which must be in version control.</p>
<p>It contains many things but the most important are:</p>
<ul>
<li>A list of all the installed packages and their semantic version allowed</li>
<li>Scripts</li>
</ul>
<p>To start this process enter the following in your terminal in the root of your project:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2799" src="https://sethaalexander.com/wp-content/uploads/2018/05/07.png" alt="npm init" width="344" height="322" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/07.png 344w, https://sethaalexander.com/wp-content/uploads/2018/05/07-300x281.png 300w" sizes="(max-width: 344px) 100vw, 344px" /></p>
<p>You&#8217;ll be asked more than a few questions, feel free to just press Enter and leave it all blank, and in the end you&#8217;ll now have a shiny new <code>package.json</code> that looks something like this:<br />
<img loading="lazy" decoding="async" class="alignnone size-large wp-image-2800" src="https://sethaalexander.com/wp-content/uploads/2018/05/08-1024x772.png" alt="package.json" width="720" height="543" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/08-1024x772.png 1024w, https://sethaalexander.com/wp-content/uploads/2018/05/08-300x226.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/08-768x579.png 768w, https://sethaalexander.com/wp-content/uploads/2018/05/08.png 1128w" sizes="(max-width: 720px) 100vw, 720px" /></p>
<h2>HTML</h2>
<p>Yes! Time to write some code! Well, this is going to be the most boring HTML you probably ever write. Create an <code>index.html</code> in the root of your project and set it up like so:<br />
<img loading="lazy" decoding="async" class="alignnone size-large wp-image-2801" src="https://sethaalexander.com/wp-content/uploads/2018/05/09-1024x576.png" alt="html" width="720" height="405" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/09-1024x576.png 1024w, https://sethaalexander.com/wp-content/uploads/2018/05/09-300x169.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/09-768x432.png 768w, https://sethaalexander.com/wp-content/uploads/2018/05/09.png 1368w" sizes="(max-width: 720px) 100vw, 720px" /></p>
<h2>React</h2>
<p>Now, let&#8217;s add React to our project.<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2802" src="https://sethaalexander.com/wp-content/uploads/2018/05/10.png" alt="react install" width="552" height="322" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/10.png 552w, https://sethaalexander.com/wp-content/uploads/2018/05/10-300x175.png 300w" sizes="(max-width: 552px) 100vw, 552px" /></p>
<p>Create this file <code>/src/components/App.js</code> and in it put the following:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2803" src="https://sethaalexander.com/wp-content/uploads/2018/05/11.png" alt="app 1" width="888" height="810" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/11.png 888w, https://sethaalexander.com/wp-content/uploads/2018/05/11-300x274.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/11-768x701.png 768w" sizes="(max-width: 888px) 100vw, 888px" /></p>
<p>Then we will render the App via an index which we will create here at <code>/src/index.js</code> and put the following in:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2804" src="https://sethaalexander.com/wp-content/uploads/2018/05/12.png" alt="index 1" width="760" height="606" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/12.png 760w, https://sethaalexander.com/wp-content/uploads/2018/05/12-300x239.png 300w" sizes="(max-width: 760px) 100vw, 760px" /></p>
<h2>Babel</h2>
<p>Babel is awesome. It lets us write the latest and greatest JavaScript while ensuring we have maximum compatibility with the code we ship. First thing is we have to install Babel and a few additional Babel packages to make this all work together. Don&#8217;t worry it&#8217;ll be explained soon.<br />
<img loading="lazy" decoding="async" class="alignnone wp-image-2901 size-large" src="https://sethaalexander.com/wp-content/uploads/2018/05/01-1-1024x217.png" alt="" width="720" height="153" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/01-1-1024x217.png 1024w, https://sethaalexander.com/wp-content/uploads/2018/05/01-1-300x64.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/01-1-768x163.png 768w, https://sethaalexander.com/wp-content/uploads/2018/05/01-1.png 1510w" sizes="(max-width: 720px) 100vw, 720px" /></p>
<p>Then we need to create a <code>.babelrc</code> in the root of our project and add the following to it:<br />
<img loading="lazy" decoding="async" class="alignnone wp-image-2902 size-full" src="https://sethaalexander.com/wp-content/uploads/2018/05/02-1.png" alt="" width="938" height="394" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/02-1.png 938w, https://sethaalexander.com/wp-content/uploads/2018/05/02-1-300x126.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/02-1-768x323.png 768w" sizes="(max-width: 938px) 100vw, 938px" /></p>
<p>Now, what does this do exactly? The <code>env</code> preset implicitly includes <code>babel-preset-es2015</code>, <code>babel-preset-es2016</code>, <code>babel-preset-es2017</code>, and <code>babel-preset-latest</code> together, which means you can run ES6, ES7, and ES8 code.</p>
<p>The <code>react</code> preset I <em>think</em> is pretty self-explanatory, but, you might be wondering why we need it if React is JavaScript. That&#8217;s because Babel doesn&#8217;t know what to do with React &amp; JSX.</p>
<p>NOTE: I removed the stage-2 preset from this update. If you’re wondering why, read this great post by the Babel team: <a href="https://babeljs.io/blog/2018/07/27/removing-babels-stage-presets" data-href="https://babeljs.io/blog/2018/07/27/removing-babels-stage-presets" class="markup--anchor markup--p-anchor" rel="nofollow noopener" target="_blank">Removing Babel’s Stage Presets</a>.</p>
<h2>Tests</h2>
<p>So we&#8217;re making progress. Now that we have a React component with our <code>App.js</code> let&#8217;s make sure to create a simple associated test for that component. This way we&#8217;re starting to ensure some good practices of having tests for the things we build. We will be using Jest with Enzyme for this project. First things first, let&#8217;s install it with:<br />
<img loading="lazy" decoding="async" class="alignnone size-large wp-image-2815" src="https://sethaalexander.com/wp-content/uploads/2018/05/15-1024x241.png" alt="jest enzyme install" width="720" height="169" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/15-1024x241.png 1024w, https://sethaalexander.com/wp-content/uploads/2018/05/15-300x71.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/15-768x181.png 768w, https://sethaalexander.com/wp-content/uploads/2018/05/15.png 1368w" sizes="(max-width: 720px) 100vw, 720px" /></p>
<p>Now create <code>/test/enzyme.setup.js</code> and put in it:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2817" src="https://sethaalexander.com/wp-content/uploads/2018/05/16.png" alt="enzyme setup" width="936" height="526" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/16.png 936w, https://sethaalexander.com/wp-content/uploads/2018/05/16-300x169.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/16-768x432.png 768w" sizes="(max-width: 936px) 100vw, 936px" /></p>
<p>We&#8217;ll need to add Jest functionality into our <code>package.json</code> so add the following to it:<br />
<img loading="lazy" decoding="async" class="alignnone size-large wp-image-2820" src="https://sethaalexander.com/wp-content/uploads/2018/05/17-1024x493.png" alt="jest functionality" width="720" height="347" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/17-1024x493.png 1024w, https://sethaalexander.com/wp-content/uploads/2018/05/17-300x144.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/17-768x370.png 768w, https://sethaalexander.com/wp-content/uploads/2018/05/17.png 1176w" sizes="(max-width: 720px) 100vw, 720px" /></p>
<p>Next, we should add our first component test! So, create a file at <code>/test/App.test.js</code> to test that our App component renders as expected. We are also going to implement a snapshot test to ensure our components structure doesn&#8217;t change from test to test. To do that we&#8217;ll need the following:<br />
<img loading="lazy" decoding="async" class="alignnone size-large wp-image-2819" src="https://sethaalexander.com/wp-content/uploads/2018/05/18-1024x583.png" alt="app test" width="720" height="410" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/18-1024x583.png 1024w, https://sethaalexander.com/wp-content/uploads/2018/05/18-300x171.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/18-768x437.png 768w, https://sethaalexander.com/wp-content/uploads/2018/05/18.png 1352w" sizes="(max-width: 720px) 100vw, 720px" /></p>
<p>You might be wondering how to run this new test. To do so we need to change the <code>test</code> script in the <code>package.json</code> to this:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2821" src="https://sethaalexander.com/wp-content/uploads/2018/05/19.png" alt="test script" width="616" height="566" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/19.png 616w, https://sethaalexander.com/wp-content/uploads/2018/05/19-300x276.png 300w" sizes="(max-width: 616px) 100vw, 616px" /></p>
<p>You can now run the test from your terminal with <code>npm test</code> and should see something like this:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2822" src="https://sethaalexander.com/wp-content/uploads/2018/05/Screenshot-from-2018-05-09-23-40-27.png" alt="jest run" width="1021" height="503" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/Screenshot-from-2018-05-09-23-40-27.png 1021w, https://sethaalexander.com/wp-content/uploads/2018/05/Screenshot-from-2018-05-09-23-40-27-300x148.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/Screenshot-from-2018-05-09-23-40-27-768x378.png 768w" sizes="(max-width: 1021px) 100vw, 1021px" /></p>
<h3>Break Time</h3>
<p>If you&#8217;ve made it this far with your React boilerplate, CONGRATS! Mostly because you&#8217;ve realized that I&#8217;m using images for my code and you have to type it all out. That&#8217;s a pain in the ass, I know. Trust me though, you&#8217;re learning more than you know by being forced to type it all and the muscle memory is going to serve you well long after this tutorial.</p>
<h2>webpack</h2>
<p>webpack will allow us to modularize our code and easily bundle it into a single file for production. Something I think a lot of people really like about webpack though is the development server! We&#8217;ll start by just installing webpack with:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2823" src="https://sethaalexander.com/wp-content/uploads/2018/05/20.png" alt="webpack install" width="600" height="322" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/20.png 600w, https://sethaalexander.com/wp-content/uploads/2018/05/20-300x161.png 300w" sizes="(max-width: 600px) 100vw, 600px" /></p>
<p>webpack looks for a <code>webpack.config.js</code> file by default in the root of the project so let&#8217;s create that and add to it a couple things:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2825" src="https://sethaalexander.com/wp-content/uploads/2018/05/21.png" alt="entry output" width="744" height="728" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/21.png 744w, https://sethaalexander.com/wp-content/uploads/2018/05/21-300x294.png 300w" sizes="(max-width: 744px) 100vw, 744px" /><br />
The <code>entry</code> is telling webpack where to find the base JavaScript file. In our application that&#8217;s <code>index.js</code>. Then it tells it where to output the built file when it&#8217;s done with it.</p>
<h3>webpack loaders</h3>
<p>Loaders are helpful pieces we can add to webpack to make it more powerful and do things to other file types. Before webpack will work properly we need to set it up to work with ES6 and JSX. We&#8217;ll do this through the <code>babel-loader</code>. Add the <code>babel-loader</code> to your project with:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2828" src="https://sethaalexander.com/wp-content/uploads/2018/05/22.png" alt="babel-loader install" width="680" height="322" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/22.png 680w, https://sethaalexander.com/wp-content/uploads/2018/05/22-300x142.png 300w" sizes="(max-width: 680px) 100vw, 680px" /></p>
<p>Then add the loader to your <code>webpack.config.js</code> like so:<br />
<img loading="lazy" decoding="async" class="alignnone size-large wp-image-2827" src="https://sethaalexander.com/wp-content/uploads/2018/05/23-831x1024.png" alt="config with babel-loader" width="720" height="887" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/23-831x1024.png 831w, https://sethaalexander.com/wp-content/uploads/2018/05/23-244x300.png 244w, https://sethaalexander.com/wp-content/uploads/2018/05/23-768x946.png 768w, https://sethaalexander.com/wp-content/uploads/2018/05/23.png 888w" sizes="(max-width: 720px) 100vw, 720px" /></p>
<p>To utilize Sass and SCSS we&#8217;ll need another loader. Now to get the best &#8220;bang for our buck&#8221; we&#8217;re going to chain three loaders together so our styles are applied immediately to the DOM. Let&#8217;s install the loaders:<br />
<img loading="lazy" decoding="async" class="alignnone size-large wp-image-2829" src="https://sethaalexander.com/wp-content/uploads/2018/05/24-1024x273.png" alt="add sass" width="720" height="192" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/24-1024x273.png 1024w, https://sethaalexander.com/wp-content/uploads/2018/05/24-300x80.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/24-768x205.png 768w, https://sethaalexander.com/wp-content/uploads/2018/05/24.png 1208w" sizes="(max-width: 720px) 100vw, 720px" /></p>
<p>And configure it like so in our <code>webpack.config.js</code>:<br />
<img loading="lazy" decoding="async" class="alignnone size-large wp-image-2830" src="https://sethaalexander.com/wp-content/uploads/2018/05/25-606x1024.png" alt="config with sass added" width="606" height="1024" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/25-606x1024.png 606w, https://sethaalexander.com/wp-content/uploads/2018/05/25-178x300.png 178w, https://sethaalexander.com/wp-content/uploads/2018/05/25-768x1297.png 768w, https://sethaalexander.com/wp-content/uploads/2018/05/25.png 888w" sizes="(max-width: 606px) 100vw, 606px" /></p>
<p>Since we just enabled some style support let&#8217;s add some. Create <code>/src/styles/style.sass</code> and put in it:<br />
<img loading="lazy" decoding="async" class="alignnone size-large wp-image-2835" src="https://sethaalexander.com/wp-content/uploads/2018/05/32-sass-1024x376.png" alt="sass code" width="720" height="264" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/32-sass-1024x376.png 1024w, https://sethaalexander.com/wp-content/uploads/2018/05/32-sass-300x110.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/32-sass-768x282.png 768w, https://sethaalexander.com/wp-content/uploads/2018/05/32-sass.png 1208w" sizes="(max-width: 720px) 100vw, 720px" /></p>
<p>Then add it to your <code>index.js</code> like so:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2836" src="https://sethaalexander.com/wp-content/uploads/2018/05/33-index-with-sass.png" alt="index with sass added" width="760" height="688" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/33-index-with-sass.png 760w, https://sethaalexander.com/wp-content/uploads/2018/05/33-index-with-sass-300x272.png 300w" sizes="(max-width: 760px) 100vw, 760px" /></p>
<p>Up next are webpack plugins. So, we need a way to include the built JavaScript in our <code>index.html</code> and of course, there&#8217;s a way to do this automatically. This is also going to take the <code>index.html</code> file and drop it into our build folder (more on the build later). Let&#8217;s add the <code>HtmlWebPackPlugin</code> and include it in our <code>webpack.config.js</code> like so:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2831" src="https://sethaalexander.com/wp-content/uploads/2018/05/26.png" alt="install html-webpack-plugin" width="792" height="322" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/26.png 792w, https://sethaalexander.com/wp-content/uploads/2018/05/26-300x122.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/26-768x312.png 768w" sizes="(max-width: 792px) 100vw, 792px" /></p>
<p>Then:<br />
<img loading="lazy" decoding="async" class="alignnone size-large wp-image-2832" src="https://sethaalexander.com/wp-content/uploads/2018/05/27-653x1024.png" alt="webpack config with htmlwebpackplugin" width="653" height="1024" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/27-653x1024.png 653w, https://sethaalexander.com/wp-content/uploads/2018/05/27-191x300.png 191w, https://sethaalexander.com/wp-content/uploads/2018/05/27-768x1204.png 768w, https://sethaalexander.com/wp-content/uploads/2018/05/27.png 1112w" sizes="(max-width: 653px) 100vw, 653px" /></p>
<p>Our next plugin is going to ensure that the directory we put our build in is cleaned out of any former files every time we run a build. We do that with these two steps:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2834" src="https://sethaalexander.com/wp-content/uploads/2018/05/28.png" alt="install clean-webpack-plugin" width="808" height="322" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/28.png 808w, https://sethaalexander.com/wp-content/uploads/2018/05/28-300x120.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/28-768x306.png 768w" sizes="(max-width: 808px) 100vw, 808px" /></p>
<p>Then:<br />
<img loading="lazy" decoding="async" class="alignnone wp-image-2928 size-full" src="https://sethaalexander.com/wp-content/uploads/2018/05/carbon.svg" alt="cleanwebpackplugin" width="589" height="849" /></p>
<p>The moment we&#8217;ve all been waiting for! Let&#8217;s get the development server setup. So we&#8217;re going to add two packages in this step. <code>webpack-cli</code> is going to be used to run our commands from our <code>package.json</code> file. First:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2837" src="https://sethaalexander.com/wp-content/uploads/2018/05/30.png" alt="webpack dev server install" width="968" height="322" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/30.png 968w, https://sethaalexander.com/wp-content/uploads/2018/05/30-300x100.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/30-768x255.png 768w" sizes="(max-width: 968px) 100vw, 968px" /></p>
<p>Then update our <code>webpack.config.js</code>:<br />
<img loading="lazy" decoding="async" class="alignnone size-large wp-image-2839" src="https://sethaalexander.com/wp-content/uploads/2018/05/31-578x1024.png" alt="add dev server" width="578" height="1024" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/31-578x1024.png 578w, https://sethaalexander.com/wp-content/uploads/2018/05/31-169x300.png 169w, https://sethaalexander.com/wp-content/uploads/2018/05/31-768x1361.png 768w, https://sethaalexander.com/wp-content/uploads/2018/05/31.png 1144w" sizes="(max-width: 578px) 100vw, 578px" /></p>
<p>Finally add to the scripts section of the <code>package.json</code>:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2840" src="https://sethaalexander.com/wp-content/uploads/2018/05/34.png" alt="start script" width="760" height="526" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/34.png 760w, https://sethaalexander.com/wp-content/uploads/2018/05/34-300x208.png 300w" sizes="(max-width: 760px) 100vw, 760px" /></p>
<p>Now fire up your development server and your default browser will open. It&#8217;ll take a second while webpack does it&#8217;s thing but you&#8217;ll soon see you React live in the browser.<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2841" src="https://sethaalexander.com/wp-content/uploads/2018/05/35.png" alt="npm start" width="360" height="322" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/35.png 360w, https://sethaalexander.com/wp-content/uploads/2018/05/35-300x268.png 300w" sizes="(max-width: 360px) 100vw, 360px" /></p>
<p>So right now we could say success! However, our code isn&#8217;t optimized for production use. However, we don&#8217;t want to optimize our code while we&#8217;re in development either because it takes a lot longer to build. So let&#8217;s create separate build files for our production and development environments and tell webpack how to handle that. I promise we&#8217;re almost done. Really we are&#8230; Up next is:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2842" src="https://sethaalexander.com/wp-content/uploads/2018/05/36.png" alt="install webpack-merge" width="696" height="322" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/36.png 696w, https://sethaalexander.com/wp-content/uploads/2018/05/36-300x139.png 300w" sizes="(max-width: 696px) 100vw, 696px" /></p>
<p>This is going to allow us to have three webpack config files. So let&#8217;s get that setup. Rename your <code>webpack.config.js</code> to <code>webpack.common.js</code>. Then create <code>webpack.dev.js</code> and <code>webpack.prod.js</code>. The idea is one will have configuration used in both development and production, one will be development only, and one will be production only. So first thing, let&#8217;s remove the development server code from common we just added in the last step and add it to <code>webpack.dev.js</code>. We&#8217;ll utilize <code>webpack-merge</code> to include everything from <code>webpack.common.js</code> and add on <code>webpack.dev.js</code>. So now your <code>webpack.common.js</code> looks like this:<br />
<img loading="lazy" decoding="async" class="alignnone size-large wp-image-2844" src="https://sethaalexander.com/wp-content/uploads/2018/05/37-642x1024.png" alt="webpack common" width="642" height="1024" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/37-642x1024.png 642w, https://sethaalexander.com/wp-content/uploads/2018/05/37-188x300.png 188w, https://sethaalexander.com/wp-content/uploads/2018/05/37-768x1225.png 768w, https://sethaalexander.com/wp-content/uploads/2018/05/37.png 1144w" sizes="(max-width: 642px) 100vw, 642px" /></p>
<p>Your <code>webpack.dev.js</code> should look like this:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2845" src="https://sethaalexander.com/wp-content/uploads/2018/05/38.png" alt="webpack dev" width="952" height="728" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/38.png 952w, https://sethaalexander.com/wp-content/uploads/2018/05/38-300x229.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/38-768x587.png 768w" sizes="(max-width: 952px) 100vw, 952px" /></p>
<p>Your <code>webpack.prod.js</code> should look like this:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2846" src="https://sethaalexander.com/wp-content/uploads/2018/05/39.png" alt="webpack prod" width="952" height="526" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/39.png 952w, https://sethaalexander.com/wp-content/uploads/2018/05/39-300x166.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/39-768x424.png 768w" sizes="(max-width: 952px) 100vw, 952px" /></p>
<p>The last step here is to update the <code>scripts</code> in our <code>package.json</code> file to utilize these different files at different times. Your new <code>scripts</code> sections should look like:<br />
<img loading="lazy" decoding="async" class="alignnone size-large wp-image-2847" src="https://sethaalexander.com/wp-content/uploads/2018/05/40-1024x507.png" alt="final scripts" width="720" height="356" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/40-1024x507.png 1024w, https://sethaalexander.com/wp-content/uploads/2018/05/40-300x148.png 300w, https://sethaalexander.com/wp-content/uploads/2018/05/40-768x380.png 768w, https://sethaalexander.com/wp-content/uploads/2018/05/40.png 1144w" sizes="(max-width: 720px) 100vw, 720px" /></p>
<h2>What now?</h2>
<p>Now you can go ahead and start your development server with:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2841" src="https://sethaalexander.com/wp-content/uploads/2018/05/35.png" alt="npm start" width="360" height="322" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/35.png 360w, https://sethaalexander.com/wp-content/uploads/2018/05/35-300x268.png 300w" sizes="(max-width: 360px) 100vw, 360px" /></p>
<p>You can build your application and have all the advantages of everything we&#8217;ve put together. When you&#8217;re ready to deploy your production application just run:<br />
<img loading="lazy" decoding="async" class="alignnone size-full wp-image-2848" src="https://sethaalexander.com/wp-content/uploads/2018/05/41.png" alt="npm run build" width="424" height="322" srcset="https://sethaalexander.com/wp-content/uploads/2018/05/41.png 424w, https://sethaalexander.com/wp-content/uploads/2018/05/41-300x228.png 300w" sizes="(max-width: 424px) 100vw, 424px" /></p>
<p>This will output an optimized version of your code into the <code>/dist</code> folder. Take those files and upload them to your favorite host and you&#8217;re good to go!</p>
<h2>What&#8217;s Next With Your React Boilerplate?</h2>
<p>Well, nothing from me! Ha, I think you&#8217;ve had enough by now. Hopefully, this empowers you to dive into creating your own boilerplate. You&#8217;ll start your personal projects steps ahead and really get an understanding of what each piece does. I <strong>HIGHLY</strong> recommend the <a href="https://webpack.js.org/concepts/">webpack docs</a> for further reading if you want to continue to add configuration to your webpack setup. There is <strong>A LOT</strong> more you can do with it. Another thing you might want to do is set up something like <a href="https://eslint.org/">ESLint</a> in your project as well. You can also dive deep into <a href="https://babeljs.io/">Babel</a> and all that it allows you to do.</p>
<p>Thanks and I&#8217;d love to hear what you think about this setup. Anything you&#8217;d add, remove or change leave in the comments below.</p>
<p>I ALMOST FORGOT! <em>Actually I did, I&#8217;m adding this after I clicked &#8220;Publish&#8221;</em>. If you want to find all this code I have it in a repo <a href="https://github.com/itzsaga/react-boilerplate-blog">here</a>.</p>
<p>The post <a href="https://sethaalexander.com/how-to-build-your-own-react-boilerplate/">How-to Build Your Own React Boilerplate</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sethaalexander.com/how-to-build-your-own-react-boilerplate/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Portfolio Site How-To For New Developers</title>
		<link>https://sethaalexander.com/portfolio-site-new-developers/</link>
					<comments>https://sethaalexander.com/portfolio-site-new-developers/#respond</comments>
		
		<dc:creator><![CDATA[Seth Alexander]]></dc:creator>
		<pubDate>Sat, 10 Mar 2018 22:22:11 +0000</pubDate>
				<category><![CDATA[General]]></category>
		<guid isPermaLink="false">https://sethaalexander.com/?p=2753</guid>

					<description><![CDATA[<p>I recently shared my portfolio site with the Free Code Camp Nashville group and got some inquiries into some of the technologies and features I used to build it. So I figured I&#8217;d share all aspects of the site and some steps to utilizing the same tools I did. Should I build my site from&#8230; <a class="more-link" href="https://sethaalexander.com/portfolio-site-new-developers/">Continue reading <span class="screen-reader-text">Portfolio Site How-To For New Developers</span> <span class="meta-nav" aria-hidden="true">&#8594;</span></a></p>
<p>The post <a href="https://sethaalexander.com/portfolio-site-new-developers/">Portfolio Site How-To For New Developers</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>I recently shared my <a href="http://sethalexander.me">portfolio site</a> with the <a href="https://www.facebook.com/groups/free.code.camp.nashville/">Free Code Camp Nashville</a> group and got some inquiries into some of the technologies and features I used to build it. So I figured I&#8217;d share all aspects of the site and some steps to utilizing the same tools I did.</p>
<h3>Should I build my site from scratch?</h3>
<p>When I asked this question to the ever helpful NashDev community I received a resounding &#8220;No&#8221; from Senior devs. This might seem counter intuitive, however, the overall thought process was if you&#8217;re just starting out, unless you&#8217;re looking to be considered a designer, then using something someone else has already done very well as the base of your portfolio is better than building it yourself. Concentrate on highlighting the things that you are going to be doing in a potential job, not on the overall layout and design of your portfolio site. I decided to go with a template from <a href="https://html5up.net/">HTML5 UP</a> for a few reasons. First, they&#8217;re FREE as long as you keep the attribution. Second, <a href="https://twitter.com/ajlkn">AJ</a> who creates these amazing templates is based out of Nashville just like me and had in the past connected me with some solid people to have beer/coffee with and discuss my career. Third, it&#8217;s a static site. That is, it&#8217;s 100% HTML, CSS &amp; JavaScript so I would have many simple options for hosting when I got to that point. Lastly, all of the templates are responsive so if a potential hiring manager clicks through from their phone they&#8217;re going to get a great experience.<br />
<span id="more-2753"></span></p>
<h3>I&#8217;ve got my template, now what?</h3>
<p>Fill er up with content! So this I don&#8217;t think I can help with too much. What you decide to include on your site is going to be up to you. However, as this is going to be something professional shy away from anything controversial. Keep it scoped around the skills you have and things you have built. A couple resources that I used for my site. The high-res background images I used all came from <a href="https://unsplash.com/">Unsplash</a>. Unsplash describes itself as:</p>
<blockquote><p>Beautiful, free photos.<br />
Gifted by the world’s most generous community of photographers. ?</p></blockquote>
<p>There aren&#8217;t <em>that</em> many coding images so once you&#8217;ve seen them you&#8217;ll start noticing them all over the web. Check them out and see if you can find interesting images that represent YOU and use them. Or don&#8217;t. Like I said, it&#8217;s up to you. Another cool place I found but didn&#8217;t get to integrate is <a href="https://coverr.co/">Coverr</a> which provides &#8220;beautiful, free videos for your homepage&#8221;. I still want to replace the top image on my site with one of their videos on a loop. I just haven&#8217;t spent the time to figure out how to implement it within the template I am using. All of my technology icons come from <a href="http://konpa.github.io/devicon/">DEVICON</a> which has sweet full color SVG&#8217;s. Note, if you don&#8217;t see it on the linked site check there GitHub repo <a href="https://github.com/konpa/devicon">here</a> as I found not all the icons are on their site. Just look in the icons folder of the repo. I like these icons because since they&#8217;re SVG&#8217;s they they will look great no matter their scale. For example this Vim icon:</p>
<p>I implemented my contact for by using <a href="https://formspree.io/">Formspree</a> which is a sweet way to add a form to a site super simply. I wouldn&#8217;t suggest using them for a production app but for something like this they&#8217;re perfect. They also include reCAPTCHA by default so you won&#8217;t have to worry about spam.</p>
<h3>It&#8217;s done! How should I host it?</h3>
<p>Before moving on to picking a web host, I think you should get yourself a domain name. I&#8217;ve been an avid user of <a href="https://namecheap.pxf.io/c/1213859/386170/5618">Namecheap</a> (<em>Full Disclosure: This is an affiliate link. I recommend them because I use them not because I can get 20% of your domain purchase.</em>) for years and purchase all my domains through them. Try for a first name, last name domain. Stay away from domains that are truly vanity and try to stick to .com, .io, .me if you can. They&#8217;re just easier to remember in general. Once again, do what you want. This is just what I would do.</p>
<p>Now because you&#8217;ve built a static site there are MANY free options that you can use in conjunction with your domain name for hosting. I currently use <a href="http://surge.sh/">Surge</a> however, <a href="https://zeit.co/now">Now</a>, <a href="https://pages.github.com/">GitHub Pages</a> and <a href="https://www.netlify.com/">Netlify</a> are also very common, free and easy to use. If you&#8217;re looking for a more fully featured web host I currently use <a href="https://account.geekghost.net/aff.php?aff=45">GeekGhost</a> (<em>Another affiliate link</em>) and enjoy them. I haven&#8217;t had any issues, they allow Let&#8217;s Encrypt SSL Certificates (an easy and free way to get your site using HTTPS) and their base plan is only $3.50/mo! I won&#8217;t go through deploying your site and setting up your domain name as this will be different for each host you may use. Feel free to ask host specific questions in the comments.</p>
<h3>I&#8217;m online, what now?</h3>
<p>Honestly, not much. Just make sure to link to your site from your resume, on LinkedIn, etc&#8230; In addition, remember to keep your site updated as you gain new work experience, publish new projects, and acquire new skills. You never know who might be looking at your portfolio and decide they want to reach out to you!</p>
<p>The post <a href="https://sethaalexander.com/portfolio-site-new-developers/">Portfolio Site How-To For New Developers</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sethaalexander.com/portfolio-site-new-developers/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>freeCodeCamp Nashville December Meetup Recap</title>
		<link>https://sethaalexander.com/freecodecamp-nashville-december-meetup-recap/</link>
					<comments>https://sethaalexander.com/freecodecamp-nashville-december-meetup-recap/#respond</comments>
		
		<dc:creator><![CDATA[Seth Alexander]]></dc:creator>
		<pubDate>Tue, 02 Jan 2018 04:03:44 +0000</pubDate>
				<category><![CDATA[freeCodeCamp Nashville]]></category>
		<guid isPermaLink="false">https://sethaalexander.com/?p=2718</guid>

					<description><![CDATA[<p>After taking a hiatus from our meetup for a month due to family obligations, Dave and I were back at it again this month for the freeCodeCamp Nashville meetup. This month we pulled together a group of technical recruiters for some Q&#38;A. The premise behind this time together was that recruiters can be a valuable&#8230; <a class="more-link" href="https://sethaalexander.com/freecodecamp-nashville-december-meetup-recap/">Continue reading <span class="screen-reader-text">freeCodeCamp Nashville December Meetup Recap</span> <span class="meta-nav" aria-hidden="true">&#8594;</span></a></p>
<p>The post <a href="https://sethaalexander.com/freecodecamp-nashville-december-meetup-recap/">freeCodeCamp Nashville December Meetup Recap</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>After taking a hiatus from our meetup for a month due to family obligations, <a href="https://github.com/davi3blu3">Dave</a> and I were back at it again this month for the <a href="https://www.meetup.com/freeCodeCamp-Nashville">freeCodeCamp Nashville</a> meetup. This month we pulled together a group of technical recruiters for some Q&amp;A. The premise behind this time together was that recruiters can be a valuable asset to people in the tech scene through their relationships with companies as well as their knowledge of how to best get past some common barriers. However, recruiters seems to get a bad wrap in general due to some bad apples in the industry. Those people who are required by a company or boss to get X number of calls or contacts in per day per position. I know I&#8217;ve personally received emails about positions that I <em>know</em> I&#8217;m not qualified for and anybody who took a few seconds to scan my LinkedIn profile would know as well.<br />
<span id="more-2718"></span><br />
First, our three panelists:<br />
&#8211; Caroline McGowan works for <a href="https://fortyau.com/">FortyAU</a> where she is an Account Manager and focuses on internal recruiting.<br />
&#8211; Hunter Mitchem works for <a href="https://www.otterbase.com/">OtterBase</a> where he is a Technical Recruiter focusing on finding talent for positions in Nashville.<br />
&#8211; Sydney Crimmins works for <a href="https://www.simplypeople.us/">SimplyPeople.us</a> where she is the Chief Recruiting Officer and focuses on filling position in Nashville.</p>
<p>Below you&#8217;ll find the highlights and some noteworthy quotes from our discussion. With any panel discussion it&#8217;s difficult to keep very detailed notes. I did the best I could and these are the types of things we hope you attend in the future with us. With that, I do hope some of this helps you out some. Use the comments for questions and further discussion. Or just join on in the #freecodecamp channel on the <a href="http://nashdev.com">NashDev</a> Slack network.</p>
<h3>One if the fist topics we discussed was <strong>LinkedIn</strong></h3>
<ul>
<li>Recruiters are keyword driven when looking through LinkedIn.</li>
<li>Make it concise and keep it professional.</li>
<li>What technologies you used and where. Not really looking at the summary.</li>
<li>&#8220;Be conscious of what you &#8220;like&#8221; because people see that,&#8221; Caroline.</li>
<li>&#8220;First impressions are key. &#8216;You get about 15 seconds before I decide to move on or stay,'&#8221; Sydney.</li>
<li>The heading should be what you know today not things that you&#8217;re going to do.</li>
</ul>
<p>Make sure that your LinkedIn account is setup so recruiters can find you:<br />
On your LinkedIn account click your profile picture, then <strong>Settings &amp; Privacy</strong>, next click <strong>Privacy</strong> at the top, then scroll down to <strong>Job Seeking</strong> and make sure that section is setup the way you&#8217;d like so recruiters can find you.<br />
<img loading="lazy" decoding="async" src="https://sethaalexander.com/wp-content/uploads/2018/01/Screenshot-2018-1-1-Share-Profile-With-Recruiter-LinkedIn.png" alt="" width="870" height="415" class="alignnone size-full wp-image-2730" srcset="https://sethaalexander.com/wp-content/uploads/2018/01/Screenshot-2018-1-1-Share-Profile-With-Recruiter-LinkedIn.png 870w, https://sethaalexander.com/wp-content/uploads/2018/01/Screenshot-2018-1-1-Share-Profile-With-Recruiter-LinkedIn-300x143.png 300w, https://sethaalexander.com/wp-content/uploads/2018/01/Screenshot-2018-1-1-Share-Profile-With-Recruiter-LinkedIn-768x366.png 768w" sizes="(max-width: 870px) 100vw, 870px" /><br />
In addition ensure your <a href="https://www.linkedin.com/jobs/career-interests">Career Interests</a> are accurate.</p>
<h3>Networking Is Key</h3>
<ul>
<li>Build your portfolio and projects you can explain. Real life in production apps that you can demonstrate.</li>
<li>Keep your Github up to date for others to look at.</li>
<li>You need the above two so that you can, &#8220;Find people to go to bat for you. Find people to say &#8216;Hey I need help. Take a look at my code or my projects.&#8217; Purely professional contacts,&#8221; Caroline.</li>
<li>References can help you fill the credibility gap so for sure list them up front when you have good ones.</li>
</ul>
<h3>The Nashville Job Market</h3>
<ul>
<li>More people interested in front end than backend. Finding backend devs is more challenging.</li>
<li>Even though the Nashville market is saturated for the Junior level positions Nashville is working on the situation and the community here is very open to people who are starting out.</li>
<li>Ruby on Rails &amp; Salesforce are in high demand.</li>
<li>Java.</li>
<li>Q3 is known as the highest time for staffing. Q4 slows down. Q1 companies typically get fresh new budgets.</li>
</ul>
<h3>Interview Tips</h3>
<ul>
<li>&#8220;Never say, &#8216;I learn quickly,&#8217; or &#8216;I&#8217;m a jack of all trades.&#8217; Be relaxed, be yourself.&#8221; Hunter.</li>
<li>&#8220;Be confident but also be humble.&#8221; &#8220;Address where your shortcomings might be up front. Point blank ask someone &#8216;What concerns can I alleviate for you.'&#8221; Caroline.</li>
<li>&#8220;Don&#8217;t be afraid to say no. Yes and no but. If you have worked with something say &#8216;Yes and&#8217; explain it. If you haven&#8217;t say, &#8220;No but&#8217; then explain something else.&#8221; Sydney.</li>
<li>Be confident and able to tell your story in a clear and <em><strong>concise</strong></em> way. &#8211; Caroline</li>
</ul>
<h3>Resume</h3>
<ul>
<li>Career changers could remove bullet points from past careers but still list the work to keep a resume concise.</li>
<li>One page is not the hard and fast rule.</li>
</ul>
<h3>Salary</h3>
<ul>
<li>Be transparent as you can with recruiters.</li>
<li>Typically on W2 roles the recruiting company gets a % so they are motivated to get you more.</li>
<li>Contract positions are typically a $ amount. So if you get paid less then the recruiting company will get more.</li>
<li>Junior in Nashville will be 50-60k typically.</li>
</ul>
<h3>General Advice</h3>
<ul>
<li>&#8220;Don&#8217;t be picky for the first gig. The experience is worth it and you can be more picky if or when you choose to move on to a new job.&#8221; Sydney.</li>
<li>Follow up with recruiters ~1 time per month when you haven&#8217;t heard from them.</li>
<li>Don&#8217;t deal with a recruiter who targets you obviously for a position you&#8217;re not qualified for. They&#8217;re just trying to get their numbers in.</li>
</ul>
<h3>Podcasts:</h3>
<ul>
<li>Freakanomics</li>
<li>Complete Developer Podcast</li>
<li>Junior Developer Toolbox</li>
<li>CodeNewbie </li>
<li>NashDev Podcast</li>
<li>JavaScript Jabber</li>
<li>NodeUp</li>
</ul>
<p>I hope this was helpful and I&#8217;m looking forward to the comments section on this one for more discussion of these topics.</p>
<p>The post <a href="https://sethaalexander.com/freecodecamp-nashville-december-meetup-recap/">freeCodeCamp Nashville December Meetup Recap</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sethaalexander.com/freecodecamp-nashville-december-meetup-recap/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>freeCodeCamp Nashville October Meetup Recap</title>
		<link>https://sethaalexander.com/freecodecamp-nashville-october-meetup-recap/</link>
					<comments>https://sethaalexander.com/freecodecamp-nashville-october-meetup-recap/#respond</comments>
		
		<dc:creator><![CDATA[Seth Alexander]]></dc:creator>
		<pubDate>Fri, 13 Oct 2017 03:48:55 +0000</pubDate>
				<category><![CDATA[freeCodeCamp Nashville]]></category>
		<guid isPermaLink="false">https://sethaalexander.com/?p=2526</guid>

					<description><![CDATA[<p>This past Saturday we had our monthly freeCodeCamp Nashville meetup at Nashville Software School. As always it was good times. We were supposed to have a guest speaker but they couldn&#8217;t make it at the last minute so our very own superstar and freeCodeCamp Nashville Co-Organizer Dave Harned stepped in and crushed it. He presented&#8230; <a class="more-link" href="https://sethaalexander.com/freecodecamp-nashville-october-meetup-recap/">Continue reading <span class="screen-reader-text">freeCodeCamp Nashville October Meetup Recap</span> <span class="meta-nav" aria-hidden="true">&#8594;</span></a></p>
<p>The post <a href="https://sethaalexander.com/freecodecamp-nashville-october-meetup-recap/">freeCodeCamp Nashville October Meetup Recap</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>This past Saturday we had our monthly freeCodeCamp Nashville meetup at Nashville Software School. As always it was good times. We were supposed to have a guest speaker but they couldn&#8217;t make it at the last minute so our very own superstar and freeCodeCamp Nashville Co-Organizer <a href="https://github.com/davi3blu3">Dave Harned</a> stepped in and crushed it. He presented a Crash Course on NodeJS. You can find the repo <a href="https://github.com/davi3blu3/fcc-node-crash">here</a> and excuse the work in progress readme. Like most things, it&#8217;s not perfect. Feel free to open a Pull Request and shore up those docs! I&#8217;m going to walk through what Dave presented on Saturday so you can see what you missed out on and come to the next one ;-). Honestly, so you can benefit from what I think is a well put together intro that&#8217;ll have you up, running, and playing around in no time.<br />
<span id="more-2526"></span><br />
Dave chose <a href="https://c9.io">Cloud9</a> as his IDE so everyone could follow along without having to worry about what people might, or might not, have on their computers. This also provides a consistent user experience so debugging is easier. So head over to Cloud9 and get signed up and logged in. Also, check out the repo from the link above and look at the readme.</p>
<p>Next, you&#8217;ll want to click <strong>Create a new workspace</strong>.<br />
<a href="https://sethaalexander.com/freecodecamp-nashville-october-meetup-recap/screenshot-from-2017-10-12-16-59-36/" rel="attachment wp-att-2529"><img loading="lazy" decoding="async" src="https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-16-59-36.png" alt="" width="331" height="372" class="aligncenter size-full wp-image-2529" srcset="https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-16-59-36.png 331w, https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-16-59-36-267x300.png 267w" sizes="(max-width: 331px) 100vw, 331px" /></a></p>
<p>Then, your <strong>Workspace name</strong> can be whatever you want. Leave <strong>Hosted workspace</strong> selected and choose <strong>Private</strong> or <strong>Public</strong>, it doesn&#8217;t matter which. In <strong>Clone from Git or Mercurial URL</strong> input <code>https://github.com/davi3blu3/fcc-node-crash.git</code>. Then, under <strong>Choose a template</strong> select <strong>Node.js</strong>. Lastly, click <strong>Create Workspace</strong>.<br />
<a href="https://sethaalexander.com/freecodecamp-nashville-october-meetup-recap/screenshot-from-2017-10-12-17-03-21/" rel="attachment wp-att-2530"><img loading="lazy" decoding="async" src="https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-17-03-21.png" alt="" width="1920" height="1026" class="aligncenter size-full wp-image-2530" srcset="https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-17-03-21.png 1920w, https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-17-03-21-300x160.png 300w, https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-17-03-21-768x410.png 768w, https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-17-03-21-1024x547.png 1024w" sizes="(max-width: 1920px) 100vw, 1920px" /></a></p>
<p>This might take a minute but eventually, you&#8217;ll have something that looks like this:<br />
<a href="https://sethaalexander.com/freecodecamp-nashville-october-meetup-recap/screenshot-from-2017-10-12-17-08-45/" rel="attachment wp-att-2531"><img loading="lazy" decoding="async" src="https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-17-08-45.png" alt="" width="1920" height="1026" class="aligncenter size-full wp-image-2531" srcset="https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-17-08-45.png 1920w, https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-17-08-45-300x160.png 300w, https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-17-08-45-768x410.png 768w, https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-17-08-45-1024x547.png 1024w" sizes="(max-width: 1920px) 100vw, 1920px" /></a></p>
<p>So first thing, let&#8217;s go to the terminal at the bottom of the screen and type in <code>npm install</code> and hit enter. That&#8217;s going to bring in all the packages at are in our <code>package.json</code> file. You&#8217;ll see a new folder in your file tree now called <code>node_modules</code>. That&#8217;s where all the packages live.</p>
<p>Now let&#8217;s open up <strong>1_helloworld.js</strong>. It should look like this (please excuse Dave&#8217;s inconsistent semicolon usage, I already ragged on him about it):</p>
<pre><code class="javascript">var hello = function() {
    console.log(&#039;Hello world&#039;);
}
hello();

// console.log(process.argv);

// var greet = process.argv[2] || &quot;World&quot;;

// var hello = function(name) {
//     console.log(&#039;Hello &#039; + name + &#039;!&#039;);
// }
// hello(greet);

</code></pre>
<p>Back in our terminal, we can run this file with <code>node 1_helloworld.js</code>. With the initial code, you should see &#8220;Hello World&#8221; printed in your terminal. This terminal is also our console inside Cloud9. So anything we <code>console.log</code> will end up here. We can see something interesting when we uncomment line 6 by taking out the <code>//</code>. So line 6 should look like this now: <code>console.log(process.argv);</code>. When we run <code>node 1_helloworld.js</code> we get our &#8220;Hello World&#8221; again but then we also get an array that has two elements. Yours should be the same as mine and be:</p>
<pre><code class="bash">[ &#039;/home/ubuntu/.nvm/versions/node/v6.11.2/bin/node&#039;,
&#039;/home/ubuntu/workspace/1_helloworld.js&#039; ]`
</code></pre>
<p>These two elements are the <a href="https://stackoverflow.com/questions/22213980/could-someone-explain-what-process-argv-means-in-node-js-please#22214003">whole command-line invocation</a>. However, we can do some interesting things with this as well. Let&#8217;s change our code up some:</p>
<pre><code class="javascript">// var hello = function() {
//     console.log(&#039;Hello world&#039;);
// }
// hello();

console.log(process.argv);

var greet = process.argv[2] || &quot;World&quot;;

var hello = function(name) {
    console.log(&#039;Hello &#039; + name + &#039;!&#039;);
}
hello(greet);
</code></pre>
<p>Okay, well not changed much just comment and uncomment stuff. So now we have our <code>console.log</code> from before, we set a variable, we set a function, and we call that function. So if we run <code>node 1_helloworld.js</code> now we&#8217;ll see our <code>process.argv</code> array and &#8220;Hello World&#8221;. If we run <code>node 1_helloworld.js &quot;freeCodeCamp Nashville&quot;</code>, we&#8217;ll see an array with 3 elements and &#8220;Hello freeCodeCamp Nashville&#8221; printed. We can pass things in this way!</p>
<p>Let&#8217;s look at <strong>2_hellofile.js</strong> now:</p>
<pre><code class="javascript">const fs = require(&#039;fs&#039;);
const fileToRead = process.argv[2] || &#039;README.md&#039;;
const lineIndex = process.argv[3] - 1 || 3;

fs.readFile(fileToRead, function (err, data) {
    if (err) throw err;

    var lines = data.toString(&#039;utf-8&#039;).split(&quot;\n&quot;);

    console.log(lines[lineIndex]);
});
</code></pre>
<p>Let&#8217;s run this with <code>node 2_hellofile.js</code> and see what we get. Whoa, where did that come from? Let&#8217;s walk through how this happened. I&#8217;m not going to walk through how <code>fs</code> works. Just know that it&#8217;s a module that comes with Node.js and if you want to learn more you can look <a href="https://nodejs.org/dist/latest-v6.x/docs/api/fs.html#fs_file_system">here</a>.</p>
<p>Once we require the module in our JavaScript file (like we did on line 1) we can use everything that comes with it.<br />
Line 2 we&#8217;re setting a variable equal to something we pass into our <code>process.argv</code> or <code>README.md</code>.<br />
Line 3 we&#8217;re setting another variable equal to something we pass into our <code>process.argv</code> or <code>3</code>.<br />
Line 5 we&#8217;re using the <code>readFile</code> function that comes with <code>fs</code> and passing in an argument and a callback function to handle an error or data.<br />
Line 6 we say we&#8217;ll throw an error if an error occurs.<br />
Line 8 we set a variable that takes the data <code>fs</code> gets for us and turns it into a string then splits it on &#8220;\n&#8221; so we end up with an array of strings.<br />
Line 10 we <code>console.log</code> the element from the <code>lines</code> array that is at <code>lineIndex</code> index position.<br />
Line 11 we close the function.</p>
<p>If you want to play with this try <code>node 2_hellofile.js &#039;README.md&#039; 14</code>. We&#8217;re taking the readme and turning it into an array split at the end of each line then logging the line that we call by number.</p>
<p>On to <strong>3_helloweb.js</strong> which should look like this:</p>
<pre><code class="javascript">const http = require(&#039;http&#039;);

// on c9.io hostname must be &#039;8080&#039;
// locally, this can be almost anything
const port = 3000;

// on c9.io hostname must be &#039;0.0.0.0&#039;
// locally, you would use &#039;localhost&#039; (a variable for &#039;127.0.0.1&#039;)
const hostname = &#039;localhost&#039;;

const server = http.createServer(function(request, response){
    response.writeHead(200, {&quot;Content-Type&quot;: &quot;text/plain&quot;});
    response.write(&quot;Hello Web! XOXO, Node&quot;);
    response.end();
});

server.listen(port, hostname, function(){
    console.log(`Server running at ${hostname}:${port}/`);
});
</code></pre>
<p>Once again not to go too deep into what <code>http</code> is but it gets our server going. This <strong>3_helloweb.js</strong> is going to be our Node.js web server. A very simple one but one nonetheless. Dave has left some notes for us. We need to change the <code>port</code> variable on line 5 to <code>8080</code> and the <code>hostname</code> variable on line 9 to <code>&#039;0.0.0.0&#039;</code>. If you were running this code locally the settings that are here should work. However, Cloud9 has some specific restrictions to how they will allow us to run a server. So make the changes and run <code>node 3_helloweb.js</code> in your terminal. You should be greeted with a <code>Server running at 0.0.0.0:8080/</code> and a green box from Cloud9 with a link to the server.<br />
<a href="https://sethaalexander.com/freecodecamp-nashville-october-meetup-recap/screenshot-from-2017-10-12-20-50-39/" rel="attachment wp-att-2532"><img loading="lazy" decoding="async" src="https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-20-50-39.png" alt="" width="1549" height="197" class="aligncenter size-full wp-image-2532" srcset="https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-20-50-39.png 1549w, https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-20-50-39-300x38.png 300w, https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-20-50-39-768x98.png 768w, https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-20-50-39-1024x130.png 1024w" sizes="(max-width: 1549px) 100vw, 1549px" /></a></p>
<p>When you click that link the first time you&#8217;ll get a nasty orange screen with a red button. That&#8217;s Cloud9 telling you to not use this type of server for anything important. So click through and you should see a web page that says &#8220;Hello Web! XOXO, Node&#8221;. That text coming straight from line 18 of our 3_helloweb.js file. To kill the server click on the terminal and <code>ctrl + c</code> or <code>cmd + c</code>.</p>
<p>Lastly, we have <strong>4_helloexpress.js</strong>:</p>
<pre><code class="javascript">// bring in dependencies / libraries
var http = require(&#039;http&#039;);
var express = require(&#039;express&#039;);
var app = express();
var bodyParser = require(&#039;body-parser&#039;);

// environment variables
var port = 8080;
var hostname = &#039;0.0.0.0&#039;;

// parses text content of a http request
app.use(bodyParser.text({ type: &#039;text/html&#039; }));

// servers static files like our html $ css from public folder
app.use(express.static(&#039;public&#039;));

// this handles our post request from the front end
app.post(&#039;/&#039;, function(req, res, next) {
    console.log(&#039;Message from browser: &#039;,  req.body);
    res.end(&#039;Message received. Hello from the back end!&#039;);
})

// start the server and listen for requests
var server = http.createServer(app);

server.listen(port, hostname, function(){
    console.log(`Server running at ${hostname}:${port}/`);
});
</code></pre>
<p>In this app, we&#8217;re going to be using <a href="https://expressjs.com/">Express</a> as our web application framework. Express is super popular, read their docs if you&#8217;re interested, I&#8217;m not going to dive into it too deeply here. I&#8217;m actually not going to get too deep into this code except to point out a few things. Let&#8217;s run our server with <code>node 4_helloexpress.js</code>. When we go to the website we should have a simple form.<br />
<a href="https://sethaalexander.com/freecodecamp-nashville-october-meetup-recap/screenshot-from-2017-10-12-20-58-04/" rel="attachment wp-att-2533"><img loading="lazy" decoding="async" src="https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-20-58-04.png" alt="" width="1021" height="678" class="aligncenter size-full wp-image-2533" srcset="https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-20-58-04.png 1021w, https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-20-58-04-300x199.png 300w, https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-20-58-04-768x510.png 768w" sizes="(max-width: 1021px) 100vw, 1021px" /></a></p>
<p>This is coming from line 15 where we tell Express to serve the files in the public folder. The public folder has three files which make up our front end. Take a look at <strong>frontend.js</strong> back in Cloud9:</p>
<pre><code class="javascript">var submit = document.getElementById(&#039;submit&#039;);

var captureData = function(e) {
    var data = document.getElementById(&#039;data&#039;);
    sendData(data.value);
}

var sendData = function(message) {

    var xhr = new XMLHttpRequest();
    xhr.open(&quot;POST&quot;, &#039;/&#039;, true);
    xhr.setRequestHeader(&quot;Content-type&quot;, &quot;text/html&quot;);
    xhr.onreadystatechange = function() {
        if(xhr.readyState == XMLHttpRequest.DONE &amp;&amp; xhr.status == 200) {
            console.log(&#039;Sending: &#039; + message + &#039;. Successful!&#039;);
            console.log(xhr.response);
        }
    }
    xhr.send(message); 
}

submit.addEventListener(&quot;click&quot;, captureData);
</code></pre>
<p>Now if you&#8217;re using Chrome (which we at freeCodeCamp Nashville recommend), open up the console (sorry none Chrome peeps) back on that ugly purple page <code>ctrl + shift + i</code> or <code>cmd + shift + i</code> should do it. If not, right-click anywhere purple and choose the &#8220;Inspect&#8221; option. You&#8217;ll see an error about favicon.ico and you can ignore that. What we want to show off here is the front end (browser) talking to the back end (server). We&#8217;re going to show this off through logging stuff to the two different consoles. So when we type something into our form and click &#8220;Submit&#8221; we should see this in our browser console:<br />
<a href="https://sethaalexander.com/freecodecamp-nashville-october-meetup-recap/screenshot-from-2017-10-12-22-15-15/" rel="attachment wp-att-2535"><img loading="lazy" decoding="async" src="https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-22-15-15.png" alt="" width="626" height="281" class="aligncenter size-full wp-image-2535" srcset="https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-22-15-15.png 626w, https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-22-15-15-300x135.png 300w" sizes="(max-width: 626px) 100vw, 626px" /></a></p>
<p>and this in our Cloud9 server terminal:<br />
<a href="https://sethaalexander.com/freecodecamp-nashville-october-meetup-recap/screenshot-from-2017-10-12-22-15-08/" rel="attachment wp-att-2534"><img loading="lazy" decoding="async" src="https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-22-15-08.png" alt="" width="831" height="356" class="aligncenter size-full wp-image-2534" srcset="https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-22-15-08.png 831w, https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-22-15-08-300x129.png 300w, https://sethaalexander.com/wp-content/uploads/2017/10/Screenshot-from-2017-10-12-22-15-08-768x329.png 768w" sizes="(max-width: 831px) 100vw, 831px" /></a></p>
<p>When we click &#8220;Submit&#8221; we&#8217;re doing a POST request on line 11 of frontend.js and on line 14 we&#8217;re creating that first console message we see in our Chrome console if the data is sent successfully. Then back in our 4_helloexpress.js on line 26, we set the server up to listen. Our front end just sent the POST so the server &#8220;hears&#8221; that and handles it on line 18 because it&#8217;s a POST. On line 19 it logs to the Cloud9 terminal what we saw before and on line 20 it sends some stuff back to the front end. Finally, line 16 in frontend.js receives the stuff the back end just sent in response and logs that to our Chrome console. That&#8217;s a lot of back and forth but illustrates how browsers and servers &#8220;talk&#8221; to each other.</p>
<p>Hopefully, this piqued your interest and you want to start building your own full stack JavaScript apps. Or maybe now you know just enough to start having fun and playing around. If you want to hook up with us who are a part of freeCodeCamp Nashville check us out on <a href="https://www.meetup.com/freeCodeCamp-Nashville">Meetup at freeCodeCamp Nashville</a>. We also have a <a href="https://www.facebook.com/groups/free.code.camp.nashville/">Free Code Camp Nashville Facebook Page</a>. My favorite is the #freecodecamp channel on the <a href="https://nashdev.com">NashDev Slack</a> network. If you want to get in on that, go to the link, enter your email, you&#8217;ll get an invite to the network, set up your account, once you log in you&#8217;ll be dumped into the #general channel by default, type <code>/join #freecodecamp</code> and hit enter and you&#8217;ll be right there with us chatting.</p>
<p>A few more pics from the meetup:<br />

<a href='https://sethaalexander.com/freecodecamp-nashville-october-meetup-recap/img_20171007_124947/'><img loading="lazy" decoding="async" width="4032" height="3024" src="https://sethaalexander.com/wp-content/uploads/2017/10/IMG_20171007_124947.jpg" class="attachment-full size-full" alt="freeCodeCamp Nashville conversation" srcset="https://sethaalexander.com/wp-content/uploads/2017/10/IMG_20171007_124947.jpg 4032w, https://sethaalexander.com/wp-content/uploads/2017/10/IMG_20171007_124947-300x225.jpg 300w, https://sethaalexander.com/wp-content/uploads/2017/10/IMG_20171007_124947-768x576.jpg 768w, https://sethaalexander.com/wp-content/uploads/2017/10/IMG_20171007_124947-1024x768.jpg 1024w" sizes="(max-width: 4032px) 100vw, 4032px" /></a>
<a href='https://sethaalexander.com/freecodecamp-nashville-october-meetup-recap/img_20171007_124940/'><img loading="lazy" decoding="async" width="4032" height="3024" src="https://sethaalexander.com/wp-content/uploads/2017/10/IMG_20171007_124940.jpg" class="attachment-full size-full" alt="freeCodeCamp Nashville Dave" srcset="https://sethaalexander.com/wp-content/uploads/2017/10/IMG_20171007_124940.jpg 4032w, https://sethaalexander.com/wp-content/uploads/2017/10/IMG_20171007_124940-300x225.jpg 300w, https://sethaalexander.com/wp-content/uploads/2017/10/IMG_20171007_124940-768x576.jpg 768w, https://sethaalexander.com/wp-content/uploads/2017/10/IMG_20171007_124940-1024x768.jpg 1024w" sizes="(max-width: 4032px) 100vw, 4032px" /></a>
<a href='https://sethaalexander.com/freecodecamp-nashville-october-meetup-recap/img_20171007_134544/'><img loading="lazy" decoding="async" width="4032" height="3024" src="https://sethaalexander.com/wp-content/uploads/2017/10/IMG_20171007_134544.jpg" class="attachment-full size-full" alt="" srcset="https://sethaalexander.com/wp-content/uploads/2017/10/IMG_20171007_134544.jpg 4032w, https://sethaalexander.com/wp-content/uploads/2017/10/IMG_20171007_134544-300x225.jpg 300w, https://sethaalexander.com/wp-content/uploads/2017/10/IMG_20171007_134544-768x576.jpg 768w, https://sethaalexander.com/wp-content/uploads/2017/10/IMG_20171007_134544-1024x768.jpg 1024w" sizes="(max-width: 4032px) 100vw, 4032px" /></a>
</p>
<p>The post <a href="https://sethaalexander.com/freecodecamp-nashville-october-meetup-recap/">freeCodeCamp Nashville October Meetup Recap</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sethaalexander.com/freecodecamp-nashville-october-meetup-recap/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>The Full Time Job before The Full Time Job</title>
		<link>https://sethaalexander.com/full-time-job-full-time-job/</link>
					<comments>https://sethaalexander.com/full-time-job-full-time-job/#respond</comments>
		
		<dc:creator><![CDATA[Seth Alexander]]></dc:creator>
		<pubDate>Sun, 16 Jul 2017 04:47:49 +0000</pubDate>
				<category><![CDATA[Daily Blog]]></category>
		<guid isPermaLink="false">https://sethaalexander.com/?p=2701</guid>

					<description><![CDATA[<p>I think this picture is pretty accurate as to how I feel right now. A pawn crowned king. I passed my final assessment the first time through and have officially been a graduate of Flatiron School for a week now. I’m also lucky enough to have a full-time job right out of school. A full-time&#8230; <a class="more-link" href="https://sethaalexander.com/full-time-job-full-time-job/">Continue reading <span class="screen-reader-text">The Full Time Job before The Full Time Job</span> <span class="meta-nav" aria-hidden="true">&#8594;</span></a></p>
<p>The post <a href="https://sethaalexander.com/full-time-job-full-time-job/">The Full Time Job before The Full Time Job</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>I think this picture is pretty accurate as to how I feel right now. A pawn crowned king. I passed my final assessment the first time through and have officially been a graduate of Flatiron School for a week now. I’m also lucky enough to have a full-time job right out of school. A full-time job looking for a job that is :-p. It’s amazing how in depth the job search can be. However, when you are provided with a solid framework to follow it’s nice to see the pieces just start falling into place. With my choice of the <a href="https://flatironschool.com/programs/online-web-developer-career-course/">Full Stack Web Developer Program</a> through Flatiron School, I receive a job guarantee if I follow some steps. Obviously there is a little more to it, like following my career coaches advice, but in general I must have 8 git commits per week to GitHub, write one blog post per week, and perform 8 job search activities per week (ie. apply for a job, meet someone at a user group, follow up thank you notes, networking outreach to meet for coffee, etc…).<br />
<span id="more-2701"></span><br />
These are things I think I would do anyway but having a structure that I am being held accountable to is definitely pushing me to get out of my comfort zone some in this process. I also have a better pace to do my outreach. If I had done it myself I probably would have blown through EVERY contact I have in this first week and now be dealing with scheduling conflicts and such going into next week. Now I am pacing it and staggering how I contact people some. If you’re like me you’re already thinking of ways to track this type of job search. Maybe build an app, or utilize Trello, or a Google Sheet. Luckily, the Flatiron School curriculum is open source so you can just find it right <a href="https://github.com/learn-co-students/careers-job-search-tracker-v-000">here</a> (look for the embedded link).</p>
<h2>Staying Active Coding</h2>
<p>While this seems like a standard practice I know it’s not. I’ve watched many boot camp graduates GitHub accounts go from consistent commits to zero after graduation. This is something I prepared for as I worked on my portfolio projects. I always knew ways that I wanted to extend them. Although, now that I have the freedom to learn <strong>ANYTHING</strong> I need to stay on track. As soon as I became a graduate a <a href="https://nodejs.org/">Node.js</a> track opened up for me in my courses listing. This is attractive as I could round out some full stack JS knowledge. I also purchased <a href="https://learnnode.com/">Wes Bos’ Learn Node</a> course while I was going through the boot camp so I have that too.</p>
<p><a href="https://sethaalexander.com/full-time-job-full-time-job/ghkey/" rel="attachment wp-att-2703"><img loading="lazy" decoding="async" src="https://sethaalexander.com/wp-content/uploads/2017/10/ghkey-300x200.jpeg" alt="" width="300" height="200" class="alignleft size-medium wp-image-2703" srcset="https://sethaalexander.com/wp-content/uploads/2017/10/ghkey-300x200.jpeg 300w, https://sethaalexander.com/wp-content/uploads/2017/10/ghkey-768x512.jpeg 768w, https://sethaalexander.com/wp-content/uploads/2017/10/ghkey-1024x682.jpeg 1024w, https://sethaalexander.com/wp-content/uploads/2017/10/ghkey.jpeg 1600w" sizes="(max-width: 300px) 100vw, 300px" /></a>It’s easy to become lax though. It’s nice to take a breath and relax. I’ve worked hard and I <em>deserve</em> a break, right? Well, no I don’t. I still have to work my butt off. I’m at the bottom right now and the climb is hard. However, the job search is pretty much full time in and of itself so now I need to find time to code too? Yes. Here’s the plan:</p>
<ol>
<li>Refactor my React with Redux project to pull from the Yelp API instead of from the Rails API I built it on. Then implement comments being persisted in the DB.</li>
<li>Finish the TODO items I left open for the rest of my projects. Work on the Ruby CLI Gem first, then my jQuery front end, then my Rails project, then my Sinatra project (maybe).</li>
<li>Node.js is next. First the Flatiron track then Wes Bos’ course.</li>
<li>If I’m still looking for work at this point I’m not sure what I’ll dive into. I might choose to build my React app using other frameworks to acquire familiarity and demonstrate my ability to learn other things.</li>
</ol>
<p>Ultimately, I don’t want my GitHub to go stale. I’m also working on algorithm challenges to prepare for technical interviews. I’m mostly working on <a href="https://codefights.com/signup/85hdF2zEPEthw6DZA/main">CodeFights</a> currently as they have an Interview Prep set of problems. However, I’ve done problems on <a href="http://www.codewars.com/r/rf2vqg">Codewars</a> which are fun and I hear a ton of good things about <a href="http://exercism.io/">exercism.io</a> which I’ll probably dive into once I’m done with CodeFights stuff.</p>
<h2>Networking</h2>
<p>While this might seem like a natural thing for me, former restaurant manager, bartender, meetup co-organizer, meetup attender, etc… It’s always awkward to reach out to someone for the first time. Luckily, I have help with this. There are some awesome resources for this in Nashville as well. I’m sure if you look around there are resources in your city as well.</p>
<p><a href="https://sethaalexander.com/full-time-job-full-time-job/bwpeople/" rel="attachment wp-att-2704"><img loading="lazy" decoding="async" src="https://sethaalexander.com/wp-content/uploads/2017/10/bwpeople-300x198.jpeg" alt="" width="300" height="198" class="alignleft size-medium wp-image-2704" srcset="https://sethaalexander.com/wp-content/uploads/2017/10/bwpeople-300x198.jpeg 300w, https://sethaalexander.com/wp-content/uploads/2017/10/bwpeople-768x507.jpeg 768w, https://sethaalexander.com/wp-content/uploads/2017/10/bwpeople-1024x676.jpeg 1024w, https://sethaalexander.com/wp-content/uploads/2017/10/bwpeople.jpeg 1600w" sizes="(max-width: 300px) 100vw, 300px" /></a><a href="https://meetup.com/">Meetup.com</a> has to be the #1 resource for networking around shared topics. There are so many user groups and these are open to the public. So, everyone at a meetup event is already a warm contact. They expect to be approached and talked to. Adding to that the topic should hopefully be something that you are interested in and can speak somewhat about. I’ve had some great conversations, met some awesome engineers and established friendly contacts that I hope to maintain long-term.</p>
<p>Another great place to check out, and meetups will help you find these, are Slack networks in your city. Nashville has the <a href="http://nashdev.com/">NashDev</a> Slack network which is a central place for people in IT in Nashville to chat. I&#8217;ve asked questions there and learned a ton from the responses from lead engineers and seasoned developers who have helped me with no strings attached. The best part is, some of these people I’ll probably end up interviewing with. Now I’m not a random name but someone that they have conversed with and taught before.</p>
<p>In addition, look for groups specifically for people to extend their learning. Started in Nashville and slowly spreading I found <a href="https://groups.google.com/forum/#!forum/penny-university">Penny University</a>. I think they describe the idea better than I can paraphrase:</p>
<blockquote><p>
  The name “Penny University” is a reference to the early coffeehouses in Oxford England. These coffeehouses held an important association with the European Age of Enlightenment. For the price of a penny, scholars and laypeople alike would be given admittance to the coffeehouse, enjoy an endless supply of coffee, and more importantly enjoy learning through conversations with their peers. Thus these coffeehouses came to be called “Penny Universities”.</p>
<p>  Our new group, Penny University, serves as a modern take on this old tradition by connecting those who desire to learn with those who are willing to share what they know. This can certainly be at a coffeehouse, but anywhere else as well, including just a quick Google Hangout.</p>
<p>  There are no mentors or mentees, leaders or followers. We are all peers and we are here to both learn and to teach.
</p></blockquote>
<p>Not surprisingly Penny U has their own Slack network.</p>
<p>Look for ways that you can donate time to coding. It’s a great way to work next to Senior developers and learn. In addition, the contacts are great. You’ll demonstrate not just what you know but how you can interact in a team setting. An awesome place to start is [Code for America] and then track down your local [Brigade] that does civic projects. I recently attended a [Code for Nashville] meetup and got hooked in with them. Was told to join their Slack network and learn some Node.js for the project they’re getting ready to start.</p>
<p>A final piece to networking is meeting people for 1 on 1 conversations. While these can be the most intimidating hopefully they aren&#8217;t completely cold. I know that I’m only asking people that I&#8217;ve met in person at a meetup or have spoken with via Slack to some extent. I’m meeting some great people this way and as soon as I’m done with my project refactors I’m going to start asking for code reviews which will help level me up as a developer too.</p>
<p>Let’s see if I can beat the odds and land a job quicker than the average bear through these efforts.</p>
<p>The post <a href="https://sethaalexander.com/full-time-job-full-time-job/">The Full Time Job before The Full Time Job</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sethaalexander.com/full-time-job-full-time-job/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>So Close to the End</title>
		<link>https://sethaalexander.com/so-close-to-the-end/</link>
					<comments>https://sethaalexander.com/so-close-to-the-end/#respond</comments>
		
		<dc:creator><![CDATA[Seth Alexander]]></dc:creator>
		<pubDate>Wed, 05 Jul 2017 21:22:28 +0000</pubDate>
				<category><![CDATA[Flatiron Blog]]></category>
		<guid isPermaLink="false">https://sethaalexander.com/?p=2464</guid>

					<description><![CDATA[<p>It&#8217;s been about 3 weeks since I last blogged. I put my head down and sprinted towards the finish line. I can&#8217;t say that I&#8217;m 100% done, yet, but I will be soon. I have completed my final portfolio project and have my assessment for it tomorrow. I must say, Redux threw me for one&#8230; <a class="more-link" href="https://sethaalexander.com/so-close-to-the-end/">Continue reading <span class="screen-reader-text">So Close to the End</span> <span class="meta-nav" aria-hidden="true">&#8594;</span></a></p>
<p>The post <a href="https://sethaalexander.com/so-close-to-the-end/">So Close to the End</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>It&#8217;s been about 3 weeks since I last blogged. I put my head down and sprinted towards the finish line. I can&#8217;t say that I&#8217;m 100% done, yet, but I will be soon. I have completed my final portfolio project and have my assessment for it tomorrow. I must say, <a href="http://redux.js.org">Redux</a> threw me for one while working on this project. I hit many stumbling blocks building this project. I think my sprint was a little ambitious and I ended up not knowing the Redux stuff as in-depth as I wanted to. I definitely created some of my own frustration because of this. However, I hacked away at it and got it. I watched YouTube videos, <a href="https://learnredux.com">Wes Bos&#8217;s Redux Course</a>, and I even used <a href="https://hackhands.com/">HackHands</a> a couple times thanks to the <a href="https://education.github.com/pack">Github Education Student Developer Pack</a> $25 credit I received.<br />
<span id="more-2464"></span><br />
HackHands was an interesting experience. Getting help from people who were not native English speakers (I assumed that&#8217;s who I&#8217;d get considering I was doing this on July 4th) and being able to communicate how I was stuck. The two times I used it I didn&#8217;t get a direct answer to my question. However, I did see someone debug my code live and in the end the source of my problem was illuminated by the help.</p>
<p>So one problem I ran into was not getting the data from my API when I called <code>fetchPlaces()</code>. I was stumped. By all accounts, it should be working. My API was returning proper JSON formatted data. I had:</p>
<pre><code class="javascript">// fetch places
function fetchPlaces () {
  return (dispatch) =&gt; {
    dispatch({type: &#039;FETCH_PLACES&#039;})
    return fetch(&#039;http://localhost:3001/api/places&#039;)
      .then(response =&gt; {
        dispatch({type: &#039;RECEIVED_PLACES&#039;, payload: response})
      })
      .catch((err) =&gt; {
        dispatch({type: &#039;FETCH_PLACES_ERROR&#039;, payload: err})
      })
  }
}
</code></pre>
<p>I couldn&#8217;t for the life of me figure out why I wasn&#8217;t getting the data that I needed back. I considered using <code>parseJSON()</code> but I didn&#8217;t think I needed to since the data being returned was already JSON. I was going to use it just like that as well. I wasn&#8217;t accounting for the fact that I was using <code>fetch()</code> to retrieve the JSON from my API. For more about the small, but important piece, that I was missing take a look at <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch">Using Fetch</a> followed by <a href="https://developer.mozilla.org/en-US/docs/Web/API/Body/json">Body.json()</a> on MDN. With that knowledge, I was able to fix my call by implementing <code>.json()</code> on line 7 below followed by another <code>.then</code> which now has the proper data to pass into the payload.</p>
<pre><code class="javascript">// fetch places
function fetchPlaces () {
  return (dispatch) =&gt; {
    dispatch({type: &#039;FETCH_PLACES&#039;})
    return fetch(&#039;http://localhost:3001/api/places&#039;)
      .then(response =&gt; {
        response.json()
        .then(json =&gt; {
          dispatch({type: &#039;RECEIVED_PLACES&#039;, payload: json})
        })
      })
      .catch((err) =&gt; {
        dispatch({type: &#039;FETCH_PLACES_ERROR&#039;, payload: err})
      })
  }
}
</code></pre>
<p>Another issue I ran into was a CORS violation. CORS stands for &#8220;Cross-origin resource sharing&#8221; and can be described as:</p>
<blockquote><p>
  Cross-origin resource sharing is a mechanism that allows restricted resources on a web page to be requested from another domain outside the domain from which the first resource was served. A web page may freely embed cross-origin images, stylesheets, scripts, iframes, and videos. Certain &#8220;cross-domain&#8221; requests, notably Ajax requests, however, are forbidden by default by the same-origin security policy.<br />
  &#8212; <a href="https://en.wikipedia.org/wiki/Cross-origin_resource_sharing">Wikipedia</a>
</p></blockquote>
<p>If that doesn&#8217;t make sense, don&#8217;t worry. Just know that CORS is implemented for security on the web. However, it also meant that unless I explicitly stated that my React app could talk to my Rails API I wasn&#8217;t going to be able to get the data. Luckily, there is a pretty easy way to enable this and it only took a few lines of code. I first added <code>gem &#039;rack-cors&#039;, :require =&gt; &#039;rack/cors&#039;</code> to my Gemfile and ran <code>bundle</code>. Next, I had to add some code:</p>
<pre><code class="ruby"># /config/initializers/cors.rb

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins &#039;localhost:3000&#039;

    resource &#039;*&#039;,
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end
</code></pre>
<p>This enabled my React application running on <code>localhost:3000</code> to talk to my Rails API server running on <code>localhost::3001</code> with no problems.</p>
<p>Ultimately I learned <strong>A LOT</strong> doing this project. I&#8217;m not 100% happy with where my app is at currently. However, to my understanding, it fulfills all the requirements of the project and that&#8217;s what I was shooting for. I can see abstracting it away from the back end and setting it up to pull all data from an external API call instead. Having built the back end though I know that it&#8217;ll always work the way I want it to and thus is a more stable project to include in a portfolio.</p>
<p>Check out <a href="https://github.com/itzsaga/foodie-view">Foodie View</a> and see what you think for yourself. I&#8217;ll get it up on Heroku soon and will link to it from GitHub.</p>
<p>Time spent total: 457:50<br />
Lessons completed total: 689</p>
<p>The post <a href="https://sethaalexander.com/so-close-to-the-end/">So Close to the End</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sethaalexander.com/so-close-to-the-end/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Sometimes The Logic Is Flawed</title>
		<link>https://sethaalexander.com/sometimes-logic-flawed/</link>
					<comments>https://sethaalexander.com/sometimes-logic-flawed/#respond</comments>
		
		<dc:creator><![CDATA[Seth Alexander]]></dc:creator>
		<pubDate>Fri, 16 Jun 2017 05:01:46 +0000</pubDate>
				<category><![CDATA[Flatiron Blog]]></category>
		<guid isPermaLink="false">https://sethaalexander.com/?p=2467</guid>

					<description><![CDATA[<p>So I&#8217;m banging away at my jQuery project. I got hung up on some code tonight but got it working right before I stopped for the night! I was stoked! So what was I stuck on? In my app a user can create as many places as they want. Each place can have as many&#8230; <a class="more-link" href="https://sethaalexander.com/sometimes-logic-flawed/">Continue reading <span class="screen-reader-text">Sometimes The Logic Is Flawed</span> <span class="meta-nav" aria-hidden="true">&#8594;</span></a></p>
<p>The post <a href="https://sethaalexander.com/sometimes-logic-flawed/">Sometimes The Logic Is Flawed</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>So I&#8217;m banging away at my jQuery project. I got hung up on some code tonight but got it working right before I stopped for the night! I was stoked! So what was I stuck on? In my app a user can create as many places as they want. Each place can have as many items as they want. A user can look at a specific item and see the name of it, the rating they gave it, any notes they wrote about it and where the item is available (the places they&#8217;ve added it to). I wanted to implement a &#8220;Next Item&#8221; button/link that when clicked will load the next item for the current user.<br />
<span id="more-2467"></span><br />
First things first I needed an array of the current users item ID #&#8217;s. I needed this because my show pages follow RESTful conventions and use the item ID in the URL. This is what the show page is expecting in its params. So I got that done relatively easily:</p>
<pre><code class="javascript">let itemsValues

$(() =&gt; {
  $.getJSON(&#039;/items.json&#039;, function (data) {
    itemsValues = $.map(data, function (e) {
      return e.id
    })
  })
})
</code></pre>
<p>Then, I wanted the functionality that I stated above. However, I didn&#8217;t want to get to the last item and just have a button that does nothing because there&#8217;s no next item. I also didn&#8217;t want the button to just disappear (I did that and I thought it was weird). So I decided when we reached the last item we should loop back around and go to the first item again. So I started coding and got to this point:</p>
<pre><code class="javascript">$(&#039;.js-next&#039;).on(&#039;click&#039;, function() {
  let nextIndex = itemsValues.indexOf(parseInt($(&#039;.js-next&#039;).attr(&#039;data-id&#039;))) + 1
  $.getJSON(&#039;/items/&#039; + itemsValues[nextIndex], function(data) {
    $(&#039;#name&#039;).html(data[&#039;name&#039;])
    $(&#039;#rating&#039;).html(data[&#039;rating&#039;])
    $(&#039;#notes&#039;).html(data[&#039;notes&#039;])
    if (nextIndex === itemsValues.length)
      $(&#039;.js-next&#039;).attr(&#039;data-id&#039;, itemsValues[0])
    else
      $(&#039;.js-next&#039;).attr(&#039;data-id&#039;, data[&#039;id&#039;])
  })
})
</code></pre>
<p>So my &#8220;Next Item&#8221; link has a class of &#8216;js-next&#8217;. Then I set a <code>nextIndex</code> variable by getting the current <code>data-id</code> of my link (ie, the current item being displayed ID number), turning that into an integer, finding the index of that ID in the <code>itemsValues</code> array and adding one to it. Then I call my internal API and get the next item&#8217;s info as a JSON object. I then fill in the new data to the DOM. Finally, I have an <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else">if&#8230;else</a> block where I try and set the <code>data-id</code> to the first item ID if the new item is the last item in the array. If not, set it to the now current item ID.</p>
<p>Looking at this now I think the logic is flawed because I increment by one on the API call after the click. So setting it to the first item <em>before</em> the click will eliminate one item from ever showing up. I actually had this happen and couldn&#8217;t figure out why. This logic was fuzzy but is probably why I ended up moving the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else">if&#8230;else</a> logic to the top of my function and when I did it worked!</p>
<pre><code class="javascript">$(&#039;.js-next&#039;).on(&#039;click&#039;, function() {
  let nextIndex
  let dataIdIndex = itemsValues.indexOf(parseInt($(&#039;.js-next&#039;).attr(&#039;data-id&#039;)))
  if (dataIdIndex === itemsValues.length - 1)
    nextIndex = 0
  else
    nextIndex = dataIdIndex + 1
  $.getJSON(&#039;/items/&#039; + itemsValues[nextIndex], function(data) {
    $(&#039;#name&#039;).html(`${data[&#039;name&#039;]} -
        &lt;a href=&quot;/items/${data[&#039;id&#039;]}/edit&quot;&gt;Edit&lt;/a&gt; -
        &lt;a data-confirm=&quot;Are you sure?&quot; rel=&quot;nofollow&quot; data-method=&quot;delete&quot; href=&quot;/items/${data[&#039;id&#039;]}&quot;&gt;Delete&lt;/a&gt;`)
    $(&#039;#rating&#039;).html(`Rating: ${data[&#039;rating&#039;]}`)
    $(&#039;#notes&#039;).html(`Notes: ${data[&#039;notes&#039;]}`)
    $(&#039;.js-next&#039;).attr(&#039;data-id&#039;, data[&#039;id&#039;])
  })
})
</code></pre>
<p>I also filled out the HTML for the name section of the page using those lovely <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals">template literals</a> I talked about in my last blog post. This project is coming along well. I&#8217;m hoping to be done with it tomorrow night at some point in time. If I can finish this off before the weekend I&#8217;ll be super happy and think right on track to be done before the end of the month.</p>
<p>Time spent today: 2:16<br />
Time spent total: 394:16<br />
Lessons completed today: 0<br />
Lessons completed total: 646</p>
<p>The post <a href="https://sethaalexander.com/sometimes-logic-flawed/">Sometimes The Logic Is Flawed</a> appeared first on <a href="https://sethaalexander.com">Seth Alexander</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://sethaalexander.com/sometimes-logic-flawed/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
