<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Gladdstone</title>
    <description>The latest articles on Forem by Gladdstone (@gladdstone).</description>
    <link>https://forem.com/gladdstone</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F23862%2F4d50e241-075a-414d-87cb-f5b957b7e92f.jpg</url>
      <title>Forem: Gladdstone</title>
      <link>https://forem.com/gladdstone</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/gladdstone"/>
    <language>en</language>
    <item>
      <title>A Lesson Learned: Making your priorities your company's</title>
      <dc:creator>Gladdstone</dc:creator>
      <pubDate>Mon, 04 May 2020 15:05:34 +0000</pubDate>
      <link>https://forem.com/gladdstone/a-lesson-learned-making-your-priorities-your-company-s-2gbd</link>
      <guid>https://forem.com/gladdstone/a-lesson-learned-making-your-priorities-your-company-s-2gbd</guid>
      <description>&lt;p&gt;In light of social distancing, we've all been forced to get a lot more family time than we may be used to (or necessarily want). As a result, I've spent a lot of time learning about exactly what it is my mother does for a living, as we're now both working from home. So it's my distinct privilege to listen as I work to the sound of my mom venting her frustrations at Carla and her inability to follow the simplest instructions, Jim and his unhelpful comments, and wave after wave of pointless calls with clueless customers.&lt;/p&gt;

&lt;p&gt;That's not to say I didn't know about her job before. I knew the company, the department, her boss, her title. Hell, I even worked there for a while, but I wasn't quite so intimately familiar with the details of her day. Namely, I wasn't so intimately familiar with her process.&lt;/p&gt;

&lt;p&gt;My mother is in middle management at a medium-sized company in a not particularly interesting sector. About as vanilla as you can get. But she's complaining to me about an issue with her latest project. It's not the first time I've heard about it, but I'm listening more closely than usual, and a few details start to stick out to me. I express to her that this project seems to have some serious internal scaling issues, and possibly some even more serious issues beyond that. We get to talking about them, and she shares my frustrations. Quietly to myself, I wonder, "why hasn't she done anything about it if she owns the project?".&lt;/p&gt;

&lt;p&gt;The next day we're talking again and mom says that she had been up late last thinking about what we had talked about, and some of the problems I had brought up. "It literally kept me up at night", she says. She had messaged her boss earlier that day about her concerns and what she thought they needed to do about it. &lt;/p&gt;

&lt;p&gt;"Although scaling is a concern, the thing I'm most worried about is the impact to customer experience" and with that and a few supporting details, my mother had successfully pivoted an entire project away from a larger disaster.&lt;/p&gt;

&lt;p&gt;This was the moment I realized the chasm of difference between myself and my mom, and where we were in our careers, and in our experience in working with management. I'd had a lot of thoughts going through my head "well if it were me,&lt;em&gt; I would have already brought it up&lt;/em&gt;".&lt;/p&gt;

&lt;p&gt;The key difference between us is the approach, and my own failure was my assessment of the situation. Although we were both able to identify the problem with the system, we saw that it didn't scale and that it would overwhelm the internal systems. What I failed to see, was where the company's priorities where at that moment, and as with many companies, it was with shipping to the customer, or the client, and not necessarily on refining the process.&lt;/p&gt;

&lt;p&gt;The lesson to be learned here is that there is a time and a place. It's easy to identify faults in a system, in fact you probably aren't the first person to identify those faults. What makes the difference is the person who finds the justification to fix those faults within the context of a larger priority.&lt;/p&gt;

&lt;h2&gt;Thanks&lt;/h2&gt;

&lt;p&gt;Thanks for reading, this was originally posted to my blog. Follow me on &lt;a href="https://twitter.com/pithpifth"&gt;Twitter&lt;/a&gt; for primarily nonsense, or check out some of my other hits like &lt;a href="https://joefarrell.dev/idempotency-in-api-design/"&gt;Idempotency in API Design&lt;/a&gt; or &lt;a href="https://joefarrell.dev/working-from-home-the-wonderful-world-of-social-distancing/"&gt;Working From Home: The Wonderful World of Social Distancing&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>career</category>
    </item>
    <item>
      <title>Breaking the Shackles of create-react-app</title>
      <dc:creator>Gladdstone</dc:creator>
      <pubDate>Tue, 31 Dec 2019 17:36:44 +0000</pubDate>
      <link>https://forem.com/gladdstone/breaking-the-shackles-of-create-react-app-17pl</link>
      <guid>https://forem.com/gladdstone/breaking-the-shackles-of-create-react-app-17pl</guid>
      <description>&lt;h1&gt;
  
  
  Breaking The Shackles of create-react-app
&lt;/h1&gt;

&lt;p&gt;The path to becoming considered a "frontend developer" is somewhat vaguely defined in 2020, however, it still begins with basic HTML, CSS, and JavaScript. From there, you'll learn about NPM, and Yarn and add CSS preprocessors like SASS and LESS. From that, most people jump straight into frameworks, and it's all downhill from there.&lt;/p&gt;

&lt;p&gt;For a lot of people, the road to React is paved with a large number of "create-react-app" projects. This isn't necessarily a bad thing, it exists for a reason, and the wonderful people behind it more than know what they're doing. However, it also masks a lot of what's going on in the backend...of your frontend.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1elRpMh3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media2.giphy.com/media/jeXiz1RAvzX44/giphy.gif%3Fcid%3D790b76118d1cc6829aaf6efcc8bde20d26633f0abbac9fb1%26rid%3Dgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1elRpMh3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media2.giphy.com/media/jeXiz1RAvzX44/giphy.gif%3Fcid%3D790b76118d1cc6829aaf6efcc8bde20d26633f0abbac9fb1%26rid%3Dgiphy.gif" alt="dr evil whatever GIF"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is create-react-app
&lt;/h2&gt;

&lt;p&gt;First lets talk about what's generated by create-react-app. A file directory structure, yes. Also a pre-loaded package.json - this is very important. If you started from scratch you would have to build that yourself. Daunting, no? Not at all. Finally, Webpack and Babel configurations, which we'll also discuss.&lt;/p&gt;

&lt;p&gt;The reason we want to build our own project is because otherwise we would have to "eject" the project in order to view these configurations, this restricts your ability to take full control of your own project.&lt;/p&gt;

&lt;h2&gt;
  
  
  The State of JavaScript
&lt;/h2&gt;

&lt;p&gt;JavaScript is a uniquely complex language. In the same way that lower-level languages must be compiled to the specifications of the processor architecture, JavaScript must match each browser engine's specifications for what it expects JavaScript to be. &lt;/p&gt;

&lt;p&gt;The difficulty with JavaScript is that it iterates on itself extremely quickly, and web developers tend to pick up these iterations and begin using them almost as fast (see: ES6). However, not all browsers are capable of interpreting this code. On the function level, we solve this with polyfills. Base structural changes to the language on the other hand call for more drastic measures. &lt;/p&gt;

&lt;p&gt;Say we want to use ES6 arrow functions, or more importantly, the ES6 module. Only recently did browsers begin supporting these features. In addition, we're using Ract, which leverages the JSX format, a syntax extension to the standard JavaScript extension which is certainly not interpretable by browsers, so how do we make this all work together? Answer - Babel.&lt;/p&gt;

&lt;p&gt;Babel is a JavaScript transpiler that gets added to your Webpack configuration as a loader. By working Babel into the Webpack deployment, web developers are able to more passively keep up with the constantly changing standards we deal with in frontend development.&lt;/p&gt;

&lt;p&gt;With all of these requirements to achieve a functioning application, you can begin to see exactly why create-react-app is so appealing. But eventually, we need to pull back the curtain and take a good long look at the little man pulling the levers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Your Dependencies
&lt;/h2&gt;

&lt;p&gt;So you've created a directory and done an &lt;code&gt;npm init&lt;/code&gt; and you'd like to know what's next.&lt;/p&gt;

&lt;p&gt;The trouble with React applications is that they pretty clearly are too large to serve up to the client. Between massive CSS files, thousands of lines of JavaScript, and Redux out the wazoo, not to mention everything is served up as twenty different files. Enter Webpack.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jsERNjcN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/webpack/media/master/logo/icon-square-big.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jsERNjcN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/webpack/media/master/logo/icon-square-big.png" alt="webpack"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Webpack is a complex beast, and frankly deserving of an article entirely its own. It's what's referred to as a module bundler.&lt;/p&gt;

&lt;p&gt;It does this by building a dependency graph of your project, and then relying on a number of loaders. Simply put, Webpack will traverse the dependency graph it's built and attempt to resolve each file it encounters against one of its loaders that are defined in its configuration file. If it isn't able to do so, it raises a runtime error. Otherwise, it generates a bundle and writes output in the form of a bootstrap script with a manifest file (think similar to Java's Maven). This manifest file describes how it should be executed in the browser.&lt;/p&gt;

&lt;p&gt;Start by installing Webpack&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install webpack
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And webpack-cli&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install webpack-cli --save-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I install path. This will make for a cleaner configuration file as our configuration file grows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install path
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now, open up your package.json to add the script to enable you to build your project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack --mode production"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, let's create our Webpack configuration file (webpack.config.js). This is where the magic happens.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const webpack = require('webpack');
const path = require('path');

module.exports = {  
    entry: path.join(__dirname, 'app', 'index.js'),  
    output: {
        path: path.join(__dirname, 'build'),
        publicPath: '/',
        filename: 'bundle.js'
    },
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What does this do? Let's start from the top, and work our way down.&lt;/p&gt;

&lt;p&gt;Entry is simple, that's our source directory. In this case, I've named it "app" and my primary entry point is index.js.&lt;/p&gt;

&lt;p&gt;Next up is the output. When Webpack runs it will create bundle.js, and place it in the build directory. That will be your final product.&lt;/p&gt;

&lt;p&gt;Technically, we're now able to run Webpack, however, like we discussed before, older browsers will not be able to understand the ES6 and JSX syntax typically used in React development.&lt;/p&gt;

&lt;p&gt;So, we'll add Babel to transpile our code to the standard ES5.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @babel/core babel-loader @babel/preset-env @babel/preset-react --save-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Babel also requires its own configuration file, .babelrc&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"presets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"@babel/preset-env"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"@babel/preset-react"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you would like to keep it simple, this can also be done right in your package.json. But beware, if you start adding plugins, you're going to get a lot of bloat, and editing can become a bit of a nightmare.&lt;/p&gt;

&lt;p&gt;Now that Babel is configured, Webpack has to be aware of it. Hence the babel-loader. Let's go back into the Webpack configuration and set up a rule. This will tell Webpack what file types to send to Babel via the loader.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: ['babel-loader', 'eslint-loader']
      },
    ]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;That covers us for JavaScript, but the app looks like hell. Turns out, Webpack doesn't load CSS files natively. &lt;/p&gt;

&lt;p&gt;create-react-app starting to look pretty good, huh?&lt;/p&gt;

&lt;p&gt;Fortunately, this is simple, and allows you to easily select the type of CSS preprocessor you want to use in your project. This will vary from pre-processor to pre-processor, but you'll always need two things: a css-loader, and a style-loader. Both equally poorly named, as the css-loader takes the output from your pre-processor specific loader (for instance, your less-loader) and converts it to CommonJS, a specification used in Node.js. style-loader then takes this and loads it from standardized JavaScript as a style, naturally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install less-loader css-loader style-loader
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rules: [
    {
        test: /\.less$/,
        use: [
            {
                loader: 'style-loader'
            },
            {
                loader: 'css-loader'
            },
            {
                loader: 'less-loader'
            }
        ]
    }
]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, you'll want to be able to run the application locally. You could do this by simply creating a production build every time, but that's not exactly ideal. Instead, we'll install the webpack-dev-server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install webpack-dev-server --save-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Add the script to your package.json&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack-dev-server --mode-development"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"webpack --mode production"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And update your Webpack configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;entry: path.join(__dirname, 'app', 'index.js'),  
output: {
    path: path.join(__dirname, 'build'),
    publicPath: '/',
    filename: 'bundle.js'
},
devServer: {
    contentBase: path.join(__dirname, '/'),
},
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;contentBase will act as the entry point for our local development server. Webpack-dev-server does not create it's own directory like the production build, as it will need to update each time we change the code locally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Now there's a lot more you can, and should do once you've made it this far. Having read this, you should have a general idea of what Webpack does, how to install and configure it, and how to add Babel, and webpack-dev-server for a functioning development environment.&lt;/p&gt;

&lt;p&gt;You'll go from here to creating your React components, but you'll also begin adding your own packages - Eslint, React Router, React Redux, etc. &lt;/p&gt;

&lt;p&gt;For more interesting reading, comments on React and Webpack, follow me on &lt;a href="https://twitter.com/@Pithpifth"&gt;Twitter&lt;/a&gt;. Or check out my other posts like &lt;a href="https://joefarrell.dev/idempotency-in-api-design/"&gt;Idempotency in API Design&lt;/a&gt; or .&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>react</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Idempotency in API Design</title>
      <dc:creator>Gladdstone</dc:creator>
      <pubDate>Sun, 22 Dec 2019 16:01:31 +0000</pubDate>
      <link>https://forem.com/gladdstone/idempotency-in-api-design-36ci</link>
      <guid>https://forem.com/gladdstone/idempotency-in-api-design-36ci</guid>
      <description>&lt;p&gt;The API is what gives a web developer his power. It's a technology used by all living things. It surrounds us and penetrates us. It binds the web together.&lt;/p&gt;

&lt;p&gt;The modern web is powered by APIs, and the ability to not only code an API, but properly architect one is an absolutely crucial skill.&lt;br&gt;
A well-designed RESTful API should be several things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Well-documented&lt;/li&gt;
&lt;li&gt;Designed around the resource for which it is providing&lt;/li&gt;
&lt;li&gt;Using a stateless request model – this means that you shouldn’t be storing any data between requests. Each should be its own operation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But above all, reliability and safety are key. An unreliable API is a useless API. Very often the measure of a good API is not the technology itself, but rather what people are able to build with it. It's very important you are not dissuading potential users with an unreliable API.&lt;/p&gt;

&lt;p&gt;So what do reliability and safety look like at the architectural level?&lt;/p&gt;
&lt;h2&gt;
  
  
  Idempotency and Safety
&lt;/h2&gt;

&lt;p&gt;RESTful APIs serve up information based on HTTP requests made by clients. These HTTP requests have an attribute referred to as “safety,” and understanding safety is the first step.&lt;/p&gt;

&lt;p&gt;SAFE HTTP REQUESTS:&lt;/p&gt;

&lt;p&gt;GET - YES&lt;br&gt;
PUT - NO&lt;br&gt;
POST - NO&lt;br&gt;
DELETE - NO&lt;br&gt;
PATCH – NO&lt;/p&gt;

&lt;p&gt;An HTTP request type is considered “safe” if it doesn’t mutate the data when it is invoked. Naturally, this would make GET requests a “safe” request type, therefore, they are considered idempotent from the get-go.&lt;/p&gt;

&lt;p&gt;But that doesn’t answer the question of idempotence. Idempotence is the principle that an API method, once invoked a single time, will not modify the server state further upon any subsequent identical requests.&lt;/p&gt;

&lt;p&gt;That’s a lot. What does that mean? Imagine it as a mathematical function.&lt;/p&gt;

&lt;p&gt;f(x) = x^2 + 2&lt;/p&gt;

&lt;p&gt;If we say x = 5, then f(x) will always be equal to 27. If we do it again, f(x) is still equal to 27, because the input data hasn’t changed. Similarly, if your user sends a request to the server that deletes a row from a database, and sends that same request again, they should get back the same “row successfully deleted” result each time, but the state will have only changed once.&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;From the client end, a POST request to the API may look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;callAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;API_URL&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is fine, it’ll return the value, but what happens if there is a network error? It would be nice to have auto-retry. &lt;/p&gt;

&lt;p&gt;This is where idempotency comes in. Network errors run both ways. In the same way that the client’s packets may be disrupted on path to the server, the response may be disrupted on its way back to the client, triggering an auto-retry. Therefore, your API methods must be prepared to handle this eventuality.&lt;/p&gt;

&lt;p&gt;Luckily, implementing idempotency is very easy. Simply attach our good friend the GUID, or Globally Unique Identifier (also called a UUID or Universally Unique Identifier but I like to say “gwid”). This 128-bit number can be generated by the client, and attached as a header value to the request.&lt;/p&gt;

&lt;p&gt;Upon authentication by the API, handling is cake. Simply save the GUID and server response for a defined period of time (make sure this data auto-removes itself, or you’ll suffer from some pretty severe bloat).&lt;/p&gt;

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

&lt;p&gt;Once that is done, all there is to do is place our callAction function within a loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;callPost&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;remainingAttempts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;exceptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;remainingAttempts&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;callAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;remainingAttempts&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;exceptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// this is where you handle the exception, whether it’s logging&lt;/span&gt;
        &lt;span class="c1"&gt;// to the console, etc&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Thanks for reading!
&lt;/h3&gt;

&lt;p&gt;Got questions? Want to talk about The Mandalorian? Follow me on &lt;a href="https://twitter.com/Pithpifth" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>api</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Twitter For The Google Home</title>
      <dc:creator>Gladdstone</dc:creator>
      <pubDate>Tue, 30 Jan 2018 21:31:21 +0000</pubDate>
      <link>https://forem.com/gladdstone/twitter-for-the-google-home-37dp</link>
      <guid>https://forem.com/gladdstone/twitter-for-the-google-home-37dp</guid>
      <description>&lt;p&gt;&lt;em&gt;originally posted on my &lt;a href="http://joefarrell.me/index.php/2018/01/30/twitter-for-google-home/"&gt;blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you follow me on Twitter (and you &lt;a href="http://www.twitter.com/Pithpifth"&gt;should&lt;/a&gt;), you're aware that I'm an avid fan of the platform. So it's only natural that when I finally got a Google Home this year, the first thing I do is start tinkering with the platform to work with my Twitter account - now, the Google Home development software allows for automatic Twitter integration, but it's not a solve-all, I needed something with a little bit more oomph.&lt;/p&gt;

&lt;p&gt;The first step was to choose my language. This was easy enough, I'd spent the past few weeks exploring NodeJS, and this seemed like the perfect opportunity to develop my skills a bit. As I developed, the application went through a number of iterations and platforms. Sometimes it used express, sometimes it didn't. I deployed to Firebase, then Heroku, the AWS Lambda, then back to Firebase, and then Google Cloud Functions (basically Firebase).&lt;/p&gt;

&lt;p&gt;But what I'll be discussing today is the process to produce the final product, or rather, the product as it exists today which, while far from perfect, is functional, and an excellent starting point for anyone interested in getting started with Google Home development.&lt;/p&gt;

&lt;h2&gt;Getting Started With Dialogflow&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lgJz7KDr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://joefarrell.me/wp-content/uploads/2018/01/dialogflow-logo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lgJz7KDr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://joefarrell.me/wp-content/uploads/2018/01/dialogflow-logo.png" alt="" width="508" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qKZwmdfM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://joefarrell.me/wp-content/uploads/2018/01/Screen-Shot-2018-01-25-at-8.32.28-AM-e1516887280252.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qKZwmdfM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://joefarrell.me/wp-content/uploads/2018/01/Screen-Shot-2018-01-25-at-8.32.28-AM-e1516887280252.png" alt="" width="260" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to build for the Google Home, the first thing you'll need to do is get yourself setup with Google's dedicated development environment. In this case, Dialogflow is a dedicated platform for training the Google Home to respond to your voice, and pass the necessary data to your app. This is, in my opinion, the coolest part of building the application, because not only is it easy to get started, but once you've registered with your Google account, your app is immediately available for testing on any Google Home under the same account.&lt;/p&gt;

&lt;p&gt;Signing up is simple, chances are you've got a Google account already, so let's go ahead and go to our console.&lt;/p&gt;

&lt;p&gt;Once you reach your console, the first thing you need to do is create a new agent, this will be your method of interacting with your web application that will make up the back end of your Google Home skill. Here you'll set the basic information - the skill name, language, default time zone, and you can also set a web hook from here, but we'll leave that blank for now. We'll come back to it later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WmLwHTmM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://joefarrell.me/wp-content/uploads/2018/01/Screen-Shot-2018-01-25-at-8.55.41-AM-e1516889531365.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WmLwHTmM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://joefarrell.me/wp-content/uploads/2018/01/Screen-Shot-2018-01-25-at-8.55.41-AM-e1516889531365.png" alt="" width="434" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations. You've officially created a Google Home skill. Sort of. It doesn't actually &lt;em&gt;do&lt;/em&gt; anything just yet, but it does exist.&lt;/p&gt;

&lt;p&gt;From here you'll train your app in intents, that's to say you'll train it to respond in a predetermined way when the user says key phrases. To get started, head over to your "Intent" bar on the left, and select "Create Intent"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jvv1Crpz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://joefarrell.me/wp-content/uploads/2018/01/Screen-Shot-2018-01-30-at-8.48.44-AM-e1517320172762.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jvv1Crpz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://joefarrell.me/wp-content/uploads/2018/01/Screen-Shot-2018-01-30-at-8.48.44-AM-e1517320172762.png" alt="" width="600" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's a lot of information here, so let's take a minute to break it down. First, you've got your intent name. This is simply for organizational purposes, so name it something that will allow you to recognize what it does.&lt;/p&gt;

&lt;p&gt;The "User Says" bar is where you will supply Google with sample phrases with which to train it to recognize commands.&lt;/p&gt;

&lt;p&gt;The "Action" bar is where we set the name of the action that will be executed by our app's backend (essentially a function). Below it is the data values and types that will be passed to that action as parameters. We'll dig into this in just a minute.&lt;/p&gt;

&lt;p&gt;Below that is your Text response, which is exactly what you think it is. For this application, we'll be leaving this blank, as the response we send will need to confirm the tweet was properly sent, therefore it will need to be handled by our backend.&lt;/p&gt;

&lt;p&gt;Finally, we have two dropdown menus - Fulfillment and Google Assistant. Go ahead and drop down Fulfillment and select "Use webhook." This will enable this intent to execute an action on our backend application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B3jtHrsU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://joefarrell.me/wp-content/uploads/2018/01/Screen-Shot-2018-01-30-at-9.17.19-AM-e1517321942934.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B3jtHrsU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://joefarrell.me/wp-content/uploads/2018/01/Screen-Shot-2018-01-30-at-9.17.19-AM-e1517321942934.png" alt="" width="400" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we need to create an entity. This entity will allow us to recognize what our user wants to do - in this case, post a tweet. So go over to "Entities" on the left and select "Create Entity." This brings us to a table with two columns. The first column is our main value, or the word that Google Assistant will recognize as the entity. On the right, we can define synonyms of this value. We want our user to be able to send a tweet by saying "Send [tweet]." So, our value on the left is send. Now we can go to the right column and enter some synonyms - post, tweet, update, etc.&lt;/p&gt;

&lt;p&gt;When you're ready, name it - in my case, I call this entity tweetPrompt, as it prompts the application to send a new tweet. Now hit save and go back to your intent.&lt;/p&gt;

&lt;p&gt;Now that we have our entity created, lets set our Event parameters. First,we set parameter name tweetPrompt. This is of entity type @tweetPrompt (the one we just created), and it has a value of $tweetPrompt (we'll set this shortly).&lt;/p&gt;

&lt;p&gt;We have the prompt, now we need the content. Effectively what we'll do here is write a blank check for Google Assistant to cash by throwing in everything that isn't the tweetPrompt (ie "Tweet [all this stuff here]"). We'll call this parameter tweetContent, and we need it to have an entity type of @sys.any. This will allow for the Google Assistant to grab anything the user says as the value of this parameter. Finally, set the value to $tweetContent.&lt;/p&gt;

&lt;p&gt;All that remains to be done now is instruct the Google Assistant in how to set these values for us. This can be a little tricky, particularly with the tweetContent, but in my experience, four or five solid examples are enough to give it a solid enough grasp of where things should go.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GbpjAfl9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://joefarrell.me/wp-content/uploads/2018/01/Screen-Shot-2018-01-30-at-9.30.37-AM-e1517322885661.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GbpjAfl9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://joefarrell.me/wp-content/uploads/2018/01/Screen-Shot-2018-01-30-at-9.30.37-AM-e1517322885661.png" alt="" width="400" height="236"&gt;&lt;/a&gt;Lets go on up to "User says" and type our first example. Type "Send I'm eating a cheeseburger" and hit enter. This will create you first example. Dialogflow should be able to pick out the word "Send" and set that as your tweetPrompt, but your tweetContent will require our intervention. To set tweetContent, simply highlight the remainder of the message. This will bring up a dialog box containing "@sys.any:tweetContent". Select this, and that portion of the text will become highlighted.&lt;/p&gt;

&lt;p&gt;That's it! Now repeat this four or five times (remember to use your synonyms for your tweetPrompt entity) in order to complete the training.&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wzfHljmi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://joefarrell.me/wp-content/uploads/2018/01/Screen-Shot-2018-01-30-at-9.32.51-AM-e1517322816820.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wzfHljmi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://joefarrell.me/wp-content/uploads/2018/01/Screen-Shot-2018-01-30-at-9.32.51-AM-e1517322816820.png" alt="" width="600" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;h2&gt;Firebase/Google Cloud Functions&lt;/h2&gt;

&lt;p&gt;For this project, we'll be using Firebase to host our application. The reason for this being that Firebase is a part of Google Cloud Functions which, as you may imagine, plays very nicely with our Dialogflow app. Other options for hosting would be things like Amazon Web Services, or Heroku, and they each have their own advantages and drawbacks, but for the sake of simplicity we'll focus on Firebase and Google Cloud Functions here.&lt;/p&gt;

&lt;p&gt;To get started, let's create a local directory on our development machine. In this case, I've called mine "Gladdstwit." Now go ahead and navigate to this directory in your terminal of choice (for me, I use PowerShell on Windows, and the stock terminal on OSX, although there are a variety of options out there). First and foremost, you'll need both NodeJS and NPM installed. If you aren't sure, you can check if they are installed with&lt;/p&gt;


&lt;p&gt;&lt;code&gt;&lt;br&gt;
node -v&lt;br&gt;
npm -v&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

If you don't have them, take a moment to download and set these up. This process will vary from operating system to operating system.

Now that we have Node and NPM ready, we can create out Firebase application. First, we run &amp;lt;code&amp;gt;npm install -g firebase-tools&amp;lt;/code&amp;gt;. This will install Firebase globally on our machine. Now we have to login to Firebase using &amp;lt;code&amp;gt;firebase login&amp;lt;/code&amp;gt;. This is a handy command that will allow you to authenticate within the browser.

With Firebase set up and authenticated, we can create our application within our working directory using &amp;lt;code&amp;gt;firebase init functions&amp;lt;/code&amp;gt;. Once you've completed setup for your JavaScript app, your project directory should look something like this (pulled from the Google documentation)

&amp;lt;p class="prettyprint"&amp;gt;&amp;lt;code&amp;gt;&amp;lt;span class="pln"&amp;gt;myproject
&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;+-&amp;lt;/span&amp;gt; &amp;lt;span class="pun"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;firebaserc    &amp;lt;/span&amp;gt;&amp;lt;span class="com"&amp;gt;# Hidden file that helps you quickly switch between&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;
&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;|&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;                 &amp;lt;/span&amp;gt;&amp;lt;span class="com"&amp;gt;# projects with `firebase use`&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;
&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;|&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;
&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;+-&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt; firebase&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;json  &amp;lt;/span&amp;gt;&amp;lt;span class="com"&amp;gt;# Describes properties for your project&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;
&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;|&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;
&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;+-&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt; functions&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;/&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;     &amp;lt;/span&amp;gt;&amp;lt;span class="com"&amp;gt;# Directory containing all your functions code&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;
&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;|&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;
&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;+-&amp;lt;/span&amp;gt; &amp;lt;span class="pun"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;eslintrc&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;json  &amp;lt;/span&amp;gt;&amp;lt;span class="com"&amp;gt;# Optional file containing rules for JavaScript linting.&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;
&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;|&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;
&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;+-&amp;lt;/span&amp;gt; &amp;lt;span class="kwd"&amp;gt;package&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;json  &amp;lt;/span&amp;gt;&amp;lt;span class="com"&amp;gt;# npm package file describing your Cloud Functions code&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;
&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;|&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;
&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;+-&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt; index&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;js      &amp;lt;/span&amp;gt;&amp;lt;span class="com"&amp;gt;# main source file for your Cloud Functions code&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;
&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;|&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;
&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;+-&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt; node_modules&amp;lt;/span&amp;gt;&amp;lt;span class="pun"&amp;gt;/&amp;lt;/span&amp;gt; &amp;lt;span class="com"&amp;gt;# directory where your dependencies (declared in&amp;lt;/span&amp;gt;&amp;lt;span class="pln"&amp;gt;
&amp;lt;/span&amp;gt;&amp;lt;span class="com"&amp;gt;# package.json) are installed&amp;lt;/span&amp;gt;&amp;lt;/code&amp;gt;

Now that our directory is set up, lets go back to Dialogflow for a moment to grab some boilerplate code that Google was ever so considerate to supply for us. To get it, navigate to "Fulfillment" on the left sidebar. This will take us to the page from which we can manage our web hook. For now, turn on the Inline Editor, this is where our boilerplate code will come from.

&amp;lt;img class="size-full wp-image-80 aligncenter" src="http://joefarrell.me/wp-content/uploads/2018/01/Screen-Shot-2018-01-25-at-10.10.02-AM-e1516893040397.png" alt="" width="500" height="293" /&amp;gt;

Go ahead and copy the text from the inline editor into your index.js file, then turn of Inline Editor and enable Webhook, we'll come back to this momentarily. Now we're ready to build our application!


&amp;lt;h2&amp;gt;Building our NodeJS Application&amp;lt;/h2&amp;gt;

All right, so you have your Dialogflow project, you've got your boilerplate code, it's time to get to coding. Before we start modifying the boilerplate, I recommend taking a few minutes to explore the code provided. The whole thing is fairly straight forward, and with a few minutes of reading, you can pretty easily get a feel for what we're going to be doing, here.

By default, the Dialogflow boilerplate code uses several NodeJS modules, but we'll need one more to allow us to communicate with the Twitter API. Now, there are several ways to do this is through the twit module. In addition to the twit module, we'll also need to include our own config.js file (this will house the necessary information that will be passed to the twit module). Once that's done, your require section should look something like this

[caption id="attachment_83" align="aligncenter" width="600"]&amp;lt;img class="wp-image-83 size-full" src="http://joefarrell.me/wp-content/uploads/2018/01/Screen-Shot-2018-01-29-at-12.09.13-AM-e1517202600217.png" alt="" width="600" height="143" /&amp;gt; &amp;lt;em&amp;gt;                                                     Don't forget to npm install twit!&amp;lt;/em&amp;gt;[/caption]

Next we need to set up the config.js file. This file will contain four unique keys provided to you by Twitter. To get these, you'll need to go to apps.twitter.com and select "Create new app."

&amp;lt;img class="size-full wp-image-84 alignleft" src="http://joefarrell.me/wp-content/uploads/2018/01/Screen-Shot-2018-01-29-at-12.14.27-AM-e1517202910111.png" alt="" width="300" height="177" /&amp;gt;

Here, you'll set your application's name, description, and associated website. Most importantly, remember to change your app's permissions from "Read Only" to "Read and Write" (otherwise our application won't work - obviously). If you intend to include direct message functionality later on, accessing those is a separate permission, and you will need to activate that instead.

Now that your app is created, you can go to your Keys and Access Tokens tab. You will need four forms of identification from here to access the Twitter API - consumer key, consumer secret, access token, and access token secret. These will all be encapsulated within a JSON object in your config.js file. Remember not to store these values anywhere someone might see them!

&amp;lt;img class="size-full wp-image-85 aligncenter" src="http://joefarrell.me/wp-content/uploads/2018/01/Screen-Shot-2018-01-29-at-12.19.54-AM-e1517203233414.png" alt="" width="600" height="139" /&amp;gt;

And there you have it! You are now ready to connect to the Twitter API. Only one step remains, and that is to process the user request to your application.

In order to do this, we'll be working with the processV1Request function. This is the function that handles standard web hook requests from Dialogflow. There is also a processV2Request function, which includes some further functionality, but is currently in beta, and we won't be dealing with it today.

The key to the processV1Request function is its actionHandlers. This contains all of the possible actions that your application can take. The first one that we'll look at is called "input.welcome." This handles the welcome message when your user opens the application from their Google Home, and as you might imagine, it's fairly simple.


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

&lt;/div&gt;


&lt;p&gt;'input.welcome': () =&amp;gt; {&lt;br&gt;
    // Use the Actions on Google lib to respond to Google requests; for other requests use JSON&lt;br&gt;
    if(requestSource===googleAssistantRequest){&lt;br&gt;
    sendGoogleResponse('Welcome to Gladdstwit, the Twitter client for Google Home.');// Send simple response to user&lt;br&gt;
    }else{&lt;br&gt;
    sendResponse('Welcome to Gladdstwit, the Twitter client for Google Home.');// Send simple response to user&lt;br&gt;
    }&lt;br&gt;
},&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

The first thing it does is verify that you are indeed connecting to it via a Google Assistant device, and then sends your message back. Easy enough. This is the rough format for all of your action handlers, and should give you a fairly good idea of what needs to happen from here on out.

Now, let's create the function that sends your tweet. We'll call this postTweet, and we'll enter it immediately after the "input.welcome" function for simplicity's sake.

Notice above the constants that are declared at the very start of the processV1Request function. The one we want to focus on right now is called "parameters." These are the values that the Google Home will pass to your application - for our purposes, this will be the tweet that our user wishes to post. So what we want to do is get that value out of parameters and send it to Twitter with the instructions to post it as a tweet.

We know that the parameter's name is tweetContent, so we can retrieve it from parameters like you would any other JSON object.


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

&lt;/div&gt;



&lt;p&gt;"postTweet": () =&amp;gt; {&lt;br&gt;
    responseToUser="Success!";&lt;br&gt;
    let statusText=parameters.tweetContent;&lt;br&gt;
    // Post the tweet&lt;/p&gt;

&lt;p&gt;    if(requestSource===googleAssistantRequest){&lt;br&gt;
        sendGoogleResponse(responseToUser);&lt;br&gt;
    }&lt;br&gt;
    else{&lt;br&gt;
        sendResponse(responseToUser);&lt;br&gt;
    }&lt;br&gt;
},&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

So now we have our tweet, we have a confirmation response to send to our user upon success, all we have to do is communicate with the Twitter API. Luckily, twit makes this extremely easy. The function, in this case, is called twitter.post(), and it takes three values - "statuses/updates", a string that defines where we are posting (our status), the status text itself in JSON format (this can also take other values, but for now we'll stick with just the plain text), and an error function (error).

Personally, rather than build a separate function, I prefer to use an arrow function to handle the error method. In this case, the code looks something like this.


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

&lt;/div&gt;



&lt;p&gt;twitter.post("statuses/update", {status: statusText}, (err, data, res) =&amp;gt; {&lt;br&gt;
    if(err){&lt;br&gt;
        responseToUser="Something went wrong";&lt;br&gt;
    }&lt;br&gt;
    else{&lt;br&gt;
        // responseToUser = "Success!";&lt;br&gt;
    }&lt;br&gt;
});&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

So, when you're done, your entire action handler should look like this.


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

&lt;/div&gt;



&lt;p&gt;"postTweet": () =&amp;gt; {&lt;br&gt;
    responseToUser="Success!";&lt;br&gt;
    letstatusText=parameters.tweetContent;&lt;br&gt;
    twitter.post("statuses/update",{status:statusText},(err,data,res)=&amp;gt;{&lt;br&gt;
    if(err){&lt;br&gt;
        responseToUser="Something went wrong";&lt;br&gt;
    }&lt;br&gt;
    else{&lt;br&gt;
        // responseToUser = "Success!";&lt;br&gt;
    }&lt;br&gt;
    });&lt;br&gt;
    if(requestSource===googleAssistantRequest){&lt;br&gt;
        sendGoogleResponse(responseToUser);&lt;br&gt;
    }&lt;br&gt;
    else{&lt;br&gt;
        sendResponse(responseToUser);&lt;br&gt;
    }&lt;br&gt;
},&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;



Not so bad, right? Thanks to the magic of Node, connecting Google and Twitter is extremely easy, and with this function implemented, we're ready to deploy our application! So go on back to your terminal and type

&amp;lt;center&amp;gt;&amp;lt;code&amp;gt;firebase deploy&amp;lt;/code&amp;gt;&amp;lt;/center&amp;gt;

In order to deploy your application. Once that's done, we can go to our Google Cloud Functions. From the menu, go to "Cloud Functions" and select your function name. Under the "trigger" menu, you will find a URL of type HTTP Trigger. Copy this URL and paste it into your webhook URL into Dialogflow and save.

That's it! You're ready to test. We can do this in a couple of ways. Dialogflow offers it's own emulator, or, if you signed up with the same account connected to your Google Home, you can simply tell your Google Home "Talk to [name of your application]."

This has a ways to go before it's ready to be called a "useful" app, but hopefully it has been helpful in showing you the ropes of working with Dialogflow and Google Cloud Functions.


**Thank you!**
This is my first attempt at something this long, I hope you enjoyed reading it. If you feel confused about something, or if I left something out (possible, if not downright likely), leave a comment or shoot me a tweet!
You can follow me on Twitter &amp;lt;a href="http://www.twitter.com/Pithpifth"&amp;gt;@Pithpifth&amp;lt;/a&amp;gt;
Or see my (brand-spanking new) blog at &amp;lt;a href="http://joefarrell.me"&amp;gt;joefarrell.me&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>learning</category>
    </item>
    <item>
      <title>Styling Your Stylesheets</title>
      <dc:creator>Gladdstone</dc:creator>
      <pubDate>Tue, 23 Jan 2018 19:21:05 +0000</pubDate>
      <link>https://forem.com/gladdstone/styling-your-stylesheets-3b52</link>
      <guid>https://forem.com/gladdstone/styling-your-stylesheets-3b52</guid>
      <description>&lt;p&gt;CSS. Cascading Style Sheets. We know them, we use them, we - well, "love" might be a strong word, but we certainly use them. Whether you're a Bootstrap evangelist, or a do-it-yourself purist, if you've ever designed a website, you've at some point had to write some CSS. This means that at some point you've had to read some CSS, and perhaps even modify someone else's. In that case, you know the pain of finding exactly the tag you're looking for.&lt;/p&gt;

&lt;p&gt;So what is it about CSS that causes such animosity, or at best, reluctance? It's a perfectly simple technology, utterly usable in nearly every aspect, dead simple to learn, and even if you absolutely refuse to write it, there are literally thousands of tool/frameworks out there that exist solely to ensure that you never have to. So why expend the energy required to hate it?&lt;/p&gt;

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

&lt;p&gt;Okay, so you might be on to something there. CSS has it's problems, but its biggest problem is really the user (which, if we're being honest, is the case with a lot of things we hate).&lt;/p&gt;

&lt;p&gt;CSS's greatest enemy is organization. Often times, people will do a reasonable job of organizing their CSS at first, but after two, three, four updates, it's not looking so hot anymore. As a student, I've had the pleasure of working with a number of wonderful people on everything from freelance, to group projects, to internships, and everything in-between, but I swear if one more person inserts their random-ass ID selector in the dead center of my code I am going to lose it.&lt;/p&gt;

&lt;p&gt;As something of a professional whackjob, I'm pretty scrupulous about formatting my code - not necessarily by standard convention, but by what I find to be most readable. Sometimes this means adhering to the styling conventions of the language, and sometimes this means improvising slightly. Often, this improvisational style of coding leads to some discrepancies from program to program, or site to site, so this is me, sitting down, and attempting to set in stone at least a few of the rules I attempt to follow on a daily basis.&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Order Your Selectors
&lt;/h1&gt;

&lt;p&gt;CSS has three main selectors, and of course, a near infinite number of combinations and permutations thereupon, so I try to keep it reasonably simple. First and foremost, I always start my CSS in the same way, with the universal selector (*). Being universal to every element on the page, this seems fairly logical.&lt;/p&gt;

&lt;p&gt;Next, you've got your standard HTML selectors. The reasoning for this is that, overall, HTML selectors are the most broad in scope (with the exception of the universal selector), as they effect every element of that type. By putting them first, you ensure that ID and class selectors will properly override their respective elements.&lt;/p&gt;

&lt;p&gt;Following the HTML selectors is ID, if for no other reason than that's the way I chose to do it, and bringing up the rear is class selectors. If I were following my logical reasoning from the previous paragraph, I suppose it would make more sense to have class followed by ID, but I'm a fairly stubborn person and it's unlikely that I'll change any time soon&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Alphabetical is King
&lt;/h1&gt;

&lt;p&gt;So you've got your selector in order. That's a good start. You know where your IDs are, your HTML element selectors, your classes, each one of them has it's place. That's probably good.&lt;/p&gt;

&lt;p&gt;Now, just need to change the width on #profile from 75% to 70% and...&lt;/p&gt;

&lt;p&gt;You see where I'm going with this. Once I have my selectors in order I further break it down alphabetically. #that_div, #this_div, #those_div, you get the picture, it's not rocket science. The part where it starts to break down is when you get into subselectors, such as when you're pointing to children, or adding a hover.&lt;/p&gt;

&lt;p&gt;As a general rule of thumb, if two selectors start with the same word, the longer one goes second. That is to say ".link:hover" comes after ".link".&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Breaking All The Rules?
&lt;/h1&gt;

&lt;p&gt;Due to the nature of CSS, it's not always possible to follow all of these rules to the t, and that's okay. I know I very rarely write any CSS in which I follow every one of these rules perfectly, simply because CSS wasn't written to operate in this way.&lt;/p&gt;

&lt;p&gt;Very frequently, you'll find yourself in a situation where element A must come after element B in order to display properly, and I tend to doubt anyone is changing their entire design for the sake of better organizing their CSS (but then again, who am I to judge).&lt;/p&gt;

&lt;p&gt;This isn't necessarily a complete ruleset, and it's certainly far from perfect, but I do believe that by following a few extra rules of thumb could help prevent some headaches for both you and your coworkers in the future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thank you!&lt;/strong&gt;&lt;br&gt;
Thanks for reading my first ever attempt at a tech blog! Feedback is certainly appreciated, my writing ability is a permanent work in progress.&lt;br&gt;
You can follow me on Twitter &lt;a href="//www.twitter.com/Pithpifth"&gt;@Pithpifth&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
