<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Springest Developer Blog</title>
    <description>At Springest you'll find thousands of courses and training programmes brought to you by hundreds of providers. Search, filter, read reviews by other people and request information directly! We are the development team.
</description>
    <link>http://devblog.springest.com/</link>
    <atom:link href="http://devblog.springest.com/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Thu, 19 Oct 2017 09:40:32 +0000</pubDate>
    <lastBuildDate>Thu, 19 Oct 2017 09:40:32 +0000</lastBuildDate>
    <generator>Jekyll v3.6.0</generator>
    
      <item>
        <title>Vacancy: senior frontend developer in Amsterdam</title>
        <description>&lt;p&gt;We want &lt;a href=&quot;https://www.springest.com/&quot;&gt;Springest&lt;/a&gt; to become the largest source for learning in the world. From books and e-learning courses to on-site trainings, we help our users discover, compare, and book everything they need to reach their personal and professional learning goals.&lt;/p&gt;

&lt;p&gt;We have a strong product focus in which everything revolves around the users of our &lt;a href=&quot;https://www.springest.nl/&quot;&gt;Dutch&lt;/a&gt;, &lt;a href=&quot;https://www.springest.de/&quot;&gt;German&lt;/a&gt;, &lt;a href=&quot;https://www.springest.be&quot;&gt;Belgian&lt;/a&gt;, &lt;a href=&quot;https://www.springest.co.uk/&quot;&gt;UK&lt;/a&gt;, and &lt;a href=&quot;https://www.springest.com/&quot;&gt;US&lt;/a&gt; sites. Next to that, more and more organisations are using our &lt;a href=&quot;https://business.springest.com/&quot;&gt;SaaS tools&lt;/a&gt; to stimulate and manage learning for their employees.&lt;/p&gt;

&lt;h3 id=&quot;working-at-springest&quot;&gt;Working at Springest&lt;/h3&gt;

&lt;p&gt;We are looking for a senior Frontend Developer to join our growing engineering team. We don’t have managers at Springest, but processes, and we feel that individuals taking responsibility is very important. At Springest, you will work in close collaboration with product owners, marketing, and sales colleagues. You are also a member of our development team where we discuss architecture, infrastructure, and keep a close watch on security and performance.&lt;/p&gt;

&lt;p&gt;Our main application runs on Ruby on Rails backed by Postgres, Redis and Memcached. Next to that we rely on Elasticsearch to power our search which is a big part of our product. We also have some smaller Go and Elixir projects in production.&lt;/p&gt;

&lt;p&gt;We are hosted on AWS and make heavy use of their offerings like RDS, CloudWatch, Elastic Beanstalk and EC2 Container Service.&lt;/p&gt;

&lt;p&gt;For our frontend stack, we work with Slim, Sass &amp;amp; CoffeeScript. Some libraries we use are jQuery, Bourbon/Neat and Backbone (but mainly we care about using the right tool for the job!).&lt;/p&gt;

&lt;p&gt;In our product development flow we often use tools like Balsamiq and Sketch for designing features. As a Frontend Developer, both your creative &amp;amp; technical input can help to refine the output.&lt;/p&gt;

&lt;p&gt;Next to our main application we build internal tools whenever necessary to help ourselves and our growing Learning Advisor team. It is extremely rewarding to see small development projects make a big impact for other Springeteers, which in turn can result in more of our visitors being helped of course!&lt;/p&gt;

&lt;p&gt;We also do a regular internal hackday where we drop everything and work on something completely different. We might give a new programming language a shot, try out an idea someone’s been toying with for a while or hack on some actual hardware. A lot of hackday ideas actually became super important for our business. Check this &lt;a href=&quot;http://devblog.springest.com/springest-june-hack-day-recap&quot;&gt;recap&lt;/a&gt; of a recent hackday to read more about why we organise them.&lt;/p&gt;

&lt;h3 id=&quot;your-new-colleagues&quot;&gt;Your New Colleagues&lt;/h3&gt;

&lt;p&gt;At Springest you will work with around 50 &lt;a href=&quot;http://over.springest.nl/&quot;&gt;colleagues&lt;/a&gt; (that’s not all of us and no we’re not always in full cowboy gear, this was our Western themed SpringFest!) who all are very skilled at what they do and all of them have a healthy dose of nerd skills that we really value. Our Product Owners also regularly ship code!&lt;/p&gt;

&lt;p&gt;Springeteers are a happy bunch and we often get together outside work to enjoy free time as well. Our office is a cosy place where anything goes and where we all take good care of together. If you’re not good at ping-pong yet, you have a good chance of becoming good here as well! 🏓.&lt;/p&gt;

&lt;p&gt;We are all active organisers and members of Meetups and other forms of knowledge exchange (learning is our hobby!) and we participate quite actively in the Amsterdam startup ecosystem. In addition to that we get a lot of attention for Springest being the poster boy of how &lt;a href=&quot;http://about.springest.com/holacracy/&quot;&gt;Holacracy&lt;/a&gt; and GTD can work for an organisation, which in turn is due to our organisational structure without managers and other unnecessary overhead.&lt;/p&gt;

&lt;h3 id=&quot;some-of-your-challenges&quot;&gt;Some of your challenges&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;helping to finish implementing our redesign (example &lt;a href=&quot;http://img.springe.st/redesign_before_after.png&quot;&gt;before-after&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;helping to craft the user experience for our big but inspiring challenge: building the ultimate product for 21st century Learning. We’re currently one of the best-known platforms where people book their classroom and e-learning courses. But in our quickly-evolving society, people continuously supplement their learning profile with personal &amp;amp; social learning experiences. Because you learn every day: from articles, books, meetings &amp;amp; inspiring conversations. For this, we need the best possible backend + frontend + AI force we can gather. We’re well on our way, but we can’t wait to strengthen our team with extra frontend power.&lt;/li&gt;
  &lt;li&gt;bringing our internal styleguides to the next level to help the whole Product Development team of full-stackers become full-stackier&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;what-we-expect-from-you&quot;&gt;What we expect from you&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;You work well in a team, and want to make the team greater than a sum of its parts.&lt;/li&gt;
  &lt;li&gt;Engagement in what it is that you are building and who you are building it for. We want you to feel involved and come up with ways to make Springest better.&lt;/li&gt;
  &lt;li&gt;The drive to improve yourself and our organisation and deliver high quality work.&lt;/li&gt;
  &lt;li&gt;You have a broad interest and deep knowledge. We are all about learning and sharing knowledge.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;what-you-get-from-us&quot;&gt;What You Get From Us&lt;/h3&gt;

&lt;p&gt;Apart from Springest being the coolest company you will ever work for, there are a few extras:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We are very remote friendly.&lt;/li&gt;
  &lt;li&gt;At least a € 1,000 education budget per year to spend on training, courses, and conferences.&lt;/li&gt;
  &lt;li&gt;Stock options after 2 years.&lt;/li&gt;
  &lt;li&gt;A cool workplace in the center of Amsterdam with height adjustable desks that you can sit and stand at, table tennis, a massage chair, and balcony with a barbecue.&lt;/li&gt;
  &lt;li&gt;A Macbook.&lt;/li&gt;
  &lt;li&gt;All software and hardware you need to do your job and have an optimal workflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Contact Rik Matena (&lt;a href=&quot;mailto:rik@springest.com&quot;&gt;rik@springest.com&lt;/a&gt;) for questions and applications. Please include links to your Github and LinkedIn profiles.&lt;/p&gt;

&lt;p&gt;Checkout these links to get to know more about us:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://devblog.springest.com&quot;&gt;Springest Developer Blog&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://about.springest.com/holacracy/&quot;&gt;Holacracy at Springest&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Springest&quot;&gt;Springest on Github&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.linkedin.com/company/springest&quot;&gt;Springest on LinkedIn&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 18 Oct 2017 00:00:00 +0000</pubDate>
        <link>http://devblog.springest.com/vacancy-senior-frontend-developer-in-amsterdam</link>
        <guid isPermaLink="true">http://devblog.springest.com/vacancy-senior-frontend-developer-in-amsterdam</guid>
        
        
        <category>jobs</category>
        
        <category>ruby</category>
        
        <category>team</category>
        
      </item>
    
      <item>
        <title>Hubot: Get notified in Slack on merge conflicts</title>
        <description>&lt;p&gt;This is the final out of three posts where I will explain how to hook up Hubot to Github’s API. The goal of these posts is to get notified in Slack when your pull request becomes unmergeable.&lt;/p&gt;

&lt;p&gt;Read &lt;a href=&quot;/hubot-part-1-get-it-running-locally-in-slack&quot;&gt;“Hubot: get it running locally in Slack”&lt;/a&gt; and &lt;a href=&quot;/hubot-part-2-listen-to-pull-request-events&quot;&gt;“Hubot: listen to Github’s pull request events”&lt;/a&gt; to get up to speed and get the code that this post builds upon.&lt;/p&gt;

&lt;h2 id=&quot;connect-to-githubs-api-to-check-the-merge-status-of-a-pull-request&quot;&gt;Connect to Github’s API to check the merge status of a pull request&lt;/h2&gt;
&lt;p&gt;Is your pull request event set up and your bot listening to your webhook? Great! Let’s do something with that data.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://developer.github.com/v3/activity/events/types/#pullrequestevent&quot;&gt;Here you can find an example&lt;/a&gt; of the data you’ll receive on pull request events.
As you can see there’s a &lt;code class=&quot;highlighter-rouge&quot;&gt;mergeable&lt;/code&gt; key. This is either &lt;code class=&quot;highlighter-rouge&quot;&gt;null&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;true&lt;/code&gt;, or &lt;code class=&quot;highlighter-rouge&quot;&gt;false&lt;/code&gt;.
You want to send a notification to Slack when the value is &lt;code class=&quot;highlighter-rouge&quot;&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hubot has built-in event listener methods: &lt;code class=&quot;highlighter-rouge&quot;&gt;emit&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;on&lt;/code&gt;. With these methods, you can create your own event that Hubot will listen to.
You define an event with &lt;code class=&quot;highlighter-rouge&quot;&gt;emit&lt;/code&gt; and you listen to it with &lt;code class=&quot;highlighter-rouge&quot;&gt;on&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can use these methods to handle errors. Wrap your data assignment in a &lt;code class=&quot;highlighter-rouge&quot;&gt;try/catch&lt;/code&gt; block and create an &lt;code class=&quot;highlighter-rouge&quot;&gt;error&lt;/code&gt; event if there is one:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;  &lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;router&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'/hubot/github/:room'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;room&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;room&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;body&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'error'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Then somewhere in your script you can add:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;  &lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'error'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;#process the error&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now that you have that sorted, you can set the values you need to work with. In this case: the Slack room name to post in and the pull request url, id and status. Add the following above the &lt;code class=&quot;highlighter-rouge&quot;&gt;catch error&lt;/code&gt; line:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;  &lt;span class=&quot;nx&quot;&gt;pull_request&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;room&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;room&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;pull_request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;url&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;pullId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;pull_request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;number&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;pullState&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;pull_request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;state&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The room is needed for the Slack notification. The &lt;code class=&quot;highlighter-rouge&quot;&gt;url&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;number&lt;/code&gt; are needed for the &lt;code class=&quot;highlighter-rouge&quot;&gt;GET&lt;/code&gt; request you’ll send to Github’s API in order to check the pull request’s &lt;code class=&quot;highlighter-rouge&quot;&gt;merge status&lt;/code&gt;. The pull request’s &lt;code class=&quot;highlighter-rouge&quot;&gt;state&lt;/code&gt; is needed to filter events on pull requests that are not open. Let’s do that first, because there’s no point in checking for a possible merge conflict in closed ones.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pull_request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;pullState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'open'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pull_request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;pullState&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'reopened'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# do stuff&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Tip:&lt;/strong&gt; throw a &lt;code class=&quot;highlighter-rouge&quot;&gt;console.log()&lt;/code&gt; in your code to see what data you have available and know what you’re working with.&lt;/p&gt;

&lt;p&gt;When someone pushes to a branch that has a pull request, the payload is sent immediately. The result is that the initial value of &lt;code class=&quot;highlighter-rouge&quot;&gt;mergeable&lt;/code&gt; in the data object is &lt;code class=&quot;highlighter-rouge&quot;&gt;unknown&lt;/code&gt;. The main reason is that it takes a few seconds until the merge status is known because the code has to be compared to the master branch.
In order to know if the pull request has a merge conflict, therefore unable to merge with the master branch, you have to check its merge status via the Github API.&lt;/p&gt;

&lt;p&gt;You can use Hubot’s &lt;code class=&quot;highlighter-rouge&quot;&gt;http&lt;/code&gt; call methods, that enable you to send &lt;code class=&quot;highlighter-rouge&quot;&gt;GET&lt;/code&gt; requests. In this case to the Github API.
Let’s create a method that takes care of this and add it at the top in &lt;code class=&quot;highlighter-rouge&quot;&gt;github.coffee&lt;/code&gt; , above the &lt;code class=&quot;highlighter-rouge&quot;&gt;export&lt;/code&gt; function:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;  &lt;span class=&quot;nx&quot;&gt;getRequest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/YourRepoName/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;repository&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/pulls/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;pullId&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;?access_token=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;token&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;headers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'Accept'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'application/rubyon'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The method accepts 3 arguments: the &lt;code class=&quot;highlighter-rouge&quot;&gt;robot&lt;/code&gt; instance, &lt;code class=&quot;highlighter-rouge&quot;&gt;data&lt;/code&gt; and a &lt;code class=&quot;highlighter-rouge&quot;&gt;callback&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Notice that the &lt;code class=&quot;highlighter-rouge&quot;&gt;url&lt;/code&gt; variable uses &lt;code class=&quot;highlighter-rouge&quot;&gt;data.repository&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;data.pullId&lt;/code&gt;. These come from the &lt;code class=&quot;highlighter-rouge&quot;&gt;pull_request&lt;/code&gt; object that you pass as the &lt;code class=&quot;highlighter-rouge&quot;&gt;data&lt;/code&gt; argument. There’s also an &lt;code class=&quot;highlighter-rouge&quot;&gt;access_token&lt;/code&gt; variable at the end. This is needed in case of a private repository. You can &lt;a href=&quot;https://github.com/settings/tokens/new&quot;&gt;set one here&lt;/a&gt;. If your repo is public, you  &lt;strong&gt;do not have to include the token&lt;/strong&gt; in the url.
What follows is the &lt;code class=&quot;highlighter-rouge&quot;&gt;GET&lt;/code&gt; request to that url.&lt;/p&gt;

&lt;p&gt;Create another method underneath called &lt;code class=&quot;highlighter-rouge&quot;&gt;checkMergeStatus&lt;/code&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;  &lt;span class=&quot;nx&quot;&gt;checkMergeStatus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;getRequest&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;JSON&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;parse&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;mergeStatus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;mergeable&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'error'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;error&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This method uses your &lt;code class=&quot;highlighter-rouge&quot;&gt;getRequest&lt;/code&gt; method and stores the &lt;code class=&quot;highlighter-rouge&quot;&gt;mergeable&lt;/code&gt; value. Now, if &lt;code class=&quot;highlighter-rouge&quot;&gt;mergeStatus&lt;/code&gt; is &lt;code class=&quot;highlighter-rouge&quot;&gt;false&lt;/code&gt;, you want to send a notification to your Slack channel. If it is &lt;code class=&quot;highlighter-rouge&quot;&gt;true&lt;/code&gt; you do not have to do anything. If it is still &lt;code class=&quot;highlighter-rouge&quot;&gt;unknown&lt;/code&gt;, you want to re-check. Add the following to the &lt;code class=&quot;highlighter-rouge&quot;&gt;checkMergeStatus&lt;/code&gt; method, inside the &lt;code class=&quot;highlighter-rouge&quot;&gt;try&lt;/code&gt; block:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mergeStatus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# send notification&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mergeStatus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'unknown'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;setTimeout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;checkMergeStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# do something?&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As you can see, if the second condition evaluates to &lt;code class=&quot;highlighter-rouge&quot;&gt;true&lt;/code&gt;, the &lt;code class=&quot;highlighter-rouge&quot;&gt;checkMergeStatus&lt;/code&gt; will keep calling itself with 1000ms (1sec) intervals, until it changes.&lt;/p&gt;

&lt;h2 id=&quot;send-a-notification-to-your-slack-channel-on-a-merge-conflict&quot;&gt;Send a notification to your Slack channel on a merge conflict&lt;/h2&gt;

&lt;p&gt;Here’s where the previously mentioned &lt;code class=&quot;highlighter-rouge&quot;&gt;emit&lt;/code&gt; method comes in handy again. You can create a &lt;code class=&quot;highlighter-rouge&quot;&gt;merge_conflict&lt;/code&gt; event for when the status is &lt;code class=&quot;highlighter-rouge&quot;&gt;false&lt;/code&gt;. Make sure it has the values you need in your Slack notification:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mergeStatus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'merge_conflict'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;room&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;room&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;pullTitle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;pullUrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;html_url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;na&quot;&gt;pullId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;number&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;All that you have to do now, is to get Hubot to take action as soon as the &lt;code class=&quot;highlighter-rouge&quot;&gt;merge_conflict&lt;/code&gt; event happens. You can let Hubot ‘listen’ to it by using the &lt;code class=&quot;highlighter-rouge&quot;&gt;on&lt;/code&gt; method. I moved the code for this to a separate script called &lt;code class=&quot;highlighter-rouge&quot;&gt;merge_conflict_notifier.coffee&lt;/code&gt; in the &lt;code class=&quot;highlighter-rouge&quot;&gt;scripts&lt;/code&gt; folder:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;  &lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'merge_conflict'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;merge_conflict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;room_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;adapter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;rtm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;dataStore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getChannelByName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;merge_conflict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;room&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;s&quot;&gt;&quot;text&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;:no_entry_sign: Merge conflict: &amp;lt;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;merge_conflict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;pullUrl&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;|#&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;merge_conflict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;merge_conflict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;pullTitle&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;gt; by &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;merge_conflict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

      &lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;messageRoom&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;room_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In order to post a message to a room via Slack’s API, you need to have the room’s id. &lt;code class=&quot;highlighter-rouge&quot;&gt;robot.adapter.client.rtm.dataStore.getChannelByName(&amp;lt;your room name&amp;gt;).id&lt;/code&gt; will get that for you.&lt;/p&gt;

&lt;p&gt;The message is formatted according to Slack’s requirements. &lt;a href=&quot;https://api.slack.com/docs/message-formatting&quot;&gt;More information&lt;/a&gt; about message formatting can be found on their website.&lt;/p&gt;

&lt;h2 id=&quot;keeping-track&quot;&gt;Keeping track&lt;/h2&gt;

&lt;p&gt;But what happens if someone is going to commit several fixes to their branch but the merge conflict does not get resolved right away?
You do not want to spam your Slack channel because that is super annoying. Therefore it would be a good idea to keep a list of the pull requests that have a merge conflict and remove them if they are resolved.&lt;/p&gt;

&lt;p&gt;At the top of the &lt;code class=&quot;highlighter-rouge&quot;&gt;github.coffee&lt;/code&gt;, add an empty array called &lt;code class=&quot;highlighter-rouge&quot;&gt;unmergeablePulls&lt;/code&gt;. Now you can add some code to keep track of them. Add the following above the &lt;code class=&quot;highlighter-rouge&quot;&gt;checkMergeStatus&lt;/code&gt; method:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;  &lt;span class=&quot;nx&quot;&gt;unmergeablePulls&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;addPullIdToList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pullId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pullId&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;unmergeablePulls&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;unmergeablePulls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;push&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pullId&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;true&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;removePullIdFromList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pullId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pullId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;null&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;indexOfPullId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;unmergeablePulls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;indexOf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pullId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;unmergeablePulls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;splice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;indexOfPullId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;pullId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Now you can use these methods in the &lt;code class=&quot;highlighter-rouge&quot;&gt;if/else&lt;/code&gt; block within the &lt;code class=&quot;highlighter-rouge&quot;&gt;checkMergeStatus&lt;/code&gt; method and add the &lt;code class=&quot;highlighter-rouge&quot;&gt;id&lt;/code&gt; of the pull request when there’s a merge conflict. When the &lt;code class=&quot;highlighter-rouge&quot;&gt;id&lt;/code&gt; has already been added, the notification is skipped. When there is no longer a merge conflict, the &lt;code class=&quot;highlighter-rouge&quot;&gt;id&lt;/code&gt; is removed from the list:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mergeStatus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;addPullIdToList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;pullId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;emit&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'merge_conflict'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;room&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;room&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;pullTitle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;pullUrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;html_url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;pullId&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;number&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mergeStatus&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'unknown'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;setTimeout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;checkMergeStatus&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;removePullIdFromList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;pullId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Hubot has a &lt;a href=&quot;https://hubot.github.com/docs/scripting/#persistence&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;robot.brain&lt;/code&gt;&lt;/a&gt; method that lets you store key-values to Redis. This could also be used to keep track of the id’s, but for now this is how I made it work.&lt;/p&gt;

&lt;p&gt;You can deploy your Hubot to Heroku. Hubot &lt;a href=&quot;https://github.com/github/hubot/blob/master/docs/deploying/heroku.md&quot;&gt;provides documentation&lt;/a&gt; on how to do that.&lt;/p&gt;

&lt;p&gt;I hope these 3 posts have helped you get an idea of how Hubot works, the advantages of a chatbot in general and how it can enhance your productivity/workflow.&lt;/p&gt;

&lt;p&gt;Happy hacking :)&lt;/p&gt;
</description>
        <pubDate>Mon, 21 Aug 2017 00:00:00 +0000</pubDate>
        <link>http://devblog.springest.com/hubot-part-3-notify-in-slack-on-a-merge-conflict</link>
        <guid isPermaLink="true">http://devblog.springest.com/hubot-part-3-notify-in-slack-on-a-merge-conflict</guid>
        
        
      </item>
    
      <item>
        <title>Efficient and effective working: a Product Tank meetup with special guest David Allen</title>
        <description>&lt;p&gt;We were proud to host the ProductTank AMS &lt;a href=&quot;https://www.meetup.com/ProductTank-AMS/events/240373056/&quot;&gt;June 22nd meetup&lt;/a&gt; about efficient and effective working at &lt;a href=&quot;https://www.springest.nl/&quot;&gt;Springest&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As a product-y person, you are usually required to communicate often and with many people. How do you make sure you still have time for “deep work”?&lt;/p&gt;

&lt;p&gt;None other than &lt;strong&gt;David Allen&lt;/strong&gt;, creator of the &lt;a href=&quot;http://gettingthingsdone.com&quot;&gt;Getting Things Done&lt;/a&gt; Time Management method, opened the evening. He made an entertaining plea for you to &lt;em&gt;not&lt;/em&gt; attempt to store all your new ideas in your brain. That thing is already busy enough dealing with the 50.000 conscious and subconscious decisions you make each day. “Your mind is a crappy office.” Tough to argue with.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/product_tank_meetup_springest_june_2017_david_allen.jpg&quot; alt=&quot;http://img.springe.st/product_tank_meetup_springest_june_2017_david_allen.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;David also gave the crowd a sense of how his company has been running on Holacracy –an &lt;a href=&quot;https://medium.com/@rubzie/why-were-adopting-holacracy-as-our-organisational-operating-system-at-springest-436c946c2b69&quot;&gt;operating system for organizations&lt;/a&gt;– for the past 6 years.&lt;/p&gt;

&lt;p&gt;This served as a nice bridge to &lt;strong&gt;Jaap-Willem Mol&lt;/strong&gt; from &lt;a href=&quot;http://www.vergaderverkalking.nl/&quot;&gt;VergaderVerkalking&lt;/a&gt; (“if you’re not Dutch and you manage to pronounce that, I’ll buy you a beer”). Jaap-Willem talked about the three basic principles that lie central to effective meetings: rules, roles and feedback. He had a good tip: find inspiration for more effective meetings in the &lt;a href=&quot;https://www.youtube.com/watch?v=wsIfEetMOBE&quot;&gt;Holacracy Tactical &amp;amp; Governance meeting at Springest&lt;/a&gt; video produced by VergaderVerkalking.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/product_tank_meetup_springest_june_2017_jaap_willem_mol.jpg&quot; alt=&quot;http://img.springe.st/product_tank_meetup_springest_june_2017_jaap_willem_mol.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dennis Paagman&lt;/strong&gt;, Product Owner &amp;amp; Developer at Springest, closed the round of presentations. He showed how GTD &amp;amp; Holacracy help us be productive and aligned on our goals, from the whole company down to each circle and individual role. Some concrete examples included quick peeks at our publicly visible &amp;amp; continuously evolving Holacratic structure at &lt;a href=&quot;http://roles.springest.com/&quot;&gt;roles.springest.com&lt;/a&gt;, and an example of our actual current OKRs (&lt;a href=&quot;https://medium.com/@rubzie/using-okrs-for-holacracy-strategy-and-targets-f97cec8be10d&quot;&gt;Objectives and Key Results&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/product_tank_meetup_springest_june_2017_dennis_paagman.jpg&quot; alt=&quot;http://img.springe.st/product_tank_meetup_springest_june_2017_dennis_paagman.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;ProductTank organizer Iris van de Kieft closed the event by hosting a nice panel session with the three speakers and an engaged audience.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/product_tank_meetup_springest_june_2017_panel.jpg&quot; alt=&quot;http://img.springe.st/product_tank_meetup_springest_june_2017_panel.jpg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Thanks to the audience, the speakers and ProductTank. We love hosting meetups at our Springest HQ (with a &lt;a href=&quot;https://www.instagram.com/p/BRWfP6-hyqR/?taken-by=springestnl&quot;&gt;view over the IJ river&lt;/a&gt;!). For example, we’re actively involved in the Amsterdam &amp;amp; Netherlands communities for Product, &lt;a href=&quot;https://www.meetup.com/Holacracy-Netherlands/&quot;&gt;Holacracy&lt;/a&gt; and &lt;a href=&quot;http://amsrb.org/&quot;&gt;Ruby&lt;/a&gt;. So, &lt;a href=&quot;mailto:dennis@springest.com&quot;&gt;reach out to Dennis&lt;/a&gt; if you’re interested! We’re also &lt;a href=&quot;http://devblog.springest.com/jobs/&quot;&gt;hiring&lt;/a&gt; backend/frontend/full-stack developers, spread the word!&lt;/p&gt;

&lt;p&gt;Photo’s taken by &lt;strong&gt;Mark Mulder&lt;/strong&gt;, Developer at Springest.&lt;/p&gt;
</description>
        <pubDate>Fri, 23 Jun 2017 00:00:00 +0000</pubDate>
        <link>http://devblog.springest.com/efficient-and-effective-working-product-tank-meetup-with-special-guest-david-allen</link>
        <guid isPermaLink="true">http://devblog.springest.com/efficient-and-effective-working-product-tank-meetup-with-special-guest-david-allen</guid>
        
        
      </item>
    
      <item>
        <title>Hubot: listen to Github's pull request events</title>
        <description>&lt;p&gt;This is the second out of three posts where I will explain how to hook up Hubot to Github’s API. The goal of these posts is to get notified in Slack when your pull request becomes unmergeable.&lt;/p&gt;

&lt;p&gt;If you have never worked with Hubot in Slack before, read the first post: &lt;a href=&quot;/hubot-part-1-get-it-running-locally-in-slack&quot;&gt;“Hubot: get it running locally in Slack”&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;githubs-api&quot;&gt;Github’s API&lt;/h2&gt;
&lt;p&gt;Github offers an extensive API to connect to your repositories and automate your daily development workflow. &lt;a href=&quot;https://developer.github.com/v3/&quot;&gt;Their documentation&lt;/a&gt; is very detailed and extensive and they have excellent &lt;a href=&quot;https://developer.github.com/guides/&quot;&gt;guides&lt;/a&gt; to help you get started. For the goal of this post, I’ll focus on Pull Request events.&lt;/p&gt;

&lt;h3 id=&quot;enable-githubs-pull-request-events&quot;&gt;Enable Github’s Pull Request events&lt;/h3&gt;
&lt;p&gt;As said above, the goal of this project is to get notified in Slack when a merge-conflict occurs. Luckily, Github supports &lt;em&gt;webhooks&lt;/em&gt;. That means you can get them to notify you whenever an &lt;em&gt;event&lt;/em&gt;, like a push or a commit, happens, which in turn enables you to check the status of your pull request. Read more about all the events at &lt;a href=&quot;https://developer.github.com/webhooks/&quot;&gt;https://developer.github.com/webhooks/&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;send-events-to-a-webhook&quot;&gt;Send events to a webhook.&lt;/h3&gt;
&lt;p&gt;When an event happens on a pull request, Github gathers all relevant data and sends that event (a payload) to the URL of your choosing. This is called a webhook.&lt;/p&gt;

&lt;p&gt;To set this up, go to the settings page of your repository. Select &lt;code class=&quot;highlighter-rouge&quot;&gt;Webhooks&lt;/code&gt;. Then click the &lt;code class=&quot;highlighter-rouge&quot;&gt;add webhook&lt;/code&gt; button.
You have to provide a so called payload URL which is the webhook URL. Since you are running everything locally, you do not yet have a public URL.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/Webhooks__Services_17-03-24-xqxeq.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;set-up-ngrok&quot;&gt;Set up ngrok&lt;/h3&gt;
&lt;p&gt;Ngrok is a tool that enables you to expose your local webserver to the internet. &lt;a href=&quot;https://ngrok.com/download&quot;&gt;Download it here&lt;/a&gt;.
Unzip it from your bot’s directory. This will install a small executable in your bot’s root directory:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;unzip /path/to/ngrok.zip&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Run it on port 8080, which is Hubot’s default port:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./ngrok http 8080&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You should see something like this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  ngrok by @inconshreveable

  Tunnel Status                 online
  Version                       2.1.3
  Region                        United States &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;us&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  Web Interface                 http://127.0.0.1:4040
  Forwarding                    http://a3b9e4e6.ngrok.io -&amp;gt; localhost:8080
  Forwarding                    https://a3b9e4e6.ngrok.io -&amp;gt; localhost:8080

  Connections                   ttl     opn     rt1     rt5     p50     p90
                                0       0       0.00    0.00    0.00    0.00&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You can use the &lt;code class=&quot;highlighter-rouge&quot;&gt;http://&lt;/code&gt; URL for now, you can open that in your browser to see a nifty web interface.&lt;/p&gt;

&lt;h3 id=&quot;set-up-the-webhook&quot;&gt;Set up the webhook.&lt;/h3&gt;

&lt;p&gt;Copy and paste the entire URL, ending with &lt;code class=&quot;highlighter-rouge&quot;&gt;.io&lt;/code&gt; into the Payload URL field of the form.
Append &lt;code class=&quot;highlighter-rouge&quot;&gt;/hubot/github/general&lt;/code&gt; to the URL. The &lt;code class=&quot;highlighter-rouge&quot;&gt;/hubot&lt;/code&gt; part is important because &lt;a href=&quot;https://github.com/github/hubot/blob/master/docs/scripting.md#http-listener&quot;&gt;it is a requirement&lt;/a&gt;. The next part, in this example &lt;code class=&quot;highlighter-rouge&quot;&gt;/github&lt;/code&gt;, can be anything you like and &lt;code class=&quot;highlighter-rouge&quot;&gt;/general&lt;/code&gt; is the room’s name in Slack (which you are free to change as well).&lt;/p&gt;

&lt;p&gt;Make sure the content type is set to &lt;code class=&quot;highlighter-rouge&quot;&gt;application/json&lt;/code&gt; and skip the secret field for now. The secret is used to protect your endpoint so we know that messages are coming from Github, but for brevity we’ll leave this up to you, the reader.&lt;/p&gt;

&lt;p&gt;Select &lt;code class=&quot;highlighter-rouge&quot;&gt;Let me select individual events&lt;/code&gt;. In this case you only want to receive &lt;code class=&quot;highlighter-rouge&quot;&gt;pull request&lt;/code&gt; events.
Click &lt;code class=&quot;highlighter-rouge&quot;&gt;Add webhook&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Every time you restart ngrok, you’ll get a new URL. Make sure to update it in your Github repo settings.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/Webhook_-_http0e21b22b.ngrok.iohubotpayloadgeneral_16-11-18-bclot.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;test-the-webhook&quot;&gt;Test the webhook.&lt;/h3&gt;

&lt;p&gt;You will see a list of recent payload deliveries underneath your webhook form right after you save it.
There is also a red error mark next to the first delivery.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/Webhook_-_http9db17a4c.ngrok.iohubotpayloadgeneral_16-11-18-qesyk.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Now check ngrok in your console. You should see this:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  HTTP Requests
  &lt;span class=&quot;nt&quot;&gt;-------------&lt;/span&gt;

  POST /                         404 Not Found&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This means 2 things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The request was received by your local server. Yay!&lt;/li&gt;
  &lt;li&gt;The endpoint it’s routed to, doesn’t exist yet.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you do not have your bot running, you’ll see a 502 Bad Gateway error.&lt;/p&gt;

&lt;h3 id=&quot;make-hubot-listen-to-the-webhook&quot;&gt;Make Hubot listen to the webhook&lt;/h3&gt;

&lt;p&gt;In order to get rid of the 404 error, you have to setup an endpoint in your bot that will execute your code when a payload is received. In your favorite editor (I use Vim), create a new coffeescript file called &lt;code class=&quot;highlighter-rouge&quot;&gt;github.coffee&lt;/code&gt; inside your bot’s &lt;code class=&quot;highlighter-rouge&quot;&gt;scripts&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;First things first, export a function:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;  &lt;span class=&quot;nx&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;exports&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is a requirement and part of the anatomy of a Hubot script. The robot parameter is an instance of your bot.&lt;/p&gt;

&lt;p&gt;Create the endpoint:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;  &lt;span class=&quot;nx&quot;&gt;robot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;router&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'/hubot/github/:room'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;room&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;params&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;room&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;req&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;body&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;== Pull request data received: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;pull_request&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;robot.router&lt;/code&gt; is a built-in Hubot method. By adding &lt;code class=&quot;highlighter-rouge&quot;&gt;.post&lt;/code&gt; you create a route for POST requests. Naturally, if you want to create a route for GET request, you simply call &lt;code class=&quot;highlighter-rouge&quot;&gt;.get&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;The string &lt;code class=&quot;highlighter-rouge&quot;&gt;'/hubot/github/:room'&lt;/code&gt; is the webhook URL you set up in your Github repo, where &lt;code class=&quot;highlighter-rouge&quot;&gt;:room&lt;/code&gt; is a variable you have to define.
The callback, &lt;code class=&quot;highlighter-rouge&quot;&gt;(req, res)&lt;/code&gt; is called when a POST request comes in. Save the room name and the JSON object that contains all data in 2 variables: &lt;code class=&quot;highlighter-rouge&quot;&gt;room&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;data&lt;/code&gt;. Then, to check that it works, the pull request’s number is printed out and will show up in your terminal.&lt;/p&gt;

&lt;p&gt;Finally, you want to tell Github you’ve successfully processed the request. You can do that by sending a success response:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;  &lt;span class=&quot;nx&quot;&gt;res&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;send&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'OK'&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;That’s it! Your Hubot is now listening to pull request events from Github. You can now move on to &lt;a href=&quot;/hubot-part-3-notify-in-slack-on-a-merge-conflict&quot;&gt;do stuff with the data you receive&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Wed, 29 Mar 2017 00:00:00 +0000</pubDate>
        <link>http://devblog.springest.com/hubot-part-2-listen-to-pull-request-events</link>
        <guid isPermaLink="true">http://devblog.springest.com/hubot-part-2-listen-to-pull-request-events</guid>
        
        
      </item>
    
      <item>
        <title>Hubot: get it running locally in Slack</title>
        <description>&lt;p&gt;This is the first out of three posts where I will explain how we hooked up Hubot to Github’s API. The goal of this is to get notified in Slack when your pull request becomes unmergeable.&lt;/p&gt;

&lt;h2 id=&quot;a-springest-hackday-idea&quot;&gt;A Springest Hackday idea&lt;/h2&gt;
&lt;p&gt;At Springest we hold &lt;a href=&quot;/springest-june-hack-day-recap&quot;&gt;regular hackdays&lt;/a&gt;. The purpose of these days is to learn, have fun together and work on something that is related to Springest, but isn’t part of our daily work-routine. It can be anything from  hanging a swing in the office to building the company’s internal Facebook app called Sputr.&lt;/p&gt;

&lt;p&gt;Starting the day, we all share our ideas during stand-up and we get to work. Either solo or in a team.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;‘Get slack notifications when a pull request becomes unmergeable’&lt;/em&gt; was one of the ideas on our hackday-list that I thought was interesting to work on.&lt;/p&gt;

&lt;p&gt;In this post, I’ll explain how to run Hubot locally in Slack, so you can test-drive your code.&lt;/p&gt;

&lt;h2 id=&quot;so-what-is-hubot-anyway&quot;&gt;So what is Hubot, anyway?&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://hubot.github.com/&quot;&gt;Hubot&lt;/a&gt; is a chat bot by Github. It is open source and written in CoffeeScript and Node.js. You can automate processes with Hubot through scripts, or just add some flavor to your team’s culture. At Springest, our bot is called ‘Ingrid’. She notifies us about all sorts of things that happen on the Springest website and we can tell her to do stuff for us, like deploying, share support ticket info or give someone karma. All by messaging in Slack.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://slack.com/&quot;&gt;Slack&lt;/a&gt; is a messaging app for teams. Messaging is categorized in channels that everyone is free to follow or not. It enables us to easily communicate with each other.&lt;/p&gt;

&lt;p&gt;To install Hubot, you need to follow these instructions:&lt;/p&gt;

&lt;h3 id=&quot;nodejs-and-npm&quot;&gt;Node.js and npm&lt;/h3&gt;

&lt;p&gt;Open your console and check if you have installed node.js and npm:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;node &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# should output node.js version&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# should output npm version&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Node.js is a server-side JavaScript environment and npm is a package manager for node programs.&lt;/p&gt;

&lt;p&gt;If nothing exists, install node.js by &lt;a href=&quot;https://nodejs.org/en/&quot;&gt;downloading it here&lt;/a&gt;. This will also install npm.&lt;/p&gt;

&lt;p&gt;Make sure you have the latest version of npm installed, by running:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm install npm &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If you have never installed hubot before, you need to install its generator. Otherwise you can skip this step.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm install &lt;span class=&quot;nt&quot;&gt;-g&lt;/span&gt; yo generator-hubot&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;lets-run-it&quot;&gt;Let’s run it!&lt;/h2&gt;

&lt;p&gt;Now that you have the generator, add a directory for your bot and create it.
I asked my six-year-old son what name he would give a robot, if he would have one. He said ‘Stone’ because robots are hard like stone. So I called it Stone for this example, no questions asked.&lt;/p&gt;

&lt;p&gt;Create your bot (just hit ‘enter’ for all questions) :&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;mkdir stone
  &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;stone
  &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;yo hubot

  ? Owner irisbune &amp;lt;xxxxxxx@gmail.com&amp;gt;
  ? Bot name stone
  ? Description A simple helpful robot &lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;your Company
  ? Bot adapter campfire
     create bin/hubot
     create bin/hubot.cmd
     create Procfile
     create README.md
     create external-scripts.json
     create hubot-scripts.json
     create .gitignore
     create package.json
     create scripts/example.coffee
     create .editorconfig
                       _____________________________
   _____              /                             &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
   &lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;   &lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;            |   Self-replication process   |
   |    |    _____    |          complete...         |
   |__&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;|   /_____&lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;  &lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;    Good luck with that.    /
     |//+  |[^_/&lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;|   /----------------------------
    |   | _|___@@__|__
    +&lt;span class=&quot;o&quot;&gt;===&lt;/span&gt;+/  ///     &lt;span class=&quot;se&quot;&gt;\_\&lt;/span&gt;
     | |_&lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;/// HUBOT/&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;
     |___/&lt;span class=&quot;se&quot;&gt;\/&lt;/span&gt;/      /  &lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;
           &lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;     /   +---+
            &lt;span class=&quot;se&quot;&gt;\_&lt;/span&gt;___/    |   |
             | //|    +&lt;span class=&quot;o&quot;&gt;===&lt;/span&gt;+
              &lt;span class=&quot;se&quot;&gt;\/&lt;/span&gt;/      |xx|

  loadDep:mime-db → request ▄ ╢████████████&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Check if it is alive and kicking by running:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;bin/hubot&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If all went well, you should now be able to chat with your bot in the console. Type ‘your-bot-name the rules’ and see if you get a reply.&lt;/p&gt;

&lt;h2 id=&quot;move-from-console-to-slack&quot;&gt;Move from console to Slack&lt;/h2&gt;

&lt;p&gt;Create an account on Slack if you do not have one yet. I’ve created my own personal channel, to test this bot before implementing the code in Ingrid, our company bot. Once you have your own channel set up, go to &lt;code class=&quot;highlighter-rouge&quot;&gt;https:// yourslackchannel .slack.com/apps/A0F7XDU93-hubot&lt;/code&gt; and click on the green button, ‘Add Configuration’.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/Hubot__irisbune_Slack_17-03-15-sjyrx.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Add your bot’s username and hit ‘Add Hubot Configuration’.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/Hubot__irisbune_Slack_17-03-15-hesy7.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Keep this page open, because you need to copy the environment variable in order to run your bot in Slack.&lt;/p&gt;

&lt;h3 id=&quot;slack-adapter&quot;&gt;Slack adapter&lt;/h3&gt;

&lt;p&gt;Now that you’ve configured your bot in Slack, and got your token, you have to install the Slack adapter and your bot is setup to run locally:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  &lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;npm install hubot-slack &lt;span class=&quot;nt&quot;&gt;--save&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Open Slack on your computer and restart your bot with Slack’s environment variable, followed by a call to hubot’s scripts, plus the adapter flag:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot; data-lang=&quot;bash&quot;&gt;  &lt;span class=&quot;nv&quot;&gt;$ HUBOT_SLACK_TOKEN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;your-hubot-api-token ./bin/hubot &lt;span class=&quot;nt&quot;&gt;--adapter&lt;/span&gt; slack&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Invite your bot to your #random Slack channel (&lt;code class=&quot;highlighter-rouge&quot;&gt;/invite @botname&lt;/code&gt;) and test it out by typing &lt;code class=&quot;highlighter-rouge&quot;&gt;@botname pug me&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/51C662EA-5FDC-46F0-B6F5-D5216B80FA28.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! You are now ready to &lt;a href=&quot;/hubot-part-2-listen-to-pull-request-events&quot;&gt;hook up Github’s pull request events&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Wed, 15 Mar 2017 00:00:00 +0000</pubDate>
        <link>http://devblog.springest.com/hubot-part-1-get-it-running-locally-in-slack</link>
        <guid isPermaLink="true">http://devblog.springest.com/hubot-part-1-get-it-running-locally-in-slack</guid>
        
        
      </item>
    
      <item>
        <title>Vim: Buffers, Tabs, Windows &amp; Modes</title>
        <description>&lt;p&gt;This is the third and last post in this Vim series. You might be interested in reading through my previous posts before you continue reading (especially if you are a real beginner):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://devblog.springest.com/vim-5-tips-to-survive-your-first-week&quot;&gt;5 Tips to Survive Your First Week&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://devblog.springest.com/vim-motions-and-command-language&quot;&gt;Motions &amp;amp; Command Language&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this post we will talk about buffers, tabs, windows and the different modes that you can find in Vim. Let’s jump in!&lt;/p&gt;

&lt;h2 id=&quot;buffers-windows-and-tabs&quot;&gt;Buffers, windows and tabs&lt;/h2&gt;

&lt;p&gt;If you are moving to Vim from another editor like SublimeText or Atom, you are used to working with tabs in a certain way. Specifically, a tab represents an open file, and as soon as you close it, it goes away. A web browser follows this same principle as well.&lt;/p&gt;

&lt;p&gt;Vim has a system for tabs too, but it works in a completely different way from what you are used to. I got quite confused by this when I first started with Vim, so don’t panic if that’s the case for you as well. You are not alone!&lt;/p&gt;

&lt;p&gt;In Vim, there are three levels of view abstraction: &lt;strong&gt;buffers, windows, and tabs&lt;/strong&gt;. Let’s look at each of them from the ground up, since it’s the best way to understand the differences in concept and learn how to use them properly.&lt;/p&gt;

&lt;h3 id=&quot;buffers&quot;&gt;Buffers&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;buffer&lt;/strong&gt; in Vim is an &lt;em&gt;open instance of a file&lt;/em&gt;. This means that the file may not be visible on the current screen, but it is saved somewhere in memory.&lt;/p&gt;

&lt;p&gt;Whenever you open a file in Vim, that file gets put into a buffer that will remain in memory until you explicitly delete it with a call to &lt;code class=&quot;highlighter-rouge&quot;&gt;:quit&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;:bdelete&lt;/code&gt;. You can list all buffers currently open within a Vim session by typing &lt;code class=&quot;highlighter-rouge&quot;&gt;:ls&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let’s look at some other useful commands:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;zz&lt;/code&gt; - Center the current line within the window&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;zt&lt;/code&gt; - Bring the current line to the top of the window&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;zb&lt;/code&gt; - Bring the current line to the bottom of the window&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although files in Vim’s buffer may not be visible at all times, its functionality is analogous to how you use tabs in familiar text editors.&lt;/p&gt;

&lt;h3 id=&quot;windows&quot;&gt;Windows&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;window&lt;/strong&gt; in Vim is a &lt;em&gt;viewport onto a single buffer&lt;/em&gt;. You can open a new window with &lt;code class=&quot;highlighter-rouge&quot;&gt;:split&lt;/code&gt; or &lt;code class=&quot;highlighter-rouge&quot;&gt;:vsplit&lt;/code&gt;, including a filename in the call. This opens your file as a new buffer (again, similar to a tab in a traditional editor) and opens a new window to display it.&lt;/p&gt;

&lt;p&gt;This is what a Vim session with multiple windows open (horizontally and vertically) looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://img.springe.st/20160720-sywxd.png&quot;&gt;&lt;img src=&quot;http://img.springe.st/20160720-sywxd.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Windows are also referred to as &lt;em&gt;Splits&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let’s look at some useful commands:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;:new [filename]&lt;/code&gt; - Open a new window &lt;strong&gt;above&lt;/strong&gt; the current window&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;:vnew [filename]&lt;/code&gt; - Open a new window &lt;strong&gt;beside&lt;/strong&gt; the current window&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;:split &amp;lt;filename&amp;gt;&lt;/code&gt; - Edit the specified file in new window &lt;strong&gt;above&lt;/strong&gt; the current window&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;:vsplit &amp;lt;filename&amp;gt;&lt;/code&gt; - Edit the specified file in a new window &lt;strong&gt;beside&lt;/strong&gt; the current window&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;Ctrl-w&amp;gt;h,j,k,l&lt;/code&gt; - Navigate to the window in the given direction&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;tabs&quot;&gt;Tabs&lt;/h3&gt;

&lt;p&gt;Finally, a &lt;strong&gt;tab&lt;/strong&gt; in Vim is a &lt;em&gt;collection of one or more windows&lt;/em&gt;. This allows you to group windows in a useful way.&lt;/p&gt;

&lt;p&gt;Let’s look at some related commands:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;:tabnew&lt;/code&gt; - Open a new tab&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;:tabedit &amp;lt;filename&amp;gt;&lt;/code&gt; - Edit the file with the provided name in a new tab&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;gt&lt;/code&gt; - Go to next tab open&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;gT&lt;/code&gt; - Go to previous tab&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;Ctrl-w&amp;gt;T&lt;/code&gt; - Break the current window out to a new tab&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;modes&quot;&gt;Modes&lt;/h2&gt;

&lt;p&gt;Enough about navigation for now. Let’s move on and talk about the different &lt;strong&gt;modes&lt;/strong&gt; that you will find in Vim’s world!&lt;/p&gt;

&lt;p&gt;Vim is a “modal” editor, which means it has various modes that change its behavior in response to your key presses. This modal nature is at the core of Vim’s power, so it’s very important to understand it in order to use Vim in the most efficient way.&lt;/p&gt;

&lt;p&gt;Vim has three different modes: &lt;strong&gt;insert, normal&lt;/strong&gt; and &lt;strong&gt;visual&lt;/strong&gt;. Let’s now look at them one at a time.&lt;/p&gt;

&lt;h3 id=&quot;insert-mode&quot;&gt;Insert Mode&lt;/h3&gt;

&lt;p&gt;When you use other editors like SublimeText or Atom, you’re always working in insert mode. In this mode, characters appear immediately in the buffer as you type them. You can enter insert mode by pressing &lt;code class=&quot;highlighter-rouge&quot;&gt;i&lt;/code&gt; in normal mode.&lt;/p&gt;

&lt;p&gt;However, Vim prioritizes moving through a file and making targeted edits, which are done in normal mode.&lt;/p&gt;

&lt;h3 id=&quot;normal-mode&quot;&gt;Normal Mode&lt;/h3&gt;

&lt;p&gt;Normal mode is the &lt;strong&gt;default mode&lt;/strong&gt; Vim starts in. You are expected to be in this mode the most of your time, while using all motions and operations that we saw in the &lt;a href=&quot;http://devblog.springest.com/vim-motions-and-command-language&quot;&gt;previous post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This fits with the idea that we, as developers, spend the majority of our time moving and editing  within a document, rather than simply adding long blocks of text.&lt;/p&gt;

&lt;h3 id=&quot;visual-mode&quot;&gt;Visual Mode&lt;/h3&gt;

&lt;p&gt;In more familiar text editors, a block of text can be selected by clicking the mouse and dragging over a number of lines or characters. Vim introduces &lt;em&gt;Visual model&lt;/em&gt;, which allows you to reuse all motion commands and operators that there are to manipulate blocks of text.&lt;/p&gt;

&lt;p&gt;Enter Visual mode by pressing &lt;code class=&quot;highlighter-rouge&quot;&gt;v&lt;/code&gt; in normal mode. Move the cursor using all the normal motions, and Vim will highlight from where you started to where you move the cursor. You can use a number of keys such as &lt;code class=&quot;highlighter-rouge&quot;&gt;d&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;x&lt;/code&gt;, or &lt;code class=&quot;highlighter-rouge&quot;&gt;c&lt;/code&gt; to operate on the visual selection, similar to how these keys would operate in normal mode.&lt;/p&gt;

&lt;p&gt;Sometimes you will need to operate on entire lines. &lt;em&gt;Visual Line Mode&lt;/em&gt; turns out to be very useful in these cases, and it can be started by pressing &lt;code class=&quot;highlighter-rouge&quot;&gt;V&lt;/code&gt; from normal mode.&lt;/p&gt;

&lt;p&gt;But what about selecting a column of text? Vim’s got you covered too, enter &lt;em&gt;Visual Block Mode&lt;/em&gt; by pressing &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;Ctrl-v&amp;gt;&lt;/code&gt; from normal mode. Here is a list of the common visual block operations and their mapping:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;d&lt;/code&gt;, or &lt;code class=&quot;highlighter-rouge&quot;&gt;x&lt;/code&gt; - Delete the visual block selection&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;c&lt;/code&gt; - Change the visual block selection&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;r&lt;/code&gt; - Replace all characters in the block with the next character you type&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;I&lt;/code&gt; - Insert text before the block&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;A&lt;/code&gt; - Insert text after the block&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Be aware that when you change or add any new text, Vim will only show the change happening in the first line of the block. After you complete the change/insertion and hit &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;esc&amp;gt;&lt;/code&gt;, it will replicate to all lines.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;stay-normal&quot;&gt;Stay Normal&lt;/h2&gt;

&lt;p&gt;If you only take one thing away from reading this blog post, let it be this: &lt;strong&gt;Normal mode is your best friend!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Avoid staying in insert mode for extended periods of time. And also, don’t move along the file while in insert mode. It might be difficult in the beginning, but once you get used to it, you will see how much faster you become. ;)&lt;/p&gt;

&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;

&lt;p&gt;This series is a quick introduction to the infinite world of Vim. It is a tool help you get started, but remember that learning Vim is a nonstop continuous process. Stay on it, make it part of your daily life, and every time that you find yourself doing something in a very inefficient way, you know what to do… Go online, look for a friend and ask for help!&lt;/p&gt;
</description>
        <pubDate>Fri, 29 Jul 2016 00:00:00 +0000</pubDate>
        <link>http://devblog.springest.com/vim-buffers-tabs-windows-and-modes</link>
        <guid isPermaLink="true">http://devblog.springest.com/vim-buffers-tabs-windows-and-modes</guid>
        
        
      </item>
    
      <item>
        <title>Vim: Motions &amp; Command Language</title>
        <description>&lt;p&gt;This is the second post in the vim series. You might be interested in reading through my previous post before you continue reading (especially if you are a real beginner):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://devblog.springest.com/vim-5-tips-to-survive-your-first-week&quot;&gt;5 Tips to Survive Your First Week&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this post we will dive into some subjects that you need to master when working with Vim. The very first one is motions, also known as &lt;em&gt;how to get your cursor where you want it&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;motions-and-moving&quot;&gt;Motions and Moving&lt;/h2&gt;

&lt;p&gt;Developers spend a lot of time navigating files and positioning the cursor where needed, and not much time typing new code. It comes as no surprise that Vim is optimized for this situation and has many ways to efficiently move the cursor where you want it.&lt;/p&gt;

&lt;p&gt;Motions are defined as the commands you use to move around Vim.&lt;/p&gt;

&lt;h3 id=&quot;moving-within-a-line&quot;&gt;Moving within a line&lt;/h3&gt;

&lt;p&gt;These are the most important key bindings for moving within a line:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;h&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;l&lt;/code&gt; - move left/right by character&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;w&lt;/code&gt; - move forward one (&lt;strong&gt;w&lt;/strong&gt;)ord&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;b&lt;/code&gt; - move (&lt;strong&gt;b&lt;/strong&gt;)ackward one word&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;e&lt;/code&gt; - move forward to the (&lt;strong&gt;e&lt;/strong&gt;)nd of a word&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before we move forward, let me give you a pro tip: Whenever you find yourself repeating or holding down a motion key to move around, take a second to consider if there is a better way of doing what you are trying to accomplish. Most probably there is one ;-)&lt;/p&gt;

&lt;h3 id=&quot;jumping-within-a-line&quot;&gt;Jumping within a line&lt;/h3&gt;

&lt;p&gt;But what if you want to move to a specific character within a line? Try any of these:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;f&amp;lt;char&amp;gt;&lt;/code&gt; - (&lt;strong&gt;f&lt;/strong&gt;)ind a character forward in a line and move to it&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;T&amp;lt;char&amp;gt;&lt;/code&gt; - find a character backward in a line and move un(&lt;strong&gt;t&lt;/strong&gt;)il it&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;t&amp;lt;char&amp;gt;&lt;/code&gt; - find a character forward in a line and move un(&lt;strong&gt;t&lt;/strong&gt;)il it (one character before)&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;F&amp;lt;char&amp;gt;&lt;/code&gt; - (&lt;strong&gt;f&lt;/strong&gt;)ind a character backward in a line and move to it&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;$&lt;/code&gt; - go to the end of the line&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;0&lt;/code&gt; - go to the beginning of the line&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;moving-between-lines&quot;&gt;Moving between lines&lt;/h3&gt;

&lt;p&gt;I know, I know… most of the files you work with contain more than one line! So here it is: How to move between different lines:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;j&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;k&lt;/code&gt; - move up/down one line&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;H&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;M&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;L&lt;/code&gt; - move (&lt;strong&gt;H&lt;/strong&gt;)igh, (&lt;strong&gt;M&lt;/strong&gt;)iddle, or (&lt;strong&gt;L&lt;/strong&gt;)ow within the viewport&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;Ctrl-u&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;Ctrl-d&lt;/code&gt; - move (&lt;strong&gt;u&lt;/strong&gt;)p or (&lt;strong&gt;d&lt;/strong&gt;)own&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;/&lt;/code&gt; - search for any word in the file&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;n&lt;/code&gt; - repeat last search&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;N&lt;/code&gt; - repeat last search in opposite direction&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;NN&amp;gt;G&lt;/code&gt; - (&lt;strong&gt;G&lt;/strong&gt;)o to the line number NN&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;G&lt;/code&gt; - go to the end of the file&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;gg&lt;/code&gt; - go to the beginning of the file&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;command-language&quot;&gt;Command Language&lt;/h2&gt;

&lt;p&gt;Enough movement for now! Next let’s focus on one of the most powerful and unique aspects of Vim: &lt;strong&gt;Vim’s Command Language&lt;/strong&gt;. Vim uses a concise and expressive language of key mappings that allows us to describe every edit we want to make. And it is worth investing the time needed to master it!&lt;/p&gt;

&lt;h3 id=&quot;editing-command-syntax&quot;&gt;Editing Command Syntax&lt;/h3&gt;

&lt;p&gt;Just as any sentence is made up of a verb and a noun, an editing command is made up of two parts: &lt;strong&gt;an operation and a section of text&lt;/strong&gt;. For example, take the commands for “delete this word”, “change the next sentence” or “copy this paragraph”. They all have the same structure:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;number&amp;gt;&amp;lt;command&amp;gt;&amp;lt;text object or motion&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;The &lt;strong&gt;number&lt;/strong&gt; is used to perform the command over multiple text objects or motions, e.g., backward three words, forward two paragraphs. This number is optional and can appear either before or after the command.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The &lt;strong&gt;command&lt;/strong&gt; is an operation, e.g., change, delete (cut) or yank (copy).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;The &lt;strong&gt;text object&lt;/strong&gt; or &lt;strong&gt;motion&lt;/strong&gt; can either be a text construct, e.g., a word, a sentence, a paragraph, or a motion, e.g., forward a line, back one page, end of the line.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s look at each of these one at a time.&lt;/p&gt;

&lt;h3 id=&quot;commands&quot;&gt;Commands&lt;/h3&gt;

&lt;p&gt;Find below some of the most useful operator mappings:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;d&lt;/code&gt; - (&lt;strong&gt;D&lt;/strong&gt;)elete&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;c&lt;/code&gt; - (&lt;strong&gt;C&lt;/strong&gt;)hange&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;y&lt;/code&gt; - (&lt;strong&gt;Y&lt;/strong&gt;)ank or copy&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; - indent, dedent&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;=&lt;/code&gt; - reformat (reindent, break long lines, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The simplest commands are made by repeating the operator a second time to act on the current line. For example, where &lt;code class=&quot;highlighter-rouge&quot;&gt;d&lt;/code&gt; is the operator for &lt;em&gt;delete&lt;/em&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;dd&lt;/code&gt; will delete the whole line. Each of &lt;code class=&quot;highlighter-rouge&quot;&gt;yy&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;cc&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;gt;&amp;gt;&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;==&lt;/code&gt; behave similarly.&lt;/p&gt;

&lt;h3 id=&quot;using-motions&quot;&gt;Using Motions&lt;/h3&gt;

&lt;p&gt;We can also identify text by using any &lt;strong&gt;motion&lt;/strong&gt;. Just like you can use &lt;code class=&quot;highlighter-rouge&quot;&gt;w&lt;/code&gt; to move to the next word, you can use &lt;code class=&quot;highlighter-rouge&quot;&gt;dw&lt;/code&gt; to delete to the next word. This also includes more complex motions such as &lt;code class=&quot;highlighter-rouge&quot;&gt;t&lt;/code&gt;, which will wait for you to specify a character to go up un(&lt;strong&gt;t&lt;/strong&gt;)il.&lt;/p&gt;

&lt;p&gt;Herein lies the magic of Vim: Just by following these rules, you can create any variation of the delete operation by combining it with any motion. Let’s look at some examples:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;dw&lt;/code&gt; - delete to the next word&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;dt,&lt;/code&gt; - delete up until the next comma on the current line&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;de&lt;/code&gt; - delete to the end of the current word&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;d2e&lt;/code&gt; - delete to the end of next word&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;dj&lt;/code&gt; - delete down a line (current and one below)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;dt)&lt;/code&gt; - delete up until next closing parenthesis&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;d/rails&lt;/code&gt; - delete up until the first search match for “rails”&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;using-text-objects&quot;&gt;Using Text Objects&lt;/h3&gt;

&lt;p&gt;You can think of text objects as a kind of “noun” that can be used in place of motions to define a range of text from anywhere within it. Let’s look at some examples:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;iw&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;aw&lt;/code&gt; - inner word, a word&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;ip&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;ap&lt;/code&gt; - inner paragraph, a paragraph&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;i)&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;ap&lt;/code&gt; - inner parenthesis, a parenthesis&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;i'&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;a'&lt;/code&gt; - inner single quote&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;i&quot;&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;a&quot;&lt;/code&gt; - inner double quote&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;it&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;at&lt;/code&gt; - inner tag, a tag&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out &lt;a href=&quot;http://blog.carbonfive.com/2011/10/17/vim-text-objects-the-definitive-guide/&quot;&gt;this blogpost&lt;/a&gt; for a nice rundown of the different text objects available and practical examples.&lt;/p&gt;

&lt;p&gt;You can also get a full listing from within Vim by typing &lt;code class=&quot;highlighter-rouge&quot;&gt;:h text-objects&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By now you might be wondering if there are any best practices to help you decide when to use motions and when to use text objects. A command using a motion, for example &lt;code class=&quot;highlighter-rouge&quot;&gt;cw&lt;/code&gt;, operates from the current cursor position. A command using a text-object, for example &lt;code class=&quot;highlighter-rouge&quot;&gt;ciw&lt;/code&gt;, operates on the whole object regardless of the cursor position. Although this requires one more character, it saves you the time and effort of moving the cursor into the “right” position.&lt;/p&gt;

&lt;p&gt;That’s why it’s generally accepted that you should try to use text objects rather than motions whenever possible.&lt;/p&gt;

&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping up&lt;/h2&gt;

&lt;p&gt;Are you still curious about the infinite world of Vim? In the next post I will focus on windows and tabs, modes and plugins. So stay tuned!&lt;/p&gt;
</description>
        <pubDate>Mon, 25 Jul 2016 00:00:00 +0000</pubDate>
        <link>http://devblog.springest.com/vim-motions-and-command-language</link>
        <guid isPermaLink="true">http://devblog.springest.com/vim-motions-and-command-language</guid>
        
        
      </item>
    
      <item>
        <title>Vim: 5 Tips to Survive Your First Week</title>
        <description>&lt;p&gt;Some months ago I organized a workshop at Springest to share the basics of tmux and Vim with the rest of the team. &lt;a href=&quot;http://devblog.springest.com/tmux-configuration-from-scratch&quot;&gt;I already wrote a post about tmux&lt;/a&gt;. And now it’s time to say something about Vim!&lt;/p&gt;

&lt;p&gt;I will be splitting the content of the workshop into different posts, this being the first one where I will focus on how to survive your first week!&lt;/p&gt;

&lt;p&gt;It goes without saying that as software developers, our jobs depend on continuous learning. It’s therefore incredibly useful to jump in as a beginner on new tools and subjects from time to time. So why don’t we all give Vim a try today? Here are 5 tips to help you go through your very first days.&lt;/p&gt;

&lt;h2 id=&quot;vimtutor&quot;&gt;Vimtutor&lt;/h2&gt;

&lt;p&gt;Vim comes along with its own interactive tutorial: &lt;a href=&quot;http://linuxcommand.org/man_pages/vimtutor1.html&quot;&gt;Vimtutor&lt;/a&gt;. Following the tutorial takes about 30 minutes, where you will learn your first Vim commands: how to create and open files, make changes and save them, etc.&lt;/p&gt;

&lt;p&gt;Open up a shell, type &lt;code class=&quot;highlighter-rouge&quot;&gt;vimtutor&lt;/code&gt; and you are ready to go!&lt;/p&gt;

&lt;h2 id=&quot;avoid-too-much-configuration&quot;&gt;Avoid too much configuration&lt;/h2&gt;

&lt;p&gt;Vim allows you to configure and extend its behavior almost without boundaries. Be careful here, since it is recommended to spend your first weeks getting to know Vim’s core behavior and its default key bindings. Try to stay away from any type of customization or configuration. I promise that when you look back in the future, you will thank yourself ;)&lt;/p&gt;

&lt;p&gt;However it is totally allowed to &lt;em&gt;borrow&lt;/em&gt; some basic configuration from a friend. Personally I learn things much better if my screen looks nice (I guess because of my design background), and the default vim colors were not so appealing for me. So some configuration was needed in my case. Back then, I borrowed &lt;a href=&quot;https://github.com/mscoutermarsh/dotfiles/blob/master/vimrc&quot;&gt;Mike Coutermarsh’s configuration&lt;/a&gt;. But you can check out my &lt;a href=&quot;https://github.com/miriamtocino/dotfiles/blob/master/vimrc&quot;&gt;.vimrc&lt;/a&gt; as well if you prefer.&lt;/p&gt;

&lt;p&gt;If you encounter any issues when using my configuration, &lt;a href=&quot;https://twitter.com/miriamtocino&quot;&gt;ping me on twitter&lt;/a&gt; and I’ll help you out.&lt;/p&gt;

&lt;h2 id=&quot;build-up-a-cheat-sheet&quot;&gt;Build up a cheat sheet&lt;/h2&gt;

&lt;p&gt;There are some very good cheat sheets out there when starting to learn vim, like &lt;a href=&quot;http://www.viemu.com/a_vi_vim_graphical_cheat_sheet_tutorial.html&quot;&gt;this one&lt;/a&gt;, that can serve as a great reference. However it is very important that you build up your own while you are learning.&lt;/p&gt;

&lt;p&gt;For those of you familiar with &lt;a href=&quot;https://asana.com/&quot;&gt;Asana&lt;/a&gt;, I created a single project when I started learning: &lt;strong&gt;Mastered Vim&lt;/strong&gt;. I was regularly adding new tasks (following different topics, like motions and moving, windows, tabs, etc.) and writing down all related key bindings in the task description. Every morning before jumping into Vim, I would review all of them and mark any task that I could already remember as completed!&lt;/p&gt;

&lt;p&gt;This method worked great for me, and I encourage you to do the same.&lt;/p&gt;

&lt;h2 id=&quot;ask-for-help&quot;&gt;Ask for help&lt;/h2&gt;

&lt;p&gt;There will be moments in which you need to ask for help. In this case, you have several options:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Vim’s Built-In Help&lt;/strong&gt; - Great resource when you know exactly what you are searching for. Open up vim and type &lt;code class=&quot;highlighter-rouge&quot;&gt;:help &amp;lt;vim-command&amp;gt;&lt;/code&gt;. From there you can follow any tag under the help by typing &lt;code class=&quot;highlighter-rouge&quot;&gt;Ctrl + ]&lt;/code&gt;.&lt;/p&gt;

    &lt;p&gt;&lt;a href=&quot;http://img.springe.st/20160718-xz9h4.png&quot;&gt;&lt;img src=&quot;http://img.springe.st/20160718-xz9h4.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://vim.wikia.com/&quot;&gt;Vim Wiki&lt;/a&gt;&lt;/strong&gt; - Visit this site when you have other more general questions, like &lt;em&gt;how to re-indent a whole file&lt;/em&gt;.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Friends&lt;/strong&gt; - At Springest there are other people that use Vim too. We created our own &lt;em&gt;#vim&lt;/em&gt; channel in Slack. I love it when I go there with a question aiming for a very direct answer and see others starting a discussion about the different ways in which it can be accomplished within the Vim world!&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;stick-with-it&quot;&gt;Stick with it&lt;/h2&gt;

&lt;p&gt;Last but not least, you need to make a commitment to yourself - &lt;em&gt;keep going when the landscape gets dark&lt;/em&gt;. Normally it takes &lt;strong&gt;about a week&lt;/strong&gt; to feel productive again. From there on you can only continue getting more and more efficient, which is something that definitely helps you grow as a developer. Enjoy the journey!&lt;/p&gt;

&lt;h2 id=&quot;other-posts-in-this-series&quot;&gt;Other posts in this series&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://devblog.springest.com/vim-motions-and-command-language&quot;&gt;Motions &amp;amp; Command Language&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://devblog.springest.com/vim-buffers-tabs-windows-and-modes&quot;&gt;Buffers, Tabs, Windows &amp;amp; Modes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Mon, 18 Jul 2016 00:00:00 +0000</pubDate>
        <link>http://devblog.springest.com/vim-5-tips-to-survive-your-first-week</link>
        <guid isPermaLink="true">http://devblog.springest.com/vim-5-tips-to-survive-your-first-week</guid>
        
        
      </item>
    
      <item>
        <title>Vacancy Senior Ruby on Rails Developer in Amsterdam</title>
        <description>&lt;p&gt;&lt;a href=&quot;http://over.springest.nl/2015/06/15/vacature-senior-ruby-on-rails-developer-amsterdam/&quot;&gt;Link to Dutch version&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We want &lt;a href=&quot;https://www.springest.com/&quot;&gt;Springest&lt;/a&gt; to become the largest source for learning in the world. From books and e-learning courses to onsite trainings, we help our users discover, compare, and book everything they need to reach their personal and professional learning goals.&lt;/p&gt;

&lt;p&gt;We have a strong product focus in which everything revolves around the users of our &lt;a href=&quot;https://www.springest.nl/&quot;&gt;Dutch&lt;/a&gt;, &lt;a href=&quot;https://www.springest.de/&quot;&gt;German&lt;/a&gt;, &lt;a href=&quot;https://www.springest.be&quot;&gt;Belgian&lt;/a&gt;, &lt;a href=&quot;https://www.springest.co.uk/&quot;&gt;UK&lt;/a&gt;, and &lt;a href=&quot;https://www.springest.com/&quot;&gt;US&lt;/a&gt; sites. Next to that, more and more organisations are using our &lt;a href=&quot;https://business.springest.com/&quot;&gt;SaaS tools&lt;/a&gt; to stimulate and manage learning for their employees.&lt;/p&gt;

&lt;h2 id=&quot;working-at-springest&quot;&gt;Working at Springest&lt;/h2&gt;

&lt;p&gt;We are looking for &lt;strong&gt;senior Ruby developers&lt;/strong&gt; to join our growing engineering team. We don’t have managers at Springest, but processes, and we feel that individuals taking responsibility is very important. At Springest, you will work in close collaboration with product owners, marketing, and sales colleagues. You are also a member of our development team where we discuss architecture, infrastructure, and keep a close watch on security and performance.&lt;/p&gt;

&lt;p&gt;Our main application runs on Ruby on Rails backed by Postgres, Redis and Memcached. Next to that we rely on Elasticsearch to power our search which is a big part of our product. We also have some smaller Go and Elixir projects in production.&lt;/p&gt;

&lt;p&gt;We are hosted on AWS and make heavy use of their offerings like RDS, CloudWatch, Elastic Beanstalk and EC2 Container Service.&lt;/p&gt;

&lt;p&gt;Next to our main application we build internal tools whenever necessary to help ourselves and our growing Learning Advisor team. It is extremely rewarding to see small development projects make a big impact for other Springeteers, which in turn can result in more of our visitors being helped of course!&lt;/p&gt;

&lt;h2 id=&quot;hackdays&quot;&gt;Hackdays!&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/springest_hackday.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We do a regular internal hackday every month where we drop everything and work on something completely different, which we feel is super valuable for coming up with new ideas. We might give a new programming language a shot, try out an idea someone’s been toying with for a while or hack on some actual hardware (that’s our temperature sensor above in its beginning stages!).&lt;/p&gt;

&lt;p&gt;A lot of hackday ideas actually became super important for our company, its a great chance to experiment with something that could grow out to become a key factor of our business.&lt;/p&gt;

&lt;p&gt;Check this &lt;a href=&quot;http://devblog.springest.com/springest-june-hack-day-recap&quot;&gt;recap&lt;/a&gt; of a recent hackday to read more about why we organise them.&lt;/p&gt;

&lt;h2 id=&quot;your-new-colleagues&quot;&gt;Your New Colleagues&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/springest_cowboy_team.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;At Springest you will work with around 50 &lt;a href=&quot;http://over.springest.nl/&quot;&gt;colleagues&lt;/a&gt; (that’s not all of us and no we’re not always in full cowboy gear, this was our Western themed SpringFest!) who all are very skilled at what they do and all of them have a healthy dose of nerd skills that we really value. Our Product Owners also regularly ship code!&lt;/p&gt;

&lt;p&gt;Springeteers are a happy bunch and we often get together outside work to enjoy free time as well. Our office is a cosy place where anything goes and where we all take good care of together. If you’re not good at ping-pong yet, you have a good chance of becoming good here as well! 🏓.&lt;/p&gt;

&lt;p&gt;We are all active organisers and members of Meetups and other forms of knowledge exchange (learning is our hobby!) and we participate quite actively in the Amsterdam startup ecosystem. In addition to that we get a lot of attention for Springest being the poster boy of how &lt;a href=&quot;http://about.springest.com/holacracy/&quot;&gt;Holacracy&lt;/a&gt; and GTD can work for an organisation, which in turn is due to our organisational structure without managers and other unnecessary overhead.&lt;/p&gt;

&lt;h2 id=&quot;what-we-expect-from-you&quot;&gt;What we expect from you&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;You work well in a team, and want to make the team greater than a sum of its parts.&lt;/li&gt;
  &lt;li&gt;Engagement in what it is that you are building and who you are building it for. We want you to feel involved and come up with ways to make Springest better.&lt;/li&gt;
  &lt;li&gt;The drive to improve yourself and our organisation and deliver high quality work.&lt;/li&gt;
  &lt;li&gt;You have a broad interest and deep knowledge, certainly not just in/about Ruby. We are all about learning and sharing knowledge.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;what-you-get-from-us&quot;&gt;What You Get From Us&lt;/h2&gt;

&lt;p&gt;Apart from Springest being the coolest company you will ever work for, there are a few extras:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We are very remote friendly.&lt;/li&gt;
  &lt;li&gt;At least a € 1,000 education budget per year to spend on training, courses, and conferences.&lt;/li&gt;
  &lt;li&gt;Stock options after 2 years.&lt;/li&gt;
  &lt;li&gt;A cool workplace in the center of Amsterdam with height adjustable desks that you can sit and stand at, table tennis, a massage chair, and balcony with a barbecue.&lt;/li&gt;
  &lt;li&gt;A Macbook.&lt;/li&gt;
  &lt;li&gt;All software and hardware you need to do your job and have an optimal workflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Contact Mark Mulder (&lt;a href=&quot;mailto:mark@springest.com&quot;&gt;mark@springest.com&lt;/a&gt;) for questions and applications. Please include links to your Github and LinkedIn profiles.&lt;/p&gt;

&lt;p&gt;Checkout these links to get to know more about us:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://devblog.springest.com&quot;&gt;Springest Developer Blog&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://about.springest.com/holacracy/&quot;&gt;Holacracy at Springest&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/Springest&quot;&gt;Springest on Github&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://www.linkedin.com/company/springest&quot;&gt;Springest on LinkedIn&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        <pubDate>Wed, 06 Jul 2016 00:00:00 +0000</pubDate>
        <link>http://devblog.springest.com/vacancy-senior-ruby-on-rails-developer-in-amsterdam</link>
        <guid isPermaLink="true">http://devblog.springest.com/vacancy-senior-ruby-on-rails-developer-in-amsterdam</guid>
        
        
        <category>jobs</category>
        
        <category>ruby</category>
        
        <category>team</category>
        
      </item>
    
      <item>
        <title>Springest June Hack Day Recap</title>
        <description>&lt;h1 id=&quot;an-inside-look-at-our-awesome-all-company-hackathons&quot;&gt;An Inside Look at Our Awesome All-Company Hackathons&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/DSCF2919.jpg&quot; alt=&quot;everyone&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Hack Day has long been a tradition on the Springest team. We’ve built some amazing prototypes in ridiculously short timeframes — some of which have gone on to become real product features.&lt;/p&gt;

&lt;p&gt;Uniquely, we also don’t limit Hack Day to the development team. From marketing to sales and customer support, everyone at Springest takes part in our monthly all-company hackathons.&lt;/p&gt;

&lt;h2 id=&quot;why-we-hack&quot;&gt;Why we hack&lt;/h2&gt;

&lt;p&gt;We have a few core goals for each hack day:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Innovate:&lt;/strong&gt; Work on something not on our usual roadmap.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Learn something:&lt;/strong&gt; Try out a new coding language, service, or skill.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Have fun:&lt;/strong&gt; Whatever you do, it should inspire you.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;preparation&quot;&gt;Preparation&lt;/h2&gt;

&lt;p&gt;All month long, Springeteers are encouraged to keep track of inefficiencies in their workflow and brainstorm possible solutions.&lt;/p&gt;

&lt;p&gt;Is there a boring, repetitive task taking up way too much of your time? Let’s find a way to automate it. Is there a key metric that takes forever to compute? Let’s write a script to calculate it for you.&lt;/p&gt;

&lt;p&gt;For coders and non-coders alike, there are plenty of awesome tech tools to hack your way to a more productive workday.&lt;/p&gt;

&lt;p&gt;For high-tech solutions, developers are brought in for cross-team collaborations, which often produce the most interesting results. For example, our grumpy Smooth Operations team ended up with a Raspberry Pi hooked up to a temperature sensor, complete with on-demand Slack notifications.&lt;/p&gt;

&lt;h2 id=&quot;execution&quot;&gt;Execution&lt;/h2&gt;

&lt;p&gt;Hack Day starts at 9:30am with an all-team meeting. We each present our ideas to the group, which often involves convincing other skilled team members to join in on a big idea. Afterwards, we’re all free to choose what we work on, and we turn on some music before settling into our projects.&lt;/p&gt;

&lt;h2 id=&quot;result&quot;&gt;Result&lt;/h2&gt;

&lt;p&gt;5pm is demo time. While some still hunch over our computers making final tweaks, the rest of us crowd into the kitchen to see whatever working (or almost-working) prototypes made it out the door.&lt;/p&gt;

&lt;p&gt;While we don’t have prizes or accolades for “winning” ideas, there is always plenty of beer and applause to go around. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And what exactly did we achieve this month? Here’s an inside look at this month’s Hack Day projects:&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;revenue-wall-of-fame&quot;&gt;Revenue Wall of Fame&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/DSCF2983.jpg&quot; alt=&quot;ewout&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hacker:&lt;/strong&gt; Ewout Meijer, Director of Corporate Partnerships&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; We hit revenue records all the time, but we have no easy way to see whether a high number is our true ‘record’ without looking it up. That’s lame - we should know when to celebrate!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hack:&lt;/strong&gt; Display the “Revenue Record” output of our Google Sheets metrics on a giant screen, so everyone can see it and get stoked.&lt;/p&gt;

&lt;h3 id=&quot;gym-class-line-jumper&quot;&gt;Gym Class Line Jumper&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/DSCF3001.jpg&quot; alt=&quot;liz&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hacker:&lt;/strong&gt; Liz Hubertz, Software Developer&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Gym classes are always full, and you have to be SO fast to register when a “you’re off the wait list!” email is sent. This decreases workday productivity, because you’re always looking out for that email.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hack:&lt;/strong&gt; Used Zapier to trigger a webhook when the email is received, then built a small Rails app to handle the automatic login and registration process. Classes are thus instantly booked upon receipt of the “you’re off the wait list!” email.&lt;/p&gt;

&lt;h3 id=&quot;ssl-quality-slack-notification&quot;&gt;SSL Quality Slack Notification&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/DSCF2991.jpg&quot; alt=&quot;tim&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hacker:&lt;/strong&gt; Tim Flapper, Software Developer&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; We currently have no way to easily and conveniently monitor our SSL setup. Wouldn’t it be awesome to get a notification right in Slack? Yes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hack:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/20160616-hcdlr.png&quot; alt=&quot;SSL checker&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;learning-advisor-booking-scoreboard&quot;&gt;Learning Advisor Booking Scoreboard&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/DSCF2988.jpg&quot; alt=&quot;midas and merel&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hackers:&lt;/strong&gt; Midas and Merel, Learning Advisors (Customer Support)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; An important part of measuring the success of our Learning Advisors is knowing how many bookings they achieve per week. This data therefore needs to be easy to find and visible for everyone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hack:&lt;/strong&gt; By linking Slack with Google Docs with Zapier, they made an automated scoreboard that keeps track of how many bookings were done by Learning Advisors and how many were done by users themselves on our site. The scoreboard will be displayed on the TV screen in the Learning Advisor corner, so they can always see how they are performing that week.&lt;/p&gt;

&lt;h3 id=&quot;new-springeteer-onboarding-program&quot;&gt;New Springeteer Onboarding Program&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Hackers:&lt;/strong&gt; Debbie van Veen, Smooth Operations Lead and Anne Nynke Jansma, Learning Advisor&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Our current onboarding process feels like it can be improved, but we don’t have any data to back up how or why!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hack:&lt;/strong&gt; Next to partially rewriting our onboarding help articles and making clearer tasks, they also created a survey for new Springeteers to track how often our tools are used and what people think of the program / what they miss.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/20160615-6369f.png&quot; alt=&quot;onboarding&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;automated-inbound-lead-email-flow&quot;&gt;Automated Inbound Lead Email Flow&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/DSCF2977.jpg&quot; alt=&quot;sofie&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hacker:&lt;/strong&gt; Sofie Angevaare, Marketing&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; We lose out on a lot of useful leads by not using smart enough filters on our inbound flow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hack:&lt;/strong&gt; Brand new automated e-mail flow that identifies whether our users should be followed up on by our provider sales team, plus a Slack notification whenever a key user is identified.&lt;/p&gt;

&lt;h3 id=&quot;polish-all-the-things&quot;&gt;Polish ALL the Things!&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/DSCF2993.jpg&quot; alt=&quot;rik&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hacker:&lt;/strong&gt; Rik Matena, Product Owner&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Rik has been working on an internal customer support tool called Scoutest for awhile, but there are always improvements to be made. As a technical guy in his own right, he also helped out non-tech folks with their hacks.&lt;br /&gt;
&lt;strong&gt;Hack:&lt;/strong&gt; Awesome UX improvements and a working and beautiful display for Ewout’s Wall of Records hack.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/20160615-pxczu.png&quot; alt=&quot;Scoutest&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;asq-api&quot;&gt;ASQ API&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/DSCF2917.jpg&quot; alt=&quot;dennis&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hacker:&lt;/strong&gt; Dennis Paagman, Product Owner and Developer&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; We want to use data from our internal tool ASQ in external applications, which generates key metrics based on saved SQL. This allows us, for example, to automate filling in KPI metrics in our Google Sheets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hack:&lt;/strong&gt; Built the API! Awesome!&lt;/p&gt;

&lt;h3 id=&quot;pldealio&quot;&gt;Pldealio&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Hacker:&lt;/strong&gt; Dennis Paagman, Product Owner and Developer&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; It would be nice to visualise our corporate sales pipeline, but deals take a long time to go through - making it seem like not much is happening.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hack:&lt;/strong&gt; Pldealio deal pipeline timeline!&lt;/p&gt;

&lt;h3 id=&quot;learning-advisor-reviews&quot;&gt;Learning Advisor Reviews&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Hackers:&lt;/strong&gt; Zoe van Dantzig and Maarten Butterman, Learning Advisors&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Our product focuses on quality reviews, so why don’t we let our users review our customer support team?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hack:&lt;/strong&gt; Created Springest trainer accounts for each Learning Advisor. Customers can now rate our customer support team in the same way that they rate trainers on the Springest website. &lt;/p&gt;

&lt;h3 id=&quot;notifilter-api--slack-bot&quot;&gt;Notifilter API &amp;amp; Slack Bot&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;http://img.springe.st/DSCF2943.jpg&quot; alt=&quot;mark&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hacker:&lt;/strong&gt; Mark Mulder, Software Developer&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Mark built an awesome internal tool called Notifilter that would be super useful with an API, because that would allow us to grab statistics and re-use these numbers in Sheets, post them to Slack, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hack:&lt;/strong&gt; Notifilter API and Slack Bot is now live!&lt;/p&gt;

&lt;h2 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;I hope our examples give you some inspiration to try out your own all-company hackathon. While not all of our hacks will survive the test of time, Hack Days promote inter-team communication, collaboration, and learning. Plus, it’s a great way to ultimately boost employee happiness and productivity — not to mention an excuse to drink beer during work hours. ;-)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt; Think Hack Day sounds awesome? We’re always hiring talented developers, and you can contact us on Twitter &lt;a href=&quot;https://twitter.com/SpringestOps&quot;&gt;@SpringestOps&lt;/a&gt; or by email at &lt;a href=&quot;mailto:mark@springest.com&quot;&gt;mark@springest.com&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Wed, 15 Jun 2016 00:00:00 +0000</pubDate>
        <link>http://devblog.springest.com/springest-june-hack-day-recap</link>
        <guid isPermaLink="true">http://devblog.springest.com/springest-june-hack-day-recap</guid>
        
        
      </item>
    
  </channel>
</rss>
