<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Daniel McMahon</title>
    <description>The latest articles on DEV Community by Daniel McMahon (@danku).</description>
    <link>https://dev.to/danku</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F53483%2F450dd32c-af21-4c5b-801c-adfd0b15bb44.jpeg</url>
      <title>DEV Community: Daniel McMahon</title>
      <link>https://dev.to/danku</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/danku"/>
    <language>en</language>
    <item>
      <title>2+ Years in Professional Development</title>
      <dc:creator>Daniel McMahon</dc:creator>
      <pubDate>Wed, 22 Jan 2020 11:02:50 +0000</pubDate>
      <link>https://dev.to/danku/2-years-in-professional-development-4kc2</link>
      <guid>https://dev.to/danku/2-years-in-professional-development-4kc2</guid>
      <description>&lt;p&gt;A follow up on my &lt;a href="https://dev.to/dan_mcm_/a-year-in-professional-software-development-1l7a"&gt;A Year in Professional Software Development&lt;/a&gt; article.&lt;br&gt;
... also yay for 2+ years ...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/l0MYt5jPR6QX5pnqM/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/l0MYt5jPR6QX5pnqM/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Year Later
&lt;/h2&gt;

&lt;p&gt;So here I am a year and a bit on and find myself thinking back a lot over the last couple of years. It's been an interesting rollercoaster ride full of ups and downs. &lt;/p&gt;

&lt;p&gt;The key points I highlighted in my older article still hold up and are things that are still relevant today as they were a year ago.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Seek the opinion &amp;amp; advice of your colleagues&lt;/li&gt;
&lt;li&gt;You code as a team, not as an individual&lt;/li&gt;
&lt;li&gt;Write tests &amp;amp; maintain documentation regularly&lt;/li&gt;
&lt;li&gt;Make the working process work for you&lt;/li&gt;
&lt;li&gt;Take the bad with the good&lt;/li&gt;
&lt;li&gt;The difference between junior &amp;amp; senior is not all that much&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last point though I have more opinions on.&lt;/p&gt;

&lt;h2&gt;
  
  
  When you're no longer a 'Junior' developer (but also not a senior developer either).
&lt;/h2&gt;

&lt;p&gt;I think it's fair to say at this stage that I'm no longer considered a 'junior' developer (something echo'd by my promotion midway last year in work). I think the distinguishing factor is that you develop a level of certainty to your uncertainty. &lt;/p&gt;

&lt;p&gt;I can quickly review the functionality of an API or code library and be able to adopt it onto my codebase fairly quickly, I can write somewhat decent tests for my code where required, and I have an idea of how to prioritise bug fixes/tech debt over new features in my codebases.&lt;/p&gt;

&lt;p&gt;More than anything though I have been through the process involved with creating, adopting, maintaining and decomissioning microservices. This has probably been the most valuable source of my learnings over the past year. Seeing how stakeholders can set expectations, how to go about building something that meets the outlined expectations, maintaining it and then opting to see if its worthwhile to maintain the services you build and how unexpected factors can influence decisions along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Continuous Upskilling
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F588%2F1%2AmFCJnG9b9RgZ8kB8bqzgPg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F588%2F1%2AmFCJnG9b9RgZ8kB8bqzgPg.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've made it a priority to maintain a certain level of upskilling throughout the past year (although notably less so than my first year). One of the more formal pillars of this would be my completion of the &lt;a href="https://aws.amazon.com/certification/certified-developer-associate/" rel="noopener noreferrer"&gt;AWS Developer Associate&lt;/a&gt; certification. Having used AWS services on and off the last few years this was a nice qualification to obtain outside of work to help fight off the imposter syndrome that comes with the job. Shoutout to the folks at &lt;a href="https://acloud.guru/" rel="noopener noreferrer"&gt;A Cloud Guru&lt;/a&gt; I definitely couldn't have passed it without their online udemy course. &lt;/p&gt;

&lt;p&gt;I currently have my sights set on completing the &lt;a href="https://www.cncf.io/certification/ckad/" rel="noopener noreferrer"&gt;Certified Kubernetes Application Developer&lt;/a&gt; program later this year.&lt;/p&gt;

&lt;h2&gt;
  
  
  Personal Projects
&lt;/h2&gt;

&lt;p&gt;When it comes to personal projects I've definitely upped the ante. I went out and purchased a few domains and setup an ecosystem where all my past, present and future work can live - &lt;a href="https://daniel-mcmahon.com/" rel="noopener noreferrer"&gt;daniel-mcmahon.com&lt;/a&gt;. This was inspired by the work over at &lt;a href="https://linktr.ee/" rel="noopener noreferrer"&gt;linktree&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;I've updated my GitHub to a more memorable name &lt;a href="https://github.com/dan-mcm" rel="noopener noreferrer"&gt;/dan-mcm&lt;/a&gt; and I have multiple live projects including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://music-centre.info/" rel="noopener noreferrer"&gt;Music Centre&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dan-mcm.github.io/dnd/" rel="noopener noreferrer"&gt;DM's Toolkit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cat-ui.herokuapp.com/" rel="noopener noreferrer"&gt;Tap the Cat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dan-mcm.github.io/docs/" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition to those frontend applications I also the the &lt;a href="https://github.com/dan-mcm/inspiration-api" rel="noopener noreferrer"&gt;Inspiration API&lt;/a&gt; and my &lt;a href="https://github.com/dan-mcm/MusicPrograms" rel="noopener noreferrer"&gt;Music Programs&lt;/a&gt; which are overdue an update.&lt;/p&gt;

&lt;p&gt;Going through the pains of setting up a static site with SSL certification through AWS CloudFront was a worthwhile exercise I definitely recommend to anybody else looking to expand their skillset.&lt;/p&gt;

&lt;p&gt;I've taken back up the piano lately and find myself touring the Dublin train stations on a frequent basis - as a result I have a handy business card that I use to direct people towards my revamped &lt;a href="https://music-centre.info/" rel="noopener noreferrer"&gt;Music Centre&lt;/a&gt; website.&lt;/p&gt;

&lt;p&gt;In addition to providing a centralised hub for my projects, I also took the time to go through them, updating any security dependencies (nobody ever warns you of the maintenance required on old projects). In addition to this I gave the readmes a good polish and even added in some Emoji's and more impressive looking &lt;a href="https://shields.io/" rel="noopener noreferrer"&gt;shields.io&lt;/a&gt; badges to make them look less 'clinical' - check them out over on my &lt;a href="https://github.com/dan-mcm" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maintaining Positive Mental Health
&lt;/h2&gt;

&lt;p&gt;I think this is something that isn't talked about enough, and it's particularly important in the tech industry. Imposter syndrome is something that is rampant throughout the industry and it's sort of expected when you enter an industry where the tech is changing rapidly and it's a constant case of the rabbit (developers) chasing the carrot on the stick (new shiny tech). &lt;/p&gt;

&lt;p&gt;I think it's important for developers to be realistic with their expectations of themselves. While there are scrum practices surrounding story points and delivery, there are other aspects that you need to maintain and be careful of. &lt;/p&gt;

&lt;p&gt;Being kind to yourself is something that is hugely underrated, particularly when you see the portrayal of rockstar developers chugging energy drinks and coding till 2/3am in the morning. Improving is very much a marathon not a sprint. You need to ensure that your output is running at a sustainable rate, there's no point in burning yourself out during the first half of a quarter and being useless for the remainder. Pay attention to your mind and your body and learn when to take the foot off the accelerator.&lt;/p&gt;

&lt;h2&gt;
  
  
  Personal Perspective
&lt;/h2&gt;

&lt;p&gt;One of my own key focuses with tech was to be a full stack developer, being able to understand how to orchestrate the backend while being able to put up a pretty facade. There are articles out there that talk about being a T developer, that is one that is good at most things but specialises in one very specific technology. I'm still searching for what that key technology might be, but I've found myself enjoying quite a lot of front end work (React/JS), building some tooling to help others write code (AppsScript, Python, Scala), and maintain good DevOps (K8, Docker, ZMON, Grafana) practices.&lt;/p&gt;

&lt;p&gt;Tech is an industry where people tend to move on quickly from place to place. I see that around me a lot lately where after a 2 year period quite a few of the people I started with have either changed teams or left. I think thats just the nature of the industry - but it makes you consider your own options and if maybe its time to start a new chapter. &lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;I often want to give back to the tech community but rarely know how, so here is an attempt at compiling a list of tools and useful resources I've used over the past year.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shell/Mac
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://iterm2.com/" rel="noopener noreferrer"&gt;iTerm 2&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://ohmyz.sh/" rel="noopener noreferrer"&gt;Oh My Zsh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mbadolato/iTerm2-Color-Schemes/blob/master/schemes/Monokai%20Remastered.itermcolors" rel="noopener noreferrer"&gt;Monokai Remastered Theme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ohmyzsh/ohmyzsh/wiki/Themes" rel="noopener noreferrer"&gt;More Themes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  IDE(s) &amp;amp; Themes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;IntelliJ - Java/Scala

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://darekkay.com/blog/monokai-theme-intellij/" rel="noopener noreferrer"&gt;Monokai&lt;/a&gt; theme&lt;/li&gt;
&lt;li&gt;&lt;a href="https://plugins.jetbrains.com/plugin/7896-markdown-navigator" rel="noopener noreferrer"&gt;Markdown Navigator&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Atom - JS/React/YAML/JSON/Python

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://atom.io/themes/city-lights-syntax" rel="noopener noreferrer"&gt;City Lights&lt;/a&gt; theme&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/file-icons/atom" rel="noopener noreferrer"&gt;file-icons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/prettier/prettier-atom" rel="noopener noreferrer"&gt;prettier-atom&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://atom.io/packages/pretty-json" rel="noopener noreferrer"&gt;pretty-json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/steelbrain/linter" rel="noopener noreferrer"&gt;linter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://atom.io/packages/go-plus" rel="noopener noreferrer"&gt;go-plus&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Build Tools
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Scala/Java - &lt;a href="https://www.scala-sbt.org/1.x/docs/" rel="noopener noreferrer"&gt;sbt&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;JavaScript/React - &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt; / &lt;a href="https://yarnpkg.com/" rel="noopener noreferrer"&gt;yarn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Golang - &lt;a href="https://blog.golang.org/using-go-modules" rel="noopener noreferrer"&gt;Go Modules&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  JS (React) Libraries/Frameworks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://create-react-app.dev/docs/getting-started/" rel="noopener noreferrer"&gt;Create React App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gatsbyjs.org/" rel="noopener noreferrer"&gt;Gatsby JS&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://graphql.org/" rel="noopener noreferrer"&gt;Graph QL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  For Multiple Routes in React
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ReactTraining/react-router" rel="noopener noreferrer"&gt;React Router&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Styling Components
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.styled-components.com/" rel="noopener noreferrer"&gt;Styled Components&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/grid-styled" rel="noopener noreferrer"&gt;Grid Styled&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reactstrap.github.io/" rel="noopener noreferrer"&gt;Reactstrap&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Code Styling &amp;amp; Linting
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/pre-commit" rel="noopener noreferrer"&gt;Pre-Commit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/prettier/prettier" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/xojs/xo" rel="noopener noreferrer"&gt;XO&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Authentication
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.passportjs.org/" rel="noopener noreferrer"&gt;Passport&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Auth Providers
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://auth0.com/" rel="noopener noreferrer"&gt;Auth0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/cognito/" rel="noopener noreferrer"&gt;Amazon Cognito&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Browser Automation
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/puppeteer/puppeteer" rel="noopener noreferrer"&gt;Puppeter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://selenium.dev/" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Server Side
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Test Frameworks
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Code Styling
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://prettier.io/" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/xojs/xo" rel="noopener noreferrer"&gt;XO&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/pre-commit" rel="noopener noreferrer"&gt;Pre-Commit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Scala Libraries/Frameworks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://akka.io/" rel="noopener noreferrer"&gt;Akka&lt;/a&gt; - AKKA HTTP Framework&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.playframework.com/" rel="noopener noreferrer"&gt;Play&lt;/a&gt; - API Framework&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/circe/circe" rel="noopener noreferrer"&gt;Circe&lt;/a&gt; - JSON Parsing&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Test Frameworks
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://site.mockito.org/" rel="noopener noreferrer"&gt;Mockito&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.scalatest.org/" rel="noopener noreferrer"&gt;ScalaTest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Code Styling
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.scalastyle.org/" rel="noopener noreferrer"&gt;Scalastyle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/scalameta/scalafmt" rel="noopener noreferrer"&gt;Scalafmt&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Pre Commit Hooks
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pre-commit.com/" rel="noopener noreferrer"&gt;Pre Commit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  API Tools
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://wiremock.org/" rel="noopener noreferrer"&gt;WireMock - Fast API Mock Tool&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://graphql.org/" rel="noopener noreferrer"&gt;GraphQL - Fast API Query Language&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gatling.io/" rel="noopener noreferrer"&gt;Gatling - Load Testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://locust.io/" rel="noopener noreferrer"&gt;Locust - Load Testing&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Databases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;SQL&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/rds/" rel="noopener noreferrer"&gt;AWS RDS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;NoSQL &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.postgresql.org/" rel="noopener noreferrer"&gt;Postgres&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/dynamodb" rel="noopener noreferrer"&gt;DynamoDB&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Documentation Generators
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.mkdocs.org/" rel="noopener noreferrer"&gt;MkDocs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pages.github.com/" rel="noopener noreferrer"&gt;Github Pages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.gatsbyjs.org/" rel="noopener noreferrer"&gt;GatsbyJS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Chrome Plugins
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://chrome.google.com/webstore/detail/nocoffee/jjeeggmbnhckmgdhmgdckeigabjfbddl" rel="noopener noreferrer"&gt;NoCoffee&lt;/a&gt; - Useful for visual impairment design work&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd" rel="noopener noreferrer"&gt;Axe&lt;/a&gt; - useful accessibility tool&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://chrome.google.com/webstore/detail/tag-assistant-by-google/kejbdjndbnbjgmefkgdddjlbokphdefk?hl=en" rel="noopener noreferrer"&gt;Google Tag Assistant&lt;/a&gt; - useful when setting up Google Analytics tags&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chrome.google.com/webstore/detail/github-file-icons/kkokonbjllgdmblmbichgkkikhlcnekp" rel="noopener noreferrer"&gt;Github File Icons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
*
*&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Scrum Stuff
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://trello.com/" rel="noopener noreferrer"&gt;Trello&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.atlassian.com/software/jira" rel="noopener noreferrer"&gt;Jira&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://asana.com/" rel="noopener noreferrer"&gt;Asana&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://leankit.com/" rel="noopener noreferrer"&gt;Leankit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Stock Photo / Icon Libraries
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://unsplash.com/" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pexels.com/" rel="noopener noreferrer"&gt;Pexels&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://burst.shopify.com/" rel="noopener noreferrer"&gt;Burst&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hatchful.shopify.com/" rel="noopener noreferrer"&gt;Hatchful&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://focastock.com/" rel="noopener noreferrer"&gt;Foca&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://freephotos.cc/" rel="noopener noreferrer"&gt;FreePhotos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pixabay.com/" rel="noopener noreferrer"&gt;Pixabay&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.toptal.com/designers/subtlepatterns/" rel="noopener noreferrer"&gt;Toptal&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.flaticon.com/" rel="noopener noreferrer"&gt;Flaticon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://placeit.net/" rel="noopener noreferrer"&gt;Placeit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Color Pallets
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://coolors.co/" rel="noopener noreferrer"&gt;Coolors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://uigradients.com/" rel="noopener noreferrer"&gt;uiGradients&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Containers &amp;amp; Deployment Systems
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Continuous Integration/Development
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.heroku.com/" rel="noopener noreferrer"&gt;Heroku&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://circleci.com/" rel="noopener noreferrer"&gt;CircleCi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/codepipeline/" rel="noopener noreferrer"&gt;AWS CodePipeline&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jenkins.io/" rel="noopener noreferrer"&gt;Jenkins&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  CMS Solutions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.squarespace.com/" rel="noopener noreferrer"&gt;Squarespace&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.shopify.com/" rel="noopener noreferrer"&gt;Shopify&lt;/a&gt; - this is amazing for e-commerce work - seemless integration with the likes of &lt;a href="https://printify.com/" rel="noopener noreferrer"&gt;Printify&lt;/a&gt; and &lt;a href="https://www.aliexpress.com/" rel="noopener noreferrer"&gt;AliExpress&lt;/a&gt;. You need to check out this latest &lt;a href="https://www.shopify.com/blog/117607173-the-definitive-guide-to-dropshipping-with-aliexpress" rel="noopener noreferrer"&gt;Dropshipping&lt;/a&gt; business trend.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Domain Registers
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/domain-register.html" rel="noopener noreferrer"&gt;Route 53&lt;/a&gt; - AWS&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.godaddy.com/" rel="noopener noreferrer"&gt;GoDaddy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.namecheap.com/" rel="noopener noreferrer"&gt;Namecheap&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
   Streamers
&lt;/h3&gt;

&lt;h4&gt;
  
  
  YouTube
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/channel/UCvjgXvBlbQiydffZU7m1_aw" rel="noopener noreferrer"&gt;Daniel Shiffman - The Coding Train (JS tutorials) - Quite fun &amp;amp; watchable does some interesting ML content too&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=iwcYp-XT7UI" rel="noopener noreferrer"&gt;George Hotz - Founder Comma AI - Complete nutjob&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Twitch
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.twitch.tv/noopkat" rel="noopener noreferrer"&gt;Suz Hinton - noopkat - IOT&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Note
&lt;/h2&gt;

&lt;p&gt;I've had a particularly difficult year with personal circumstances but throughout that entire period work has been a solid foundation I could rely on both for support and drive, and I'm grateful towards all my coworkers for that.&lt;/p&gt;

&lt;p&gt;I hope 2020 will be a better one, and that I'll get the opportunity to write more and possibly speak at a conference or two!&lt;/p&gt;

&lt;p&gt;As always if you have any questions or queries don't hesitate to get in contact in the comments below.&lt;/p&gt;

&lt;p&gt;In the meantime I look forward to doing the 3 year review with you!&lt;br&gt;
Dan.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>webdev</category>
      <category>career</category>
    </item>
    <item>
      <title>Building a Chrome Plugin - Image Swap it up!</title>
      <dc:creator>Daniel McMahon</dc:creator>
      <pubDate>Tue, 05 Feb 2019 17:12:38 +0000</pubDate>
      <link>https://dev.to/danku/building-a-chrome-plugin---image-swap-it-up-589e</link>
      <guid>https://dev.to/danku/building-a-chrome-plugin---image-swap-it-up-589e</guid>
      <description>&lt;p&gt;I'd like to start by apologising in advance for the ridiculousness of &lt;a href="https://github.com/daniel40392/giantbomb-ify" rel="noopener noreferrer"&gt;this Chrome extension&lt;/a&gt;, but hopefully it'll serve as a useful reference if you want to go build your own!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/a4970bb797511ac525ac0fefb16f249d323ef247/68747470733a2f2f7468756d62732e6766796361742e636f6d2f436f6c6f7373616c5175617272656c736f6d6542756e6e792d73697a655f726573747269637465642e676966" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/a4970bb797511ac525ac0fefb16f249d323ef247/68747470733a2f2f7468756d62732e6766796361742e636f6d2f436f6c6f7373616c5175617272656c736f6d6542756e6e792d73697a655f726573747269637465642e676966"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  From Simple Intentions...
&lt;/h2&gt;

&lt;p&gt;This project was initially intended as a useful reference in the event I ever needed to go and build a new Chrome extension. The basic goal and functionality of the project was to build a Chrome extension that when clicked would swap all the images on the page.&lt;/p&gt;

&lt;p&gt;When starting out I had selected a series of &lt;a href="https://www.giantbomb.com/" rel="noopener noreferrer"&gt;GiantBomb&lt;/a&gt; images/gifs from the web as a starting point for what would prove to be a dumb inside joke. I wanted to be able to use web based images as well as local images in order to demonstrated the full functionality of building such an application. &lt;/p&gt;

&lt;p&gt;Having recently seen the &lt;a href="https://dev.to/mkrl/apis-you-didnt-know-you-needed-38c"&gt;APIs you didn't know you needed&lt;/a&gt; article I couldn't help myself but to update the project to also be able to dynamically swap in Bill Murray &amp;amp; Nicolas Cage related images as well. Something I think a wider audience might appreciate.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Implementation
&lt;/h2&gt;

&lt;p&gt;When it comes to setting up a Chrome extension your starting point lies with the manifest.json. You can think of this as a similar version of a package.json for your standard NPM project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GiantBomb-ify"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"manifest_version"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Replaces all images with GB Staff"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"icons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"16"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"logo-small.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"48"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"logo-small.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"128"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"logo-small.png"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"background"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"scripts/background.js"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"browser_action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"default_icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"logo-small.png"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"web_accessible_resources"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"images/*.jpg"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"activeTab"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The name, icon, version, description fields should feel somewhat familiar to NPM or React devs out there, they can be populated with pretty generic details. The other fields are worth explaining in a bit more details.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;manifest_version&lt;/em&gt;: this is specific to the Chrome API, version 2 is the current default version that should be used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;background&lt;/em&gt;: this dictates what scripts should be running in the background once the chrome extension is enabled.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;browser_action&lt;/em&gt;: this dictates the default action that should occur when the chrome extension is added to your browser, in this instance it simply sets a default_icon.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;web_accessible_resources&lt;/em&gt;: this is required to allow public access to the images stored within the extensions codebase. Without this you may have difficulties accessing localised images.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;permissions&lt;/em&gt;: this field limits the permissions of the chrome extension to only the active Chrome tab you have open.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Scripts
&lt;/h2&gt;

&lt;p&gt;As per the manifest.json the background.js script is the first one executed during the extensions addition to a new tab. The script is only being used here to trigger another file 'imageswap.js'. In a more generic setting the script coudl be used to add more functionality to the wider Chrome api and handle items such as firing multiple scripts or injecting global variables etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;browserAction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onClicked&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;executeScript&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts/imageswap.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The logic of the imageswap.js contains some very basic JS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;chromeExtensionId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;iaimgpoecjggdpdlmlhhidciphppgfcf&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementsByTagName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;img&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;gb_images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://static.giantbomb.com/uploads/scale_medium/18/187968/2743737-yplezwp.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//drew headset&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://pbs.twimg.com/media/BpxlFaHCYAIQvvY.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//brad mohawk&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://static.giantbomb.com/uploads/original/7/72053/2671808-rorie.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//rorie glasses&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://static.giantbomb.com/uploads/original/13/139155/2536312-2379004-jeff_headshake.gif&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;//jeff disapproval&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://static.giantbomb.com/uploads/original/17/179932/2783337-4310291077-prUNU.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// dan creep&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://static.giantbomb.com/uploads/original/2/23893/2455096-1935536898-10875.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// vinny alpha protocol&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://www.deepfreeze.it/img/j_headshots/alex_navarro.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// alex smile&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://magnettheater.com/oldImages/headshots/large_abbyrussell_2017.jpg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// abby face&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://static.giantbomb.com/uploads/original/23/233047/2986879-2776158-0471975364-o4gps.gif&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// jason approval&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://78.media.tumblr.com/e0b2ba4e1fd8b1323b4e9c88477db345/tumblr_oshzt0nUPs1u7bbkho1_400.gif&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// ben disapproval&lt;/span&gt;
  &lt;span class="s2"&gt;`chrome-extension://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;chromeExtensionId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/images/ryan.jpg`&lt;/span&gt; &lt;span class="c1"&gt;// local file example - ryan&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nx"&gt;gb_images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

  &lt;span class="c1"&gt;// GB implementation (default)&lt;/span&gt;
  &lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gb_images&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="c1"&gt;// Nicolas Cage implementation&lt;/span&gt;
  &lt;span class="c1"&gt;// images[i].src = "https://www.placecage.com/" + images[i].width + "/" + images[i].height&lt;/span&gt;

  &lt;span class="c1"&gt;// Bill Murray Implementation&lt;/span&gt;
  &lt;span class="c1"&gt;// images[i].src = "https://fillmurray.com/" + images[i].width + "/" + images[i].height&lt;/span&gt;

  &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;chromeExtensionId&lt;/em&gt; variable is used for accessing local files, if you want to use local images you will have to update this value with your own chromeExtensionId once you have followed the instructions in the projects readme. This is used  for populating the local image file ryan.jpg.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;images&lt;/em&gt; variable is used to get all the image tags on a page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;em&gt;gb_images&lt;/em&gt; array is used as our set of 10 GiantBomb staff images for switching&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A for loop is used to iterate through all the images on the page, and for each one it uses a randomly selected index from our gb_images array and displays that instead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The alternative code for implementing the Bill Murray or Nicolas Cage images follows a similar pattern except in their scenarios the height and width values of the images are used and passed into the corresponding urls to generate the associated images. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sample Results
&lt;/h2&gt;

&lt;p&gt;Of course I couldn't sign off without showing some quick screenshots from the results of this horrific extension...&lt;/p&gt;

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

&lt;p&gt;A few things you can note from these screenshots:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Yes I simply searched red in google then fired the plugin - it provides a more interesting/psychotic effect when used on Twitter/Facebook but I don't have the time to censor my own personal profiles for the sake of screenshots.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In both cases for Bill Murray and Nicholas Cage due to the way the corresponding API's &lt;a href="https://www.placecage.com/" rel="noopener noreferrer"&gt;Placecage&lt;/a&gt; and &lt;a href="https://fillmurray.com/" rel="noopener noreferrer"&gt;Fillmurray&lt;/a&gt; work you will see a lot of repetition on images of the same size, because these APIs take in width and height parameters this is inevitable. Some custom logic could be added to modify this.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the case of GiantBomb as there is a limited number of images the output is a bit bland and not super mixed, this can easily be updated with the inclusion of more images instead of the 10 hardcoded.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the case of GiantBomb you may notice one broken image. This is corresponding to the local file that is referenced - I have left this error in to emphasise as mentioned above that you need to ensure to update the chromeExtensionId to match your local version to have this work correctly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Possible Implementations
&lt;/h2&gt;

&lt;p&gt;So the use case here is pretty basic and there are limited reasons to want to swap out all the images on a page, however if you wanted to dig dipper and experiment more there are a few other modification you could make to try improve the functionality from this basic foundation - here are some that immediately spring to mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add in a blacklisted image url list - you could create your own censorship extension&lt;/li&gt;
&lt;li&gt;Use the extension to write the discovered URLs on a page to a DB, might be a useful way to obtain training data for some image learning models&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;I don't get to spend a lot of time lately developing with JavaScript but I love being able to get started quickly with something fun, relatively easy and having a practical output by the end. This specific extension isn't released on the Google Chrome store however their &lt;a href="https://developer.chrome.com/webstore/publish" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; is relatively helpful and should help you publish your own extension should you wish to go down that route!&lt;/p&gt;

&lt;p&gt;You can checkout the project &amp;amp; the readme with setup instructions &lt;a href="https://github.com/daniel40392/giantbomb-ify" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As always be sure to leave your feedback and thoughts below.&lt;/p&gt;

&lt;p&gt;'Till next time!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Do you unit test private methods?</title>
      <dc:creator>Daniel McMahon</dc:creator>
      <pubDate>Tue, 08 Jan 2019 14:43:16 +0000</pubDate>
      <link>https://dev.to/danku/do-you-unit-test-private-methods-23eg</link>
      <guid>https://dev.to/danku/do-you-unit-test-private-methods-23eg</guid>
      <description>&lt;p&gt;Encountered an interesting issue at work recently when it came to unit testing a new repo that was setup. The repo in question was relatively small and functioned as a basic cronjob, however in order to follow some best practices I decided to opt in for including some basic unit tests.&lt;/p&gt;

&lt;p&gt;In doing so I mistakenly wrote a unit test for a private Python class signified with the standard underscore prefix! As I haven't coded in Python in a while I had forgotten about this syntax, but I was a little stunned to hear from a colleague that best practice seems to be to purposefully not test private methods.&lt;/p&gt;

&lt;p&gt;I'm curious to hear the thoughts from the Dev community on this one? I get by their very nature you should probably opt to test the Class that the method belongs to end to end rather than opt for a unit test, but what about when you're looking for simple test functionality in a timely manner?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fekiy5aot90-flywheel.netdna-ssl.com%2Fwp-content%2Fuploads%2F2014%2F10%2Fsegue-blog-benefits-unit-testing.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fekiy5aot90-flywheel.netdna-ssl.com%2Fwp-content%2Fuploads%2F2014%2F10%2Fsegue-blog-benefits-unit-testing.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Curious to hear from the community on this one! (across different languages/frameworks too - not just Python)&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>programming</category>
      <category>testing</category>
      <category>python</category>
    </item>
    <item>
      <title>Lucas - A Webscraper in Go</title>
      <dc:creator>Daniel McMahon</dc:creator>
      <pubDate>Thu, 06 Dec 2018 18:35:25 +0000</pubDate>
      <link>https://dev.to/danku/lucas---a-webscraper-in-go-3jkc</link>
      <guid>https://dev.to/danku/lucas---a-webscraper-in-go-3jkc</guid>
      <description>&lt;h1&gt;
  
  
  Lucas
&lt;/h1&gt;

&lt;p&gt;Lucas is a webscraper built using &lt;a href="https://golang.org/" rel="noopener noreferrer"&gt;Go&lt;/a&gt; and the &lt;a href="https://github.com/gocolly/colly" rel="noopener noreferrer"&gt;Colly&lt;/a&gt; library. He's also an adorable spider on &lt;a href="https://www.youtube.com/watch?v=VrS6akzR3sk" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/26u4ltSAwnEb0Hpwk/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/26u4ltSAwnEb0Hpwk/giphy.gif" width="364" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;I wanted to experiment a little with Go as it's a programming language used by certain teams at my office and not something I often get hands on with. I figured it would be fun to try deconstruct a random online website and see if I could come up with a programmatic way to abstract the HTML data in a way that could be perceived as useful.&lt;/p&gt;

&lt;p&gt;The project started out as a fun experiment but after taking it as far as I have I decided to stop working on it for a few reasons which I'll outline below.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Morality of Web Scraping
&lt;/h2&gt;

&lt;p&gt;As will be apparent to many out there, web scraping is a bit of a 'grey' area morally speaking. From all the research and reading I've done on the subject I usually boil it down to this:&lt;/p&gt;

&lt;p&gt;'if you are not violating fair terms of use, abiding by a companies &lt;a href="https://en.wikipedia.org/wiki/Robots_exclusion_standard" rel="noopener noreferrer"&gt;robots.txt&lt;/a&gt; file &amp;amp; notifying them that you are doing so, then you should be in the clear'&lt;/p&gt;

&lt;p&gt;This is a highly generalised statement for this complex issue but I find its a nice guideline to try follow.&lt;/p&gt;

&lt;p&gt;When it comes to e-commerce online websites can hold some highly profitable data, data which they may not even necessarily surface on the frontend of their stores, but they will still have the JSON floating around in their static page content. &lt;/p&gt;

&lt;p&gt;Some types of information e-commerce stores may leave floating around in their HTML include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stock levels (things like low in stock flags or even exact stock numbers!)&lt;/li&gt;
&lt;li&gt;Size availability&lt;/li&gt;
&lt;li&gt;Pricing/Sales Rates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For general user purposes this data can go unnoticed but it can be a simple case of right clicking on a storefront and selecting 'view page source' to access this data.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 'Drawbacks' of Structured data
&lt;/h2&gt;

&lt;p&gt;When it comes to designing a web scraper you want to try analyse the structure of your 'target' sites pages. Ask yourself these kinds of questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is there an easy pattern to follow to access product specific pages&lt;/li&gt;
&lt;li&gt;Is there a replicated structure across multiple pages to allow easy html parsing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the more technical side of things consider the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the website update its HTML often?&lt;/li&gt;
&lt;li&gt;Can you account for missing data during your web scraping?&lt;/li&gt;
&lt;li&gt;How will you store the data? Will a DB be fast enough?&lt;/li&gt;
&lt;li&gt;Do you plan to handle multi-threading/distributed scraping?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How the scraper works
&lt;/h2&gt;

&lt;p&gt;So onto the fun part - the code! I will talk in generalised terms here so the practices used can be applied to any form of e-commerce store.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Storage
&lt;/h3&gt;

&lt;p&gt;In order to setup a way to store the scraped websites data I decided to roll with a postgres DB, for no other reason than I was familiar with it and it was easy to setup via a docker-compose file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;lucas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;lucas&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:9.6-alpine&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;5432:5432'&lt;/span&gt;
  &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;lucas_db'&lt;/span&gt;
    &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this basic PSQL db I was able to setup a basic table by running the following command with the following input file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;psql &lt;span class="nt"&gt;-h&lt;/span&gt; localhost &lt;span class="nt"&gt;-U&lt;/span&gt; user lucas_db &lt;span class="nt"&gt;-f&lt;/span&gt; dbsetup.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;dbsetup.sql:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;
&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt; &lt;span class="n"&gt;lucas_db&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;floryday&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;index&lt;/span&gt; &lt;span class="nb"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="nb"&gt;decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;53&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see from the table there were a few basic details I decided to scrape from the web pages in question:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;index: this was just used as a unique id&lt;/li&gt;
&lt;li&gt;product: name of the product item&lt;/li&gt;
&lt;li&gt;code: code of the product in question&lt;/li&gt;
&lt;li&gt;description: the description text of the product&lt;/li&gt;
&lt;li&gt;price: the price of the product&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As listed above there are other additional fields you might be interested in abstracting in your own experiences like size &amp;amp; availability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Go Dependencies
&lt;/h3&gt;

&lt;p&gt;I was a little sloppy in my service setup in that I did not rely on a Go service dependency management tool like dep, instead I just took care of manually installing them (as there were only 3 dependencies it wasn't so bad). These were the three main external libraries I used they can be installed with the command &lt;code&gt;go get &amp;lt;repo-name&amp;gt;&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/gocolly/colly" rel="noopener noreferrer"&gt;github.com/gocolly/colly&lt;/a&gt; - webscraping package&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/fatih/color" rel="noopener noreferrer"&gt;github.com/fatih/color&lt;/a&gt; - command line colors package&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/lib/pq" rel="noopener noreferrer"&gt;github.com/lib/pq&lt;/a&gt; - postgres driver package&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To make this setup a little easier I setup a Dockerfile to keep track of the installation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; golang:1.11&lt;/span&gt;

&lt;span class="k"&gt;MAINTAINER&lt;/span&gt;&lt;span class="s"&gt; Daniel McMahon &amp;lt;daniel40392@gmail.com&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /opt/lucas&lt;/span&gt;

&lt;span class="k"&gt;ADD&lt;/span&gt;&lt;span class="s"&gt; . /opt/lucas&lt;/span&gt;

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; PORT blergh&lt;/span&gt;

&lt;span class="c"&gt;# installing our golang dependencies&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/gocolly/colly &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/fatih/color &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/lib/pq

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8000&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; go run lucas.go&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The main logic
&lt;/h3&gt;

&lt;p&gt;In short the main code does the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Starts at a seed url&lt;/li&gt;
&lt;li&gt;Scans all the links on the page&lt;/li&gt;
&lt;li&gt;Looks for a page that matches a certain regex i.e. -Dresses we know from some basic checks that these pages all have a similar page structure and are usually product pages that we are interested in&lt;/li&gt;
&lt;li&gt;Define a Struct to represent our clothing values of interest&lt;/li&gt;
&lt;li&gt;Write the Struct to the postgres DB&lt;/li&gt;
&lt;li&gt;Continue up to a size of 200 writes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the main bulk of the code with comments explaining the logic - it is not optimized and still quite rough around the edges but its key functionality is in place:&lt;/p&gt;

&lt;p&gt;lucas.go&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// as our scraper will only use one file this will be our main package&lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="c"&gt;// importing dependencies&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/json"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"strings"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/gocolly/colly"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/fatih/color"&lt;/span&gt;
    &lt;span class="s"&gt;"database/sql"&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="s"&gt;"github.com/lib/pq"&lt;/span&gt;
    &lt;span class="s"&gt;"strconv"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// setting up a datastruture to represent a form of Clothing&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Clothing&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt;                    &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Code&lt;/span&gt;                    &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Description&lt;/span&gt;     &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;Price&lt;/span&gt;                   &lt;span class="kt"&gt;float64&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// setting up a function to write to our db &lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;dbWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="n"&gt;Clothing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;host&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt;
      &lt;span class="n"&gt;port&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5432&lt;/span&gt;
      &lt;span class="n"&gt;user&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"user"&lt;/span&gt;
      &lt;span class="c"&gt;// password = ""&lt;/span&gt;
      &lt;span class="n"&gt;dbname&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"lucas_db"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;psqlInfo&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"host=%s port=%d user=%s "&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
    &lt;span class="s"&gt;"dbname=%s sslmode=disable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dbname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"postgres"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;psqlInfo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ping&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c"&gt;// some debug print logs&lt;/span&gt;
  &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Successfully connected!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s, %s, %s, %f"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;sqlStatement&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;`
    INSERT INTO floryday (product, code, description, price)
    VALUES ($1, $2, $3, $4)`&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sqlStatement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// our main function - using a colly collector&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// creating our new colly collector with a localised cache&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;colly&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewCollector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="c"&gt;// colly.AllowedDomains("https://www.clotheswebsite.com/"),&lt;/span&gt;
        &lt;span class="n"&gt;colly&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CacheDir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;".floryday_cache"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="c"&gt;// colly.MaxDepth(5), // keeping crawling limited for our initial experiments&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// clothing detail scraping collector&lt;/span&gt;
    &lt;span class="n"&gt;detailCollector&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="c"&gt;// setting our array of clothing to size 200&lt;/span&gt;
    &lt;span class="n"&gt;clothes&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="n"&gt;Clothing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Find and visit all links&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"a[href]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;colly&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTMLElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="n"&gt;link&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c"&gt;// hardcoded urls to skip -&amp;gt; these arent relevant for products&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HasPrefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/?country_code"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/cart.php"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/login.php"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/cart.php"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
        &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/account"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"/privacy-policy.html"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// scrape the page&lt;/span&gt;
        &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;link&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c"&gt;// printing visiting message for debug purposes&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;colly&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Visiting"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c"&gt;// visting any href links -&amp;gt; this can be optimised later&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`a[href]`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;colly&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTMLElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="n"&gt;clothingURL&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AbsoluteURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Attr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="c"&gt;// this was a way to determine the page was definitely a product&lt;/span&gt;
                &lt;span class="c"&gt;// if it contained -Dress- we were good to scrape&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clothingURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"-Dress-"&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
            &lt;span class="c"&gt;// Activate detailCollector&lt;/span&gt;
            &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Green&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Crawling Link Validated -&amp;gt; Commencing Crawl for %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clothingURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;detailCollector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clothingURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Red&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Validation Failed -&amp;gt; Cancelling Crawl for %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clothingURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c"&gt;// Extract details of the clothing&lt;/span&gt;
    &lt;span class="n"&gt;detailCollector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnHTML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`div[class=prod-right-in]`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;colly&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTMLElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// some html parsing to get the exact values we want&lt;/span&gt;
        &lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ChildText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;".prod-name"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ChildText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;".prod-item-code"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;stringPrice&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TrimPrefix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ChildText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;".prod-price"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="s"&gt;"€ "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
        &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseFloat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stringPrice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// conversion to float64&lt;/span&gt;
        &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Red&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"err in parsing price -&amp;gt; %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ChildText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;".grid-uniform"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;clothing&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Clothing&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;                   &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Code&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;                   &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Description&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;        &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Price&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;                  &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c"&gt;// writing as we go to DB&lt;/span&gt;
        &lt;span class="c"&gt;// TODO optiize to handle bulk array uploads instead of one at a time&lt;/span&gt;
        &lt;span class="n"&gt;dbWrite&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clothing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c"&gt;// appending to our output array...&lt;/span&gt;
        &lt;span class="n"&gt;clothes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clothes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clothing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c"&gt;// start scraping at our seed address&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://www.ourclothingwebstore.com/Dresses-r9872/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;enc&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;enc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetIndent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"  "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Dump json to the standard output&lt;/span&gt;
    &lt;span class="n"&gt;enc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;clothes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dangerzone
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fnerdist.com%2Fwp-content%2Fuploads%2F2017%2F05%2FTop-Gun-tom-Cruise.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fnerdist.com%2Fwp-content%2Fuploads%2F2017%2F05%2FTop-Gun-tom-Cruise.jpg" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After getting the basic functionality setup and working it was at this point I decided to try experiment with multiple product seed pages. I discovered that this particular store laid out its main products on a page called: &lt;a href="https://www.ourclothingwebstore.com/Dresses-r9872/" rel="noopener noreferrer"&gt;https://www.ourclothingwebstore.com/Dresses-r9872/&lt;/a&gt; however this could be paginated with a simple /p2 at the end of the url, or /p3, /p4 all the way up to p80 something! On average there was around 40+ products on each of these pages. I had implemented a simple for loop that iterated over this seed url updating it each time. I could in essence with a little more logic setup the crawler to hit all the Dress products this store had on sale (and similarly I'm sure with a small regex tweak the logic could have been applied to other fashion categories the retailer had on offer).&lt;/p&gt;

&lt;p&gt;It was at this point that I decided to stop work on the project as I had achieved the basic goals I set out to do and learned perhaps a little too easily how malicious this innocent project could turn. It was turning into a one way stop into essentailly having a DB that contained the entire storefront of this ecommerce site.&lt;/p&gt;

&lt;p&gt;There are definitely optimisations that would be required to achieve this goal but I imagine with the use of goroutines you could get some parallelisation of this scraper happening to speed up the process to potentially scrape the entire website in a short timespan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;I had some fun trying to reverse engineer the websites HTML structure and figure out how they were displaying product pages and how to go about abstracting the right product hrefs to crawl and the correct data to be able to obtain and write to a DB. It was enjoyable but it all felt a little too close to the sun for my legal liking.&lt;/p&gt;

&lt;p&gt;I have deliberately not referenced the 'real' websites name in this example for the sake of their anonymity but the underlying principles should be applicable to most major online ecommerce retailers.&lt;/p&gt;

&lt;p&gt;I was amazed with how easy it was to get up and running with the Colly library - I definitely suggest testing it out but be careful with what data you decide to scrape/store and that you investigate your targets robots.txt file to ensure you have permission to hit their website. &lt;/p&gt;

&lt;p&gt;Any thoughts/opinions/comments feel free to leave below.&lt;/p&gt;

&lt;p&gt;See you next time!&lt;/p&gt;

</description>
      <category>go</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Integrating Docker with your Personal Projects</title>
      <dc:creator>Daniel McMahon</dc:creator>
      <pubDate>Tue, 04 Dec 2018 20:22:41 +0000</pubDate>
      <link>https://dev.to/danku/integrating-docker-with-your-personal-projects-19cl</link>
      <guid>https://dev.to/danku/integrating-docker-with-your-personal-projects-19cl</guid>
      <description>&lt;h2&gt;
  
  
  Why?
&lt;/h2&gt;

&lt;p&gt;Docker themselves outline the use cases for adopting their container based infrastructure over on their &lt;a href="https://www.docker.com/why-docker" rel="noopener noreferrer"&gt;main website&lt;/a&gt;. I can provide a brief snapshot of my own opinions on why it's a useful tool and how it can be used to optimize your project workflow as well as how it can make your projects stand out after just leaving college.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/PA2XJCpgvv1Is/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/PA2XJCpgvv1Is/giphy.gif" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Benefits
&lt;/h2&gt;

&lt;p&gt;I'm going to avoid the ship shipping ships container metaphors here. If you've ever heard or come across Docker or Kubernetes the landscape is littered with these metaphors. I'll try keep things a little more simplistic in outlining some of the benefits of this tooling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Dependency Validation&lt;/em&gt;: Docker allows you to create images based on a build of your project. This means all your dependencies are self contained, allowing you to build the project locally as a docker image, run it as a container and verify that it works and has all the correct dependencies. This prevents weird oversights you might have with globally installed packages on your local machine that aren't defined in the projects package.json, sbt or dep file. If the Docker image runs on your Windows PC, it should run fine on your Linux EC2 instance or other devices you plan to run the Docker image on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Version Control&lt;/em&gt;: don't just rely on GitHub! As mentioned above you can build Docker Images which are essentially snapshots of your projects builds at various points in time. Imagine a scenario where you need to demo your service locally, you pull the latest version from master, build it and it crashes... you don't have time to revert to an older commit, build the service and then launch it... instead you can just pull the older commit image and run it - as its all self contained it will be much faster in building/running. It's also a handy way to quickly compare old features and new features -&amp;gt; it can also be an interesting way of viewing how a project originally looked 5+ years ago compared to how it is now.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;CI/CD&lt;/em&gt;: If you're using continuous integration/development solutions and you accidentally deploy a broken build in a pipeline, it can be quite time efficient to simply refer to an earlier docker image rather than rebuild the project from scratch again. A popular method of development is to wrap up your projects as docker images, upload them to a cloud solution (such as the public &lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;Docker Hub&lt;/a&gt; or a more private solution hosted on a service like &lt;a href="https://aws.amazon.com/ecr/" rel="noopener noreferrer"&gt;AWS Elastic Container Registry&lt;/a&gt;) and then use those images in the prod environment. This is a particularly powerful solution when paired with a service like Kubernetes that may be running replicas of services across multiple pods or EC2 instances. It's simply more efficient using a docker image then pulling the repo 3 times, installing and building all the dependencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Imitating Prod Dependencies Locally &amp;amp; Quickly&lt;/em&gt;: quite often when working in a professional environment you may be working on a front end codebase that requires access to a a postgres db for storing some site documentation while also requiring access to a storage solution like Redis for managing user session storage. It can be quite time consuming setting up your development environment as a result of these dependencies, however Docker have a useful tool &lt;a href="https://docs.docker.com/compose/overview/#features" rel="noopener noreferrer"&gt;docker-compose&lt;/a&gt; that will allow you to run a postgres and redis setup with a single command 'docker-compose up -d' with a yaml file containing less than 10 lines of code.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll quickly acknowledge at this point that Docker is not the be all and end all solution. Inductor has an interesting article &lt;a href="https://dev.to/inductor/do-you-really-need-docker-or-kubernetes-in-your-system-11nk"&gt;Do you really need docker or kubernetes in your system link&lt;/a&gt; that I highly recommend checking out.&lt;/p&gt;

&lt;p&gt;As a college graduate or new developer being able to demonstrate interest and knowledge in how you would plan to make your project scalable and deployable in a production environment can give you the edge over other candidates in interviews. Having a basic Dockerfile setup in your personal projects gives you another unique talking point and skill to reference in your interviews.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating Docker with your beginner projects
&lt;/h2&gt;

&lt;p&gt;I took on the challenge to go about integrating Docker into some previous projects I've worked on to help provide some end to end insight on the practical use cases of the tooling and how easy it can be to add this extra functionality. I've previously written articles on the development of these basic projects so beginners can gain a better insight into how a project can develop new features over time by reviewing these past articles.&lt;/p&gt;

&lt;p&gt;There is a general pattern adopted across all three of these projects which you will notice (and which emphasises how easy it can be to generate these files)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use a base image i.e. node/openjdk/golang&lt;/li&gt;
&lt;li&gt;Set the Maintainer&lt;/li&gt;
&lt;li&gt;Set the working directory and add the relevant files&lt;/li&gt;
&lt;li&gt;Set any ENV vars i.e. ports/versions -&amp;gt; this allows easy updates later&lt;/li&gt;
&lt;li&gt;Install your dependencies using 'RUN'&lt;/li&gt;
&lt;li&gt;Expose your required port/ports&lt;/li&gt;
&lt;li&gt;Run your main command i.e. npm start&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now lets have a look at the generated files.&lt;/p&gt;

&lt;h3&gt;
  
  
  JavaScript: React Portfolio - &lt;a href="https://github.com/daniel40392/react-portfolio" rel="noopener noreferrer"&gt;Code&lt;/a&gt; - &lt;a href="https://dev.to/daniel40392/building-a-portfolio-the-painful-way-3im8"&gt;Article&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This project evolved from a simple create-react-app.&lt;br&gt;
The generated Dockerfile looks as follows:&lt;/p&gt;

&lt;p&gt;Dockerfile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:8&lt;/span&gt;

&lt;span class="k"&gt;MAINTAINER&lt;/span&gt;&lt;span class="s"&gt; Daniel McMahon &amp;lt;daniel40392@gmail.com&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /opt/react-portfolio&lt;/span&gt;

&lt;span class="k"&gt;ADD&lt;/span&gt;&lt;span class="s"&gt; . /opt/react-portfolio&lt;/span&gt;

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; PORT 3000&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; npm start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is an NPM package that might help you auto generate Dockerfiles in future. Checkout the &lt;a href="https://www.npmjs.com/package/dockerfile-generator" rel="noopener noreferrer"&gt;dockerfile-generator&lt;/a&gt; package available over at NPM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scala: The Inspiration API - &lt;a href="https://github.com/daniel40392/inspiration-api" rel="noopener noreferrer"&gt;Code&lt;/a&gt; - &lt;a href="https://dev.to/daniel40392/the-inspiration-api-a-project-built-with-scala--play-framework-195d"&gt;Article&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This project evolved as a basic Scala/Play application built from SBT. This service has a dependency on a postgres DB that can be setup locally using docker-compose.&lt;/p&gt;

&lt;p&gt;Dockerfile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; openjdk:8&lt;/span&gt;

&lt;span class="k"&gt;MAINTAINER&lt;/span&gt;&lt;span class="s"&gt; Daniel McMahon &amp;lt;daniel40392@gmail.com&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /opt/inspiration-api&lt;/span&gt;

&lt;span class="k"&gt;ADD&lt;/span&gt;&lt;span class="s"&gt; . /opt/inspiration-api&lt;/span&gt;

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; SBT_VERSION 0.13.15&lt;/span&gt;

&lt;span class="c"&gt;# Install sbt&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="se"&gt;\
&lt;/span&gt;  curl &lt;span class="nt"&gt;-L&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; sbt-&lt;span class="nv"&gt;$SBT_VERSION&lt;/span&gt;.deb http://dl.bintray.com/sbt/debian/sbt-&lt;span class="nv"&gt;$SBT_VERSION&lt;/span&gt;.deb &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  dpkg &lt;span class="nt"&gt;-i&lt;/span&gt; sbt-&lt;span class="nv"&gt;$SBT_VERSION&lt;/span&gt;.deb &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="nb"&gt;rm &lt;/span&gt;sbt-&lt;span class="nv"&gt;$SBT_VERSION&lt;/span&gt;.deb &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  apt-get &lt;span class="nb"&gt;install &lt;/span&gt;sbt &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  sbt sbtVersion

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 9000&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; sbt run&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;docker-compose.yaml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;inspiration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;inspiration&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:9.6-alpine&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;5432:5432'&lt;/span&gt;
  &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;inspiration_db'&lt;/span&gt;
    &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to correctly have the Docker container running the service communicate with a local DB setup you will need to run it with the following port setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# setup db dependencies&lt;/span&gt;
docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
psql &lt;span class="nt"&gt;-h&lt;/span&gt; localhost &lt;span class="nt"&gt;-U&lt;/span&gt; user inspiration_db &lt;span class="nt"&gt;-f&lt;/span&gt; dbsetup.sql

&lt;span class="c"&gt;# build and tag image locally&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; inspiration_api:v1 &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# port forwarding Docker to localhost:9000&lt;/span&gt;
&lt;span class="c"&gt;# note: this seems to be broken atm - I'll update when fixed!&lt;/span&gt;
docker run &lt;span class="nt"&gt;-ti&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 9000:9000 &lt;span class="nt"&gt;-p&lt;/span&gt; 5432:5432 &amp;lt;docker-image-id&amp;gt;

&lt;span class="c"&gt;# publish docker image to docker hub&lt;/span&gt;
docker push &amp;lt;docker-repo&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Interested in automating this process? There are a few Scala libraries that will auto generate and push docker images for you. Checkout marcuslonnberg's &lt;a href="https://github.com/marcuslonnberg/sbt-docker" rel="noopener noreferrer"&gt;sbt-docker&lt;/a&gt; plugin.&lt;/p&gt;

&lt;h3&gt;
  
  
  Golang: Lucas - &lt;a href="https://github.com/daniel40392/lucas" rel="noopener noreferrer"&gt;Code&lt;/a&gt; - [article incoming...]
&lt;/h3&gt;

&lt;p&gt;This project is a basic web crawler built using Go and the Colly library. This service has a dependency on a postgres DB that can be setup locally using docker-compose.&lt;/p&gt;

&lt;p&gt;Dockerfile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; golang:1.11&lt;/span&gt;

&lt;span class="k"&gt;MAINTAINER&lt;/span&gt;&lt;span class="s"&gt; Daniel McMahon &amp;lt;daniel40392@gmail.com&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /opt/lucas&lt;/span&gt;

&lt;span class="k"&gt;ADD&lt;/span&gt;&lt;span class="s"&gt; . /opt/lucas&lt;/span&gt;

&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; PORT blergh&lt;/span&gt;

&lt;span class="c"&gt;# installing our golang dependencies&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/gocolly/colly &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/fatih/color &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/lib/pq

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8000&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; go run lucas.go&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;docker-compose.yaml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;lucas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;lucas&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:9.6-alpine&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;5432:5432'&lt;/span&gt;
  &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;lucas_db'&lt;/span&gt;
    &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;user'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to correctly have the Docker container running the service communicate with a local DB setup you will need to run it with a network flag in host mode:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# setup db dependencies&lt;/span&gt;
docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
psql &lt;span class="nt"&gt;-h&lt;/span&gt; localhost &lt;span class="nt"&gt;-U&lt;/span&gt; user lucas_db &lt;span class="nt"&gt;-f&lt;/span&gt; dbsetup.sql

&lt;span class="c"&gt;# build docker image&lt;/span&gt;
docker build &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# run docker container and portforward port 3000&lt;/span&gt;
&lt;span class="c"&gt;# the host network flag will allow your container to speak to your local DB&lt;/span&gt;
docker run &lt;span class="nt"&gt;-ti&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8000:8000 &lt;span class="nt"&gt;--network&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"host"&lt;/span&gt; &amp;lt;docker-image-id&amp;gt;

&lt;span class="c"&gt;# publish docker image to docker hub&lt;/span&gt;
docker push &amp;lt;docker-repo&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;As you can see from the above its relatively straight forward to get your applications up and running on Docker. It can be a little tricky when you first get used to the concepts behind Docker but once you get the hang of it the advantages it offers are fantastic.&lt;/p&gt;

&lt;p&gt;There is a super cool tool I stumbled upon this week that will let you analyse the quality of your docker images and give you a % rating for how well optimized it is i.e. if you have too much bloat from installed packages etc. Go check it out - the libraries called '&lt;a href="https://github.com/wagoodman/dive" rel="noopener noreferrer"&gt;dive&lt;/a&gt;'.&lt;/p&gt;

&lt;p&gt;The natural next step from 'Dockerising' your applications is to look at deploying it through some sort of CI/CD solution. I hope to try take a look at setting up your own Kubernetes cluster using a library called &lt;a href="https://github.com/kubernetes/kops" rel="noopener noreferrer"&gt;kops&lt;/a&gt; and deploying the above services through it. &lt;/p&gt;

&lt;p&gt;Any feedback/thoughts/suggestions feel free to comment below.&lt;/p&gt;

&lt;p&gt;See you next time!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>javascript</category>
      <category>go</category>
    </item>
    <item>
      <title>A Year in Professional Software Development</title>
      <dc:creator>Daniel McMahon</dc:creator>
      <pubDate>Sat, 01 Sep 2018 13:35:06 +0000</pubDate>
      <link>https://dev.to/danku/a-year-in-professional-software-development-1l7a</link>
      <guid>https://dev.to/danku/a-year-in-professional-software-development-1l7a</guid>
      <description>&lt;h2&gt;
  
  
  A Year in Professional Software Development
&lt;/h2&gt;

&lt;p&gt;I survived a year working in Professional Software Development - Huzzah!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/hZj44bR9FVI3K/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/hZj44bR9FVI3K/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I feel there may be some value in recalling my own personal experiences a year after being thrown into the software engineering workforce after coming straight out of a 1 year computer science conversion program. I was lucky enough to be hired by the company I conducted work experience at straight out of my course and since then its been a long and mainly prosperous road.&lt;/p&gt;

&lt;p&gt;There are a few things that I feel are worth sharing so those new to the industry can feel some security in their mindsets and how they might evolve and adapt over their coming work year. Here are the key lessons I’ve learned in the past year:&lt;/p&gt;

&lt;h3&gt;
  
  
  Seek the opinions &amp;amp; advice of your colleagues
&lt;/h3&gt;

&lt;p&gt;This may seem obvious but having worked with a wide variety of developers from the typical rockstar dev who pops up services and repos overnight with zero test coverage, to the devs who provide agonising feedback over a single line PR change to some production code its important that you weigh the opinions of your colleagues against your own.&lt;/p&gt;

&lt;p&gt;When you are a new developer everyone seems more experienced but the more exposure you get to codebases and different people's approaches to their workflow you start to see patterns between the developers who provide genuine value to the company/your team and those who are churning out code for their own means whether thats to just get a service out the door or to try and emphasise their own unique contributions during a certain quarter or sprint. The experiences both sides of the spectrum have to offer can be enlightening and helpful towards your own personal development and workflow style.&lt;/p&gt;

&lt;h3&gt;
  
  
  You code as a team. Not as an individual
&lt;/h3&gt;

&lt;p&gt;I’ve worked across multiple teams this past year and found that teamwork really is essential to achieving your goals. (Duh). I’ve found that teams who spend time planning out quarters or sprints and factor in the skills and talents of their members accurately are in a much better position to scope work out accurately and overall provide a positive work atmosphere. &lt;/p&gt;

&lt;p&gt;As a new developer you will need to lean heavily on the support of your colleagues. There is an inevitable build up time before you are able to make meaningful contributions of your own however it is important to realise that your colleagues have a responsibility to assist you and its not something you should feel shy or embarrassed about requesting. In the same way they provide support to you, you should be able to provide further support to new devs who join in the future.&lt;/p&gt;

&lt;p&gt;Its a dog eat dog world out there and us developers have to stick together. And on the note of team consideration…&lt;/p&gt;

&lt;h3&gt;
  
  
  Write tests &amp;amp; maintain documentation regularly
&lt;/h3&gt;

&lt;p&gt;For your own sanity and the sanity of your co-workers do not test code in production if you can avoid it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmemegenerator.net%2Fimg%2Finstances%2F68965818.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmemegenerator.net%2Fimg%2Finstances%2F68965818.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You need to ensure the code you commit is to a certain production quality standard with a &lt;em&gt;high level of test coverage&lt;/em&gt; and decent &lt;em&gt;documentation&lt;/em&gt;. This is beneficial for so many reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Any future changes to the codebase that may impact your changes will be instantly picked up when changes are made and your tests fail. When services pop up overnight with limited test coverage and get thrown into production down the road, you or even worse your team mates will have to pick up to the technical debt down the road to implement the tests when something breaks later on.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Quality documentation make the codebase easier to understand how to deploy services locally, in production or just provide insight into what your application is and how you can test its functionality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Team understanding. If you are a new developer you will benefit greatly to exposure of codebases with quality testing and good documentation. You should consider it a responsibility to make your work to a standard that new developers can easily adopt and work with. Thats not to say your code should always be simple but take care with the basic things including use of descriptive variable names and the use of details local/production deploy instructions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To understand your code you need to be able to write tests for it. This is something I will openly admit to struggling with from time to time as often its easier to just write a block of code then it may be to mock up a server call to test it. Always try relate back to the &lt;em&gt;test triangle&lt;/em&gt; when it comes to your work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make the working process work for you
&lt;/h3&gt;

&lt;p&gt;Whether your team has adopted an agile kanban, scrum or waterfall style of development its key that you focus on making the existing system work to your advantage. There are many methods of working in software development but the most common one I’ve seen is the use of a Kanban board (Jira, Trello, LeanKit) with specific rules around epics, stories, tasks, bugs and how they are all individually handled. &lt;/p&gt;

&lt;p&gt;Learn the systems in place, learn how to write the various tickets, learn how to use the systems in place to optimise your workflow. If theres a streamlined process for logging and tackling bugs be sure to follow that system. I would never suggest blindly taking the systems in place to be optimal, and by all means you should question at every corner if the particular ‘way of working’ implemented by your team or larger org currently makes sense.&lt;/p&gt;

&lt;p&gt;When it comes to handling things like rituals i.e. standups, refinement, planning, retrospectives, post-mortems adapt and use the processes that make the most sense for those on your team. There is little point in engaging in daily standups with your team if nobody is getting value from it. Similarly if there are issues with planning taking too long or being of minimal value speak up and provide alternative options to try and handle the problems encountered.&lt;/p&gt;

&lt;p&gt;Never just go with the flow, especially if the flow is detrimental to team productivity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Take the bad with the good
&lt;/h3&gt;

&lt;p&gt;By its very nature software development is going to be a bumpy road full of the highest highs and lowest lows. I’ve had plenty of experiences where some block of code was not behaving as expected and banged my head against the wall for hours only to discover a typo somewhere in a variable name. I’ve also had the struggle with getting weird results from querying Postgres DBs with what should be a simply order by query only to discover the JS library I was using had its own quirks. There were even times when I tried applying stuff from college like the use of xmlhttp requests only to discover that in React it was so much faster to just whip out an axios library to do the same job. Don’t even get me started on the amount of CORS related issues I’ve had to debug the past year…&lt;/p&gt;

&lt;p&gt;These experiences are only a handful of personal experiences I’ve encountered along the way, all of which drove me up the wall at the time, but from each one I’ve learned a lot and adjusted my own personal debugging approaches. If you haven’t heard of it you need to go and checkout &lt;strong&gt;&lt;em&gt;Rubber Duck Debugging&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fhackerboss.com%2Fwp%2Fwp-content%2Fuploads%2F2009%2F08%2Frubber-duck-debugging.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fhackerboss.com%2Fwp%2Fwp-content%2Fuploads%2F2009%2F08%2Frubber-duck-debugging.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But at its very core software engineering is problem solving. As a junior developer you will not learn if you don’t make mistakes. The important factor is to try and ask for assistance only when you need it. Don’t be afraid to tackle a problem head on before seeking the advice of the puzzle-masters that are the more senior developers. You don’t get better at puzzles by being given the answers, you get better by being exposed to them and adapting your thinking towards how to solve them.&lt;/p&gt;

&lt;h3&gt;
  
  
  The difference between Junior &amp;amp; Senior is not all that much…
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fscontent-lax3-1.cdninstagram.com%2Fvp%2F301e9d9db4944fecf45de75d1863eeb6%2F5C046797%2Ft51.2885-15%2Fe35%2Fs480x480%2F38904439_194279941296056_1112725133316849664_n.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fscontent-lax3-1.cdninstagram.com%2Fvp%2F301e9d9db4944fecf45de75d1863eeb6%2F5C046797%2Ft51.2885-15%2Fe35%2Fs480x480%2F38904439_194279941296056_1112725133316849664_n.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My point here is that graduate developers are all to quick to label themselves as ‘juniors’ despite spending perhaps up to 4 years working on independent projects or college related material. Try not to think of yourself as a junior developer but instead focus on the steps you can take to become a better developer&lt;/p&gt;

&lt;p&gt;The biggest difference I found between ‘junior’ and ‘senior’ developers aside from experience is the perspective used to approach problems. Senior engineers possess an attribute of persistence when they encounter a bug and use their wealth of knowledge (i.e. advanced google/stack-overflow skills) to continuously poke at solutions to various problems.&lt;/p&gt;

&lt;p&gt;Consider the scenario you hit a bug, just can’t get that API to work, you’ve been trying for a couple days and just cant wrap your head around it. You eventually cave in, ask a senior dev for help. They leave for a few minutes to check something, come back and like magic solve your issue with a less than 10 minute turnaround. You can bet your ass the reason they were able to fix that solution was they had encountered it before, remembered googling it and using result #3 to resolve it. &lt;/p&gt;

&lt;p&gt;Now I’m not using a blanket statement to say this is how it works in all cases and developers shouldn’t be overly reliant on these resources, but it is always worth considering that senior developers dont necessarily know all the answers but rather they know how to debug or search for solutions in different ways to you. It is a very valuable experience sitting with your peers during pair programming and watching the approaches they adopt to approach debugging some broken code. These debug skills will be some of the most valuable you can obtain.&lt;/p&gt;

&lt;h3&gt;
  
  
  The most surprising things…
&lt;/h3&gt;

&lt;p&gt;When you’re a fresh eyed college graduate there are certain things that you quickly become exposed to that you may not expect in the professional development world. Heres a few points that surprised me along the way that you may want to watch out for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You will be dealing with large codebases for even the most simplest projects. Give it time to understand new codebases - try not to be intimidated by the sizing of some projects compared to what you may be used to dealing with in college&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The simplest tasks will often take longer than you initially expect. I still struggle on a regular basis with trying to assign accurate story points to tech tickets. Estimating the time it takes to complete a task is something that comes with time and experience. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;External dependencies are some of the most frustrating things you can deal with. Whether its relying on another team to get X service up and running or to merge Y PR before you can implement your changes… never underestimate the additional complexity of a task when relying on external teams or resources outside of your immediate control&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Different developers withhold different standards for things like documentation and PRs. One of the key bits of advice I try to follow is to remain consistent. Regardless of the size of a PR I always take time to put in a brief description, link it to an issue, insert a changeling and a flag for whether or not the PR is ready for review. While this can take some additional time its worthwhile remaining consistent and clear with even these basic things.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You will spend what feels like a lifetime waiting for continuous pipelines, code compilation and many other fun processes to complete. The key with this is to plan your time carefully around these potential time sinks. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F7WtCtRw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2F7WtCtRw.jpg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git can be a harsh mistress. Its worth getting familiar with using git to do things like rebaseing commits to tidy up your PRs so you dont have long commit history chains with duplicate commit message or worse. Its worth taking the time to read up on the git documentation and practicing working across multiple branches and rebasing commits. Commands like git stash and git stash pop are also invaluable to have at your disposal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgs.xkcd.com%2Fcomics%2Fgit_commit.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fimgs.xkcd.com%2Fcomics%2Fgit_commit.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Comparisons can be detrimental. Try not to compare your weekly output to that of your more experienced colleagues. Its a natural thing to try and keep up to speed with the best of the best but starting out you need to a accept that you may need to work at a slightly slower pace, and thats perfectly ok. Developers take some of there knowledge for granted and when passing along work they can often forget that something that they’ve done 101 times is actually pretty tricky the first 4 or 5 times. People won’t know your limitations unless you are able to voice them. This can be tricky depending on your work environment but if you work for a company that has understanding colleagues and a positive work environment you should be in a scenario to feel free shouting out that you can’t complete a task in the time allotted, or that you may need some help with pair programming on a certain task. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The stuff you learned in college, while useful, didn’t cover half of what you most likely will use in work. In my own practical case I never had exposure to technologies like Docker &amp;amp; Kubernetes, Continuous Integration Pipelines, Build Tools and in some cases even the languages I ended up adopting for projects including React/JavaScript and Scala/Play/Akka. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Technology really does change frequently and often. Chances are you will go through using various languages, tech stacks, deployment services. databases and many other resources within a very short time frame. Working in the tech sector is very much a continuous college-esque experience where upskilling is vital to your career. You might have graduated and started a new job but the real learning experiences are only just beginning.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;I’m very grateful for having the opportunity to switch careers into the tech industry and gain exposure and knowledge of so many different technologies. I find myself in a very fortunate position to have fantastic work colleagues and an amazing work environment under which I have had room to grow my own skillset. I would be lying if I said it was an easy and smooth ride - working in tech can be challenging but therein lies the fun. If it was easy it would be boring.&lt;/p&gt;

&lt;p&gt;I think the first year of working will be one of the toughest for many graduates going into the professional software engineering world. My advice is to keep asking questions, find yourselves as many mentors as possible, continuously request feedback and keep plucking away at your own personal projects. Upskilling can be boring at times relying on online courses and occasionally boring lecturers however nothing can beat the thrill and exposure of building your own applications end to end and deploying them on AWS/Heroku/Firebase or any other service you can access.&lt;/p&gt;

&lt;p&gt;I hope there is some knowledge in here that will help others who are moving into the professional software development world. I’d love to here the experiences of others who are approaching the one year mark and get your feedback. Be sure to comment below any advice or experiences you have to share to the community.&lt;/p&gt;

&lt;p&gt;Many thanks for reading.&lt;br&gt;
Until next time!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>webdev</category>
      <category>career</category>
    </item>
    <item>
      <title>The Inspiration API: A project built with Scala &amp; Play Framework</title>
      <dc:creator>Daniel McMahon</dc:creator>
      <pubDate>Tue, 17 Jul 2018 19:43:37 +0000</pubDate>
      <link>https://dev.to/danku/the-inspiration-api-a-project-built-with-scala--play-framework-195d</link>
      <guid>https://dev.to/danku/the-inspiration-api-a-project-built-with-scala--play-framework-195d</guid>
      <description>&lt;p&gt;You don't learn to walk by following rules. You learn by doing, and by falling over. - Richard Branson&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelopers.giphy.com%2Fstatic%2Fimg%2Fapi.c99e353f761d.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevelopers.giphy.com%2Fstatic%2Fimg%2Fapi.c99e353f761d.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Inspiration API is the start of my journey down the path of trying to improve my Scala skills. Having coded very little in this language I decided to attempt to build a basic API using the language alongside the Play Framework. Rather than take the textbook approach I often find at times you just need to get your hands dirty and learn from your mistakes. I mean... how hard can it be?&lt;/p&gt;

&lt;p&gt;Up to recently my primary coding focus has been on Frontend or more JavaScript heavy services. For work and personal purposes I wanted to expand my skillset to encompass a more broad scope of programming practices, and so I've found my way to Scala. I've studied the OOP basics of Java in college and taken some Scala training on the job but being rusty with using the JVM and blind to the more complex usages of the functional programming paradigm I've been ill prepared to adopt it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Inspiration API
&lt;/h2&gt;

&lt;p&gt;The Codebase: &lt;a href="https://github.com/daniel40392/inspiration-api" rel="noopener noreferrer"&gt;Available Here!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I guess the name of the API is self evident -&amp;gt; I needed some sort of project to keep me inspired and interested in learning a new language. As many of you are aware it can be difficult at the best of times to find energy coding after a full days work!&lt;/p&gt;

&lt;p&gt;So I was a little lazy at this point... I basically googled 'inspirational quotes' and grabbed the first 10 I came across that didn't sound entirely cheesy or ridiculous and decided to use them for the basis of the API's data.&lt;/p&gt;

&lt;p&gt;Note that I say data here as my first attempt at making the API was focused on setting up a basic GET endpoint that return a response. Rather than relying on a DB I started with a basic array of JSON objects, I used a &lt;a href="https://daniel40392.github.io/dnd/" rel="noopener noreferrer"&gt;similar trick&lt;/a&gt; in another project to populate a dropdown menu on a static site instead of relying on a DB. Start small and work my way up I figured...&lt;/p&gt;

&lt;p&gt;I set up a bunch of github issues which linked to an overall RESTful API milestone, essentially it was more or less 1 issue per CRUD feature:&lt;/p&gt;

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

&lt;p&gt;When starting out I cloned a Play/Scala seed from the play website -&amp;gt; in retrospect this featured quite a lot of what I'll playfully call Bash bloatware that wasn't necessary for just building the project locally with SBT - however it did the job!&lt;/p&gt;

&lt;p&gt;The main considerations for using play was that it should be as simple as modifying your routes configuration to determine your GET, POST, PUT, DELETE endpoints to point to a specific controller.&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling JSON in Scala
&lt;/h2&gt;

&lt;p&gt;Immediately it became evident that there is a big difference in the level of Google Fu required between searching for how to do something in JS versus how to do something in Scala. And to be fair I can accept that JSON is native to JavaScript... We can all agree that Stack Overflow development isn't an optimal way of programming however it can prove a useful tool when starting out and wanting to build something with a tool you have had very limited use with!&lt;/p&gt;

&lt;p&gt;So the basic logic of my JSON solution (and prior to this an array implementation) featured a Play controller which looked a little like this (forgive the placeholder variable names... I never do this in production code... honest!):&lt;/p&gt;

&lt;p&gt;Routes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;#&lt;/span&gt; &lt;span class="nc"&gt;Routes&lt;/span&gt;
&lt;span class="k"&gt;#&lt;/span&gt; &lt;span class="nc"&gt;This&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="n"&gt;defines&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt; &lt;span class="nf"&gt;routes&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Higher&lt;/span&gt; &lt;span class="n"&gt;priority&lt;/span&gt; &lt;span class="n"&gt;routes&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;#&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="o"&gt;://&lt;/span&gt;&lt;span class="nv"&gt;www&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;playframework&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;documentation&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nc"&gt;ScalaRouting&lt;/span&gt;
&lt;span class="k"&gt;#&lt;/span&gt; &lt;span class="o"&gt;~~~~&lt;/span&gt;

&lt;span class="k"&gt;#&lt;/span&gt; &lt;span class="nc"&gt;An&lt;/span&gt; &lt;span class="n"&gt;example&lt;/span&gt; &lt;span class="n"&gt;controller&lt;/span&gt; &lt;span class="n"&gt;showing&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;sample&lt;/span&gt; &lt;span class="n"&gt;home&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;
&lt;span class="nc"&gt;GET&lt;/span&gt;     &lt;span class="o"&gt;/&lt;/span&gt;                           &lt;span class="nv"&gt;controllers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;HomeController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;index&lt;/span&gt;

&lt;span class="k"&gt;#&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt; &lt;span class="n"&gt;static&lt;/span&gt; &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;public&lt;/span&gt; &lt;span class="n"&gt;folder&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;assets&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;
&lt;span class="nc"&gt;GET&lt;/span&gt;     &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;assets&lt;/span&gt;&lt;span class="cm"&gt;/*file               controllers.Assets.versioned(path="/public", file: Asset)

# Inspiration CRUD endpoints
GET     /inspiration                controllers.InspirationController.index
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inspiration Controller:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;controllers&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.inject._&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;play.api._&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;play.api.mvc._&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;play.api.libs.json._&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;scala.collection.mutable.ArrayBuffer&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * This controller creates an `Action` to handle HTTP requests to the
 * application's home page.
 */&lt;/span&gt;
&lt;span class="nd"&gt;@Singleton&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InspirationController&lt;/span&gt; &lt;span class="nd"&gt;@Inject&lt;/span&gt;&lt;span class="o"&gt;()(&lt;/span&gt;&lt;span class="n"&gt;cc&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;ControllerComponents&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractController&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cc&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Action&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="k"&gt;implicit&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Request&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;AnyContent&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nc"&gt;Ok&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;generateQuote&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;scala&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;nextInt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// json method of generating quotes&lt;/span&gt;
  &lt;span class="c1"&gt;// (y(scala.util.Random.nextInt(10))\"quote").get&lt;/span&gt;

  &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;JsValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;arr&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
      &lt;span class="nv"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quote"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Make your life a masterpiece, imagine no limitations on what you can be, have or do."&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"author"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Brian Tracy"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
      &lt;span class="nv"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quote"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"We may encounter many defeats but we must not be defeated."&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"author"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Maya Angelou"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
      &lt;span class="nv"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quote"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"I am not a product of my circumstances. I am a product of my decisions."&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"author"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Stephen Covey"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
      &lt;span class="nv"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quote"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"We must let go of the life we have planned, so as to accept the one that is waiting for us."&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"author"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Joseph Campbell"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
      &lt;span class="nv"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quote"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Believe you can and you're halfway there."&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"author"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Theodore Roosevelt"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
      &lt;span class="nv"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quote"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"We know what we are, but know not what we may be."&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"author"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"William Shakespeare"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
      &lt;span class="nv"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quote"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"We can't help everyone, but everyone can help someone."&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"author"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Ronald Reagan"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
      &lt;span class="nv"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quote"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"When you have a dream, you've got to grab it an never let go."&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"author"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Carol Burnett"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
      &lt;span class="nv"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quote"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Your present circumstances don't determine where you can go; they merely determine where you start."&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"author"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Nido Quebein"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt;
      &lt;span class="nv"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quote"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Thinking: the talking of the soul with itself."&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"author"&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Plato"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Function that returns a random string include quote &amp;amp; author&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generateQuote&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;quotes&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;JsValue&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;JsValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;quotes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;)\&lt;/span&gt;&lt;span class="s"&gt;"quote"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;get&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;JsValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;quotes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;)\&lt;/span&gt;&lt;span class="s"&gt;"author"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;get&lt;/span&gt;
    &lt;span class="nf"&gt;return&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;author&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;as&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;": "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;quote&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;as&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// array method of generating quotes&lt;/span&gt;
  &lt;span class="c1"&gt;// quotes(scala.util.Random.nextInt(10))&lt;/span&gt;
  &lt;span class="c1"&gt;//  var quotes = ArrayBuffer[String]()&lt;/span&gt;
  &lt;span class="c1"&gt;//  quotes += "Make your life a masterpiece, imagine no limitations on what you can be, have or do. - Brian Tracy"&lt;/span&gt;
  &lt;span class="c1"&gt;//  quotes += "We may encounter many defeats but we must not be defeated. - Maya Angelou"&lt;/span&gt;
  &lt;span class="c1"&gt;//  quotes += "I am not a product of my circumstances. I am a product of my decisions. - Stephen Covey"&lt;/span&gt;
  &lt;span class="c1"&gt;//  quotes += "We must let go of the life we have planned, so as to accept the one that is waiting for us. - Joseph Campbell"&lt;/span&gt;
  &lt;span class="c1"&gt;//  quotes += "Believe you can and you're halfway there. - Theodore Roosevelt"&lt;/span&gt;
  &lt;span class="c1"&gt;//  quotes += "We know what we are, but know not what we may be. - William Shakespeare"&lt;/span&gt;
  &lt;span class="c1"&gt;//  quotes += "We can't help everyone, but everyone can help someone. - Ronald Reagan"&lt;/span&gt;
  &lt;span class="c1"&gt;//  quotes += "When you have a dream, you've got to grab it an never let go. - Carol Burnett"&lt;/span&gt;
  &lt;span class="c1"&gt;//  quotes += "Your present circumstances don't determine where you can go; they merely determine where you start. - Nido Quebein"&lt;/span&gt;
  &lt;span class="c1"&gt;//  quotes += "Thinking: the talking of the soul with itself. - Plato"&lt;/span&gt;

&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wahey - just like that we have our GET /inspiration up and running!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Database Hookup
&lt;/h2&gt;

&lt;p&gt;This was the MOST painful part of the project for several reasons.&lt;/p&gt;

&lt;p&gt;Did you know that you can't run Docker natively on Windows 10 Home edition? You have to use Docker Toolbox combined with vagrant or some virtualbox setup? &lt;/p&gt;

&lt;p&gt;I wanted to use Docker to run a simple postgres database that my service would connect to. I had used Docker before and figured this would be the easiest solution! This shouldn't have caused me so many issues (and time) but it did. I usually code on a MacBook in work but on a Windows PC at home for personal projects - I find its a good way to stay ambidextrous across platforms. In the end I called it quits and settled with using my trusty MacBook (which worked almost instantly once I cloned the Dockerfile locally).&lt;/p&gt;

&lt;p&gt;To try and keep things self contained I included a basic dbsetup.sql file in the repository that users could load into their Docker container using a simple command.&lt;/p&gt;

&lt;p&gt;dbsetup.sql (comment below if you have any better default quotes I should include!):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt; &lt;span class="n"&gt;inspiration_db&lt;/span&gt;

&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;quotations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;index&lt;/span&gt; &lt;span class="nb"&gt;serial&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;author&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;quote&lt;/span&gt; &lt;span class="nb"&gt;varchar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;quotations&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Brian Tracy'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Make your life a masterpiece, imagine no limitations on what you can be, have or do.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;quotations&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Maya Angelou'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'We may encounter many defeats but we must not be defeated.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;quotations&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Stephen Covey'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'I am not a product of my circumstances. I am a product of my decisions.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;quotations&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Joseph Campbell'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'We must let go of the life we have planned, so as to accept the one that is waiting for us.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;quotations&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Theodore Roosevelt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Believe you can and you&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;re halfway there.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;quotations&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'William Shakespeare'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'We know what we are, but know not what we may be.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;quotations&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Ronald Reagan'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'We can&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;t help everyone, but everyone can help someone.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;quotations&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Carol Burnett'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'When you have a dream, you&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;ve got to grab it an never let go.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;quotations&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Nido Quebein'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Your present circumstances don&lt;/span&gt;&lt;span class="se"&gt;''&lt;/span&gt;&lt;span class="s1"&gt;t determine where you can go; they merely determine where you start.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;quotations&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Plato'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Thinking: the talking of the soul with itself.'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker Commands for setting up the Docker DB &amp;amp; Inserting above rows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
psql &lt;span class="nt"&gt;-h&lt;/span&gt; localhost &lt;span class="nt"&gt;-U&lt;/span&gt; user inspiration_db &lt;span class="nt"&gt;-f&lt;/span&gt; dbsetup.sql

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

&lt;/div&gt;



&lt;p&gt;At this point I had to start the Google searching: 'how to connect to a postgres db with scala' and there are a bunch of different libraries and results that showed up such as jdbc, postgres-scala, doobie and many more... It was a little overwhelming and difficult to just get a few lines of documentation for a super simple implementation. In the end I went with a library called &lt;a href="http://slick.lightbend.com/doc/3.1.0/database.html" rel="noopener noreferrer"&gt;Slick&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After settling on Slick I setup a basic Class to represent the quote entries for the DB. I had to do some tinkering before figuring out how the heck to handle serial (auto incrementing) postgres values but thats a story best unmentioned! Just enjoy the completed functioning code!&lt;/p&gt;

&lt;p&gt;Class matching quotes structure form the postgres DB:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Matches schema of the docker-compose psql DB quotations table&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Quotes&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Tag&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Table&lt;/span&gt;&lt;span class="o"&gt;[(&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;, &lt;span class="kt"&gt;String&lt;/span&gt;, &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)](&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"quotations"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;](&lt;/span&gt;&lt;span class="s"&gt;"index"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;author&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;](&lt;/span&gt;&lt;span class="s"&gt;"author"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;quote&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;](&lt;/span&gt;&lt;span class="s"&gt;"quote"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;*&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point the rest of the 'hard' work came down to figuring out how to translate postgresSQL to this Slick style syntax. Heres a rough breakdown of how the various endpoints worked:&lt;/p&gt;

&lt;p&gt;GET /inspiration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;scala.slick.driver.PostgresDriver.simple._&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Action&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="k"&gt;implicit&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Request&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;AnyContent&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nc"&gt;Ok&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;generateQuote&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;scala&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;util&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;nextInt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;connectionUrl&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"jdbc:postgresql://localhost:5432/inspiration_db?user=user"&lt;/span&gt;

 &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generateQuote&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;

    &lt;span class="c1"&gt;// connecting to postgres db for accessing data&lt;/span&gt;
    &lt;span class="nv"&gt;Database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;forURL&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connectionUrl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"org.postgresql.Driver"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;withSession&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;implicit&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;quotes&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TableQuery&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Quotes&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;// SELECT * FROM quotations WHERE id=randomInt&lt;/span&gt;
        &lt;span class="nv"&gt;quotes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;index&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;list&lt;/span&gt; &lt;span class="n"&gt;foreach&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;row&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;_2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;": "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;row&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;_3&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;POST /inspiration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;scala.slick.driver.PostgresDriver.simple._&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Action&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;AnyContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;body&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;json&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;JsValue&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;asJson&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;author&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"author"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;stripPrefix&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\""&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;stripSuffix&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\""&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;trim&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;quote&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quote"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;stripPrefix&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\""&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;stripSuffix&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\""&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;trim&lt;/span&gt;
    &lt;span class="nf"&gt;addQuote&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;Ok&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Successfully updated quotations DB"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;connectionUrl&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"jdbc:postgresql://localhost:5432/inspiration_db?user=user"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;addQuote&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt; &lt;span class="o"&gt;={&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="nv"&gt;Database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;forURL&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connectionUrl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"org.postgresql.Driver"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;withSession&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;implicit&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;quotes&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TableQuery&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Quotes&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="c1"&gt;// getting id of last element in table&lt;/span&gt;
        &lt;span class="nv"&gt;quotes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;sortBy&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;desc&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;take&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;list&lt;/span&gt; &lt;span class="n"&gt;foreach&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
          &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;row&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;_1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;quotes&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PUT /inspiration&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;scala.slick.driver.PostgresDriver.simple._&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Action&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;AnyContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;request&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;body&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;json&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;JsValue&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;asJson&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;index&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"index"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;toInt&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;author&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"author"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;stripPrefix&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\""&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;stripSuffix&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\""&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;trim&lt;/span&gt;
    &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;quote&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"quote"&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;stripPrefix&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\""&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;stripSuffix&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\""&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;trim&lt;/span&gt;
    &lt;span class="nf"&gt;updateQuote&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;Ok&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Successfully updated quotations DB"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;connectionUrl&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"jdbc:postgresql://localhost:5432/inspiration_db?user=user"&lt;/span&gt;

 &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;updateQuote&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;Database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;forURL&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connectionUrl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"org.postgresql.Driver"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;withSession&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;implicit&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;quotes&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TableQuery&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Quotes&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="nv"&gt;quotes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;index&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;update&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;author&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quote&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DELETE /inspiration/:index&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;scala.slick.driver.PostgresDriver.simple._&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Action&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;deleteQuote&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;Ok&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="s"&gt;"Successfully deleted entry $index"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;connectionUrl&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"jdbc:postgresql://localhost:5432/inspiration_db?user=user"&lt;/span&gt;

 &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;deleteQuote&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;Database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;forURL&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connectionUrl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;driver&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"org.postgresql.Driver"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="n"&gt;withSession&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;implicit&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="nv"&gt;quotes&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TableQuery&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;Quotes&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
        &lt;span class="nv"&gt;quotes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;index&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="py"&gt;delete&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The routes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scala"&gt;&lt;code&gt;&lt;span class="nc"&gt;GET&lt;/span&gt;     &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;inspiration&lt;/span&gt;                &lt;span class="nv"&gt;controllers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;InspirationController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;index&lt;/span&gt;
&lt;span class="nc"&gt;POST&lt;/span&gt;    &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;inspiration&lt;/span&gt;                &lt;span class="nv"&gt;controllers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;InspirationController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;add&lt;/span&gt;
&lt;span class="nc"&gt;PUT&lt;/span&gt;     &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;inspiration&lt;/span&gt;                &lt;span class="nv"&gt;controllers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;InspirationController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;replace&lt;/span&gt;
&lt;span class="nc"&gt;DELETE&lt;/span&gt;  &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;inspiration&lt;/span&gt;&lt;span class="o"&gt;/:&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;         &lt;span class="nv"&gt;controllers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;InspirationController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="py"&gt;delete&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="k"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there you have it - a basic RESTful API in Scala &amp;amp; Play!&lt;/p&gt;

&lt;p&gt;The Codebase: &lt;a href="https://github.com/daniel40392/inspiration-api" rel="noopener noreferrer"&gt;Available Here!&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;The project was a nice way to go off book and try learn by developing something directly. There were some minor pain points I definitely learned from including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to connect to a Postgres DB with scala&lt;/li&gt;
&lt;li&gt;How to handle Array &amp;amp; JSON data structures with scala&lt;/li&gt;
&lt;li&gt;How to handle routes with the Play Framework&lt;/li&gt;
&lt;li&gt;How to setup a basic frontend for paths in the Play Framework&lt;/li&gt;
&lt;li&gt;Handling Docker on Windows... this one still irks me for the time wasted!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Improvements
&lt;/h2&gt;

&lt;p&gt;Theres a bunch of additions I plan to make to this project over time including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adjusting the GET endpoint to return items in the DB with an index higher than 10 -&amp;gt; currently this is hardcoded but it should be easy to swap it out for a DB count amount&lt;/li&gt;
&lt;li&gt;Setup an API swagger definition for the generated API -&amp;gt; this would just be some useful additional experience&lt;/li&gt;
&lt;li&gt;Deploy the API somewhere -&amp;gt; Heroku is the lead favourite for now... Once deployed implementing some endpoint tracking &amp;amp; analytics would be interesting -&amp;gt; potentially some oAuth as well but that's generally a headache to setup.&lt;/li&gt;
&lt;li&gt;Develop basic SDKs from the generated Swagger using a service like &lt;a href="https://github.com/swagger-api/swagger-codegen" rel="noopener noreferrer"&gt;Swagger Codegen&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Add Tests&lt;/li&gt;
&lt;li&gt;Modify OK section on routes to return correct response i.e. 200, 201, 202 etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As always if you have any feedback, suggestions or thoughts feel free to share below.&lt;/p&gt;

&lt;p&gt;'Till Next Time!&lt;/p&gt;

</description>
      <category>scala</category>
      <category>java</category>
      <category>play</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Building A Portfolio: The Painful Way</title>
      <dc:creator>Daniel McMahon</dc:creator>
      <pubDate>Mon, 18 Jun 2018 22:30:55 +0000</pubDate>
      <link>https://dev.to/danku/building-a-portfolio-the-painful-way-3im8</link>
      <guid>https://dev.to/danku/building-a-portfolio-the-painful-way-3im8</guid>
      <description>&lt;p&gt;The Goal: Lets combine all the JS &amp;amp; React related things I've learned to date in one big project! What could go wrong?&lt;/p&gt;

&lt;p&gt;The End Result: &lt;a href="https://daniel40392.github.io/react-portfolio/" rel="noopener noreferrer"&gt;Website&lt;/a&gt; &amp;amp; &lt;a href="https://github.com/daniel40392/react-portfolio" rel="noopener noreferrer"&gt;Codebase&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AOF0xEMkWBv-69zvmNs6RDQ.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AOF0xEMkWBv-69zvmNs6RDQ.gif" width="760" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript is complicated... &lt;em&gt;sorta&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;I've learned a lot of things about JavaScript over the past year on the job, things that anybody new to the field will no doubt also go through - here are some questions I faced along the way that some of you can no doubt relate to and will hopefully take some comfort in reading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What IDE should I use for programming in JS?&lt;/li&gt;
&lt;li&gt;What Plugins should I use to optimize my work flow?&lt;/li&gt;
&lt;li&gt;Whats a package manager and whats the big fuss between Yarn or NPM?&lt;/li&gt;
&lt;li&gt;What the hell is Webpack and why do I already hate it?&lt;/li&gt;
&lt;li&gt;ESLINT? Sure its nice in theory but have you tried setting up the config yourself - painful!&lt;/li&gt;
&lt;li&gt;Enzyme, Jest &amp;amp; Mocha - are you sure you're still talking about JS?&lt;/li&gt;
&lt;li&gt;Whats the difference between CommonJS, ES6 &amp;amp; ES2018?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Over the past year I've come to terms with the peculiarities of the language and can happily work alongside it. It is still very much a love hate relationship but having tackled multiple projects ranging from full-stack web apps, chrome extensions and publishing basic node packages I feel much more confident in my abilities using this language as a coding medium.&lt;/p&gt;

&lt;p&gt;I felt so confident that I figured I would try demonstrate my knowledge and skills by creating a portfolio site on my personal GitHub to try out all the techniques I had learned and marvel at what monstrosity would come out.&lt;/p&gt;

&lt;h2&gt;
  
  
  KISS - Keep It Simple Stupid
&lt;/h2&gt;

&lt;p&gt;Those who work in UX will know that in advance of any project you should ideally do mock up designs and user testing to deliver an optimal product to achieve maximum impact. This was a venture down the perfect road of what not to do... make it up as you go along.&lt;/p&gt;

&lt;p&gt;I had an idea (a rough sketch) on a notepad that I would use as the basis for the site structure and figured I would work from there... so how did the process work out?&lt;/p&gt;

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

&lt;p&gt;First things first I had to setup the project from scratch. I used a basic create-react-app template to start with. &lt;/p&gt;

&lt;p&gt;To make the development process streamlined I had setup my &lt;a href="https://atom.io/" rel="noopener noreferrer"&gt;Atom&lt;/a&gt; IDE with &lt;a href="https://prettier.io/" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt; for handling some automatic line indentation on save, and added my favourite &lt;a href="http://citylights.xyz/" rel="noopener noreferrer"&gt;City Lights&lt;/a&gt; theme to make the project easier on my eyes.&lt;/p&gt;

&lt;p&gt;I set out building some basic reusable React components such as Cards, Headers, Footers and NavBars. In order to allow for multiple page functionality I ended up adding React Router and React DOM - not something I had really done with the create-react-app template before.&lt;/p&gt;

&lt;p&gt;I ended up treating the individual pages as 'containers' as opposed to 'components' in order to make the code base more legible. It appeared a good way to segment what should be dumb stateless components from the more intelligent stateful page components.&lt;/p&gt;

&lt;p&gt;Next up I wanted to try show off some of the libraries I had been using over the past year so I added in &lt;a href="https://www.styled-components.com/" rel="noopener noreferrer"&gt;Styled Components&lt;/a&gt; &amp;amp; &lt;a href="http://jxnblk.com/grid-styled/" rel="noopener noreferrer"&gt;Grid Styled&lt;/a&gt; to help structure the individual pages layouts with custom styling.&lt;/p&gt;

&lt;p&gt;I decided to add in a tribute to a design library I had encountered during the past year with the inclusion of the &lt;a href="https://ant.design/" rel="noopener noreferrer"&gt;Ant Design&lt;/a&gt; Carousel. I'd like to build my own Carousel in the near future but for now this felt like a good placeholder and the end result was quite satisfying.&lt;/p&gt;

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

&lt;p&gt;I added in a Donut graph to represent my confidence levels in my top skills so that the landing page of the site would give anybody interested in my skill sets a snapshot of my strengths and weaknesses.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Venturing into the unknown... css media
&lt;/h2&gt;

&lt;p&gt;I had no exposure to using animations or transitions with css and wanted to try something new so I was browsing some other dev.to developers portfolio sites for inspiration. In particular &lt;a href="https://www.alispit.tel/" rel="noopener noreferrer"&gt;Ali Spittel&lt;/a&gt;'s site stood out to me. I loved her use of cards to display some samples of work she had done. I always enjoyed the playful nature of the 'about' section on her page with a rotating image and decided to integrate this on my own projects page with the addition of rotating skill icons.&lt;/p&gt;

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

&lt;p&gt;I decided to take this media exploration a step further and ended up including rotating cards on my homepage to reveal the flip of each outlined skill to contain some placeholder text. This works with a hover in browser and with a tap on mobile devices. I had initially seen this technique in a tutorial demonstrating face down poker cards that revealed themselves on mouse hover. The idea interested me so I couldn't resist adding it!&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The 'awwwww yes' features
&lt;/h2&gt;

&lt;p&gt;There were some parts of what I had designed that I was oddly proud of and had not tried implementing before. I always struggled with the concept of how to handle with mobile -v- desktop web applications and controlling the content to optimize the user experience. I ended up using some custom divs to hide the display of both the Donut graph and the Carousel when the screen was below a set resolution so as to allow for a beneficial experience on mobile and desktop experiences. While this is not the optimal way to handle this problem, it was something new and creative that I enjoyed implementing.&lt;/p&gt;

&lt;p&gt;I had experimenting with using some custom css grayscaling features to allow for hoverable social media icons on the contact page that turned out relatively well but could use refinement at a later date.&lt;/p&gt;

&lt;p&gt;The cards I had setup for demonstrating my projects were a personal highlight, especially seeing the interactivity between having custom buttons, rotating skill icons and clear text being displayed in harmony.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 'above and beyond' pain points
&lt;/h2&gt;

&lt;p&gt;The following features were an absolute pain for me to implement and still require some fine tuning but I'm glad to have gone through the pain from the ground up.&lt;/p&gt;

&lt;p&gt;I set out to use some custom eslinting rules and combined them with some pre-commit library to prevent the ability to commit your code unless it passed the linting parameters. Traditionally eslinting is used with a 'eslintrc' file defining individual rules. I had not previously setup one of these from scratch and ended up causing myself an awful headache when trying to handle the setup of an eslinter alongside the &lt;a href="https://github.com/xojs/xo" rel="noopener noreferrer"&gt;xo&lt;/a&gt; library. In the end I managed to get a form of the xo library working with some plugins, however as of yet the code is still not 100% eslinted correctly, however good progress has been made so far to counteract this minor issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 'to be completed' list
&lt;/h2&gt;

&lt;p&gt;A lot of work has gone into the basic outline of the portfolio site to date however there are some essential missing features that will need to be included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Circle CI Integration with Protected Master Branch&lt;/li&gt;
&lt;li&gt;Updated landing page card text&lt;/li&gt;
&lt;li&gt;Jest Tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have some duplicated custom styling used across multiple components that I plan to consolidate to a single file and allow for importing to prevent duplication of styling code.&lt;/p&gt;

&lt;p&gt;Other key additions I would like to add to the site include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The integration of Redux &lt;/li&gt;
&lt;li&gt;A switch to using server side rendering with Express to serve the content. &lt;/li&gt;
&lt;li&gt;Integration of canvas elements (perhaps demonstrating some &lt;a href="https://p5js.org/" rel="noopener noreferrer"&gt;p5.js&lt;/a&gt; knowledge)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While these would be a good way to showcase some more of my skills I feel that the static nature of the site makes these additional features redundant for the time being.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;While the site is a continued work in progress here are a few of my ongoing thoughts on the project&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It was fun and interesting to build my own reusable responsive components, this might be something I look at expanding into a reusable component library project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The media-css modifications were fun, while only adding minor animations and interactivity it's definitely something I'll explore for future webdev work&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I'll definitely put more effort into the UX considerations prior to starting the project as the site in its current form has already undergone many design changes during its development. I may consider the use of marvelapp or sketch for future wireframe design&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Static site generators such as SquareSpace tend to be much more artistic in their site layouts with full screen landing pages, cleaner colors and more layered elements creating a more visually appealing style. I feel like taking this more heavily design oriented approach for a different project will be a fun challenge moving forward.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;While it was fun doing all this in React, I couldn't help but reflect on how much faster and easier it could have been creating something similar in Bootstrap. I even stopped to consider the simpler tool sets available to developers ranging from pre-defined site design services like SquareSpace and WordPress&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was overall a fun experiment that I was glad to start, however the end result is not as clean and crisp as I would like it to be. This is a result from a lack of design planning. That said I learned a lot engaging in it and after only a years exposure to JavaScript the finished product isn't too shaby!&lt;/p&gt;

&lt;p&gt;If you have any feedback or suggestions in terms of what might be some useful additions, or how I could benefit from adding Redux to the service be sure to let me know in the comments.&lt;/p&gt;

&lt;p&gt;If you have worked on a similar project be sure to share below - I'd love to have a look! &lt;/p&gt;

&lt;p&gt;Many thanks for reading.&lt;br&gt;
till next time!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Leveling Up: From Create-React-App to Express (&amp; some neat styling libraries)</title>
      <dc:creator>Daniel McMahon</dc:creator>
      <pubDate>Mon, 09 Apr 2018 18:10:37 +0000</pubDate>
      <link>https://dev.to/danku/leveling-up-from-create-react-app-to-express--some-neat-styling-libraries-130p</link>
      <guid>https://dev.to/danku/leveling-up-from-create-react-app-to-express--some-neat-styling-libraries-130p</guid>
      <description>&lt;p&gt;&lt;em&gt;Two months later - time for my second article! You can read my previous article on Visualizing Fibonacci &lt;a href="https://dev.to/daniel40392/visualizing-fibonacci-for-the-music-lover-in-you-2609"&gt;here&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1abv3PCP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/mv5l79mtnvqpz8r65ahh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1abv3PCP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/mv5l79mtnvqpz8r65ahh.png" alt="Website Screenshot" width="800" height="490"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://cat-ui.herokuapp.com/"&gt;Link to the Live Site&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Project
&lt;/h2&gt;

&lt;p&gt;I'm a professional software engineer and still to this day I find that saying this out loud scares me a little. To try and concrete my confidence in my skills and abilities I've been engaging in a few personal side-projects where I take the fundamental methods of building an application and apply them to some sort of fun side project. This is the first in a hopeful series of posts about my experiences to date.&lt;/p&gt;

&lt;p&gt;I had previously developed a few create-react-app static site generation projects that I hosted via GitHub pages as a simple way of developing my understanding of the React component library. For this project I decided to take the create-react-app boilerplate, tie it into the Express web framework, and host it online somewhere for free (copying a GitHub page type flow) so I can easily have it linked on my GitHub repository for anybody wishing to view my personal portfolio (for the total price of... free!).&lt;/p&gt;

&lt;p&gt;I wanted an easy way to communicate with some public API but rather than expose the API I was communicating to on my client side code I wanted to keep it on the server side to simulate communicating to my own APIs running on confidential endpoints. I had found a couple of Cat APIs that returned some random images so I figured I'd roll with those and see what I could come up with. You can check the APIs out here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://thecatapi.com/"&gt;The Cat API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cataas.com/"&gt;Cat as a Service&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The end application simply displays an image of a cat that changes on click/tap by making a call to our backend express server, which calls the cat api, and returns the image url for display on the main web page. I added in an additional Spotify player of some random cat noises as a requested extra feature. You can check out the live version of the site &lt;a href="https://cat-ui.herokuapp.com/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Initial Setup
&lt;/h2&gt;

&lt;p&gt;I used &lt;a href="https://github.com/facebook/create-react-app"&gt;create-react-app&lt;/a&gt; as a starting point for my project. It's a very friendly boilerplate that'll get you setup with everything you need to start making a basic React application. In a more professional environment it has certain drawbacks related to the customization of some of its webpack configuration but for the purposes of this project its more than sufficient. Once installed it's as simple as running three commands to get your app started:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;create-react-app my-app
&lt;span class="nb"&gt;cd &lt;/span&gt;my-app
npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Awesome so now we have our application running! &lt;/p&gt;

&lt;p&gt;To handle some of the styling aspects of the application I installed two additional packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.styled-components.com/"&gt;styled-components&lt;/a&gt; for custom element styling.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://jxnblk.com/grid-styled/"&gt;grid-styled&lt;/a&gt; for responsive design styling with flexbox&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I highly recommend checking out both libraries if you are new to React and designing some basic UI frontend work. Heres a little summary of what the main purpose of these libraries are:&lt;/p&gt;

&lt;h3&gt;
  
  
  Styled Components
&lt;/h3&gt;

&lt;p&gt;The common problem with styling, at least during my own time working in web development, has been thatthe global nature of css app styling (at least in the create-react-app framework) makes it difficult to customize your CSS on a component by component level.&lt;/p&gt;

&lt;p&gt;The Styled Components library lets you rely on component-defined styles. An example of this from my own code looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;styled-components&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CatPic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="s2"&gt;`
  margin: auto;
  background-color: white;
  max-width: 60vw;
  max-height: 60vh;
  margin: 2em;
  border-radius: 10px;
  &amp;amp;:hover {
    cursor: pointer;
  }
  border: 0.2em solid lightgrey;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;When using it in my React Component instead of using an &lt;code&gt;&amp;lt;img/&amp;gt;&lt;/code&gt; tag I just have to use a &lt;code&gt;&amp;lt;CatPic/&amp;gt;&lt;/code&gt; tag and it will import the custom styling defined above.&lt;/p&gt;

&lt;h3&gt;
  
  
  Grid Styled
&lt;/h3&gt;

&lt;p&gt;Grid styled offered me an easy solution to allow my main Cat component to take up 3/4s of the screen at full resolution, and my Spotify component to take up 1/4 of the screen. Then when the resolution changed to a phone styled size it would flip and allow a full width for the Cat component and a full width for the spotify component. This is a godsend for easy mobile responsiveness design. No more auto calculating pixel widths!&lt;/p&gt;

&lt;p&gt;A simplified version of this layout can be seen below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Flex&lt;/span&gt; &lt;span class="nx"&gt;flexWrap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;wrap&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Box&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="nx"&gt;cat&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Box&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Box&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="nx"&gt;spotify&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt; &lt;span class="nx"&gt;here&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Box&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Flex&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Integrating Express
&lt;/h2&gt;

&lt;p&gt;Now onto the more challenging part. After installing Express (&lt;code&gt;npm install express&lt;/code&gt;) I created a server.js file in the main project directory which looks like the below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bodyParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body-parser&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sendFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;After setting up this file I had to modify some of the scripts in the package.json file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-scripts start"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node server.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-scripts build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-scripts test --env=jsdom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"eject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"react-scripts eject"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt;These new scripts mean that when the dev runs the command npm start rather than running the standard react-scripts start command it will instead run &lt;code&gt;node server.js&lt;/code&gt;. The main thing from the script above is in the app.get("/") section which essentially means that when the dev goes to port 8080 after running &lt;code&gt;npm run start&lt;/code&gt; Express will direct the individual to the index.html file of the main react application. &lt;/p&gt;

&lt;p&gt;The important thing to note at this point is that in order to have valid index.html created you need to have run &lt;code&gt;npm run build&lt;/code&gt; prior to &lt;code&gt;npm run start&lt;/code&gt;. Rather than having to wait to run a new build and start it every time you make any local changes, I added an extra script called 'dev' which runs the application directly on port 3000. This is a nice work around for developing on the applications features without caring about any of the other server issues.&lt;/p&gt;

&lt;p&gt;Another required change I made to the package.json was the inclusion of &lt;code&gt;"proxy": "http://localhost:8080"&lt;/code&gt; which proxies the Express server to port 8080, so when the service is running in production any other endpoints setup (i.e. app.get("any-other-endpoint-here") will be accessible when the app is exposed at a URL online.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend to Backend Communication
&lt;/h2&gt;

&lt;p&gt;I added an additional endpoint to the server.js file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/cat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;axios&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://thecatapi.com/api/images/get&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseUrl&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I had setup a Cat component that queried this endpoint and used the parsed responseUrl as the src for an img tag (set via the components state). You'll also see below on the initial page load I have the url state query the cat as a service endpoint - just for some added variety:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;styled-components&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CatPic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="s2"&gt;`
  margin: auto;
  background-color: white;
  max-width: 60vw;
  max-height: 60vh;
  margin: 2em;
  border-radius: 10px;
  &amp;amp;:hover {
    cursor: pointer;
  }
  border: 0.2em solid lightgrey;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://cataas.com/cat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;//default image - calling another cat api!&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getCat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getCat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;getCat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;axios&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/cat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CatPic&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getCat&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Heroku Integration
&lt;/h2&gt;

&lt;p&gt;So up to this point when working on the project I was commiting all the changes to my local GitHub repository and had not selected a platform for serving the application. I had several services I wanted to try out including Heroku, Firebase and AWS static hosting. In order to go for an easy and cheap hosting solution I ended up trying out Heroku.&lt;/p&gt;

&lt;p&gt;I setup my Heroku project and configuring it so that when I made a new commit to my master branch on my project it would auto deploy a new build and expose the service publically. Ideally in the future I'm going to add in some &lt;a href="https://circleci.com/"&gt;CircleCI&lt;/a&gt; testing and protected master branch settings to prevent directly pushing changes to the master branch. For the purposes of this side project the current setup is fine but any errors pushed will go live on the site almost instantly. Instructions for setting up some of this configuration are available over on &lt;a href="https://devcenter.heroku.com/articles/github-integration"&gt;Heroku&lt;/a&gt; if you have any questions on that process feel free to comment below.&lt;/p&gt;

&lt;h2&gt;
  
  
  The End Result
&lt;/h2&gt;

&lt;p&gt;The application is currently exposed live over &lt;a href="https://cat-ui.herokuapp.com/"&gt;here&lt;/a&gt;. The codebase is available &lt;a href="https://github.com/daniel40392/cat-ui"&gt;here&lt;/a&gt; if you're interested in having a look or using it as a boilerplate of sorts for your own create-react-app / Express hybrid application!&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Improvments
&lt;/h2&gt;

&lt;p&gt;Theres a bunch that can be improved about the current implementation including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use of node development environments to auto switch urls being used for express communication when developing the service locally&lt;/li&gt;
&lt;li&gt;Alternate between APIs being called in backend&lt;/li&gt;
&lt;li&gt;Processing of data returned by APIs -&amp;gt; generally response is an image bytestream or some similar structure that may be processible into an image displayed directly on the main page&lt;/li&gt;
&lt;li&gt;Security Cert Bug - seems on some Mac devices Chrome has some issue related so the SSL cert on the page, I suspect this can be fixed with some additional Heroku configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Your Thoughts &amp;amp; Questions?
&lt;/h2&gt;

&lt;p&gt;Feel free to drop and thoughts or questions you have below. I'd be interested to see if the above is useful to anybody starting out with react and looking to start using services like express with create-react-app.&lt;/p&gt;

&lt;p&gt;There are a variety of boilerplates available out there for use that are better than this setup, however the aim of the project was to show how to go from the basic create-react-app to something a bit more complex using an Express backend. This is a very simple example of calling an API in the backend, but you can imagine how this can be taken to the next level to do more complex calculations or communications to private services via the Express server.&lt;/p&gt;

&lt;p&gt;Till next time!&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>heroku</category>
      <category>express</category>
    </item>
    <item>
      <title>Visualizing Fibonacci: For the Music Lover in You!</title>
      <dc:creator>Daniel McMahon</dc:creator>
      <pubDate>Tue, 06 Feb 2018 23:12:38 +0000</pubDate>
      <link>https://dev.to/danku/visualizing-fibonacci-for-the-music-lover-in-you-2609</link>
      <guid>https://dev.to/danku/visualizing-fibonacci-for-the-music-lover-in-you-2609</guid>
      <description>&lt;p&gt;&lt;em&gt;First time article so excuse the typos and errors!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A Common Problem: Programming the Fibonacci Series
&lt;/h2&gt;

&lt;p&gt;Throughout my recent computer science conversion course I studied introductions to both Python and Java. Across both languages one of the common challenges presented was to be to write a program to display up to the n-th number of the Fibonacci Series. This seems to be a common stepping stone for most programmers when learning a new language.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcartesianproduct.files.wordpress.com%2F2011%2F03%2Ffib.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcartesianproduct.files.wordpress.com%2F2011%2F03%2Ffib.png" title="The Fibonacci Series" alt="The Fibonacci Series" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Having found myself wanting to apply what I was learning in class to an independent project, I had stumbled across this idea of visualizing the Fibonacci Series as sheet music. I don't quite remember where or when I had heard of the idea - possibly from Matt Parker, Hannah Fry or one of my lecturers in passing. I had googled the topic and didn't find any immediate practical implementation of the Fibonacci series being visualized on sheet music. Therein lay my task. In retrospect perhaps a quick github search would have yielded more results - but again I was a younger and more naive developer then I am today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python - Which Libraries?
&lt;/h2&gt;

&lt;p&gt;Ok so I had the overall project idea - generate up to the n-th number of the Fibonacci series and somehow visualize that data on sheet music. After some quick research I had settled on using a Python library called &lt;a href="http://bspaans.github.io/python-mingus/" rel="noopener noreferrer"&gt;Mingus&lt;/a&gt; in combination with the program &lt;a href="http://lilypond.org/" rel="noopener noreferrer"&gt;Lilypond&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How not to waste time rebuilding a python2 library to work with python3...
&lt;/h2&gt;

&lt;p&gt;This should go without saying, at the time I was less experienced and prone to these errors. I ended up downloading a version of Mingus that ran on Python2 while I was running Python3. Rather than looking up if a Python 3 package existed, I ended up doing some manual tweaking of the package to make it work. D'oh! For the younger Dev's out there be sure to check the python versions of any installed packages!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Chromatic Scale
&lt;/h2&gt;

&lt;p&gt;While not the most elegant solution I ended up essentially modifying a previously developed college solution that outputted the Fibonacci series up to the n-th number, and used a modulus of that number to determine which note it would represent. Using a modulus of 12 I was able to associate the various numbers to all the notes in a chromatic scale starting on a base note of C (I only used sharps for convenience sake)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.pianowizardacademy.com%2Fcampus%2Ffiles%2F2015%2F10%2FChromScale.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.pianowizardacademy.com%2Fcampus%2Ffiles%2F2015%2F10%2FChromScale.png" title="The Chromatic Scale" alt="The Chromatic Scale" width="800" height="213"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After establishing the connection between the Fibonacci series and the chromatic notes of the scale the only 'difficult part' from there was essentially figuring out how to translate these generated notes into sheet music.&lt;/p&gt;

&lt;p&gt;After importing the Mingus library this was actually pretty straight forward!&lt;br&gt;
The code looked a little like this (yes I know its a little inefficient - I haven't gone back and refactored the code since it was originally thrown together):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from mingus.containers import Bar
from mingus.containers import Composition
from mingus.containers import Track
from mingus.containers import NoteContainer
import mingus.extra.LilyPond as LilyPond

x = int(input('Song Length (number of notes): '))

song = []
b = Bar() # creates new bar element for Mingus = has limit of 4/4 timing by default
b.set_meter((4,4))

c = Composition()
c.set_author('Daniel McMahon', 'daniel40392@gmail.com')
c.set_title('Ode to Fibonnachi')
t = Track()
t.add_bar(b)
c.add_track(t)

def fib(n):
    """Function that generates notes based off the Fibonnachi Series"""
    a=0
    b=1
    print('Generating Music.... Please Wait....',end='')

    for i in range (1,n+1):
        fib=a+b
        if fib%12==1:
            song.append('C')
        elif fib%12==2:
            song.append('C#')
        elif fib%12==3:
            song.append('D')
        elif fib%12==4:
            song.append('D#')
        elif fib%12==5:
            song.append('E')
        elif fib%12==6:
            song.append( 'F')
        elif fib%12==7:
            song.append('F#')
        elif fib%12==8:
            song.append('G')
        elif fib%12==9:
            song.append('G#')
        elif fib%12==10:
            song.append( 'A')
        elif fib%12==11:
            song.append('A#')
        elif fib%12==0:
            song.append('B')
        a=b
        b=fib

    #this code will print song in reverse
    #for i in reversed(song):
    #    print (i + ' ,', end='')

    n = NoteContainer(song)

while x != '':
    fib(x)
    print()
    for note in song:
            b + note
            c.add_note(note)
    comp = LilyPond.from_Composition(c)
    LilyPond.to_pdf(comp, "Ode_to _Fibonnachi")
    print("Song completed - check desktop for exported PDF")
    x = int(input('Song Length (number of notes): '))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Result?
&lt;/h2&gt;

&lt;p&gt;Below is a small snapshot of the result - an interesting pattern emerges for the outputted music showing a repeated pattern every 25 or so notes!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tf115uqa35omomhv7ht.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tf115uqa35omomhv7ht.png" alt="Ode to Fibonacci" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A link to the GitHub repo is available &lt;a href="https://github.com/daniel40392/MusicPrograms" rel="noopener noreferrer"&gt;here&lt;/a&gt; with the sample output available as a PDF file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some additional ideas and experiments...
&lt;/h2&gt;

&lt;p&gt;This sheet music generation approach would work well with other mathematical series - the immediate ones that I thought of adopting include the Catalan and Figurate series. Some sample Fibonacci note generations for these are also included in the linked repo above.&lt;/p&gt;

&lt;p&gt;It may also be worth experimenting with starting on a different note of the chromatic scale - however the intervals will still remain the same between the notes.&lt;/p&gt;

&lt;p&gt;The next logical step in this project is to get musical output from the generated sheet music. I had initially tried this when working on the project 2 years ago on an old Windows laptop, I will have to go back to it soon and see if I can get some live musical feedback integrated.&lt;/p&gt;

&lt;p&gt;Another interesting approach I've taken in the repository is using the &lt;a href="http://www.nltk.org/" rel="noopener noreferrer"&gt;NLTK&lt;/a&gt; library to generate the frequency of note appearances in different series of Fibonacci numbers. You get some fascinating results using different mathematical series - I recommend experimenting with it yourself!&lt;/p&gt;

&lt;h2&gt;
  
  
  Some Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The project itself was used as a basic way to integrate my love of music into my coding. The Fibonacci series can be considered quite a boring topic when attempting to implement it in a new language, but when you add in some of these basic additional steps you can generate something really interesting and creative!&lt;/p&gt;

&lt;p&gt;I would always encourage new developers to explore the basic building blocks of programming languages in new and creative ways. Personally you may find it more rewarding - plus its a great way to build up your personal portfolio and have something extra to chat about in any future job interviews!&lt;/p&gt;

&lt;p&gt;Perhaps you've tried programming something similar in different languages with interesting results - I'd love to hear about it - be sure to leave any feedback or comments below.&lt;/p&gt;

&lt;p&gt;Again excuse any typos or formatting issues - its my first of hopefully many posts here!&lt;/p&gt;

&lt;p&gt;Warmest Regards,&lt;br&gt;
Daniel McMahon&lt;/p&gt;

</description>
      <category>fibonacci</category>
      <category>python</category>
      <category>sheetmusic</category>
      <category>music</category>
    </item>
  </channel>
</rss>
