<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Samuel Bernheim on Medium]]></title>
        <description><![CDATA[Stories by Samuel Bernheim on Medium]]></description>
        <link>https://medium.com/@sambernheim?source=rss-fa4df7a7b495------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*76LMUsOdbM3MhGd4.</url>
            <title>Stories by Samuel Bernheim on Medium</title>
            <link>https://medium.com/@sambernheim?source=rss-fa4df7a7b495------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 14 Nov 2026 04:47:19 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@sambernheim/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Configuring a Personal Access Token]]></title>
            <link>https://medium.com/@sambernheim/configuring-a-personal-access-token-cb5ae25712c3?source=rss-fa4df7a7b495------2</link>
            <guid isPermaLink="false">https://medium.com/p/cb5ae25712c3</guid>
            <category><![CDATA[github]]></category>
            <category><![CDATA[personal-access-tokens]]></category>
            <category><![CDATA[git]]></category>
            <dc:creator><![CDATA[Samuel Bernheim]]></dc:creator>
            <pubDate>Sun, 15 Aug 2021 23:56:15 GMT</pubDate>
            <atom:updated>2023-10-22T00:59:03.069Z</atom:updated>
            <content:encoded><![CDATA[<p>Github recently changed their system to disallow authenticating repo access with a username and password.</p><p>It’s probably better and safer but it’s an annoying change that requires many people to update their local setup.</p><p>I had trouble finding out exactly how to update my local setup to enable personal access tokens. So here’s how I did it.</p><p>This is if you’re on a mac.</p><p>I assume you already have a personal access token. Those are easy enough to generate and there are plenty of good tutorials. Here’s one.</p><p><a href="https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token">Creating a personal access token - GitHub Docs</a></p><p>Once you have your personal access token save it in a temporary location on your computer (your notes app for example).</p><p>Then run these two commands. It installs a secret’s manager that Microsoft developed.</p><pre>brew tap microsoft/git<br>brew install --cask git-credential-manager</pre><p>Once that’s done installing, try rerunning whatever git command that failed. Likely it was:</p><pre>git push</pre><p>Run that command and a nice window should pop up. There will be an option to enter a Personal Access Token (might be referenced as an Access Token). Select it and paste in your personal access token. Now you can delete wherever you were storing it temporarily.</p><p>You won’t have to do this again (unless you’re Personal Access Token expires).</p><p>Congrats!</p><p>You did it 🙂.</p><p>Now back to whatever you were coding.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cb5ae25712c3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[UI Regression Testing]]></title>
            <link>https://medium.com/disney-streaming/ui-regression-testing-71b2ef1bd9b4?source=rss-fa4df7a7b495------2</link>
            <guid isPermaLink="false">https://medium.com/p/71b2ef1bd9b4</guid>
            <category><![CDATA[webdriverio]]></category>
            <category><![CDATA[regression-testing]]></category>
            <category><![CDATA[selenium]]></category>
            <category><![CDATA[snapshot-testing]]></category>
            <category><![CDATA[technology]]></category>
            <dc:creator><![CDATA[Samuel Bernheim]]></dc:creator>
            <pubDate>Fri, 29 Mar 2019 21:08:01 GMT</pubDate>
            <atom:updated>2019-03-29T21:08:01.908Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/827/1*MJvXK0CeotN5k6kOW4BdWw.png" /><figcaption>Baseline image on the left and incorrect background color of the same page on the right</figcaption></figure><p>UI testing is hard. So hard that most companies have a suite of QA teams devoted to testing new versions of their site. Yes we have unit tests, yes we have integration tests; but while these provide great assurances on the functionality of our code, they fail to ensure that a user will see what they expect. When components move around or colors change, users can become frustrated when presented with an unfamiliar interface.</p><p>UI Regression testing compares a screenshot of a given page to a baseline of what it should be, and outputs a diff image when applicable. When a difference is found, you have many options on how to proceed. You can set up your CI/CD pipeline so that the build fails, trigger a pager duty alert, or send a slack message to the team responsible.</p><p>In this post, I’ll be going over the tooling and setup of how we built our solution, and show how you can do it too!</p><h3>Tooling</h3><p>Here’s what we used:</p><ul><li>Docker / docker-compose</li><li>Selenium</li><li>WebdriverIO</li><li>AWS S3</li><li>Blink-Diff</li></ul><p>Docker provides a sandboxed environment and makes it easy to deploy this to our CI/CD pipeline. WebdriverIO allows us to control the headless browsers managed by Selenium, S3 stores our files (baseline images, diff outputs etc), and Blink-Diff is our image comparison tool (note that it’s an npm package).</p><h3>The Process</h3><ul><li>Download baseline images from S3</li><li>Take screenshots of the local version of the site</li><li>Test for any differences between the screenshot and baseline</li><li>Upload any generated diff images</li><li>Cleanup and alerting</li></ul><p>Downloading the baseline images from S3 is simple. Whatever language you’re using, AWS likely has an API for it. Similarly, dockerizing your website should be fairly easy, though if you’re running a legacy site, it could be more involved. I won’t discuss how to do this since there are many articles and tutorials on this subject, and it’s very much platform specific based on your stack.</p><h3>Docker</h3><p>We’ll be using docker-compose with a couple pre-built images all set up to run <a href="https://github.com/SeleniumHQ/docker-selenium">Chrome and Firefox in Selenium</a>.</p><p>Here’s the start of the docker-compose file that sets up the three services (one for each browser, and one that controls them). We’ll be adding to this file as we go on.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/85a40f02fc2af6549fb144186ec8a862/href">https://medium.com/media/85a40f02fc2af6549fb144186ec8a862/href</a></iframe><p>We set up our selenium hub and two browsers to run as their own service. The browsers connect to the hub on port 4444, which we then also expose in the hub service so that we can see what’s going on (this would be done by visiting localhost:4444).</p><h3>Adding your Site to docker-compose.yml</h3><p>You’ll need to add your website as another service. This requires adding something like the below to your docker-compose.yml. We define a new service called app, and tell it to look in the folder ./webapp for its Dockerfile. The Dockerfile for the service should copy over its files, install dependencies and start up its server.</p><pre>app:<br>    build: ./app # build using the Dockerfile in the `app` folder<br>    ports:<br>      - &quot;3000:3000&quot; # expose port 3000 (The port the app runs on)<br>    logging:<br>      driver: none # hide logs</pre><p>I expose port 3000 here so that when the service is running I can visit the site and make sure I’m able to hit it. Once this is verified you can remove this if you want.</p><h3>Adding WebdriverIO</h3><p>Similarly, you’ll need to have another service for the actual testing process. This will involve running WebdriverIO, downloading and uploading files to and from S3, diff generation, as well as any other business logic specific to your needs. To get started, you’ll want to add something like the following to your docker-compose.yml.</p><pre>testing:<br>  build: ./testing<br>  depends_on:<br>     - selenium-hub<br>  logging:<br>    driver: none # turns of logs in your terminal</pre><p>In here we specify that this service depends on selenium-hub so that selenium starts up before the testing service. You may need or want more control over only starting one service before another then this provides. <a href="https://docs.docker.com/compose/startup-order/">Check out this docker documentation on how to do that</a>.</p><h3>Setting up WebdriverIO</h3><p>WebdriverIO is pretty cool, but can be difficult to understand when first getting started. We’ll be using wdio which is the test runner built into WebdriverIO, but it’s difficult to see where one ends and the other begins. To set it up run the following:</p><p>npm i -g @wdio/cli</p><p>wdio config</p><p>You’ll then be asked a bunch of questions to set up your env. Below is an image of the questions you can expect to be asked.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*d1uBfIWoka_AgNMUf4q2HQ.png" /><figcaption>WDIO Config Setup</figcaption></figure><p>This will generate a wdio.conf.js file with all your settings. The file has a ton of comments explaining each part of the config. If you’re having problems in getting the test runner to work, this file is likely the culprit. I’ve pasted below a version that I know works and that I have used myself. I’d spend some time going through the file that you create through the CLI tool and comparing it to the one below.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8215c156fe890633c92bfef9c18f2eca/href">https://medium.com/media/8215c156fe890633c92bfef9c18f2eca/href</a></iframe><p>You’ll likely have to play around with some of the settings. For example, the timeout values may cause a problem and need to be increased, or the path to your test files might be different.</p><p>When going through the setup process, wdio will offer to install any additional packages that you need based on your answers. This includes the report package and the testing framework among others.</p><p>The last step I’ll cover is using WebdriverIO to actually run your tests. Take a look at the following code sample to see how I set this up. I define a few helper functions ,and then simply loop through all the screen sizes and routes that I want to test.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/94ed4d64f91ec4f364bc0f9605f202ce/href">https://medium.com/media/94ed4d64f91ec4f364bc0f9605f202ce/href</a></iframe><p>Next, I define a list of screenshots in a separate JSON file which allows me to easily run a diff comparison for any number of screen sizes. This lets me test what the page looks like on an iPhone SE vs an iPhone X vs a 13 inch computer etc. Similarly I pull the list of routes to test from an external location. You can set this up any way you want based on your architecture and requirements.</p><p>A few notes</p><ul><li>Based on the browser, I use a different method to resize the browser</li><li>The URL of the site is <a href="https://app:3000/$%7Broute%7D">https://app:3000/${route}</a>. app is the name of the docker service running the website. I specify the port as well and use the route passed in as a parameter</li><li>I wait 1 second before taking the screenshot. There are likely better ways than just waiting a little to know when the page is loaded. You can test for an element on the page or perhaps maybe for an event to have been fired.</li></ul><h3>All the Other Bits</h3><p>A few more scripts are needed for this to work. You’ll need to run the image comparisons, upload and download files from S3, and perform any other tasks that you want to occur for any given situation. These aren’t difficult to write, and are fairly trivial, so I’ll leave their design up to you.</p><h3>The Final Piece</h3><p>The last question in all this is: what happens when a build fails this test? This is more of a process issue than a technical question. Is the diff found intentional? If so, then you need a way to update your baseline image to the new image. This requires another part, a diff reviewer that allows people — application developers, people on your QA team, product owners or anyone else who needs access — to accept or reject the changes found. Accepting the changes would require updating the baseline image to the new screenshot image, while a rejection would have to notify the dev team responsible for the changes.</p><h3>The Output</h3><p>Below is an example output that is produced by the diff tool. On the left is the baseline image, the middle is baseline overlaid on top of the screenshot, and on the right is the screenshot. The baseline has the drawing on it, since it was easier for me to add a quick edit to the baseline rather then edit the contents of the page.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*E_F4fiyTWvUFBRw3uGQkrA.png" /><figcaption>Example diff output</figcaption></figure><p>One cool way to expand on this would be by integrating an AI to determine when a change is valid. You would either need to train your own model on good and bad UIs, or find a pre-trained model and then integrate it into the process and use that rather than blink-diff. While this is certainly a cool advancement to make, it’s by no means a requirement; and doing simple image comparisons will take you far.</p><h3>Potential Issues</h3><p>I’ll end with a few open questions and potential issues that you may encounter.</p><ul><li>You’ll need to have some business logic to determine if baseline images exist. If not, then it means it’s the first run and the screenshots should be named, labeled, or stored in a way as to make them the baseline images for subsequent runs.</li><li>Timeouts can cause trouble. It’s possible you’ll have to increase the timeouts in the wdio.conf.js file to prevent the runner from exiting prematurely.</li></ul><p>While this is a complex problem, and this solution doesn’t solve everything, I hope it’s given you some insight into how you can build your own automated UI regression testing suite. Since all of this runs in docker it’s very easy to drop into your CI/CD pipeline whether it be Jenkins, Travis, AWS or any other provider.</p><p>Happy testing!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=71b2ef1bd9b4" width="1" height="1" alt=""><hr><p><a href="https://medium.com/disney-streaming/ui-regression-testing-71b2ef1bd9b4">UI Regression Testing</a> was originally published in <a href="https://medium.com/disney-streaming">disney-streaming</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How to Customize your Terminal with ZSH]]></title>
            <link>https://medium.com/hackernoon/how-to-trick-out-terminal-287c0e93fce0?source=rss-fa4df7a7b495------2</link>
            <guid isPermaLink="false">https://medium.com/p/287c0e93fce0</guid>
            <category><![CDATA[customization]]></category>
            <category><![CDATA[terminal]]></category>
            <category><![CDATA[zsh]]></category>
            <category><![CDATA[oh-my-zsh]]></category>
            <category><![CDATA[developer-tools]]></category>
            <dc:creator><![CDATA[Samuel Bernheim]]></dc:creator>
            <pubDate>Tue, 28 Aug 2018 01:52:01 GMT</pubDate>
            <atom:updated>2019-04-17T17:00:32.680Z</atom:updated>
            <content:encoded><![CDATA[<p>When I first began using my terminal it looked like this</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DUhOBGuy40x2K_hho2Lf6A.png" /><figcaption>Basic Terminal</figcaption></figure><p>And now, it looks LIKE THIS:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RyOl2cK_pD5IbQvHBZ85ug.png" /><figcaption>Tricked out Terminal</figcaption></figure><p>So how do you get from one to the other, well for me it took about 2 years to learn enough but lets see if we can’t help speed that up for YOU!</p><p>😎</p><h3>Step 1: Ditch Bash and Use ZSH + <a href="https://github.com/robbyrussell/oh-my-zsh">Oh-My-ZSH</a></h3><p>First, some terminalogy — bwhahaha get it TERMINALogy!! *wipes tear from eye* 😂</p><p>Ok, maybe thats it for the terrible puns</p><p>So you have your terminal application. This is the default terminal app on mac/linux/windows or iTerm2 or powershell etc. (<a href="https://www.iterm2.com/downloads.html">You should definitely be using iTerm2</a> though).</p><p>Then you have the shell which is the thing running in the application. There are a bunch of these</p><ul><li>Bash (stands for Bourne Again Shell)</li><li>ZSH (Z-Shell)</li><li>C-Shell</li><li>Fish</li><li>etc etc</li></ul><p>They all work a little differently or support different features. ZSH is super easy to customize though which is why we’ll be using it. If you have a mac you can brew install zsh or for linux sudo apt-get install zsh if neither work/for more info <a href="https://github.com/robbyrussell/oh-my-zsh/wiki/Installing-ZSH#install-and-set-up-zsh-as-default">check here for more methods to install.</a></p><p>Now all you need to do is set it as your default shell with this command chsh -s zsh. chsh stands for, you guessed it change shell, -s tells the command that you want to change it to a specific shell which you pass in as an argument which here is zsh. You’ll be asked for your computer password too.</p><h3><em>Step 2: Install Oh-My-ZSH</em></h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/337/0*ElbozurqAg26rVSt.png" /></figure><p>Install instructions here: <a href="https://github.com/robbyrussell/oh-my-zsh#via-curl">https://github.com/robbyrussell/oh-my-zsh#via-curl</a></p><p>Congrats, Two steps done!! See how easy this is.</p><h3>Step 3: Getting the Right Fonts</h3><p>You’ll want to check out this repo: <a href="https://github.com/ryanoasis/nerd-fonts#font-installation">https://github.com/ryanoasis/nerd-fonts#font-installation</a> which contains a ton of fonts which support all the awesome, cool symbols you’ll want to use. Its a lot of fonts to install so be sure you don’t run this while your connectivity might drop or if you’re in a rush.</p><p>Nerdfont fonts support font-awesome glyphs, material design icons, octicons and more.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/956/1*8tEAx7NwOalIydhha5REqQ.png" /><figcaption>Nerdfont source fonts diagram</figcaption></figure><p>If you just want to get one, <a href="https://github.com/ryanoasis/nerd-fonts/blob/master/patched-fonts/DejaVuSansMono/Regular/complete/DejaVu%20Sans%20Mono%20Nerd%20Font%20Complete%20Mono%20Windows%20Compatible.ttf">this is the font</a> I’m using and its worked great. Just click the link, download the ttf file and install the font to your computer. If you see the box with a question mark in it a times, it means the font you are using in your terminal doesn’t support that character.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/24/1*VjZkkvB0g7nwrea0rtSx6Q.png" /><figcaption>Unsupported character symbol</figcaption></figure><h3>Step 4: Themes and Colors</h3><p>You have two things to focus on when customizing your terminal. The first is the theme. This is the way the terminal is going to look. The second is the colors of those things. This determines what shade of blue is your blue, what red is your red etc.</p><p>First lets talk themes. To get started take a look at <a href="https://github.com/robbyrussell/oh-my-zsh/wiki/themes">https://github.com/robbyrussell/oh-my-zsh/wiki/themes</a></p><p>All of these are baked into oh-my-zsh and all you have to do is edit your .zshrc file (its located at ~/.zshrc) and set ZSH_THEME=&quot;THEME_NAME&quot;, so ZSH_THEME=&quot;agnoster&quot; for example, and thats it.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/634/0*7XyxgOboj-BaF2ha" /><figcaption>Example of iTerm2 Color Scheme called Broadcast</figcaption></figure><p>As for colors, you can <a href="https://github.com/mbadolato/iTerm2-Color-Schemes">take a look at this repo</a> which has a bunch of nice color schemes ready to download for iTerm2. The colors can be edited in the settings. Go to settings &gt; profiles &gt; colors. In the bottom right corner is the color presets list. Click this and you’ll see an option to import a color scheme or select some built in ones. Import any of the color schemes you download from that repo.</p><h3>Step 5: Powerlevel 9K</h3><p>Another awesome repo I recently found is <a href="https://github.com/bhilburn/powerlevel9k">PowerLevel 9K</a>. It serves the same purpose as the themes in oh-my-zsh.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/0*g3VOlVqU2Q13ybTX" /></figure><p><a href="https://github.com/bhilburn/powerlevel9k/wiki/Install-Instructions#step-1-install-powerlevel9k">To install PowerLevel 9k check here for instructions</a></p><p><a href="https://github.com/bhilburn/powerlevel9k/wiki/Show-Off-Your-Config">And then check out this page</a> to see all the cool stuff other people have built. Find one you like and copy their settings into your .zshrc file and then you can modify bits and pieces until its just how you like. I’d do this first before you try and build your own from scratch. Your mileage may vary with some of them. But once you find one you like you can modify any of the variables until its just how you like it.</p><p>(Some of the configs might include POWERLEVEL9K_MODE=&quot;SOMETHING_HERE&quot; and ZSH_THEME=&quot;powerlevel9k/powerlevel9k&quot;. If you already have them in your .zshrc delete the duplicate and if you’re setting the first option make sure its set before ZSH_THEME is.)</p><h3>Step 6: Writing Your Own Functions</h3><p>Powerlevel 9K supports a lot out of the box including github status/other version control systems, current working directory, host, node version, time/date, <a href="https://github.com/bhilburn/powerlevel9k#available-prompt-segments">and tons more</a>.</p><p>You can also write your own functions to display more stuff. Below is the function I have to show if I’m connected to the internet. If so I display the symbol in green. Otherwise in red. You can write any bash function and have it echo a statement at the end . Then to include it in the prompt add custom_internet_signal (or whatever your function is called) and whatever the function echo’s will appear!</p><p>Note: this function is stored in .zshrc.</p><p>Note 2: \uXXXX is saying display this unicode character. To actually know what character that is google u+XXXX unicode character.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/62fc4d3b34b66684387f41769f16f879/href">https://medium.com/media/62fc4d3b34b66684387f41769f16f879/href</a></iframe><p>You can write functions to show your battery level (different icons for different statuses, different colors for different levels etc). The song playing on Spotify etc (this might take some work but check out <a href="https://github.com/hnarayanan/shpotify">https://github.com/hnarayanan/shpotify</a> or <a href="https://github.com/johnelse/spotify-cli">https://github.com/johnelse/spotify-cli</a>), Docker status etc.</p><p>And thats it! 6 steps to trick out your terminal!</p><p><a href="https://github.com/sbernheim4/dotfiles/blob/master/.zshrc">As always if you want to take a look at my dotfiles for reference here it is.</a> Feel free to fork or clone it (I wouldn’t use the install script though to replicate everything, its fairly buggy and is not up to date).</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fupscri.be%2Fdde502%3Fas_embed%3Dtrue&amp;dntp=1&amp;url=https%3A%2F%2Fupscri.be%2Fdde502%2F&amp;image=https%3A%2F%2Fucarecdn.com%2F57662ddc-da7c-407b-afcb-cb45184b2705%2F&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=upscri" width="800" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/d25dd15e8727342107fbe0b6d67b030e/href">https://medium.com/media/d25dd15e8727342107fbe0b6d67b030e/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=287c0e93fce0" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/how-to-trick-out-terminal-287c0e93fce0">How to Customize your Terminal with ZSH</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Getting a Free SSL Certificate on AWS a How-To Guide]]></title>
            <link>https://medium.com/hackernoon/getting-a-free-ssl-certificate-on-aws-a-how-to-guide-6ef29e576d22?source=rss-fa4df7a7b495------2</link>
            <guid isPermaLink="false">https://medium.com/p/6ef29e576d22</guid>
            <category><![CDATA[ssl-certificate-on-aws]]></category>
            <category><![CDATA[aws]]></category>
            <category><![CDATA[aws-ssl-certificate]]></category>
            <category><![CDATA[ssl]]></category>
            <category><![CDATA[free-ssl-certificate]]></category>
            <dc:creator><![CDATA[Samuel Bernheim]]></dc:creator>
            <pubDate>Fri, 27 Jul 2018 23:46:01 GMT</pubDate>
            <atom:updated>2019-04-17T16:58:16.454Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*7-ekxg6lcdudP8gA1oFy5w.png" /></figure><p>AWS gives you a FREE SSL certificate if you use their load balancer (yes you do have to pay for the load balancer but its pretty cheap and in then end is something your site should have anyway) but I found the setup to be confusing. Setting up a load balancer, connecting it to the EC2 instance, configuring the DNS, and putting in all the correct information is not a trivial process. This guide gives you everything you need to get up and running with an SSL cert.</p><p>What’s Covered</p><ul><li>Setting up a Security Group</li><li>Setting up an EC2 Instance w/ Elastic IP</li><li>Setting up SSL with the Amazon Certificate Manager (ACM)</li><li>Setting up a Load Balancer</li><li>Setting up Target Groups</li></ul><p>I assume you have some app that is ready to deploy. Whether it uses NodeJS, Python, or Java on the backend doesn’t matter. All that does matter is that it runs on some port that you can control. For this article I’ll assume port 8080. This is not a special port. It would work the same with port 1234, or 3000, or 5000. I just set my stuff up with 8080 so it will be easiest to follow.</p><h3><strong>Setting up an EC2 Instance</strong></h3><p>This part is easy. Log on to the amazon console and under services click EC2. Click on the launch instance button. It looks like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nlE1NRlGNFIPViEE4I-atw.png" /><figcaption>Launch new EC2 Instance</figcaption></figure><p>Then you have to select which AMI (Amazon Machine Image) you want. This is the OS the instance will use. Typically you’ll just want a linux instance but you might want something different depending on your needs. I’m going to choose the first one:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FnMeamvQ_KMeKCzYeJzhZg.png" /></figure><p>Click select and then select your instance type. This is to configure how much RAM your server will have, how much processing power, the size, and type. I personally just go with the defaults. Keeps things easy.</p><p>When you get to step 6 be you’ll want to make a new Security Group. The settings should look like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DfvgyjUetxmr6B1ARjf5eA.png" /></figure><p>When you hit launch you will be given the option of making a new key. This is what will let you SSH into the instance. Make a new one (or use an old one if you still have access to the .pem file and want to use it) and give it a name. Download it and keep it somewhere on your computer that is easy to access (I usually keep it in ~/).</p><p>In your terminal cd to the folder where the .pem file is and follow the instructions that pop up when you hit the connect button (you need to have the instance selected by clicking on it). Once you’re SSH’d into the instance you can clone your code from GitHub or wherever its being stored, install any dependencies and start your server. Then exit out. Thats all the terminal work we’ll be doing :).</p><h3>Setting up your Elastic IP Address</h3><p>Next you’ll need an IP address for your instance to make it publicly accessible. AWS does this with Elastic IPs. It’s listed on the left side panel. Find it and open up the page. Click on Allocate new address and then when the EC2 instance you just made shows up in the list, CTRL click on it and select Associate Address. Then select the instance you just created and click Associate.</p><p>Visiting this IP address and then :PORT_NUM should bring you to your site. So if your Elastic IP was 34.200.70.235, and your app was running on port 8080, visiting 34.200.70.235:8080would make a get request to / .</p><blockquote>Addendum: Thanks to <a href="https://medium.com/u/4970c5a0d076">Michael Flaxman</a> for catching a mistake! In the security group shown in the above image, port 8080 is not included which means visiting 34.200.70.235:8080 would be blocked. To allow access, edit the security group and simply add port 8080 with type http with the same source options as ports 80 and 443.</blockquote><p>Congrats!! You just deployed your website on AWS! Lets try and improve it a bit by adding SSL and associating it with a domain name.</p><h3>Setting Up SSL</h3><p>We’ll do this using ACM, AWS’s certificate manager. Click on services, search ACM and click on Certificate Manager.</p><p>Click Request a Certificate. You want a Public Certificate. Click on Request a Certificate and add all your domain names to the box. This should only include the main domain (also referred to as the naked domain) aka mypage.com and not things like mypage.com/blah. If you have other versions like <a href="http://www.mypage.com/">www.mypage.com</a> or blog.mypage.com add those too and click next.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*S-qCmBro9REjvi4xbVTgjQ.png" /><figcaption>Add your domains</figcaption></figure><p>Now AWS needs to verify you are in fact the owner of that domain. Select DNS Validation if you have access to the DNS settings (this would be through Route53, Namecheap, GoDaddy or any other domain name provider) or Email Validation if you do not. DNS validation is better and faster. If you are using Route 53 (which I recommend), then the remaining setup is very easy since AWS can add the required records for you to the DNS settings. Otherwise you will have to copy and paste them in. Save your changes and then you should then see something like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tc1M8ylfO8GGbEywayDpPQ.png" /></figure><p>If you are using Route 53 an additional button will be available offering to add the CNAME Records to your DNS (shown below). Click it for each version of the domain (the www and non-www version and any other subdomains you added in the previous step). Otherwise copy the name and value and add it as a CNAME record to your DNS settings. Each version requires its own record so be sure to add all of them to your DNS settings.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wfVU7d8nC5h0ja26fyEg_Q.png" /></figure><p>Once AWS verifies everything the validation status will update to say Success in green. This may take some time (0–30+ mins but typically around 5) so don’t worry if it doesn’t happen immediately.</p><h3>Setting up your Load Balancer</h3><p>Now we need to configure the load balancer. This is also found in the left side panel in EC2. A load balancer makes it easy to evenly distribute traffic to your site to the multiple servers that are running it. We won’t really be making use of this aspect (since we only have one instance running) but that is its main function. Open up its page and click Create Load Balancer.</p><p>Which brings you to this page:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wN0pj6KE0-pTiLnGh9QKSA.png" /><figcaption>Create Load Balancer Options</figcaption></figure><p>We’ll be using the first option, HTTP and HTTPS. Click and give it a name. Under Load Balancer Protocol we’ll want to add HTTP and HTTPS as options. The HTTP option should be set to use port 80 and the HTTPS option port 443. Choose some availability zones (2 are required at a minimum). The setup should then look like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_16ihgBicUFNID7uWFerTQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0oFbBliLAEgA8yWHI6NQDw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mhZp670tMWr-dGAEO_VAew.png" /></figure><p>Notice how for port it specifies the Load Balancer Port. This is the port the of the load balancer, NOT of your application (which is 8080). This is because the Load Balancer will sit in front of your server and listens on ports 80 and 443 (what we just set up). When a request comes in on either of these ports, the load balancer will then take some action to forward the request onto your application which will be listening on port 8080 (We’ll set that up in the next step).</p><p>Once this is done click next.</p><p>This is where you connect the SSL certificate to the Load Balancer. Select Choose a Certificate from ACM and the cert you just made from the drop down menu. The default security policy is good to go.</p><p>See, not to bad and we’re almost done.</p><p>Go now to Target Groups, also on the left side of the EC2 settings and just below Load Balancers, and create a new target group.</p><p>Give it a name and use HTTP as the protocol with a port value of 8080 (the same as the port your actual server is listening on).</p><p>Select it, click on Targets in the bottom panel and then edit. You’re going to select your EC2 instance in the bottom and then click Add to registered and be sure the port is 8080 and then Save. It should now appear in the top part as a registered target.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*i7U8ABbB2lTDMof25BIQYw.png" /></figure><p>Go back to the load balancer settings and select your load balancer. Choose listeners and click Add listener with a port value of 80 and forward to the Target group we just made (Ignore the red below).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*d_b9KVepBa6_kRdyyCBy8A.png" /></figure><p>Do the same thing again but instead of HTTP do HTTPS and use port 443 again with the same Target group we just made. For this one though we will set the SSL info to be from ACM and then select the Certificate we made earlier. Hit save and it should now look like this in the listeners section.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*E6EJRnGvRkxXkKkule_gRQ.png" /></figure><p>Be sure to also set up the security group for the load balancer to allow traffic to enter on port 80. To make a new security group, find the tab on the left panel of the EC2 page. Create a new security group allowing traffic from all sources in on port 80 like below. If you get an error about CIDR it’s because you have to set the source column.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uMJsoGRWjA4AOD1jbDEJ1w.png" /></figure><h3>Pointing your Domain to the Load Balancer</h3><p>The last and final step is to update the DNS records for your site to now point to the load balancer.</p><p>Go to Route 53 in the console and open up the settings for your Domain.</p><p>If you don’t have them already, you’ll need to add two A records. If you already do have them, you’ll need to update them.</p><p>For type, select A record and then just below it you’ll see a yes or no option for Alias. Choose Yes.</p><p>Then click on the text book to the right of Alias Target and select the load balancer you just made from the list.</p><p>AND THAT’S IT!!!</p><p>When a request comes in to your domain (whether it be http or https), Route 53 will direct it to the Load balancer which will use the target group to send it to the EC2 instance.</p><p>If you run into any problems google the service you were working with (ACM, EC2, Route53, etc) and then the issue or drop a comment below. I hope this has helped you get your site running with SSL</p><p>As Jeb Bush said, please clap: <a href="https://youtu.be/DdCYMvaUcrA?t=23">https://youtu.be/DdCYMvaUcrA?t=23</a> :)</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fupscri.be%2Fdde502%3Fas_embed%3Dtrue&amp;dntp=1&amp;url=https%3A%2F%2Fupscri.be%2Fdde502%2F&amp;image=https%3A%2F%2Fucarecdn.com%2F57662ddc-da7c-407b-afcb-cb45184b2705%2F&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=upscri" width="800" height="400" frameborder="0" scrolling="no"><a href="https://medium.com/media/d25dd15e8727342107fbe0b6d67b030e/href">https://medium.com/media/d25dd15e8727342107fbe0b6d67b030e/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6ef29e576d22" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/getting-a-free-ssl-certificate-on-aws-a-how-to-guide-6ef29e576d22">Getting a Free SSL Certificate on AWS a How-To Guide</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[PassportJS — The Confusing Parts Explained]]></title>
            <link>https://medium.com/hackernoon/passportjs-the-confusing-parts-explained-edca874ebead?source=rss-fa4df7a7b495------2</link>
            <guid isPermaLink="false">https://medium.com/p/edca874ebead</guid>
            <category><![CDATA[gmail-sign-up]]></category>
            <category><![CDATA[login]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[authentication]]></category>
            <category><![CDATA[passport]]></category>
            <dc:creator><![CDATA[Samuel Bernheim]]></dc:creator>
            <pubDate>Sat, 14 Jul 2018 00:36:21 GMT</pubDate>
            <atom:updated>2019-05-04T23:37:31.297Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/830/0*HRTuYtgIwzQ6o5Oo" /></figure><p>PassportJS is awesome. It provides an abstraction layer over logging in with various providers such as Facebook, Google, Github, Twitter and more.</p><p>When first getting started though it can be a little challenging to understand what’s going on and why. Their documentation is pretty good but leaves out some specifics that I initially found difficult to understand. Hopefully this helps answer some of your questions and clears up some confusion. I assume you’ve read the docs a little and have maybe tried implementing it. Even if you haven’t though, you should still be able to follow along. Even if you have, this should still prove useful in understanding PassportJS a little better.</p><p>Here’s what’s covered</p><ul><li>The Callback Function in Strategy Setup</li><li>Why passport.authenticate() is needed in the callback</li><li>Checking if the User is Logged in</li><li>Understanding serializeUser() and deserializeUser()</li></ul><p>Alright, lets go!</p><h3><strong>Issue 1: Understanding the Callback in Strategy Setup</strong></h3><p>Take a look at the code below. We require our modules, set up our google strategy and create two routes, one for handling logging in and another for the callbackURL.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/873798a49baff3a82b8318b267db72dd/href">https://medium.com/media/873798a49baff3a82b8318b267db72dd/href</a></iframe><p>When a user visits /login/google, we authenticate with google and in this case, request their email and profile information.</p><p>One key part though is, as part of passport.authenticate(), the function on line 9 is called before the console.log() is on line 15.</p><p>This function is the first time you have access to the profile information. Typically this is where you would add the user to your DB if it doesn’t already contain it (See code example below). But how do you exit this function to get back to your code, specifically to the route handler for the callbackURL specified on line 19.</p><p>To do this you call done().</p><p>What is done()? An internal PassportJS function. You pass it two arguments, null and the profile info like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7a917438388c699a43baada8916d3f42/href">https://medium.com/media/7a917438388c699a43baada8916d3f42/href</a></iframe><p>This takes the profile info and attaches it on the request object so its available on your callback url as req.user. This will be available for the route /login/google/return as defined on line 41 and this is where you would set the session for the user and then send them on their way to another part of your site.</p><h3>Issue 2: Why the passport.authenticate() in the callbackURL?</h3><p>If a user makes it back to /login/google/return, why do we need another passport.authenticate()? This is partly to make sure the user didn’t just go to the route directly and verifies that they are in fact logged in. This is handled internally by PassportJS.</p><p>As a side note, you should not use passport.authenticate()as a method to check if a user is logged in. This should only be used to actually log a user in which is needed in this case since they might not yet be logged in if they just typed in the url and route and hit enter.</p><h3><strong>Issue 3: Check if a User is Logged In</strong></h3><p>On line 36 in the code block above we set req.session.user to equal the profile of the person who just logged in. To check if someone is logged in we can just see if this value has been set and then use this function as middleware on any route we want where the user has to be logged in. Here is an example of the middleware function.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b636ce47b8dc35c501e56bb6dcdba157/href">https://medium.com/media/b636ce47b8dc35c501e56bb6dcdba157/href</a></iframe><p>Then if you want to ensure a user is logged in for a route, just do this</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/58bd0a2d1c629d0b5b829301d175f8cb/href">https://medium.com/media/58bd0a2d1c629d0b5b829301d175f8cb/href</a></iframe><p>This will call isLoggedIn. If req.session.user is set then the request continues on due to the next() call. Otherwise the user is redirected to /login.</p><h3><strong>Issue 4: What is this Serialization and Deserialization Business?</strong></h3><p>From above we said that passport attaches the profile information to req.user. This occurs as a direct result of the serializeUser() and deserializeUser() functions.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a18e1536fcfd358f5a7e82700f1d6e26/href">https://medium.com/media/a18e1536fcfd358f5a7e82700f1d6e26/href</a></iframe><p>When you write done() in the callback function specified when setting up the strategy (look at the second code block all the way at the top where we do done(null, dbUserRecord or done(null, newUser)), we pass in the entire user profile object (in this example as either dbUserRecord or as newUser).</p><p>The reason for this is because it is received by serializeUser(). This function then calls done(null, user.id). Passport takes that user id and stores it internally on req.session.passport which is passport’s internal mechanism to keep track of things.</p><p>Then in deserializeUser(), the first argument is an id which is the same id that was passed in done(null, user.id) of serializeUser(). deserializeUser() then makes a request to our DB to find the full profile information for the user and then calls done(null, user). This is where the user profile is attached to the request handler at req.user. Then finally after all this occurs, the user is routed back to the /login/google/return route handler where we can finally access the user profile information on req.user.</p><p>To understand this user flow a little better take a look at the diagram on this StackOverflow answer: <a href="https://stackoverflow.com/questions/27637609/understanding-passport-serialize-deserialize?answertab=votes#tab-top">https://stackoverflow.com/questions/27637609/understanding-passport-serialize-deserialize?answertab=votes#tab-top</a>.</p><h3><strong>Wrapping Up</strong></h3><p>You might ask yourself now, why is all this necessary. Handling user info in this manner means PassportJS only has to store the user id and not the entire user profile. This decreases the likelihood of confusing req.session.user which is something we set and req.session.passport.user which is PassportJS’s way of keeping track of what’s going on.</p><p>This can be seen by logging req.session which will return something like this</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0e2df172130e0a1a8c57d85420f6b393/href">https://medium.com/media/0e2df172130e0a1a8c57d85420f6b393/href</a></iframe><p>Notice how passport.user is the same as user._id. They have to be so we can perform the database lookup with the right information. Further passport.user only stores the id and nothing else like name or googleID which we see in the user object.</p><h3>Conclusion</h3><p>PassportJS makes it really easy to get setup but understanding its data flow can be confusing. I hope this helps explain some of the underlying principles it uses. If you have any questions please leave them in the comments.</p><p>Thanks for reading!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=edca874ebead" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/passportjs-the-confusing-parts-explained-edca874ebead">PassportJS — The Confusing Parts Explained</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building Budgeteer - Lessons and Experiences]]></title>
            <link>https://medium.com/hackernoon/building-budgeteer-lessons-and-experiences-97dec9031006?source=rss-fa4df7a7b495------2</link>
            <guid isPermaLink="false">https://medium.com/p/97dec9031006</guid>
            <category><![CDATA[money]]></category>
            <category><![CDATA[building-budgeteer]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[finance]]></category>
            <category><![CDATA[progressive-web-app]]></category>
            <dc:creator><![CDATA[Samuel Bernheim]]></dc:creator>
            <pubDate>Fri, 01 Jun 2018 15:16:01 GMT</pubDate>
            <atom:updated>2018-06-29T16:51:48.495Z</atom:updated>
            <content:encoded><![CDATA[<h3>Building Budgeteer — Lessons and Experiences</h3><p>With less than a semester left of college, and a need to build something I realized I needed a budget app. I knew of course about Mint, and later learned of Clarity Money far into development, but I wanted something smaller and more focused without all the extra heft that Mint provides, or the advertising and recommendations that Clarity Money includes.</p><p>Budgeteer was born (My sister came up with the name at dinner when I was home on vacation, I am not that creative). This is the story of how I built it, lessons learned, and experience gained. It’s not finished, and still requires a fair amount of work left, but not so much that I couldn’t finish in a couple of weeks if I really wanted to, or couple of months if I want to relax with it. Please feel free to <a href="https://budgeteer-prod.herokuapp.com/budgeteer">check it out</a> and leave any comments you have here (Please just avoid adding or removing too many accounts in the settings page as it does update the DB and I don’t want to check one day and see 50 linked accounts that I have to remove). Design advice is particularly welcome.</p><p>Why another budgeting app you ask. While banks and credit cards provide a lot of the same statistical information, few companies aggregate all of it together. Most people I figure have at least 2 credit cards, a savings account, a checking account, and a retirement account. Thats a lot of accounts to keep track of and the data from each individual account is useless without being combined with the others. This is the why for Budgeteer.</p><h3>The Stack</h3><p>MERN. MongoDB, ExpressJS, ReactJS and NodeJS. Its awesome and powerful.</p><p>In addition to these, I use Mongoose, PassportJS, Webpack , date-fns (awesome date library — very modular = tiny size), Plaid, ReactRouter, Recharts, and a few others.</p><p>Why am I sharing all the tech I used? Cause I doubt someone else wants to go through it and rebuild exactly the same product. And frankly if they do and can do it better, then go for it. I’m a free market kind of guy. I may try and bring this to market and sell it as a subscription (Plaid is the only big cost if I were to sell it as a service) but with a developer account, I am happy to be the only user and can do so for free.</p><h3>Scope</h3><p>Defining the scope of this project was an evolutionary process. First I focused on a desktop site. Then I wanted it to also be mobile friendly and look great on a phone with a screen as small as 4&quot;. Then I decided to build it as a Progressive Web App both as a means to learn what PWAs entail and because I think PWAs will be far more popular in the near future. With one codebase I can hit every device and get native app functionality.</p><p>The core of this product revolved around getting data from banks. Was I to resign to picking a few banks (aka the ones I use) and go through their API documentation (if it even existed) which was bound to be terrible or was there a better way. Enter <a href="https://plaid.com/">Plaid</a>, an awesome API that lets developers let users link bank accounts and access transactional information among many other data points. But for me, I got TRANSACTION DATA. The only data I needed, beautifully formatted and organized. If you ever need to work with bank accounts for whatever reason, check them out.</p><h4>Core Functionality</h4><p>Above all I wanted simplicity, an elegant design, and a tool that would in the end be helpful and not just a shallow clone. No advertising, no weird partnerships, no financial products recommendation, no nothing. Just an honest, quality product that I would want to use. I hope you will too. I’ve listed below the core functionality.</p><ul><li>View and search transaction data across all accounts</li><li>Provide meaningful feedback that helps users understand their spending patterns — visualized statistics with charts</li><li>Easily view your Net Worth</li><li>Track monthly recurring expenses like Netflix, Spotify, HBO NOW, etc</li><li>Easily add or remove accounts without any fuss or hoop jumping</li></ul><h4>Transactions</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6-Ke02iuzjVd-xRc8-yqrQ.png" /><figcaption>Desktop view of the transactions page</figcaption></figure><p>Being able to view all your transactions across all your accounts gives users the power to see in one place where they spend their money, where they can cut back, and make tackling a tough subject easier. Being able to search transactions and filter by category, date, and account type makes tracking various expenses easy. Knowing what you’ve spent in the past week in the chart keeps you honest about how you’re doing in the short term while the statistics sections help focus your attention on the medium and long term. (NOTE: The calendar button doesn’t do anything yet. Still trying to find a good calendar drop in that I can use — suggestions welcome).</p><h4>Statistics</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*UXWlAWYeYrk8MyqBg1_VGw.png" /></figure><p>This required a charting library. I first started with ChartJS and after sticking with it for a while, I eventually switched to Recharts. ChartJS styling and option configuration is weird. Mentally picturing how something should look after an edit frequently failed to match the reality. Recharts, though more complex at first, was far easier to configure and style. The five charts I create are explained below</p><ul><li>Categorical breakdown of spending as a doughnut chart</li><li>Annual spending by month for the past year with a line for the average amount per month</li><li>Monthly Budget chart showing amount spent so far in the current month and the amount remaining</li><li>Week vs Weekend spending to better understand if your spending changes drastically during one or the other</li><li>Heat map showing transactions in various locations with hotter regions indicative of more spent (IN PROGRESS — Not in the demo).</li></ul><p>Each of these charts answers valuable financial questions. Where is my money going? How am I spending it? Where can I cut back? Am I on track with my Budget? Is my spending consistent month to month? Where physically am I spending the most? Each of these charts and graphs offers a quick snapshot of a different perspective on a user’s financial health without overwhelming them with extraneous information. It crystallizes the rough idea people keep mentally remember by showing them the hard numbers of their finances. Above all, each chart is insightful and simple.</p><h4>Net Worth and Recurring Payments</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qGDPtK7xUqyYzsYCXNWtqA.png" /></figure><p>Net Worth quickly allows people to view their total account balances and know how much cash they have on hand in their various accounts whether it be an emergency fund they set up or their primary checking account. Showing each account gives users the transparency they need to ensure they can allocate their money effectively instead of roughly tracking amounts in their head.</p><p>Recurring transactions give users a good sense of the products and services they pay for monthly. Maybe that Pandora subscription you forgot about isn’t necessary anymore now that you started using Spotify or since you stopped using it entirely.</p><h4>Settings Page</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gSy6FEmGawm40XHVSqACpA.png" /></figure><p>The settings page is all about bringing even more transparency to the user. They can easily remove any accounts they would rather not have linked and see if they are missing anything. Once they click remove the access tokens stored in the database are deleted and more importantly invalidated so even if someone got them they wouldn’t work.</p><h3>Design</h3><p>Designing Budgeteer was the most interesting part of this project. I have gone through so many iterations of finding the right way to display transactions, show the charts, style the nav bar etc. I’ve checked-out different commits across the history so you can see the progress below.</p><h3>Transactions Page</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ib7xtYdl0u4iqdUPcbsvAA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZKhP9ctucf2UEegyo0nTSQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5ButkWw88teh2A-6CmAH6g.png" /><figcaption>3 Different Versions of the Transactions Page</figcaption></figure><p>The difference is stark. Transactions are far more elegant and take up much less space while communicating nearly double the information. The graph adds a visual perspective which breaks up the UI and provides the user with another quick summary of their spending trends. All the sorting options were compacted into smaller expandable parts reducing clutter and adding much needed visual breaks. It makes the design mobile friendly and easy to navigate.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/608/1*k6pHd3Fp9FOLEJ4dhRRuPA.png" /></figure><h3>Statistics Page</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8TSKaMFg0tEXd2Tc025lyw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*P3w4_HLx6BZDt-HdCD8VIA.gif" /></figure><p>At first I started with a tab based design. I thought that looked cool on desktop but knew it wouldn’t scale on mobile. Then I decided to have a slider like option with next and previous buttons which the user could press to change graphs. While it doesn’t look awesome on desktop yet, it does on mobile. Maybe next I’ll switch to having a little menu bar on the bottom with an icon for each graph. That would take up the extra visual space on a computer while still also fitting on mobile. Desktop could contain words if they fit, switch to icons with a breakpoint when they don’t, and stay that way for mobile.</p><h3>The Nav Bar</h3><p>Oh boy. The Nav Bar. Easy on desktop but a lot of iterations on mobile. The three main ones are below. The biggest difference in the final version is in the nice little bump at the end which makes it feel more dynamic and interactive. Whether this remains the final version or I go with a more native app feel of leaving the left side attached is yet to be determined.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/608/1*j8q_KH523clP5oiOyrDF6w.gif" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/608/1*q91_HvCi-Z8RFaEgT2nrqA.gif" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/608/1*jBFb3a4gO2Aj4tCLXcdQ9A.gif" /></figure><p>— UPDATE — I went with a native mobile navbar. <a href="https://budgeteer-prod.herokuapp.com/budgeteer">View the site</a> on your phone or make the window smaller on desktop to see how it looks.</p><h3>Broader Comments on Design</h3><p>In some of the images you might notice the font is a little thicker. I switched at some point from a 400 weight (normal) to a 300 weight (just a little thinner) and the difference was astounding. It created so much space I was amazed. Everything felt modern, cleaner and just looked better. Another idea I had was to make the color of the price in a transaction red or green based on if it was a payment or a return.</p><p>Further, using larger font sizes for the transaction name and a smaller one for the account name below it, focuses the users attention to the more important information. These and many other tricks I learned by spending time on other websites and apps just looking.</p><p>Taking a moment to notice just how an animation of a menu bar in an app looks, seeing where your eye is drawn to on a page and why, or by looking at how color is used to convey information gave me a lot of inspiration for what good design and UX entails.</p><p>Lastly, absolutely check out <a href="https://medium.muz.li/">https://medium.muz.li/</a> for awesome designs and trends. This was my first go to when I felt stuck or needed quick inspiration. The designers behind their submissions are seriously talented.</p><h3>Developing as a Progressive Web App</h3><p>One of the most interesting parts of this project has been working to build it as a Progressive Web App. This allows it to be installed and function like a native app. The primary benefits are push notifications, setting up offline functionality and cacheing resources locally to reduce network requests. This means that with one codebase I get a site for desktop and mobile as well as native app like functionality. PWAs are kind of weird though. I have had some problems cacheing resources from a CDN with a different domain, a CORS issue I know, properly configuring a service worker, setting up push notifications, and figuring out how to get the install pop up to appear automatically. Also testing it is always difficult since it caches everything but updates to the code may not always invalidate the now stale cache.</p><p>While React Native would have let me actually build a native app, this lets users choose exactly how they want to use this product whether it be infrequently on their computers, a few times a week on their phone’s browser, or as often they use other apps. The PWA version isn’t pushed as I’m still working out the kinks of cacheing and push notifications but I hope to finish this part next and then tackle final design issues followed by any functionality I’ve put off *ahem, sorting transactions *cough, by date *cough, ahem, clears throat.</p><h3>Conclusion</h3><p>I’ve learned a tremendous amount about design and building a product. From tooling, to API integrations this has been one of the most rewarding projects I’ve taken up. When bored at school or when I wanted to procrastinate HW I would work on this and working on it was so much fun.</p><p>As a final thought I’ll ask you all to please leave a comment if you think a light theme would be better than the current dark theme. This has been an ongoing debate with my sister.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=97dec9031006" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/building-budgeteer-lessons-and-experiences-97dec9031006">Building Budgeteer - Lessons and Experiences</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Customizing Tmux]]></title>
            <link>https://medium.com/hackernoon/customizing-tmux-b3d2a5050207?source=rss-fa4df7a7b495------2</link>
            <guid isPermaLink="false">https://medium.com/p/b3d2a5050207</guid>
            <category><![CDATA[tmux-customization]]></category>
            <category><![CDATA[status-line]]></category>
            <category><![CDATA[tmux]]></category>
            <dc:creator><![CDATA[Samuel Bernheim]]></dc:creator>
            <pubDate>Fri, 26 Jan 2018 05:18:40 GMT</pubDate>
            <atom:updated>2020-07-26T04:47:02.526Z</atom:updated>
            <content:encoded><![CDATA[<h3>The Definitive Guide to Customizing the Tmux Status Line</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*h12p00mTjaRZmwgyTxDPWg.png" /></figure><p>I assume you already have a .tmux.conf file set up that is already being used. If not first look up setting up .tmux.conf or something similar.</p><h3>Step 1: How to Change the Status Line</h3><blockquote>set -g status-left &lt;options&gt;</blockquote><blockquote>set -g status-right &lt;options&gt;</blockquote><p>Replace &lt;options&gt; with a string of all the options you want. Background color can be set using #[bg=colour*] where * is some number 0–255 for terminals with 256 color support. To change the foreground color (text color) it’s just #[fg=colour*] (Again replacing * with a number between 0 and 255).</p><p>To view all 255 colors at once see the comment of <a href="https://superuser.com/a/1104214">this stack overflow answer</a></p><p>One of the first things I wanted to do was to add the date and time in the status line. Simple enough right. Here is a complete list of options <a href="https://linux.die.net/man/3/strftime">https://linux.die.net/man/3/strftime</a> or for a shorter more readable list see part of my <a href="https://github.com/sbernheim4/dotfiles/blob/master/.tmux.conf#L59.">.tmux.conf</a></p><p>Adding %H:%M in the &lt;options&gt; string will show the current time in a 24 hour format without seconds (something like 15:38).</p><h3>Step 2: Tmux Specific Values</h3><p>Tmux has its own set of values that stand for different things. For example #H refers to the hostname of the computer you are currently on and #S to the index of the current session. For the complete list of options go <a href="https://linux.die.net/man/1/tmux">here</a> and search for this phrase “Character pair Replaced with”</p><p>— UPDATE 4/20/18 —</p><p>So I recently learned how to show or hide text in the status line given the current state (if the prefix has been pressed or if a window is zoomed etc). The <a href="http://netbsd.gw.com/cgi-bin/man-cgi/man?tmux+1+NetBSD-current">official man page of tmux</a> has a list of attributes which keep track of the state of the pane/window/session. Visit the page and search for “The following variables are available, where appropriate” and you will see a long list of options. How can these be used you ask, well for knowing if the prefix has been pressed or not I change the color of part of my status line with the following code.</p><blockquote>#{?client_prefix,#[bg=colour2],}</blockquote><p>If the prefix is active (as in I just pressed it), then it inserts the text after the first comma and otherwise inserts the text after the second comma which is nothing in this case. Here I’m inserting text to change the background color but any text can be inserted including… ICONS. For displaying an icon if the current window is zoomed in (which can be done with prefix + z) see the code below.</p><blockquote>#{?window_zoomed_flag, ,🔍}</blockquote><p>This will add a magnifying glass in the status line wherever this is placed in the line. (For icons, you might have to play around with adding additional spaces before and after the icon. I add an extra space here both before and after to keep it from looking cramped).</p><p>— END UPDATE —</p><h3>Step 3: Using Bash Commands to Display Cool Stuff</h3><p>The last key step is being able to display cool information using bash commands. This can include things like battery percentage, current song playing etc. To do this you first have to find a bash script or command that gives you the output you want. For example, I display the current battery percentage using the following command:</p><blockquote>pmset -g batt | grep [0-9][0-9]% | awk ‘NR==1{print$3}’ | cut -c 1–3</blockquote><p>Note: This only works for Macs since pmset is a mac specific terminal command.</p><p>I have a file stored on my computer called battery.sh. The file is two lines long. Line 1 is the bash shebang (<em>#!/bin/bash</em>) and line 2 is the command above. To show the battery in the status line, in my .tmux.conf in &lt;options&gt; I have</p><blockquote>#(path/to/battery.sh)</blockquote><p>(Pro Tip: adding an emoji like: ♥ before the # will display it as ♥ 64% in the status line which looks cooler than just 64%)</p><h3>Step 4: Plugins</h3><p>Alright so these aren’t really plugins so much as they are scripts that other people have already written. Check out <a href="https://github.com/jdxcode/tmux-spotify-info">https://github.com/jdxcode/tmux-spotify-info</a> for getting the current playing Spotify song, this again is mac only because the developer wrote this script in apple script. But the point is you can find scripts that other people already wrote for your environment and easily add them to your status line.</p><h3>Step 5: Customizing the Windows</h3><p>Hopefully you already know the difference between sessions, windows, and panes. if not, quickly read up on that.</p><p>Point is, beyond the left and right side of the status line you can also customize how the windows are displayed in the status with:</p><blockquote>set -g window-status-format &lt;options&gt;</blockquote><p>where &lt;options&gt; is the same configuration as it was way above. You also can customize the display for the current window you are on with:</p><blockquote>set -g window-status-current-format &lt;options&gt;</blockquote><p>See <a href="https://linux.die.net/man/1/tmux">this</a> site again and search “Character pair Replaced with” to view some specially reserved Tmux commands for windows. You can also then customize the separators that are used to show the difference between windows. Customizing the separators may require a patched font to display certain characters. A quick google search of patched fonts should get you some good results. For cool unicode character separators (still might require a patched font even though they’re unicode) check out <a href="http://www.amp-what.com/unicode/search/">this site</a>.</p><blockquote>hint: try searching stuff like left triangle</blockquote><p>Thanks for reading. <a href="https://github.com/sbernheim4/dotfiles/blob/251a30db0dbbd2953df35bfa0ef43e92ce15b752/tmux/.tmux.conf#L1">View my own .tmux.conf</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b3d2a5050207" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/customizing-tmux-b3d2a5050207">Customizing Tmux</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>