<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Robert Nealan</title><description>Design engineering, writing and work by Robert Nealan.</description><link>https://robertnealan.com/</link><atom:link href="https://robertnealan.com/rss.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Fri, 30 Oct 2026 06:24:18 GMT</lastBuildDate><item><title>Using the WordPress REST API with React.js</title><link>https://robertnealan.com/using-the-wordpress-rest-api-with-custom-post-types-custom-metadata/</link><guid isPermaLink="true">https://robertnealan.com/using-the-wordpress-rest-api-with-custom-post-types-custom-metadata/</guid><description>It&apos;d been a few (happy) years since I last used WordPress for a client project, but with its now (questionably-)stable REST API it came up last year as a…</description><pubDate>Sat, 03 Nov 2018 00:02:17 GMT</pubDate><content:encoded>&lt;p&gt;It’d been a few (happy) years since I last used Wordpress for a client project, but with its now (questionably-)stable REST API it came up last year as a potential candidate for backing a React-based magazine/news site. After doing some digging it became clear that it was not only a possible candidate, but a frontrunner amongst the options as it would provide ~80% of what we needed with minimal work, potentially providing huge time and cost savings to our client.&lt;/p&gt;
&lt;p&gt;Unfortunately, its cryptic documentation left something to be desired and most articles around the web were either for v1.x, out of date with current v2.x changes, or just plain wrong. So as usual with Wordpress, it was up to us to sort out that other 20% for ourselves.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#adding-endpoints-for-custom-post-types&quot;&gt;Adding Endpoints for Custom Post Types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#adding-custom-metadata-to-api-responses&quot;&gt;Adding Custom Metadata to API Responses&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#adding-the-featured-thumbnail-to-single-post-responses&quot;&gt;Adding the Featured Thumbnail to Single Post Responses&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;adding-endpoints-for-custom-post-types&quot;&gt;Adding Endpoints for Custom Post Types&lt;/h2&gt;
&lt;p&gt;In our project’s case we are using the default Wordpress “Post” post-type for the bulk of the site’s news and blog articles (sorted into categories), but needed to add &lt;a href=&quot;https://codex.wordpress.org/Post_Types#Custom_Post_Types&quot;&gt;Custom Post Types&lt;/a&gt; for our other content types like Events &amp;amp; Videos.&lt;/p&gt;
&lt;p&gt;If you’re familiar with adding Custom Post Types (CPTs) the snippet below for our “Events” CPT should look familiar (if not I recommend reading up on them first in the &lt;a href=&quot;https://codex.wordpress.org/Post_Types#Custom_Post_Types&quot;&gt;Wordpress Codex&lt;/a&gt; or on Elegant Themes’ excellent &lt;a href=&quot;https://www.elegantthemes.com/blog/tips-tricks/creating-custom-post-types-in-wordpress&quot;&gt;guide to Custom Post Types&lt;/a&gt;). There’s a lot going on this, but lines 35-37 are the specific part relevant to making the CPT accessible through the REST API.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Line 35&lt;/strong&gt; tells Wordpress to expose this CPT in the rest API (pretty self explanatory).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Line 36&lt;/strong&gt; gives the CPT a URL base within the API. Rather than query &lt;code&gt;/wp-json/wp/v2/posts/&lt;/code&gt; for a normal Post, this tells Wordpress you want to be able to query this CPT at &lt;code&gt;/wp-json/wp/v2/events/&lt;/code&gt;. You can change this to be anything you want as long as it doesn’t collide with another CPT or built-in post types (Post, Page, etc), though it generally makes sense to keep it the same as the CPT’s name.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Line 37&lt;/strong&gt; tells Wordpress to extend the default WP_REST_Posts_Controller for functionality related to handling API calls. It’s technically possible to heavily extend or customize this, but that’s outside the scope of this article.&lt;/p&gt;
&lt;p&gt;For our purposes we’re using these CPT endpoints as read-only GET requests, but they can also be used for your standard POST/PATCH/DELETE requests if you setup an auth layer to verify those requests.&lt;/p&gt;
&lt;h2 id=&quot;adding-custom-metadata-to-api-responses&quot;&gt;Adding Custom Metadata to API Responses&lt;/h2&gt;
&lt;p&gt;Now that we have a CPT setup we can query the API for a list of events, a single event, and more (all documented reasonably well &lt;a href=&quot;https://developer.wordpress.org/rest-api/reference/posts/&quot;&gt;here on the REST API Handbook&lt;/a&gt;). Unfortunately, if you’re creating a CPT there’s a good chance the default schema won’t store everything you need and you’ll need to customize the response to add additional fields. There’s two ways of doing this that we explored and found as viable routes:&lt;/p&gt;
&lt;h3 id=&quot;the-native-wordpress-way&quot;&gt;The Native Wordpress Way&lt;/h3&gt;
&lt;p&gt;To add additional fields without using a plugin you’ll have to use the register_meta hook in your &lt;code&gt;functions.php&lt;/code&gt;. This is documented here, but is formatted as &lt;code&gt;register_meta(post_type, meta_field_name, array($args));&lt;/code&gt;. In our case wanted to add the city our event was taking place in (amongst other things):&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;register_meta(&apos;event&apos;, &apos;city&apos;, array(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     &apos;type&apos;         =&amp;gt; &apos;string&apos;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     &apos;description&apos;  =&amp;gt; &apos;An string containing the city in which the event is taking place.&apos;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     &apos;single&apos;       =&amp;gt; true,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;     &apos;show_in_rest&apos; =&amp;gt; true&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt; ));&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;event&lt;/code&gt; is our custom post type from earlier, and &lt;code&gt;city&lt;/code&gt; is the name of the metadata field we’re adding.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;type&lt;/code&gt; can be either a &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;object&lt;/code&gt;, or &lt;code&gt;integer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;description&lt;/code&gt; should be a plain English explanation for what the field is used.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;single&lt;/code&gt; tells Wordpress that this meta field should be used on an individual (or “single”) post.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;show_in_rest&lt;/code&gt; is what actually exposes the field on the API response.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;using-advanced-custom-fields-acf-for-custom-metadata&quot;&gt;Using Advanced Custom Fields (ACF) for Custom Metadata&lt;/h3&gt;
&lt;p&gt;The above way of registering custom metadata works well, but unfortunately left us with the issue of needing to either build custom metaboxes or having our client edit the content using the clunky default metaboxes, which wouldn’t work for fields where there might be zero, one, or several repeating items depending on the “Event” — enter using ACF Pro.&lt;/p&gt;
&lt;p&gt;ACF has been a staple of most Wordpress projects I’ve built in the past several years, and is one of maybe two or three plugins I can actively recommend using on a site&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. It’s &lt;em&gt;extremely&lt;/em&gt; easy to setup and customize, and by default has a much improved editing experience for editors than the default Wordpress metaboxes. Unfortunately integrating it with the Wordpress REST API isn’t officially supported just yet, and there wasn’t a clear answer on the best way to add data input through ACF forms to each API response.&lt;/p&gt;
&lt;h2 id=&quot;adding-the-featured-thumbnail-to-single-post-responses&quot;&gt;Adding the Featured Thumbnail to Single Post Responses&lt;/h2&gt;
&lt;p&gt;Oddly the Wordpress API only exposes the media ID for post‘s featured image rather than embedding it directly. While it would be pretty easy to get the image URL by querying the &lt;a href=&quot;https://developer.wordpress.org/rest-api/reference/media/&quot;&gt;media endpoint&lt;/a&gt; after receiving the first response it seemed wasteful to make multiple API calls if it could be avoided, and this wouldn’t scale well once we start showing lists of posts where they all have featured images. Enter the &lt;code&gt;_embed&lt;/code&gt; query param.&lt;/p&gt;
&lt;p&gt;This is briefly documented on the &lt;a href=&quot;https://developer.wordpress.org/rest-api/using-the-rest-api/linking-and-embedding&quot;&gt;Linking &amp;amp; Embedding&lt;/a&gt; page of the API Handbook, but simply requires adding a &lt;code&gt;?_embed&lt;/code&gt; query param to the end of your request, so a GET request to &lt;code&gt;/wp-json/wp/v2/events/&lt;/code&gt; becomes &lt;code&gt;/wp-json/wp/v2/events?_embed&lt;/code&gt;. It’s not entirely clear why the Wordpress team has taken this approach, but it updates the response to include an attribute called &lt;code&gt;wp:embedded&lt;/code&gt; on the response object, which includes all details about attached featured images.&lt;/p&gt;
&lt;p&gt;Just be wary if you’re fetching a large number of posts as this can balloon the JSON response size substantially.&lt;/p&gt;
&lt;hr&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;I otherwise avoid plugins at all costs as they tend to trade flexibility for stability, and are rarely written correctly. &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content:encoded></item><item><title>An Adventure in Blurring a Cross-Origin Image Client Side Using the HTML5 Canvas</title><link>https://robertnealan.com/an-adventure-in-blurring-a-cross-origin-image-client-side-using-the-html5-canvas/</link><guid isPermaLink="true">https://robertnealan.com/an-adventure-in-blurring-a-cross-origin-image-client-side-using-the-html5-canvas/</guid><description>While working as a frontend developer means I get to experiment with new javascript frameworks on at least a yearly basis, it&apos;s far less frequent that I get…</description><pubDate>Fri, 21 Oct 2016 02:45:00 GMT</pubDate><content:encoded>&lt;p&gt;While working as a frontend developer means I get to experiment with new javascript frameworks on at least a yearly basis, it’s far less frequent that I get to interact with new, native browser technologies, let alone ones that have wide enough support to be used in production. Thankfully Proton Radio, one of my [amazing] long-running clients has provided the exciting opportunity to experiment with the Web Audio API (more on that later) as well as the HTML5 Canvas in order to implement a variety of features that wouldn’t otherwise have been possible.&lt;/p&gt;
&lt;h2 id=&quot;the-project-and-the-problem&quot;&gt;The Project and the Problem&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://beta.protonradio.com/&quot;&gt;Proton Radio&lt;/a&gt; is an online radio station that continuously streams ~1-2 hour electronic DJ mixes 24 hours a day, and features a custom banner image for most of those mixes (for those that don’t have their own banner image we have a variety of fallback images so they still look spiffy). As part of our new Beta redesign we really wanted to minimize the noise by putting these unique banners front and center, and started looking at ways we could make the landing page feel unique to the current DJ mix by applying a matching unique full-page background.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://robertnealan.com/content/images/2016/10/1-1.jpg&quot; alt=&quot;Screenshot of Proton Beta prior to canvas background blur implementation.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;The Proton Beta prior to our canvas adventure.We knew we wanted to take that image in the middle and apply it to the gray background in an elegant way, but we weren’t quite sure of the best way to make it happen.&lt;/p&gt;
&lt;p&gt;Unfortunately, to make things more complicated all the original image assets were created at 578x291 pixel resolution (some dating from the early-2000’s), and stretching them out even on small screens causes them to quickly become extremely pixelated. While we hope to create new banners at higher resolutions in the future, redoing the entire back catalog of thousands of images just wouldn’t be practical.&lt;/p&gt;
&lt;h2 id=&quot;considering-the-options&quot;&gt;Considering the Options&lt;/h2&gt;
&lt;p&gt;We initially discussed extracting the color profile from the image to a CSS gradient to the background, but this seemed like a halfway solution as it wouldn’t have nearly as much depth as the images itself. Instead, we decided to explore the possibility of scaling up and applying a gaussian blur to the image itself as it would both mask any evidence of pixelation and would give the page a great sense of depth between the foreground and background.&lt;/p&gt;
&lt;h3 id=&quot;process-images-server-side&quot;&gt;Process Images Server-Side&lt;/h3&gt;
&lt;p&gt;The most obvious solution was to process all the banner images server-side to have a new 1920x1080, pre-blurred copy that we could then apply as a fullscreen CSS &lt;code&gt;background-image&lt;/code&gt; with &lt;code&gt;background-size: cover;&lt;/code&gt; to keep it in proportion. From a technical standpoint this would actually be easy to implement as open source image processing libraries are plentiful and simple to use, but on the downside our users would suddenly need to download an additional 150-200kb+ image that exists only to add some blurred, superficial ambiance — something we wanted to avoid if at all possible in our mission to keep page load time down.&lt;/p&gt;
&lt;h3 id=&quot;css3-filters&quot;&gt;CSS3 Filters&lt;/h3&gt;
&lt;p&gt;The second suggested solution was to use the CSS3 Blur filter, but as I suspected support is still &lt;a href=&quot;http://caniuse.com/#feat=css-filters&quot;&gt;pretty spotty&lt;/a&gt;, and the performance is abysmal enough to make the fans in my 2015 Macbook Pro sound like a jet engine about to take off. There’s also the annoying issue that the blur filter leaves a lighter ring around the image edge due to it assuming the off-canvas area is white/transparent, so you have to do temperamental negative margin hacks inside of a container element with &lt;code&gt;overflow: hidden;&lt;/code&gt; set to get it looking right.&lt;/p&gt;
&lt;p&gt;I look forward to the day CSS3 filters are production ready, but I’m guessing we’ve still got at least a few years to go.&lt;/p&gt;
&lt;h3 id=&quot;image-processing-with-javascript&quot;&gt;Image Processing With Javascript&lt;/h3&gt;
&lt;p&gt;This left us with our third option of processing the images client-side with javascript — an option I honestly wasn’t all too familiar with despite working in javascript on a daily basis, and assumed wouldn’t be reasonable from a performance standpoint on older devices.&lt;/p&gt;
&lt;p&gt;Looking into it I quickly figured out that we’d likely need to use a &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element, which based on a &lt;a href=&quot;https://www.html5rocks.com/en/tutorials/canvas/imagefilters/&quot;&gt;few different blog posts should allow me to apply almost any image filter imaginable&lt;/a&gt;. Unfortunately, up until this point I never completely grasped the purpose of the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element, so I decided to do some research and try to add some clarity, starting with the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial&quot;&gt;Mozilla Developer Network (MDN)&lt;/a&gt; Canvas tutorial.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; is an HTML element which can be used to draw graphics using scripting (usually JavaScript). This can, for instance, be used to draw graphs, make photo composition or simple (and not so simple) animations…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This quick description along with the rest of the article helped, but I still had only a vague understanding and too many unanswered questions. Why do we need an element to draw to when we have the DOM? Why can’t we just use SVG? What’s better about the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; compared to anything else? It wasn’t until I actually started playing around with the canvas in javascript and used some basic drawing methods that it really clicked.&lt;/p&gt;
&lt;p&gt;Looking back, I think the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; can be better introduced as “a rectangular DOM element that contains a 2-dimensional grid of pixels, onto which you can draw arbitrary lines, shapes, or graphics using x,y or vector coordinates relative to the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element itself, without the performance overhead normally involved with manipulating DOM elements.”&lt;/p&gt;
&lt;p&gt;Or more simply, it’s kinda like MSPaint for the browser, except you draw with code instead of a paintbrush tool. And it’s fast…real fast.&lt;/p&gt;
&lt;h2 id=&quot;getting-knee-deep-in-canvas-land&quot;&gt;Getting Knee Deep in Canvas Land&lt;/h2&gt;
&lt;p&gt;With all that in mind I quickly came across a few image blurring libraries, the most popular of which is an old-school standalone script called &lt;a href=&quot;http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html&quot;&gt;Stackblur.js&lt;/a&gt;. At first glance I was a bit wary as its author’s website hasn’t been updated in years and it lacks an official Github page, but it thankfully turns out there’s several popular forks of it on Github, including a NPM module called &lt;a href=&quot;https://github.com/flozz/StackBlur&quot;&gt;stackblur-canvas&lt;/a&gt; that adds a few extra features. As a plus, this fork also has just short of 500 stars and the occasional Github issue filed, so I can be a little more confident there’s some community support to push patches should it needed to be updated in the future.&lt;/p&gt;
&lt;p&gt;While setting it up and blurring an image based on the README was surprisingly quick, there were a few gotchas we figured out along the way.&lt;/p&gt;
&lt;h3 id=&quot;canvas-elements-are-dumb-by-design&quot;&gt;Canvas Elements Are Dumb by Design&lt;/h3&gt;
&lt;p&gt;Canvas elements are by design unaware of anything you draw in them other than the color value of each pixel. This can be frustrating if you need to get intelligent information out of a canvas element, but its what helps make them so performant compared to manipulating full DOM elements. Rather than keeping track of the position of a bunch of vector elements, its just a X/Y grid with a native API to help you draw to it. The downside of this is it also means that the canvas element is unaware of your original image’s aspect ratio, so you have to do those calculations prior to drawing into it and recalculate anytime there’s a window resize event.&lt;/p&gt;
&lt;p&gt;// resizeCanvas()
//
// Resizes the background canvas element to maintain img proportions
// while centering and stretching canvas to fill fullscreen.&lt;/p&gt;
&lt;p&gt;let resizeCanvas = function(img_ratio) {&lt;br&gt;
let window_w = window.innerWidth;&lt;br&gt;
let window_h = window.innerHeight;&lt;/p&gt;
&lt;p&gt;let window_ratio = window_w / window_h;&lt;/p&gt;
&lt;p&gt;if (img_ratio &amp;gt; window_ratio) {&lt;br&gt;
$(‘#dataCanvas’).css(‘height’, window_h).css(‘width’, ‘auto’);&lt;br&gt;
let canvas_w = $(‘#dataCanvas’).width();&lt;br&gt;
$(‘#dataCanvas’).css(‘left’, ((canvas_w - window_w)/2) * -1)&lt;br&gt;
.css(‘top’, ‘auto’);&lt;br&gt;
} else if (img_ratio &amp;lt; window_ratio) {&lt;br&gt;
$(‘#dataCanvas’).css(‘height’, ‘auto’)&lt;br&gt;
.css(‘width’, window_w);&lt;br&gt;
let canvas_h = $(‘#dataCanvas’).height();&lt;br&gt;
$(‘#dataCanvas’).css(‘left’, ‘auto’)&lt;br&gt;
.css(‘top’, ((canvas_h - window_h)/2) * -1);&lt;br&gt;
}&lt;br&gt;
};&lt;/p&gt;
&lt;h3 id=&quot;canvas-elements-require-cors-headers&quot;&gt;Canvas Elements Require CORS Headers&lt;/h3&gt;
&lt;p&gt;Canvas elements require proper CORS headers on images to be set prior to drawing, otherwise the canvas becomes “tainted” and you can no longer read information out of it due to the potential security implications. While we aren’t reading out any information for our application in an obvious way, behind the scenes it turns out Stackblur actually applies the image to the canvas, reads out all the pixel data, calculates the new blurred values, and then applies that over the original image.&lt;/p&gt;
&lt;p&gt;The good news is that setting CORS headers for a specific directory is actually really simple in most HTTP servers, and for us amounted to adding the three lines of code below to our Apache &lt;code&gt;httpd.conf&lt;/code&gt; file (in many cases this will/should actually be a separate &lt;code&gt;.conf&lt;/code&gt; file in the &lt;code&gt;/etc/apache2/sites-available/&lt;/code&gt; folder specific to the VirtualHost in question). You’ll also likely need to set the &lt;code&gt;img.crossorigin&lt;/code&gt; attribute to &lt;code&gt;&apos;&apos;&lt;/code&gt; or &lt;code&gt;&apos;anonymous&apos;&lt;/code&gt; in order to prevent it from having issues in certain browsers (you can read more about &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image&quot;&gt;CORS enabled images on MDN’s article&lt;/a&gt;), though browser support for this attribute seems to be inconsistently implemented at best.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;apache&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Directory&lt;/span&gt;&lt;span style=&quot;color:#9ECBFF&quot;&gt; &quot;/path/to/folder/containing/images&quot;&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  # If you have specific sub-domains you can list them instead&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6A737D&quot;&gt;  # of using the &apos;*&apos; wildcard.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#F97583&quot;&gt;  Header&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; always &lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt; Access-Control-&lt;/span&gt;&lt;span style=&quot;color:#F97583&quot;&gt;Allow&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;-Origin &quot;*&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#B392F0&quot;&gt;Directory&lt;/span&gt;&lt;span style=&quot;color:#E1E4E8&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;android-44-and-below-dont-support-image-cors-rules&quot;&gt;Android 4.4 and Below Don’t Support Image CORS Rules&lt;/h3&gt;
&lt;p&gt;Android 4.4 and below aren’t a huge part of our user base, but at ~2.5% its still enough traffic to be concerned when there’s a application-breaking bug present. In our case we kept getting a cryptic “Uncaught Error: unable to access image data: Error: unable to access local image data: Error: SECURITY_ERR: DOM Exception 18” reported in &lt;a href=&quot;http://bugsnag.com/&quot;&gt;Bugsnag&lt;/a&gt;&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; for old Android devices that didn’t seem to be accurately working with sourcemaps and had no clear answer we could find on StackOverflow. As luck would have it though, I temporarily disabled the background blur for the better part of an afternoon and the error suddenly disappeared. With an Android emulator I was able to reproduce the error, which revealed a less-cryptic alert message I was then able to trace back to the uncompiled Stackblur.js library. I thought it might have to do with the outdated &lt;code&gt;netscape.security.PrivilegeManager&lt;/code&gt; rules (the &lt;code&gt;stackblur-canvas&lt;/code&gt; package has since removed these), but manually omitting them didn’t seem to make a difference.&lt;/p&gt;
&lt;p&gt;While I couldn’t find any answers via Google, I finally looked deeper into CORS rules and support to see if I was missing something — turns out that Android 4.3 and below specifically don’t support CORS for images in a canvas — exactly what we were trying to do! You’d think this would be a common point of discussion, but with Android &amp;lt;4.3 being on its way out I ended up discovering it in the footnotes of the &lt;a href=&quot;http://caniuse.com/#feat=cors&quot;&gt;CanIUse CORS page&lt;/a&gt; (only shows up “Show All” is enabled).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://robertnealan.com/content/images/2016/10/2.jpg&quot; alt=&quot;Screenshot of CORS page on caniuse.com&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of caniuse.com’s CORS InformationAlways make sure to click “Show All” and double check the footnotes for potentially vital &lt;del&gt;life&lt;/del&gt; time-saving information.&lt;/p&gt;
&lt;p&gt;If you’re serving images from the same domain as your client application this of course won’t matter, but in our case changing the infrastructure to serve our flyers off the same domain as our Beta, Staging, and local environments wasn’t worth the extra complexity it’d introduce to our already-complex infrastructure setup.&lt;/p&gt;
&lt;p&gt;After some deliberation we agreed that not having a blurred background image for older Android users was an acceptable level of “graceful degradation”, so I added a simple method to detect Android browser versions and skip over the &lt;code&gt;backgroundBlur&lt;/code&gt; method for those with problems&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1-2&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. Despite caniuse.com showing that Android 4.4 &lt;em&gt;should&lt;/em&gt; support CORS rules on images, we noticed that about half our Android 4.4 users were experiencing problems so we opted to exclude them also.&lt;/p&gt;
&lt;p&gt;// whichAndroid()
//
// Checks the userAgent to see if it’s an Android device and returns the version
// number if true. Returns false on all other browsers/devices.&lt;/p&gt;
&lt;p&gt;let whichAndroid = function() {&lt;br&gt;
var userAgent = navigator.userAgent.toLowerCase();&lt;br&gt;
var check = userAgent.match(/android\\s([0-9.]*)/);&lt;br&gt;
return check ? check[1] : false;&lt;br&gt;
};&lt;/p&gt;
&lt;h2 id=&quot;chaining-it-all-together&quot;&gt;Chaining it All Together&lt;/h2&gt;
&lt;p&gt;After a lot of research, some trial and error, and a bit of luck, we pushed our last update to the background blur several weeks back and haven’t seen any related bugs since. One last minute change was to hide the &lt;code&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; element with the CSS opacity property until after it finishes blurring, then animate it in using the CSS &lt;code&gt;transition&lt;/code&gt; property — this really tied it together and made the whole experience feel more elegant than if it flickered in and out until it was properly blurred.&lt;/p&gt;
&lt;p&gt;The screenshot below is what it looks like right now, but you can check it out &lt;a href=&quot;https://beta.protonradio.com/&quot;&gt;live at Proton Beta&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://robertnealan.com/content/images/2016/10/3-1.jpg&quot; alt=&quot;Screenshot of Proton Beta with background blur&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;The Proton Beta with background blur applied.It took a lot of work, but in the end we couldn’t be happier with how great the page looks with the blur effect.&lt;/p&gt;
&lt;p&gt;For readability’s sake here’s a Gist with all the relevant code from my Marionette/Backbone view (excludes the Apache CORS rules). Depending on your choice of framework/tools it’ll likely need to be adapted, but it should be a good starting point for most views written in javascript.&lt;/p&gt;
&lt;h4 id=&quot;blurbackground-method&quot;&gt;blurBackground Method&lt;/h4&gt;
&lt;p&gt;Show.RadioView = Marionette.LayoutView.extend({
blurBackground: function() {
if(whichAndroid() &amp;gt; 4.4 || whichAndroid() === false) {
const img = new Image();
const canvas = document.getElementById(‘dataCanvas’);
const radius = 50;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // Make it work with CORS&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  img.crossOrigin = &apos;&apos;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  img.src = this.imageURL;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  // Wait till image loads&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  img.onload = (e) =&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // Setup image vars&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    let img_w = img.naturalWidth;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    let img_h = img.naturalHeight;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    let img_ratio = img_w / img_h;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    let window_w = window.innerWidth;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    let window_h = window.innerHeight;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    let canvas_h = window_h;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    let canvas_w = (window_h/img_h * img_w);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    canvas.height = img_h;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    canvas.width = img_w;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // I have a global Backbone “resize” event that I listen &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // for in Marionette, but you can also listen manually here.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // $(window).on(&apos;resize&apos;, () =&amp;gt; resizeCanvas(img_ratio));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    StackBlur.image(img, canvas, radius, false);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    resizeCanvas(img_ratio)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // Make the canvas visible once processing is done. I use a&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    // CSS3 transition to have it fade in after the class is added.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    $(canvas).addClass(&apos;is-visible&apos;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;br&gt;
});&lt;/p&gt;
&lt;p&gt;// resizeCanvas()&lt;br&gt;
//&lt;br&gt;
// Resizes the background canvas element to maintain img proportions&lt;br&gt;
// while centering and stretching canvas to fill fullscreen.&lt;/p&gt;
&lt;p&gt;let resizeCanvas = function(img_ratio) {&lt;br&gt;
let window_w = window.innerWidth;&lt;br&gt;
let window_h = window.innerHeight;&lt;/p&gt;
&lt;p&gt;let window_ratio = window_w / window_h;&lt;/p&gt;
&lt;p&gt;if (img_ratio &amp;gt; window_ratio) {&lt;br&gt;
$(‘#dataCanvas’).css(‘height’, window_h).css(‘width’, ‘auto’);&lt;br&gt;
let canvas_w = $(‘#dataCanvas’).width();&lt;br&gt;
$(‘#dataCanvas’).css(‘left’, ((canvas_w - window_w)/2) * -1)&lt;br&gt;
.css(‘top’, ‘auto’);&lt;br&gt;
} else if (img_ratio &amp;lt; window_ratio) {&lt;br&gt;
$(‘#dataCanvas’).css(‘height’, ‘auto’)&lt;br&gt;
.css(‘width’, window_w);&lt;br&gt;
let canvas_h = $(‘#dataCanvas’).height();&lt;br&gt;
$(‘#dataCanvas’).css(‘left’, ‘auto’)&lt;br&gt;
.css(‘top’, ((canvas_h - window_h)/2) * -1);&lt;br&gt;
}&lt;br&gt;
};&lt;/p&gt;
&lt;p&gt;let whichAndroid = function() {&lt;br&gt;
var userAgent = navigator.userAgent.toLowerCase();&lt;br&gt;
var check = userAgent.match(/android\\s([0-9.]*)/);&lt;br&gt;
return check ? check[1] : false;&lt;br&gt;
};&lt;/p&gt;
&lt;p&gt;Notice something amiss or want to chat? Feel free to get in touch with me at &lt;a href=&quot;mailto:rob@atomidesign.com&quot;&gt;rob@atomidesign.com&lt;/a&gt;!&lt;/p&gt;
&lt;hr&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;I normally wouldn’t condone using User Agent sniffing in production, but in this case there’s no accurate way to detect support for this feature in a “progressive enhancement” manner, and the browser in question is old enough that its highly unlikely that the UserAgent will ever change. &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-2&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content:encoded></item><item><title>Day 1 of Writing a Webapp: Getting My Hands Dirty with NodeJS, Express, and MongoDB</title><link>https://robertnealan.com/day-1-of-writing-a-webapp-getting-my-hands-dirty-with-nodejs-express-and-mongodb/</link><guid isPermaLink="true">https://robertnealan.com/day-1-of-writing-a-webapp-getting-my-hands-dirty-with-nodejs-express-and-mongodb/</guid><description>On any given day I probably have at least a dozen new ideas of what to build floating around in my head, but for one reason or another most come and go…</description><pubDate>Tue, 18 Oct 2016 03:47:00 GMT</pubDate><content:encoded>&lt;p&gt;On any given day I probably have at least a dozen new ideas of what to build floating around in my head, but for one reason or another most come and go without much further thought. About a year ago now one of those ideas floated into my head, and ever since it hasn’t left.&lt;/p&gt;
&lt;p&gt;Rather than letting this idea continue to nag at the back of my mind I’ve finally decided to do something about it, and will periodically blog about it along the way to help keep myself accountable and self-reflect along the way.&lt;/p&gt;
&lt;h2 id=&quot;the-problem-the-solution&quot;&gt;The Problem, The Solution&lt;/h2&gt;
&lt;p&gt;Without a doubt the &lt;em&gt;biggest&lt;/em&gt; pain year-after-year as a self-employed individual is keeping my finances in order and paying my taxes upfront/on time. Almost every how-to or blog article about getting started on your own business repeatedly screams at you to stay on top of your finances, yet it seems to repeatedly be one of the most common problems for almost every recently self-employed individual I meet. There’s tons of financial software out there, but it’s almost always targeted at accountants or larger businesses (overkill for a contractor), or is meant for people who are employed full time by the same company. Instead, contractors/freelancers are left hodge-podging all their finance information together using various different software that provide subpar solutions&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. Ironically the best piece of software I’ve used for tracking my expenses has been Freshbooks, an amazing SAAS product whose primary purpose is instead for invoicing.&lt;/p&gt;
&lt;p&gt;Enter Transact — my plan for a simple web and mobile app that helps me keep track of not only my income and expenses, but also details about each expense to create a clear paper trail. Right now I’m just trying to hit my head against a wall build a [mostly] functional webapp that consumes its own API, that can then be reused to connect to from a React Native powered iOS/Android application.&lt;/p&gt;
&lt;p&gt;This might be naive, but I figure if I can build an app that I personally find useful and streamlined enough to use on a day-to-day basis, then there’s probably other self-employed people out there who will find value in it.&lt;/p&gt;
&lt;h2 id=&quot;stepping-off-the-deep-end&quot;&gt;Stepping Off the Deep End&lt;/h2&gt;
&lt;p&gt;I’m a designer and frontend developer by practice, so delving into backend code is always a little awkward. On the other hand, writing a backend application from scratch feels completely insane.&lt;/p&gt;
&lt;p&gt;Prior to leaving San Francisco I briefly started working on the same idea with my friend and backend developer extraordinaire Dev, who started hobbling together a proof-of-concept Rails API for our purposes.&lt;/p&gt;
&lt;p&gt;Unfortunately, I don’t know Rails.&lt;/p&gt;
&lt;p&gt;On more than one occasion I’ve tried to teach myself, but without the ability to dedicate a long period of time to learning the syntax, lingo, and other “gotchas” of the Rails ecosystem it would be an excruciatingly slow, painful march of progress, and at this point I just want to get something rolling.&lt;/p&gt;
&lt;p&gt;The good news is I &lt;em&gt;do&lt;/em&gt; know javascript, and have spent my fair share of time working within the confines of NodeJS/Express applications in the past (albeit mostly on the frontend). I’m sure there’s a hundred reasons why “Framework A is more suited to this than NodeJS” or how “NodeJS really sucks and is going to cause problems in a year”, but for now I just need to optimize for progress based on what I already know and am at least vaguely familiar with.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://robertnealan.com/content/images/2016/10/1-2.jpg&quot; alt=&quot;Screenshot of ExpressJS App Source&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Screenshot of the code-in-progress…So far its been a constant “be confused for 2+ hours, solve one tiny problem” sort of day.&lt;/p&gt;
&lt;h3 id=&quot;progress-so-far&quot;&gt;Progress So Far&lt;/h3&gt;
&lt;p&gt;I’m writing this as a brief break from coding, but as of this afternoon I’ve managed to scrape together a basic ExpressJS + MongoDB application with user authentication using the Node Passport package that has its own API that it self-consumes so adding other clients (iOS/Android) in the future will be a much smoother process. Currently I’m using Babel to enable using ES2015 (ES6) syntax and ESLint to help keep my code quality in check.&lt;/p&gt;
&lt;p&gt;I’m admittedly a little wary of using MongoDB as heard some of the scaling horror stories, but for now it’s the fastest and easiest way to get things up and moving (famous last words?). So far its running without a hitch, though I’m still a little fuzzy on some of the core concepts, especially around how Mongoose abstracts interacting with Mongo and how you properly reference models from one another using Mongoose’s helpers.&lt;/p&gt;
&lt;p&gt;For getting bank transaction data I’m testing out the Plaid API, which as far as I can tell is the only option out there short of writing your own custom bank integrations (no thanks). Thankfully, their documentation and API are in the best of their class and they include libraries for most major backend languages/frameworks.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://robertnealan.com/content/images/2016/10/2-1.jpg&quot; alt=&quot;Screenshot of Plaid Documentation&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Think you’ve got good docs?Here’s a snippet of Plaid’s Connect docs, which is the basic endpoint allowing you to pull in both general bank account information as well as detailed transaction data. They’re without a doubt some of the clearest, best docs I’ve ever seen.&lt;/p&gt;
&lt;p&gt;Overall I have to say I’m really impressed with how the Node ecosystem has grown since I last looked at it, and how quickly I’ve been able to get a basic server application running. On the downside, it seems to be weirdly difficult to find good, complex Node/Express applications to use as a point of reference compared to other large communities (aka Rails, Backbone, React, etc). Over the next few days I hope to better learn how Mongoose (the Mongo ODM) works, be able to pull real bank data from my own Wells Fargo business accounts, and start calculating a rough estimated amount for how much tax I owe based a simple calculation of income minus expenses.&lt;/p&gt;
&lt;hr&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;I tested out Intuit’s “Quickbooks Self Employed” but received an error when trying to connect my Wells Fargo Business Account. That aside, after connecting my person account it still seemed to be riddled with bugs and didn’t serve the purpose I’m looking to fill. That said, the fact that a company as large as Intuit is working a product targeting self-employed workers only helps prove how large of a market freelancers are becoming, especially with the proliferation of contractor-based companies like Uber. &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content:encoded></item><item><title>Why Designers Should Code</title><link>https://robertnealan.com/why-designers-should-code/</link><guid isPermaLink="true">https://robertnealan.com/why-designers-should-code/</guid><description>Over the past several years the topic of the designer who codes has generated quite the lot of controversy within the tech community.</description><pubDate>Mon, 22 Aug 2016 08:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Over the past several years the topic of the designer who codes has generated quite the lot of controversy within the tech community. Some camps believe designers shouldn’t distract themselves with code and instead maintain their roots in graphic design as pixel-pushers, while others think that designers should be getting their hands dirty with code down in the trenches alongside their developer cohorts.&lt;/p&gt;
&lt;p&gt;As I’ve written on the topic on more than one occasion&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; and non-coincidentally run a meetup group called &lt;a href=&quot;http://dwc.io/&quot;&gt;Designers Who Code&lt;/a&gt;, it should come as no secret that I fall into the latter camp.&lt;/p&gt;
&lt;h2 id=&quot;at-the-outset&quot;&gt;At the Outset&lt;/h2&gt;
&lt;p&gt;When I first started teaching myself web design back in university I didn’t have any mentors to consult or tell me what to do. While I had plenty of friends in the computer science program, I was surprised to discover that they were all learning old-school Java/C++, and knew almost nothing in the realm of modern web languages nor web application development &lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1-2&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. I’d had some exposure to the world of table-based HTML layouts and &lt;code&gt;&amp;lt;font&amp;gt;&lt;/code&gt; tags back in high school, so in my need to make extra money to pay for beer my rent, I figured I’d just learn by Googling the hell out of anything and everything.&lt;/p&gt;
&lt;p&gt;This way of learning has its faults, but as I had nobody telling me what or what not to do, it just seemed like common sense that I’d code up my own designs too. At the time they were mostly simple static HTML/CSS layouts, so anything I didn’t already know I could quickly figure out (aka frantically Google and hit my head against the keyboard until 4am). It wasn’t until I moved to San Francisco in 2012 that I found out that designers coding wasn’t the norm, and what seemed like common sense to me was a foreign concept to most people I met.&lt;/p&gt;
&lt;p&gt;This quote from Jeremy Bell from the blog of [the regretfully defunct] Teehan + Lax sums up what I encountered and how I felt pretty accurately&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1-3&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;…If I was to be a designer, I couldn’t be a developer. There was never an option to do both. Instead, I’d spend hours designing static pages in Photoshop that would simply be handed to the developers for reproduction in HTML. There was rarely an opportunity to collaborate throughout the process. Hell, we barely spoke. Sometimes we weren’t even in the same timezone, let alone the same room.&lt;/p&gt;
&lt;p&gt;That was 16 years ago, and not much has changed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As I’ve previously written about, at my first full-time web design job I encountered the same problem — I was hired as the UI/UX Designer in party because I &lt;em&gt;could&lt;/em&gt; code and communicate with developers in a way they’d understand, but within the first few hours of my first day the CTO quickly asserted that, “Designers don’t touch code” (a huge sticking point that resulted in a relatively short-lived employment)&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1-4&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. While the concept of designers being anything more than pixel-pushers still remains a foreign concept to many companies, it thankfully seem to have been gaining more and more traction over the past few years as job listings for UI/UX Designers now regularly include “HTML/CSS” as requirements or nice-to-haves, or are listed under the guise of a “UI Developer” position instead.&lt;/p&gt;
&lt;p&gt;You might ask, “So what, why &lt;em&gt;should&lt;/em&gt; designers code?”&lt;/p&gt;
&lt;p&gt;The full answer is a long one, but in short a [good] designer isn’t someone who just makes things “pretty” or “functional”, but someone who strives to understand the problems at hand and develop the optimal solution to that problem, whatever set of skills that might require. This isn’t to say a designers should do everything, but a good designer should know where they or their colleagues can deliver more value more efficiently and coordinate their role appropriately. In this case, there’s numerous clear benefits to the designer building the frontend templates themselves.&lt;/p&gt;
&lt;h2 id=&quot;tightening-the-feedback-loop&quot;&gt;Tightening the Feedback Loop&lt;/h2&gt;
&lt;p&gt;Nearly every web designer, myself included, has numerous stories of handing off mockups to a developer only to have the built version look nothing like the mockups that were provided. At the time it’s always easy to rant and criticize the developer, but what else would you expect when you’re handing off the responsibility of implementing the design to someone whose job is only tangentially related to design, and often doesn’t care about the design nearly as much as you do?&lt;/p&gt;
&lt;p&gt;This is by no means meant to criticize developers, but instead quite the opposite as I suspect a very similar problem would arise if the situation were reversed and developers gave designers specs to implement a new a feature. It might “work” in the designer’s eyes, but any experienced developer would likely cringe during the code review. Instead, a developer’s job should be to build complex features and applications, not to fret over a few pixels here, a font weight there, and the crazy nuances of cross-browser CSS — that’s the designer’s job, and it makes infinitely more sense for the designer to be able to tweak those nuances directly rather than hunting down, bothering, and distracting a developer from their own responsibilities.&lt;/p&gt;
&lt;p&gt;In reading a great Medium article by David Cole&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1-5&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; I came across a rather strong quote from Jennifer Tidwell&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1-6&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;So there’s lots of good stuff to learn before you can create production-quality software systems. But here’s what I worry about: it takes years to learn it well, and this is what a lot of good software engineers do for 50+ hours per week, building knowledge and picking up new skills. Practice, practice, practice.&lt;/p&gt;
&lt;p&gt;Hey, designer. Can you afford to invest those years?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Cole goes on to dispute Tidwell by arguing that tools built for designers will help alleviate that learning curve, which while true to a certain degree, I think it misses the larger point at hand.&lt;/p&gt;
&lt;p&gt;Designers don’t need to practice 50 hours/week on development because the skills they need to cover design responsibilities aren’t nearly as broad as your typical developer. Designers don’t need to build a full javascript single page app (SPA) or an efficient Rails API to implement their designs effectively&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1-7&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;; instead, they need to be able to work with primarily HTML and CSS (or SASS/LESS/etc), to build code-based static templates of their designs that can then (if needed) be taken by a developer and integrated into a larger application.&lt;/p&gt;
&lt;p&gt;A developer who isn’t trained in design nor practices it on a daily basis isn’t going to notice the minute pixel differences a designer does, and being able to directly and immediately make those changes yourself helps tighten the designer/developer feedback loop in a way that pawning off frontend development responsibilities will never be able to match. Instead of a 12+ step process of delayed designer-developer communication, it instead becomes something more akin to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Wireframes + Mockups&lt;/li&gt;
&lt;li&gt;Build HTML rapid prototypes to test design elements.&lt;/li&gt;
&lt;li&gt;Build templates from mockups, making edits and adjustments as needed along the way.&lt;/li&gt;
&lt;li&gt;Iterate.&lt;/li&gt;
&lt;li&gt;Hand off templates to developer.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This not only makes for a much faster iteration cycle, but results in both a better end-product and frees up developers time so they can focus on building features rather than making small design tweaks. Additionally, any time you’re discussing changes to an existing site with your product manager or management, rather than going through the full gambit of producing an updated mockup and iterating with your developer, you can instead often fire up Chrome Developer Tools or Firebug and test out the edits in real time, discuss, and make a fast decision right then and there.&lt;/p&gt;
&lt;h2 id=&quot;briefly-on-the-topic-of-css--javascript&quot;&gt;Briefly on the topic of CSS &amp;amp; Javascript&lt;/h2&gt;
&lt;p&gt;CSS itself as a “programming language” is incredibly easy to criticize given it’s problematic cross-browser history&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1-8&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; and inconsistent syntax, but if someone has to deal with its insane idiosyncrasies across half a dozen browsers across dozens of devices with versions dating back at least several years, who better than the one person who &lt;em&gt;really&lt;/em&gt; cares enough to fight their way through it all? And realistically, once you’ve used CSS long enough on a regular basis you start to quickly learn the quirks and ins and outs of the language, and how to use it in a way that’s effective and cross-browser friendly.&lt;/p&gt;
&lt;p&gt;To add to the mockup-to-code problem, anyone who has worked both sides of design and front-end development knows that what works in Photoshop/Sketch/[InsertToolHere] almost never perfectly translates 1:1 to what various browsers do, and you always need to make adjustments along the way. The design’s not done until it’s shipped, and trying to freeze it after you deliver some mockups to your development team is only doing the job halfway, and any time you try to lock-in a project that requires creative thinking you’re going to achieve subpar results.&lt;/p&gt;
&lt;p&gt;Regarding javascript, I personally love to learn new things and ended up diving head-first into its dark and magical ecosystem of libraries, frameworks, and package managers that install other package managers. I don’t think this level of javascript knowledge is necessary for the majority of designers, but a minimal level of javascript knowledge goes a long way in communicating some of the finer points of your design. Want to simulate a panel or modal animating into view in a way that requires toggling or modifying style properties? Rather than mocking it up in After Effects or Keynote, you can actually &lt;em&gt;build&lt;/em&gt; that animation exactly how you want it the first time around, and not nitpick with a developer about how it’s off by 50ms or how it doesn’t feel “quite right”.&lt;/p&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;There’s much, &lt;em&gt;much&lt;/em&gt; more to be written about on this topic, and I intend to do so over the coming weeks (and probably months). I’ve only begun to scratch the tip of the iceberg in my research efforts, and already I have well over a dozen articles from other designers and developers on the topic. As I continue to write more I might circle back and make adjustments/additions, so if you have something to say on the topic feel free reach out by Googlechat at &lt;a href=&quot;mailto:robertnealan@gmail.com&quot;&gt;robertnealan@gmail.com&lt;/a&gt; or email me at &lt;a href=&quot;mailto:rob@atomidesign.com&quot;&gt;rob@atomidesign.com&lt;/a&gt; — I’d love to chat.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;This is the first in a planned series of articles on the topic of being a designer who codes. As I publish additional articles in the series they will appear here accordingly. Cover photo is a screenshot of the Proton Radio Beta, a just publicly launched client work-in-progress.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;I’m looking at you Internet Explorer 6 through 10… &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-2&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1-3&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-3&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1-4&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-4&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1-5&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-5&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;sup&gt;5&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1-6&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-6&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;sup&gt;6&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1-7&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-7&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;sup&gt;7&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1-8&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-8&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;sup&gt;8&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content:encoded></item><item><title>Working Remotely as a Digital Nomad While Traveling</title><link>https://robertnealan.com/working-remotely-as-a-digital-nomad-while-traveling/</link><guid isPermaLink="true">https://robertnealan.com/working-remotely-as-a-digital-nomad-while-traveling/</guid><description>On June 3rd, 2016 my girlfriend and I left San Francisco for New York City, kicking off the start of a 6 1/2 month journey that would take us around the world…</description><pubDate>Sun, 14 Aug 2016 09:40:00 GMT</pubDate><content:encoded>&lt;p&gt;On June 3rd, 2016 my girlfriend and I left San Francisco for New York City, kicking off the start of a 6 1/2 month journey that would take us around the world until we return to California just before the Christmas holiday.&lt;/p&gt;
&lt;p&gt;While its all been &lt;em&gt;extremely&lt;/em&gt; exciting, traveling for the better half of a year presented an interesting predicament as traveling tends to be expensive, and I’m regretfully not rich (yet). The good news is I already almost always work remotely and most places we’ve been traveling are &lt;em&gt;significantly&lt;/em&gt; cheaper than living in San Francisco, so making the jump to being a digital nomad is relatively seamless. In fact, I did the math on our former San Francisco one bedroom apartment’s monthly rent, and it came out to an inane $77.71/day — more than we’ve generally spent on housing, food, and all living costs combined, especially now that we’re in Thailand.&lt;/p&gt;
&lt;p&gt;That said, there’s still some considerations to be had and &lt;em&gt;a lot&lt;/em&gt; of preparation to be made in advance with this kind of trip. This is definitely written from the point of view of a web contractor, but will hopefully be applicable to anyone looking to transition to being a digital nomad for.&lt;/p&gt;
&lt;h2 id=&quot;talk-to-clients-as-early-as-possible&quot;&gt;Talk to clients as early as possible!&lt;/h2&gt;
&lt;p&gt;I wanted to believe work would be a 100% seamless transition where clients wouldn’t even know I’m on an island in the Gulf of Thailand, but in reality there’s going to be a few hiccups along the way. Unless you plan on staying in one place long-term, assume you’ll have at least a few days where you don’t have a working cell phone and/or internet fast enough to upload your work (or no internet at all). Chances are this will happen more frequently if you’re traveling in second and third-world countries, but even in highly developed places like Europe you’ll likely find yourself with a few days that are a wash.&lt;/p&gt;
&lt;p&gt;While I do my best to avoid these situations whenever possible, you need clients who will be understanding when you do fall off the grid for 24-48 hours (power/internet here sometimes drops randomly for hours at a time!), and if anything be excited for the journey you’re about to take. In the event that an existing client (or employer) isn’t comfortable with that kind of possibility, you need to work with them to wind things down leading up to your departure, and if possible help them get your replacement up to speed sooner than later.&lt;/p&gt;
&lt;h2 id=&quot;be-realistic-about-how-much-you-can-work-and-communicate-when-you-cant&quot;&gt;Be realistic about how much you can work and communicate when you can’t.&lt;/h2&gt;
&lt;p&gt;Working constantly while traveling is not like working at home — it’s way more chaotic, exhausting, and ultimately takes time away from enjoying all the exciting things happening around you. 30 hour work weeks may sound like living the dream compared to the 40+ hour work weeks most people experience at home, but when you’re hopping around the world on planes and trains there’s a good chance those 30 hours will feel a lot more like 60. Plan your work ahead as much as possible, and talk to your client about working extra hours leading up to and following periods where you know you won’t be able to put in your normal amount of work. Research where you’re going ahead of time, and if you know internet might be spotty be sure to let your client know ahead of time.&lt;/p&gt;
&lt;h2 id=&quot;be-honest-and-dont-be-afraid-to-turn-down-clients&quot;&gt;Be honest and don’t be afraid to turn down clients.&lt;/h2&gt;
&lt;p&gt;This is arguably good advice for even non-nomads, but it’s especially important when your traveling and time is limited. Be upfront and honest with both yourselves and your client(s)/potential client(s) about you can and can’t do, and strongly consider not just the number of hours you’ll be working, but also the responsibility you’ll owe to your client to do a quality job within the timeline you’re agreeing to. It’s always tough to say no when you’ve got dollar signs in your eyes, but unless you’re incredibly strapped for cash you should aim for a balance between work and enjoying the new culture around you.&lt;/p&gt;
&lt;h2 id=&quot;dont-compromise-just-because-youre-traveling&quot;&gt;Don’t compromise just because you’re traveling.&lt;/h2&gt;
&lt;p&gt;I have no idea what was in the water in July, but I personally had an onslaught of potential projects (at least 8!) thrown my way over a period of two weeks, and am forever thankful that I turned down all but one. Of the other ~7 that I turned down, at least 2 asked if I could relocate to their location earlier than the planned end of our trip, and one even asked what my discounted rate was as I was out of the country where cost of living is cheaper. (Spoiler Alert: I only offer “discounted” rates for long-term retainer-based contracts of 2+ months at 40+ hours/month or more as there’s an inherent benefit in not needing to constantly follow up on new project leads while managing a dozen different projects.).&lt;/p&gt;
&lt;p&gt;There’s something to be said about full time salaries being adjusted based on cost of living, but as a contractor you’re selling your expertise, skill, and most importantly your time. If a client wants to hire a cheaper overseas contractor they are more than welcome to do so, but you shouldn’t make yourself that contractor.&lt;/p&gt;
&lt;h2 id=&quot;the-internet-is-your-friend-seriously&quot;&gt;The Internet is your friend (seriously).&lt;/h2&gt;
&lt;p&gt;There’s a &lt;em&gt;huge&lt;/em&gt; wealth of resources out there to help you plan around your work needs — use them. My personal favorites have been a few travel staples like &lt;a href=&quot;https://lonelyplanet.com/&quot;&gt;lonelyplanet.com&lt;/a&gt; and &lt;a href=&quot;https://wikitravel.org/&quot;&gt;wikitravel.org&lt;/a&gt;, and a few lesser known ones like &lt;a href=&quot;https://nomadlist.com/&quot;&gt;nomadlist.com&lt;/a&gt; and &lt;a href=&quot;https://nomadforum.io/&quot;&gt;nomadforum.io&lt;/a&gt;. Also, if you’re going to Southeast Asia be sure to check out Facebook Groups — while we mostly use Facebook for connecting with friends in the United States, there seems to be a group in each city for literally &lt;em&gt;everything&lt;/em&gt;, from meeting other expats to dating to renting an apartment.&lt;/p&gt;
&lt;h2 id=&quot;get-used-to-working-offline&quot;&gt;Get used to working offline.&lt;/h2&gt;
&lt;p&gt;I might work as a web designer and developer, but not having internet can’t be an excuse for not getting any work done. In the weeks leading up to traveling try intentionally turning off your wifi for a half day at a time and figure out what you can and can’t do while offline. Work on gradually making sure anything you normally would need the internet for can be done offline, and if it can’t then give yourself a list of alternative tasks you can do in the meantime. Prior to leaving I gradually made sure all my web projects can run locally without an internet connection and training myself to use &lt;a href=&quot;https://kapeli.com/dash&quot;&gt;Dash for OSX&lt;/a&gt; to read docs rather than searching online. For one project it admittedly required a good few modifications to the backend server, but more than paid for itself when I was able to do a solid 8 hours of work while on the slow ferry from Athens to Milos in the Greek Isles.&lt;/p&gt;
&lt;p&gt;If there’s any large uploads/downloads you’ll need to make be sure to do them either before you leave or while you’re in major cities where connections are fast and latency to US services are low — it’s easy to forget when living in the US or Europe, but uploading/downloading to a server on the other side of the world can take 100x as long even when you have a fast local connection.&lt;/p&gt;
&lt;h2 id=&quot;work-asynchronously&quot;&gt;Work Asynchronously&lt;/h2&gt;
&lt;p&gt;Taking 1AM calls is part of the deal you make when you choose to work remotely and travel the world, but it definitely shouldn’t be the norm. Make sure that whatever client’s you’re keeping or accepting are used to working in an asynchronous manner via either email, chat applications like Slack, or project management applications like &lt;a href=&quot;https://github.com/&quot;&gt;Github&lt;/a&gt;, &lt;a href=&quot;https://asana.com/&quot;&gt;Asana&lt;/a&gt;, or &lt;a href=&quot;https://trello.com/&quot;&gt;Trello&lt;/a&gt;. My primary two clients have employees around the world across at least a dozen timezones, and using Slack for almost all our communication has made it barely any different than when I was living in San Francisco. The main thing you (and your client) need to keep in mind is that &lt;em&gt;every sentence counts&lt;/em&gt; when you get to be on a 12+ hour time difference. If you forget to say something or you’re not clear in what you need, that could mean another 24 hour delay from your original message.&lt;/p&gt;
&lt;p&gt;If you haven’t already, check out &lt;a href=&quot;https://www.amazon.com/Remote-Office-Required-Jason-Fried/dp/0804137501&quot;&gt;Remote by Jason Fried&lt;/a&gt; (founder of &lt;a href=&quot;https://basecamp.com/&quot;&gt;37Signals/Basecamp&lt;/a&gt;). It’s admittedly at times a bit general, but overall it lays down a lot of common sense principals for both individuals and clients/employers that can help make working remotely successful.&lt;/p&gt;
&lt;h2 id=&quot;get-a-vpn-virtual-private-network&quot;&gt;Get a VPN (Virtual Private Network)&lt;/h2&gt;
&lt;p&gt;While using a VPN for security might be overkill in your situation, you’d be surprised how many websites don’t work properly when they detect you’re in another country. Paypal alone has already refused to let me access my account in both Greece and Thailand, and without a VPN to route my traffic through the US I wouldn’t have a way to get payments from one of my clients to my actual checking account. If you’re doing development work there’s also a good chance you’ll encounter public wifi that (for reasons unbeknownst to me) block port 22, making SSH worthless without a VPN.&lt;/p&gt;
&lt;p&gt;If you need to sign up for one I can’t recommend &lt;a href=&quot;https://www.privateinternetaccess.com/&quot;&gt;Private Internet Access&lt;/a&gt; highly enough. Their setup isn’t the prettiest or fanciest, but their servers have so far been extremely reliable, as fast as one can expect when routing traffic halfway around the world and back, and they take their user’s privacy to an extreme by forcing you to use anonymous usernames, not maintaining logs of any user traffic, and allowing you to pay via (more) anonymous methods like Bitcoin. In at least one case over the past 6 months they’ve sent a newsletter letting all users know that they were retiring their Russian VPN locations due to concerns over new legislation that would potentially compromise their customer’s privacy.&lt;/p&gt;
&lt;h2 id=&quot;if-youre-starting-a-new-business-give-yourself-at-least-3-months-to-be-revenue-positive&quot;&gt;If you’re starting a new business, give yourself at least 3 months to be revenue-positive.&lt;/h2&gt;
&lt;p&gt;Lastly, traveling can be the perfect time to start a digital or online business, but remember that it takes time (and often money) to build something profitable from scratch (it took me almost 6 months of contracting back in 2012 before my income stream was stable). If you can, do as much of the upfront legwork before you leave, and make sure you have enough savings to pay for everything for at &lt;em&gt;least&lt;/em&gt; 3 months. In the highly possible event you aren’t making enough money by the time your savings starts to run dry, be sure to have a backup plan in place that either lets you jump ship for back home or pickup a local job that covers the bills.&lt;/p&gt;
&lt;h2 id=&quot;be-prepared-for-a-worst-case-technology-scenario&quot;&gt;Be Prepared for a “Worst Case [Technology] Scenario”&lt;/h2&gt;
&lt;p&gt;Within a few weeks of starting our trip, my girlfriend encountered my worst fear: with no prior signs of issues her barely one year old Macbook Pro wouldn’t power on. I tried every combination of system reset keys in the book, but as it wouldn’t even begin to power on it looked like it was a hardware issue. Unfortunately, we were at the time in Dublin, Ireland where there’s oddly no official Apple Store and any secondary repair shops had a 3-5 day turnaround time…not promising when we had a flight to London in two days. We looked at getting it fixed in London, but all their Apple Store appointments were booked a full two weeks out, and the next Apple Store we’d encounter with open appointments wasn’t for two weeks in Milano, Italy.&lt;/p&gt;
&lt;p&gt;In the end we thankfully we got it fixed (damn faulty Mac logic boards), but as it was just barely outside it’s warranty window &lt;em&gt;and&lt;/em&gt; under a US warranty (many companies, Apple included, don’t always honor warranties from different countries) it ended up being a few hundred dollar repair. There’s not a lot you can do to prepare for this one, but just remember that as reliable as your laptop is now, getting it repaired overseas might not be as simple as hopping down to the nearest Apple Store. If having a running laptop is crucial to your work, it’s worth having that emergency fund for that unexpected repair or replacement.&lt;/p&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;Working remotely as a digital nomad can be an extremely rewarding experience, just make sure you have everything in order &lt;em&gt;before&lt;/em&gt; you hit the road and most of all: communicate, communicate, &lt;strong&gt;COMMUNICATE&lt;/strong&gt;! Almost all problems that come from working remotely can be avoided if both parties are communicating clearly (and honestly) as early as possible.&lt;/p&gt;
&lt;p&gt;Have you or are you working as a digital nomad and have something you think would be worth adding? Email me at rob at atomidesign.com and let’s chat!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://robertnealan.com/content/images/2016/08/DSC_0534-edited.jpg&quot; alt=&quot;Client meeting in progress&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;When things don’t go according to plan.An important client meeting in progress from Piraeus Port in Athens via mobile Google Hangouts. Our ferry from Santorini to Athens ran 3 hours late due to rough seas and I had to start the call while deboarding with a thousand other people.&lt;/p&gt;
</content:encoded></item><item><title>Setting Up SSL for Ghost on DigitalOcean with Lets Encrypt</title><link>https://robertnealan.com/setting-up-ssl-for-ghost-on-digitalocean-with-lets-encrypt/</link><guid isPermaLink="true">https://robertnealan.com/setting-up-ssl-for-ghost-on-digitalocean-with-lets-encrypt/</guid><description>After reading entirely too many articles and a lot of trial &amp; error, I&apos;ve written this guide on how to get HTTPS working on a DigitalOcean-powered…</description><pubDate>Thu, 19 May 2016 21:51:59 GMT</pubDate><content:encoded>&lt;p&gt;After reading entirely too many articles and a lot of trial &amp;amp; error, I’ve written this guide on how to get HTTPS working on a DigitalOcean-powered, Nginx-backed Ghost blog using LetsEncrypt’s free SSL certificates. For years people have argued whether it’s worth setting up SSL on websites that have no inherent need for strong security (credit card processing, user logins, etc), but now that SSL certificates are free for anyone and Google is prioritizing HTTPS sites over non-HTTP sites there’s no excuse not to.&lt;/p&gt;
&lt;p&gt;While DigitalOcean’s pre-made Ghost Droplet gets us pretty far, there’s still a few steps to get HTTPS and your custom domain running.&lt;/p&gt;
&lt;h2 id=&quot;the-guide&quot;&gt;The Guide&lt;/h2&gt;
&lt;p&gt;All steps are written from the viewpoint of a Ghost blog that was setup on DigitalOcean using it’s one-click installer, but they’re likely applicable to most Nginx/Ghost setups in general. Regardless you should probably be familiar with using a &lt;a href=&quot;http://ashleynolan.co.uk/blog/getting-started-with-terminal&quot;&gt;terminal&lt;/a&gt; and &lt;a href=&quot;https://semaphoreci.com/community/tutorials/getting-started-with-ssh&quot;&gt;SSH&lt;/a&gt; — if you aren’t I &lt;em&gt;highly recommend&lt;/em&gt; brushing up via those links before you get started.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If you already have a Ghost blog setup then skip to step 2. If not, go ahead and create a new droplet on DigitalOcean using the Ghost “One-Click App” install (Ghost 1.2.11 on Ubuntu 16.04 as of this writing — we’ll update it to the latest Ghost version in a few steps!) with 512mb of memory&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; (the $5/month option). Feel free to choose whichever datacenter is closest to yourself (or your users), and add an SSH key so you can access your Droplet via your local terminal.&lt;/li&gt;
&lt;li&gt;Once the droplet is finished building, access your droplet over SSH via the terminal of your choosing with &lt;code&gt;ssh root@0.0.0.0&lt;/code&gt;, where &lt;code&gt;0.0.0.0&lt;/code&gt; is the IP address of your droplet as listed in your account. If it prompts you to trust the RSA key type &lt;code&gt;yes&lt;/code&gt; and press &lt;code&gt;ENTER&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Once you’re inside your server (synonymous with “droplet”), run &lt;code&gt;apt-get update &amp;amp;&amp;amp; apt-get upgrade -y&lt;/code&gt; to bring all Linux dependencies up to date. If it prompts you to setup mail config or provides a warning about the &lt;code&gt;/root/grub/menu.lst&lt;/code&gt; I recommend choosing the default “No Configuration” and “Keep local…” unless you have reason to do otherwise.&lt;/li&gt;
&lt;li&gt;Switch to the “ghost-mgr” user DigitalOcean already setup by running &lt;code&gt;su - ghost-mgr&lt;/code&gt; (&lt;code&gt;su&lt;/code&gt; = switch user).&lt;/li&gt;
&lt;li&gt;Install Node Version Manager (NVM) so we can easily update to a more recent version of Node by running &lt;code&gt;curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash&lt;/code&gt;. Activate the &lt;code&gt;nvm&lt;/code&gt; bash alias by running &lt;code&gt;source ~/.bashrc&lt;/code&gt; or &lt;code&gt;exit&lt;/code&gt;’ing and switching back to the &lt;code&gt;ghost-mgr&lt;/code&gt; user.&lt;/li&gt;
&lt;li&gt;Install Node v8.9.3 and set it as the default by running &lt;code&gt;nvm install 8.9.3 &amp;amp;&amp;amp; nvm alias default node&lt;/code&gt;. You can check that the setup worked by running &lt;code&gt;node -v&lt;/code&gt;, which should return &lt;code&gt;v8.9.3&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Install the Ghost CLI with &lt;code&gt;sudo npm i -g ghost-cli&lt;/code&gt; so we can easily upgrade to the latest version of Ghost (v1.23.0 as of current) now and upgrade easily in the future.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;cd /var/www/ghost/&lt;/code&gt; to switch into your project’s folder, and then &lt;code&gt;ghost update&lt;/code&gt; to update to the latest version.&lt;/li&gt;
&lt;li&gt;Next let’s install LetsEncrypt’s CertBot to get our SSL certificate — type &lt;code&gt;exit&lt;/code&gt; to go back to the &lt;code&gt;root&lt;/code&gt; user (or start a new SSH session as root) and install the CertBot package with…&lt;br&gt;
&lt;code&gt;sudo apt-get install software-properties-common&lt;/code&gt;&lt;br&gt;
&lt;code&gt;sudo add-apt-repository ppa:certbot/certbot&lt;/code&gt;&lt;br&gt;
&lt;code&gt;sudo apt-get update&lt;/code&gt;&lt;br&gt;
&lt;code&gt;sudo apt-get install python-certbot-nginx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;sudo certbot --nginx&lt;/code&gt; and follow the prompts along. Make sure to add a real email as they’ll send you SSL renewal reminders, and select &lt;code&gt;2: Redirect&lt;/code&gt; when prompted so all visitors are forced to the HTTPS version of your site.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;vim /var/www/ghost/config.production.json&lt;/code&gt; to edit the &lt;code&gt;url&lt;/code&gt; attribute to reflect your site’s domain name (in my case &lt;code&gt;url: &quot;https://robertnealan.com&quot;,&lt;/code&gt;, exit, and then run &lt;code&gt;ghost restart&lt;/code&gt; (make sure you’re in your project directory!).&lt;/li&gt;
&lt;li&gt;Remove the default IP-based Nginx config by running &lt;code&gt;cd /etc/nginx/sites-available &amp;amp;&amp;amp; ls&lt;/code&gt;, and then removing the IP address file with &lt;code&gt;rm 0.0.0.0&lt;/code&gt;. Next open the &lt;code&gt;default&lt;/code&gt; config in vim and edit it to match the configuration file below, replacing all instances of &lt;code&gt;robertnealan.com&lt;/code&gt; with your own respective domain name&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot; id=&quot;user-content-fnref-2&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;service nginx restart&lt;/code&gt; — if you get any errors run &lt;code&gt;nginx -t&lt;/code&gt; and it should point you to any syntax errors you might have made in the &lt;code&gt;/etc/nginx/sites-available/default&lt;/code&gt; conf file.&lt;/li&gt;
&lt;li&gt;Test &lt;code&gt;https://yourdomain.com&lt;/code&gt; to make sure that SSL is working properly…if it is then celebrate! 🎉&lt;/li&gt;
&lt;li&gt;Lastly, you’ll want to set up a cronjob to automatically renew the certificate every 60 days or so, otherwise they’ll expire after 90 days. First run &lt;code&gt;/usr/bin/certbot renew --dry-run&lt;/code&gt; to make sure it’ll work as expected. Next go ahead and run &lt;code&gt;crontab -e&lt;/code&gt; in your server terminal, and you should see something similar to the image below. On the last line add &lt;code&gt;0 0 1 */2 * /usr/bin/certbot renew --nginx --quiet&lt;/code&gt;, which tells cron to rerun the certificate renewal for you on the first day of every other month. With this cron in place you can safely ignore the renewal emails from LetsEncrypt.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://robertnealan.com/content/images/2018/05/Screenshot-2018-05-23-13.44.15.png&quot; alt=&quot;Crontab Screenshot&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;And that’s it! If you have any issues or find an error feel free to comment on the gist, &lt;a href=&quot;https://twitter.com/robertnealan&quot;&gt;tweet at me&lt;/a&gt;, or message me via the &lt;a href=&quot;https://robertnealan.com/#contact&quot;&gt;contact page&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;nginx-config&quot;&gt;Nginx Config&lt;/h3&gt;
&lt;p&gt;server {
listen 80;
listen [::]:80;&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;server_name robertnealan.com;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;root /var/www/ghost/system/nginx-root;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;location / {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    proxy_set_header X-Forwarded-Proto $scheme;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    proxy_set_header X-Real-IP $remote_addr;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    proxy_set_header Host $http_host;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    proxy_pass http://127.0.0.1:2368;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;location ~ /.well-known {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    allow all;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;client_max_body_size 50m;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;listen [::]:443 ssl ipv6only=on; # managed by Certbot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;listen 443 ssl; # managed by Certbot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ssl_certificate /etc/letsencrypt/live/robertnealan.com/fullchain.pem; # managed by Certbot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ssl_certificate_key /etc/letsencrypt/live/robertnealan.com/privkey.pem; # managed by Certbot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;server {&lt;br&gt;
if ($host = robertnealan.com) {&lt;br&gt;
return 301 https://$host$request_uri;&lt;br&gt;
} # managed by Certbot&lt;/p&gt;
&lt;pre class=&quot;astro-code github-dark&quot; style=&quot;background-color:#24292e;color:#e1e4e8; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;listen 80 ;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;listen [::]:80 ;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;server_name robertnealan.com;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;return 404; # managed by Certbot&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;h2 id=&quot;other-basic-ghost-setup-tasks&quot;&gt;Other Basic Ghost Setup Tasks&lt;/h2&gt;
&lt;h3 id=&quot;redirecting-from-non-www-to-www-instead&quot;&gt;Redirecting From non-www to www Instead&lt;/h3&gt;
&lt;p&gt;I’ve personally always favored non-www addresses, if you prefer to have the www version then make sure to use &lt;code&gt;www.yourdomain.com&lt;/code&gt; during the CertBot registration, and subsequently make sure the &lt;code&gt;server_name&lt;/code&gt; directives in the Nginx &lt;code&gt;default&lt;/code&gt; conf file have &lt;code&gt;www.yourname.com&lt;/code&gt; rather than &lt;code&gt;yourdomain.com&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;reference-links&quot;&gt;Reference Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;CertBot Documentation: &lt;a href=&quot;https://certbot.eff.org/lets-encrypt/ubuntuxenial-nginx&quot;&gt;https://certbot.eff.org/lets-encrypt/ubuntuxenial-nginx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ghost Production Setup: &lt;a href=&quot;https://docs.ghost.org/docs/install#section-create-a-new-user&quot;&gt;https://docs.ghost.org/docs/install#section-create-a-new-user&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Ghost Mail Configuration: &lt;a href=&quot;https://docs.ghost.org/docs/mail-config&quot;&gt;https://docs.ghost.org/docs/mail-config&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Node Version Manager (NVM): &lt;a href=&quot;https://github.com/creationix/nvm&quot;&gt;https://github.com/creationix/nvm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;updates&quot;&gt;Updates&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;August 11, 2016: Updated guide to add steps breaking apart enabling HTTP, verifying LetsEncrypt, and enabling HTTPS.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;October 19, 2016: Updated the Nginx config to have the default root directory as &lt;code&gt;/var/www/ghost&lt;/code&gt; instead of just &lt;code&gt;/var/www&lt;/code&gt;.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;January 24, 2017: Updated the Nginx config to fix a bug where www to non-www redirects wouldn’t occur properly on HTTPS URLs, and added instructions on how to redirect from non-www to www instead.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;July 3, 2017: Removed lines 59-61 in the Nginx config Gist and code snippet, which previously manually routed the robots.txt and sitemap.xml, as Ghost now handles these automatically for the past several major versions. Huge thanks to both &lt;a href=&quot;https://twitter.com/tomblackshire?lang=en&quot;&gt;Tom Blackshire&lt;/a&gt; &amp;amp; &lt;a href=&quot;https://github.com/grantwinney&quot;&gt;Grant Whinney&lt;/a&gt; for both giving me the heads up!&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;May 23, 2018: Fully overhauled the post to use DigitalOcean’s newer Ghost Droplet, Ubuntu 16.04, the new Ghost CLI, and the latest version of LetsEncrypt’s CertBot.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;If you’re worried about only having 512mb of memory feel free to upgrade, though this blog has handled upwards of 650 concurrent visitors without skipping a beat. &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-2&quot;&gt;
&lt;p&gt;If you’re interested in learning more about Nginx configuration you can read up on it on their official wiki, &lt;a href=&quot;https://www.nginx.com/resources/wiki/start/&quot;&gt;https://www.nginx.com/resources/wiki/start/&lt;/a&gt;. &lt;a href=&quot;#user-content-fnref-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content:encoded></item><item><title>Turning Down the Noise</title><link>https://robertnealan.com/turning-down-the-noise/</link><guid isPermaLink="true">https://robertnealan.com/turning-down-the-noise/</guid><description>I still remember getting my first cell phone. The year was 1999 and my mom passed down her beater of a silver Sprint flip phone.</description><pubDate>Tue, 23 Feb 2016 21:08:31 GMT</pubDate><content:encoded>&lt;p&gt;I still remember getting my first cell phone.&lt;/p&gt;
&lt;p&gt;The year was 1999 and my mom passed down her beater of a silver Sprint flip phone. For the time it was high tech, featuring an exterior notification screen, polyphonic ringtones, and a few games that would later look “totally lame” next to Snake on my friend’s Nokia brick-phones. Despite the terror that is being a cell phone owned by an 11 year old kid, it lasted several years until I convinced my parents to upgrade me to a a new LG phone with a “totally cool” color screen (and countless software bugs).&lt;/p&gt;
&lt;p&gt;Fast forward to 2008 where I found myself in need of a new phone having had my latest victim Razer flip phone split in half. In an effort to show mercy to my parents, I made the mature decision to get my own phone plan and a sexy, contract-subsidized iPhone 3G for &lt;em&gt;only&lt;/em&gt; $200.&lt;/p&gt;
&lt;p&gt;For the first few years having an iPhone was similar to having a dumbphone, just with a better screen, a browser that worked, and countless other bells and whistles that were more of a novelty than necessity. Unfortunately, somewhere along the way those novelties gave way to alerts, push notifications, and constant buzzing, beeping, and blooping that turned the my “smart” into a constant point of annoyance and stress as it begged for my attention.&lt;/p&gt;
&lt;p&gt;It’s for this reason that I’ve been diving into the &lt;em&gt;extremely&lt;/em&gt; extensive notification settings and turning off as many active notifications as possible (active being anything that makes my phone buzz, beep, or otherwise distract my attention when it’s not in front of my face). The only three apps for which I’ve left active notifications fully intact are “Phone”, “Messages”, and “Facetime”, or what I still consider to be the core functions a phone should provide (and even those are 100% silent at the flip the switch on the side of my iPhone).&lt;/p&gt;
&lt;p&gt;Additionally, to help minimized distractions when I am on my phone I’ve also disabled the majority of passive notifications (badges, banner alerts, etc - anything that unobtrusively appears once you’re already on the phone), and only left them intact for the few work-critical apps like Mailbox, Slack, and Google Hangouts.&lt;/p&gt;
&lt;p&gt;A few weeks in I now check my email once or twice a day, Facebook a few times per week, and otherwise only pull out my phone when I have true downtime rather than out of habit. Surprisingly, I’ve yet to miss anything work-related that couldn’t wait until later, and what started out as an experiment in being able to focus better on work has turned into a much better balance between myself and what should be a tool rather than a constant distraction. If you find yourself distracted or pestered by your phone I’d recommend giving it a try.&lt;/p&gt;
&lt;p&gt;As someone who works as a designer and developer I get it — the more we use our phone the better for your company, but as a human being with limited time and attention I have to wonder if there’s a better way? All things aside, that old Sprint phone had one feature that makes it appealing compared to phones of today — the damn thing was silent 99% of the time.&lt;/p&gt;
</content:encoded></item><item><title>2015 - Year in Review</title><link>https://robertnealan.com/2015/</link><guid isPermaLink="true">https://robertnealan.com/2015/</guid><description>It seemed like 2015 went by fast, but I&apos;ve blinked twice and it&apos;s already almost the end of January halfway through February (okay I&apos;ve really been…</description><pubDate>Wed, 17 Feb 2016 21:01:00 GMT</pubDate><content:encoded>&lt;p&gt;It seemed like 2015 went by fast, but I’ve blinked twice and it’s already almost the end of January halfway through February (okay I’ve really been procrastinating on this post). For years I’ve read “years in review” by others in the tech community, but never did one of my own because it never seemed like my experience was worth sharing. While I’m still skeptical how much value others might get out of this, especially considering how informal it is, it’s at minimum helpful in collecting my own thoughts.&lt;/p&gt;
&lt;p&gt;So to start, in general it was a &lt;em&gt;great&lt;/em&gt; year — not necessarily just for business, but all around it felt great. That’s not necessarily a quantifiable metric, but that’s what it was.&lt;/p&gt;
&lt;h2 id=&quot;client-work&quot;&gt;Client Work&lt;/h2&gt;
&lt;p&gt;In 2013 and 2014 my consulting business had always afforded me the freedom to work my own schedule and forgo an employed job, but never quite amounted to what I could have made working a market rate job. In the early days there were even a few of those “oh god I have no work lined up and can’t pay rent ” occasions that I’ll never forgot, but somehow it always worked out.&lt;/p&gt;
&lt;p&gt;Twenty Fifteen, on the other hand, seems to be the year that things have not only gotten extremely stable with an upward trend in income, but also in quality of clients, ongoing relationships with clients, and ease of finding work when needed (and turning it down when not).&lt;/p&gt;
&lt;h4 id=&quot;by-the-numbers&quot;&gt;By the Numbers&lt;/h4&gt;
&lt;p&gt;In 2015 I worked on a total of 17 different projects with 12 different clients — an insane amount compared to previous years and something I aim to curb moving forward (more on that below). Net income saw a 94.1% increase over the previous year, and gross income increased by 82.2%. While the prior is indicative of overall business health, the latter is effectively my take home pay as I don’t have a salaried job and all income after business expenses is personal income in the all-seeing eyes of the Internal Revenue Service.&lt;/p&gt;
&lt;p&gt;For the visual learnings out there here’s a chart showing year-by-year income and revenue, as expressed in emoji (I was a full time student until 2012, so any income was minimal and likely to be spent on cheap beer).&lt;/p&gt;
&lt;p&gt;Looking back, this was a much better year than 2014, which saw a net income increase of 52.8% and gross income increase of 11.2% over 2013. If you factor in the fact that I was employed full time from January through April of 2013, I likely actually saw a negligible increase in income compared to the previous year.&lt;/p&gt;
&lt;p&gt;I unofficially had made a net income goal for 2015, which I exceeded by roughly 15%. My goal for 2016 is actually to maintain that same income level, but while working on client projects roughly 30% less. It’s always been my goal to design and build my own products (analog &amp;amp; digital), so I hope this extra time will be enough to start focusing more time on doing so compared to previous years.&lt;/p&gt;
&lt;h3 id=&quot;what-went-wrong&quot;&gt;What Went Wrong&lt;/h3&gt;
&lt;p&gt;That said, it wasn’t all good.&lt;/p&gt;
&lt;p&gt;First, as mentioned before I worked on &lt;strong&gt;seventeen projects&lt;/strong&gt;, which was &lt;em&gt;way&lt;/em&gt; too many for one person to handle. For the most part everything worked out, but at times I was stressed to the point I wanted to punch a wall (I didn’t), which is exactly the opposite of why I got into contracting.&lt;/p&gt;
&lt;p&gt;Second, I took on a client that gave me “a bad feeling”. That client also happened to coincide/cause that peak of stress partway through the year. As the project went on it became more and more demanding to the detriment of my other work, and worse yet it was a product I neither believed in nor thought should exist. In the end I talked to my friend on the project and we decided to let the client know we would be ending our contract after delivering the current project milestone in a few weeks.&lt;/p&gt;
&lt;p&gt;It’s always hard to say no to someone trying to hand you a check, but being able to pays dividends in your personal well-being and being able to deliver the quality you already promised to your existing clients.&lt;/p&gt;
&lt;h2 id=&quot;designers-who-code&quot;&gt;Designers Who Code&lt;/h2&gt;
&lt;p&gt;Designers Who Code has exceeded my wildest expectations. What started as a hunch that their might be other “designer-developers” out there has turned into a group of 2000 2200 members. We hosted 6 events from January through April with companies like Heroku, Zurb, and Carbon Five, and had a total of 784 RSVP’s between those 6 events.&lt;/p&gt;
&lt;p&gt;All things considered I think we had some great events and were able to engage a considerable number of people despite being dormant the latter half of the year.&lt;/p&gt;
&lt;p&gt;In good news I recently launched a &lt;a href=&quot;http://dwc.io/&quot;&gt;new website&lt;/a&gt; for the group that was designed/built intermittently over the course of a few months on top of Jekyll. It’s pretty minimal and still has gaps, but will serve as a good foundation for a myriad of other features I hope to include as I aim to allow the group to exist independent of Meetup.com’s platform.&lt;/p&gt;
&lt;p&gt;Additionally, I’m in talks with friends about becoming co-organizers (so things don’t necessarily go dark when I do), and it’s looking like we’ll be having our first events outside San Francisco this year.&lt;/p&gt;
&lt;h2 id=&quot;backpacking-trips&quot;&gt;Backpacking Trips&lt;/h2&gt;
&lt;p&gt;As someone who loves the outdoors and is generally active, it surprised me when I realized that I’d never been on a proper backpacking trip. Fast forward to April and I’m trekking down an Arizona desert canyon riverbed with my girlfriend, her brother, and his girlfriend for 40 miles over 3 days. I could write an entire post to the trip alone, but put simply it was nothing short of amazing. While I’m not sure I’d ever want to live in the desert permanently, it’s an environment I appreciate and respect far and above any other.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://robertnealan.com/content/images/2016/02/11401418_10153039948342023_8577766825221316792_n.jpg&quot; alt=&quot;Paria Canyon&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;_About 15 miles into Paria Canyon in the “narrows”._&lt;/p&gt;
&lt;p&gt;After the trip I couldn’t shake the feeling that I needed to go on a longer trip, so I naturally opted for the 212 mile John Muir Trail (40 miles to 212 miles…totally reasonable). I’ve written a post on my gear and preparing for the trip in general, but have yet to write anything detailed otherwise. I tried, but at the time any words I could put down seemed to pale in comparison to the awe and wonder two weeks in the Sierras instilled in myself.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://robertnealan.com/content/images/2016/02/12138612_10153269575487023_1653335228737265945_o.jpg&quot; alt=&quot;Forester Pass&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;_Looking back down from the top of Forrester Pass at 13,500’_&lt;/p&gt;
&lt;h2 id=&quot;looking-to-the-future&quot;&gt;Looking to the Future&lt;/h2&gt;
&lt;p&gt;I’m currently working with a colleague of mine on an app aimed at helping make freelancers lives easier. It’s still pretty early to say much, but I’m sure I’ll have a followup post down the line.&lt;/p&gt;
&lt;p&gt;And the big news for the year…my girlfriend and I will be traveling the world the second half of 2016! What started as an idea to be expats in Thailand has turned into a trip that includes the eastern US, a myriad of European countries, and an unplanned number of countries in Southeast Asia. As part of the trip I’m looking at writing a “digital nomad” series for those thinking about working and traveling at the same time.&lt;/p&gt;
&lt;p&gt;Words of Wisdom for 2016:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“You have Cost, Quality, and Speed — Pick Two.”&lt;/p&gt;
&lt;/blockquote&gt;
</content:encoded></item><item><title>Is Self Hosted Blogging Dead?</title><link>https://robertnealan.com/is-self-hosted-blogging-dead/</link><guid isPermaLink="true">https://robertnealan.com/is-self-hosted-blogging-dead/</guid><description>Or, the case against hosted blogging options. More and more I find myself reading articles on blog networks, and by networks I mean Medium.</description><pubDate>Thu, 21 Jan 2016 21:23:00 GMT</pubDate><content:encoded>&lt;h3 id=&quot;or-the-case-against-hosted-blogging-options&quot;&gt;Or, the case against hosted blogging options.&lt;/h3&gt;
&lt;p&gt;More and more I find myself reading articles on blog networks, and by networks I mean &lt;a href=&quot;http://medium.com/&quot;&gt;Medium&lt;/a&gt;. There was a promising short lived moment where smaller, topic-oriented blog networks like &lt;a href=&quot;http://svbtle.com/&quot;&gt;Svbtle&lt;/a&gt; (amongst others) started appearing, but even those seem to have gone by the wayside and are increasingly being replaced by Medium.&lt;/p&gt;
&lt;p&gt;It’s not that I have anything inherently against these sites; they are incredibly well designed and seem to be doing a fantastic job at fostering a community and discussion around the writing of people spanning the whole spectrum of society. What I do have a problem with is trusting all my writing to a third-party company, which may or may not decide to monetize my content, shutdown, or update their application in a way that makes it a moot platform for future writing.&lt;/p&gt;
&lt;p&gt;Don’t get me wrong, from those the few people I’ve met who work at Medium and Svbtle they seem like honest, top-notch people, but when I read through their Terms of Service it’s hard not to be a little concerned.&lt;/p&gt;
&lt;p&gt;Like this snippet from Svbtle:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“As a paid customer, you give Svbtle a perpetual world-wide license to use your company’s assets and logos, unless Svbtle agrees in writing otherwise. These assets and logos will be used purely for marketing and sales efforts, such as being displayed on the home page.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So by posting to Svbtle once, they suddenly have a &lt;em&gt;perpetual&lt;/em&gt; license to use my company’s logo in way’s I’m forever unable to control unless they agree not to in writing, presumably before I ever use their service? It’s not that I think they’re necessarily going to do anything I disagree with right now or in the near future, but times &lt;strong&gt;do&lt;/strong&gt; change — companies transition or are sold to a new owner, and you hear horror stories about formerly reputable companies like Sourceforge, the formerly ubiquitous choice for version control hosting, &lt;a href=&quot;http://arstechnica.com/information-technology/2015/05/sourceforge-grabs-gimp-for-windows-account-wraps-installer-in-bundle-pushing-adware/&quot;&gt;hijacking GIMP’s unused Windows distribution account for their own profit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Or what about this one:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Svbtle reserves the right, at its sole discretion, to modify or replace any part of this Agreement. It is your responsibility to check this Agreement periodically for changes. Your continued use of or access to the Services following the posting of any changes to this Agreement constitutes acceptance of those changes.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Not only can they update the Terms of Service at any point in time without notifying their users, but it’s the &lt;strong&gt;user’s responsibility&lt;/strong&gt; to check it for changes? I’m not a lawyer, but it seems extremely questionable that they can’t commit to providing some sort of outreach before those changes take effect. This is the same type of shady practice that previously earned Facebook heaps of backlash from its users, and led to them adding a clause to their Terms of Service that they’ll transparently &lt;a href=&quot;https://www.facebook.com/terms.php&quot;&gt;communicating future changes in advance of them going into effect&lt;/a&gt;.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; I don’t know about you, but I highly doubt many people are checking the Terms of Service for changes every time they go to make a blog post.&lt;/p&gt;
&lt;p&gt;Medium.com’s Terms of Service are thankfully written in as much honest, plain-speaking words as possible with upfront statements like, “Even if your eyes normally glaze over the word “Terms,” it’s a good idea to read this agreement carefully before you use Medium.” and “You own the rights to the content you post on Medium. We don’t claim ownership over any of it.”&lt;/p&gt;
&lt;p&gt;Still though, you look further down and come across this piece:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“…we may change, terminate, or restrict access to any aspect of the service, at any time, without notice.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As a web designer and developer, I get it — times inevitably change and you don’t want to find themselves in a lawsuit because someone’s favorite feature got removed, but still that risk doesn’t seem worth it. It’s hard enough to muster the time to put my thoughts into words, and the last thing I want is for all that effort to hinge on the decisions of a benign dictator.&lt;/p&gt;
&lt;p&gt;Lastly, as great as the Medium community is currently, it’s still a walled garden. You write on Medium, read on Medium, discuss on Medium, and inevitably live or die based on the choices of the company behind Medium.&lt;/p&gt;
&lt;h2 id=&quot;long-live-self-hosted-blogs&quot;&gt;Long Live Self Hosted Blogs&lt;/h2&gt;
&lt;p&gt;For my own blog I personally self-host &lt;a href=&quot;http://ghost.org/download&quot;&gt;Ghost’s open-source platform&lt;/a&gt;. As it’s still pre-1.0&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1-2&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; it requires a little bit of technical know-how to get setup, but with options like DigitalOcean’s pre-configured Ghost Droplet it’s getting easier and easier to manage. On the downside the only writing format it currently accepts is Markdown, which depending on your preferences will be a polarizing feature (I love it).&lt;/p&gt;
&lt;p&gt;So maybe Ghost isn’t your jam, and that’s okay. That’s the beauty of self-hosting your own blog, there’s so many options out there! Things like &lt;a href=&quot;http://wordpress.org/&quot;&gt;Wordpress&lt;/a&gt;, &lt;a href=&quot;https://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;, &lt;a href=&quot;https://middlemanapp.com/&quot;&gt;Middleman&lt;/a&gt;, &lt;a href=&quot;http://octopress.org/&quot;&gt;Octopress&lt;/a&gt;, &lt;a href=&quot;https://anchorcms.com/&quot;&gt;AnchorCMS&lt;/a&gt;, &lt;a href=&quot;http://picocms.org/&quot;&gt;PicoCMS&lt;/a&gt;, &lt;a href=&quot;http://dropplets.com/&quot;&gt;Dropplets&lt;/a&gt;, &lt;strong&gt;takes breath&lt;/strong&gt; …and at least hundred others are free and available for you to use, customize, update (or not), etc at your own choosing. That’s the beauty of having control over your own writing — the Ghost community might opt to add or remove a feature I disagree with, at which point I have full control to not update to the newest version and plan a transition to a different platform that fits my needs.&lt;/p&gt;
&lt;hr&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;&lt;a href=&quot;http://dev.ghost.org/ghost-0-7-5/&quot;&gt;Version v0.7.5&lt;/a&gt; at the time of this writing. &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-2&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content:encoded></item><item><title>12 Resolutions for 2016</title><link>https://robertnealan.com/2016-resolutions/</link><guid isPermaLink="true">https://robertnealan.com/2016-resolutions/</guid><description>I&apos;ve always thought that if something in life is important enough you shouldn&apos;t need a yearly resolution to make that change.</description><pubDate>Fri, 15 Jan 2016 23:09:20 GMT</pubDate><content:encoded>&lt;p&gt;I’ve always thought that if something in life is important enough you shouldn’t need a yearly resolution to make that change. Unfortunately life isn’t that simple, so after more than a decade of abstaining from resolutions I’ve decided to give it a go with an appropriate first item:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Regularly re-evaluate pre-conceived ideas and opinions.&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;Read daily.&lt;/li&gt;
&lt;li&gt;Start each morning by meditating. (No idea how this will go, but I figure it can’t hurt.)&lt;/li&gt;
&lt;li&gt;Write daily with the goal of writing a book this year.&lt;/li&gt;
&lt;li&gt;Build at least one product/application for myself.&lt;/li&gt;
&lt;li&gt;Build at least one product/application to sell to others.&lt;/li&gt;
&lt;li&gt;Go jogging at least 3 times per week, bouldering at least once per week, and biking at least once per week.&lt;/li&gt;
&lt;li&gt;Put a minimum of 20% of my 2016 pre-tax income towards savings/stocks/retirement/etc.&lt;/li&gt;
&lt;li&gt;Purchase food locally as frequently as possible (farmers markets, coop boxes, etc).&lt;/li&gt;
&lt;li&gt;Publish at least one article per month — can be on this blog or elsewhere.&lt;/li&gt;
&lt;li&gt;Cook something new at least once per week.&lt;/li&gt;
&lt;li&gt;Organize at least one meetup for Designers Who Code every other month (socials/happy hours don’t count).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Maybe I’ll fail, maybe I won’t. What I do know is that 3 1/2 years out of college it’s far too easy to become content and fall into the same rhythmic pattern day-after-day, only to look back and realize not much has happened in the past few years. This thankfully hasn’t been the case, but I’m adamant to make sure that it doesn’t happen.&lt;/p&gt;
</content:encoded></item><item><title>Gearing Up for the John Muir Trail</title><link>https://robertnealan.com/gearing-up-for-the-john-muir-trail/</link><guid isPermaLink="true">https://robertnealan.com/gearing-up-for-the-john-muir-trail/</guid><description>To those who know me personally it&apos;s no secret that I love a good adventure.</description><pubDate>Mon, 14 Sep 2015 18:36:56 GMT</pubDate><content:encoded>&lt;p&gt;To those who know me personally it’s no secret that I love a good adventure. Whether it’s traveling in a foreign country or biking across my own, testing your limits by pushing yourself outside your normal comfort zone positively expands your character in a way that no other type of experience can quite compare.&lt;/p&gt;
&lt;p&gt;Having gone backpacking for the first time earlier this summer in Paria Canyon (despite having lived out of a tent for several months of the past decade), it only made sense to immediately plan the longest backpacking trip I could manage between projects before the onset of winter’s freezing temperatures, [hopefully] snow in the Sierra Nevadas, and the El Niño-pocalypse that meteorologists are predicting for this year. So with a few months summer to spare, I immediately booked a late-season permit for two on the John Muir Trail and tricked a good friend into take two weeks off work to join me in the adventure — it still amazes me how much of a draw “backpacking the John Muir Trail” has over “backpacking in the mountains for two weeks”.&lt;/p&gt;
&lt;p&gt;With the help of numerous other blogs, the JMT facebook group, and a bit of my own intuition I’ve come up with what should stand to be a setup that combines the best of comfort and weight savings as well as some gear that should serve future trips for years to come. Additionally, I’ve included a link to both my original Google Spreadsheet both as filled out by myself and blank for anyone else to use (WIP).&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;the-gear&quot;&gt;The Gear&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Spreadsheet Last Updated: Sep 14th, 2015 at 4:00PM PST&lt;/em&gt;&lt;br&gt;
&lt;a href=&quot;https://docs.google.com/spreadsheets/d/1MQQqY0z0noiJg7CUWhkjYgsABQoRF7-l2W3Ub9ROlEE/edit?usp=sharing&quot;&gt;https://docs.google.com/spreadsheets/d/1MQQqY0z0noiJg7CUWhkjYgsABQoRF7-l2W3Ub9ROlEE/edit?usp=sharing&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;packing&quot;&gt;Packing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rei.com/product/864669/osprey-exos-58-pack&quot;&gt;Osprey Exos 58 Backpack&lt;/a&gt; — &lt;em&gt;I’ve been nothing but impressed by the weight and comfort of this pack. At 2lbs it’s lighter than almost any other pack in its class but still provides the comforts of an internal frame pack.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Sea to Summit Medium Dry Cover&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rei.com/product/768902/bearvault-bv500-food-container&quot;&gt;BearVault BV500 Bear Can&lt;/a&gt; — &lt;em&gt;Light as you could hope for, transparent, and doubles as a pretty sweet campfire chair.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;1 Osprey Dry Sack&lt;/li&gt;
&lt;li&gt;2 Odor Bags A few gallon sized Ziploc Bags&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;shelter--sleeping&quot;&gt;Shelter &amp;amp; Sleeping&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rei.com/product/865388/big-agnes-copper-spur-ul-1-tent&quot;&gt;Big Agnes Copper Spur UL1 Tent &amp;amp; Footprint&lt;/a&gt; — &lt;em&gt;It was a tossup between this and the Fly Creek, but the CS won out despite the extra ounces primarily due to being freestanding and affording more space for my pack beneath the fly. As a huge bonus, having a side-door is way better than the Fly Creek’s front door in the rain, and gives you the option to sit inside your tent and hang out with your campmates when cold.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rei.com/product/862529/rei-flash-sleeping-bag&quot;&gt;REI Flash Sleeping Bag&lt;/a&gt; — &lt;em&gt;It’s half the cost of any other sleeping bag in its weight/warmth class and packs down small. Only has a 30-degree rating, but I sleep pretty warm and am willing to layer up above 10,000’.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rei.com/product/829826/therm-a-rest-z-lite-sol-sleeping-pad&quot;&gt;Thermarest Z-Lite Foam Sleeping Pad&lt;/a&gt; — &lt;em&gt;Not nearly has comfortable as inflatable sleeping pads, but much lighter and more reliable. Also double’s great as a seating pad outside the tent.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;survival--tools&quot;&gt;Survival &amp;amp; Tools&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rei.com/product/863073/black-diamond-trail-ergo-cork-trekking-poles-pair&quot;&gt;Black Diamond Ergo Cork Trekking Poles&lt;/a&gt; — &lt;em&gt;Usually keep me from toppling over when I’m tired.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rei.com/product/799009/gsi-outdoors-cathole-sanitation-trowel&quot;&gt;GSI Cathole Trowel&lt;/a&gt; — &lt;em&gt;For when nature, gardening, or sand castle building calls.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rei.com/product/866989/petzl-tikka-xp-headlamp&quot;&gt;Petzyl Tikka XP Headlamp&lt;/a&gt; — &lt;em&gt;Runs on AAA batteries for far longer than I would’ve guessed and is blindingly bright on its highest setting.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Zippo Lighter &amp;amp; Small Box Matches&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;clothing--accessories&quot;&gt;Clothing &amp;amp; Accessories&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.backcountry.com/arcteryx-cerium-lt-hooded-down-jacket-mens&quot;&gt;Arc’teryx Cerium LT Hoodie Down Jacket&lt;/a&gt; — &lt;em&gt;Keeps me sweating even in freezing weather.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.backcountry.com/arcteryx-beta-ar-jacket-mens&quot;&gt;Arc’teryx Beta AR Hardshell Jacket&lt;/a&gt; — &lt;em&gt;The California drought has kept me from putting this to the test, but as with all Arc’teryx gear I doubt I’ll need to worry.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;REI Waterproof Hiking Pants&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rei.com/product/810264/prana-stretch-zion-shorts-mens&quot;&gt;Prana Mojo Shorts&lt;/a&gt; (Worn) — &lt;em&gt;These are my go-to climbing shorts but double as a pair of extremely comfortable hiking shorts.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rei.com/product/863045/rei-sahara-t-shirt-mens&quot;&gt;REI Sahara Shirt&lt;/a&gt; (Worn)&lt;/li&gt;
&lt;li&gt;Patagonia Capilene Middle Weight Long Sleeve Baselayer&lt;/li&gt;
&lt;li&gt;Vasque Hiking Boots — &lt;em&gt;I’ve had these for at least 6 years and they’re still rock solid. Never have gotten a single blister nor had a single complaint.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Patagonia Capilene Heavyweight Baselayer Underwear&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.patagonia.com/us/product/mens-capilene-daily-boxer-briefs?p=32477-0&quot;&gt;2 pairs Patagonia boxer briefs&lt;/a&gt; (1 Pair Worn) — &lt;em&gt;Should stay much cleaner, much longer than cotton underwear.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;1 Pair Misc über thick alpaca wool socks&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rei.com/product/712774/rei-lightweight-merino-wool-hiking-quarter-socks&quot;&gt;1 Pair REI quarter hiking socks&lt;/a&gt; (Worn)&lt;/li&gt;
&lt;li&gt;Rayban Wayfarer Liteforce (Worn) — &lt;em&gt;Just my polarized sunglasses of choice.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;cooking--hydration&quot;&gt;Cooking &amp;amp; Hydration&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rei.com/product/791308/jetboil-flash-cooking-system&quot;&gt;Jetboil Flash&lt;/a&gt; — &lt;em&gt;I’ve had this for going on 4 years and bring it anytime I’m camping (even if we have a full stove).&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.amazon.com/Snow-Peak-SCT-004BL-Parent-Titanium-Spork/dp/B00GZJSJ9Y&quot;&gt;Snow Peak Titanium Spork&lt;/a&gt; — &lt;em&gt;Because.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rei.com/product/812089/camelbak-antidote-reservoir-70-fl-oz&quot;&gt;Camelbak 2L Water Bladder&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Nalgene Water Bottle — &lt;em&gt;If you don’t need/want something as sturdy as a Nalgene Smart Water bottles work great and weigh next to nothing.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.rei.com/product/830745/katadyn-hiker-pro-water-filter&quot;&gt;Katydyn Hiker Pro Water Filter&lt;/a&gt; — &lt;em&gt;Quick and has a carbon filter that helps improve the taste when filtering impure water.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Sawyer Squeeze w/Smart Water Bottles — &lt;em&gt;The Katydyn unfortunately broke while on the trail, and after seeing/using several Sawyer Squeeze’s will be switching as soon as I make it to REI.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;food&quot;&gt;Food&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://bigsurbar.com/shop/&quot;&gt;Big Sur Bars&lt;/a&gt; — &lt;em&gt;A college meal staple from the Central Coast of California. Buy them, you won’t regret it (original &amp;amp; white zest recommended).&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Pro Meal Bars&lt;/li&gt;
&lt;li&gt;Justin’s Single Serve Peanut/Hazelnut/Almond Butter — &lt;em&gt;Ordered in bulk on Amazon.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Peanut M&amp;amp;M’s&lt;/li&gt;
&lt;li&gt;Beef Jerky&lt;/li&gt;
&lt;li&gt;Mountain House Meals — &lt;em&gt;Ordered in bulk online and repacked into ziplock bags to save space.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;hygiene&quot;&gt;Hygiene&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Toilet Paper&lt;/li&gt;
&lt;li&gt;Toothbrush&lt;/li&gt;
&lt;li&gt;Toothpaste&lt;/li&gt;
&lt;li&gt;REI Lite Mini Multi Towel — &lt;em&gt;Amusingly tiny but nonetheless handy in cleaning dishes and/or washing off.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Dr Bronners Peppermint Soap (4oz) — Realized I had no real use until I got off the trail and left it in the car.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;miscellaneous&quot;&gt;Miscellaneous&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Banana Boat SPF50 Sunscreen (4oz) — &lt;em&gt;Because Irish/Italian/English people were not meant to get tan.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.amazon.com/John-Muir-Trail-Map-Pack-Harrison/dp/1877689343&quot;&gt;Tom Harris JMT Maps&lt;/a&gt; — &lt;em&gt;Great maps for great adventures.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Wallet (Rubber Band, ID, Credit Card, Debit Card)&lt;/li&gt;
&lt;li&gt;Ben’s 30% Insect Repellent — &lt;em&gt;Likely unnecessary in September, but critical for Sierra hiking earlier in May/June/July.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Duct Tape — &lt;em&gt;Rewrap some off the roll onto your trekking poles below the handles to save space in your pack.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;iPhone 6 — &lt;em&gt;Will be off 99% of the time, but useful when we get out of the mountains.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Misc medical kit (bandages, medicine, etc)&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Death by Inertial Scrolling</title><link>https://robertnealan.com/death-by-inertial-scrolling/</link><guid isPermaLink="true">https://robertnealan.com/death-by-inertial-scrolling/</guid><description>Every year there&apos;s a few design trends on the web that make their rounds.</description><pubDate>Mon, 16 Feb 2015 22:21:20 GMT</pubDate><content:encoded>&lt;p&gt;Every year there’s a few design trends on the web that make their rounds. Some are recognized as good design patterns and persist while others gradually fade out. Thankfully most of these trends are tacky and cringeworthy at worst (web 2.0 rounded glossy buttons anybody?), but every so often there’s one that’s just so downright awful, so downright evil, that when I cross paths with it I can inevitably be witnessed at public cafes twitching and muttering swear words under my breath.&lt;/p&gt;
&lt;p&gt;Currently that cardinal sin of a trend I continue to encounter is the introduction of javascript controlled accelerated scrolling on non-touch devices.&lt;/p&gt;
&lt;p&gt;If you’re not sure what I’m talking about then hop over to &lt;a href=&quot;http://writefullapp.com/&quot;&gt;writefullapp.com&lt;/a&gt; and try scrolling with either your laptop’s touchpad or a mouse scroll wheel. You should notice that it’s going a bit faster than normal and has a bit of a slingshot effect. This is what I’m referring to with accelerated scrolling. Rather than letting the browser treat scrolling like it does on 99.99% of other websites, a javascript library hijacks the scrolling action to create a &lt;em&gt;supposedly&lt;/em&gt; more natural scroll that has inertial momentum.&lt;/p&gt;
&lt;p&gt;So why is this bad?&lt;/p&gt;
&lt;p&gt;Because good design should make a user’s experience as fluid and effortless as possible. We’re trained to expect certain differences in website’s designs, but at the core of our browsing experience we assume that the way we interact with them will be done in the same manner. When a new &lt;em&gt;feature&lt;/em&gt; alters a basic interaction in an unexpected and inconsistent way, it requires heavy concentration from the end user that almost inevitably causes confusion and frustration.&lt;/p&gt;
&lt;p&gt;This isn’t to say that inertial scrolling is a bad idea in and of itself — Windows could take a cue from OSX on that point — but it’s only good when it’s done in a way that both feels natural and is implemented system (or potentially application) wide.&lt;/p&gt;
&lt;p&gt;I’m all for new features that enhance our experience on the web, even when it’s ahead of the curve regarding browser support, but this new trend is definitely not one of them.&lt;/p&gt;
</content:encoded></item><item><title>Tools for Designing in the Browser</title><link>https://robertnealan.com/tools-for-designing-in-the-browser/</link><guid isPermaLink="true">https://robertnealan.com/tools-for-designing-in-the-browser/</guid><description>This post is intended to be a regularly updated list of tools, articles, and other goodies that help make designing in the browser both easier and more…</description><pubDate>Thu, 12 Jun 2014 22:10:04 GMT</pubDate><content:encoded>&lt;p&gt;This post is intended to be a regularly updated list of tools, articles, and other goodies that help make designing in the browser both easier and more efficient. If you’re currently a designer-developer hopefully you might learn something new of use, while if you’re new to the game hopefully this will get you started off in the right direction. Tools that I currently use are marked with an (*), while others I have used in the past.&lt;/p&gt;
&lt;p&gt;Have something you use that think should be here? Email me with a link at rob at atomidesign.com, and I’ll be sure to check it out.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Last updated: June 12, 2014&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h4 id=&quot;articles&quot;&gt;Articles&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.teamtreehouse.com/5-good-reasons-why-designers-should-code&quot;&gt;5 Good Reasons Why Designers Should Code&lt;/a&gt; by Team Treehouse&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.teehanlax.com/blog/designing-with-code/&quot;&gt;Designing With Code&lt;/a&gt; by Jeremy Bell @ Teehan + Lax&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/design-startups/designers-will-code-6c423fc5ccef&quot;&gt;Designers Will Code&lt;/a&gt; by David Cole @ Quora&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.inc.com/garry-tan/the-great-value-of-the-designer-who-codes.html&quot;&gt;The Great Value of the Designer Who Codes&lt;/a&gt; by Garry Tan&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;browser-inspectors&quot;&gt;Browser Inspectors&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://getfirebug.com/&quot;&gt;Firebug&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.chrome.com/devtools/index&quot;&gt;Chrome Dev Tools&lt;/a&gt; *&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;css-preprocessors&quot;&gt;CSS Preprocessors&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://sass-lang.com/&quot;&gt;Sass&lt;/a&gt; + &lt;a href=&quot;http://compass-style.org/&quot;&gt;Compass&lt;/a&gt; *&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://lesscss.org/&quot;&gt;LESS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://learnboost.github.io/stylus/&quot;&gt;Stylus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://myth.io/&quot;&gt;Myth&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;version-control&quot;&gt;Version Control&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://git-scm.com/&quot;&gt;Git&lt;/a&gt; *&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://subversion.apache.org/&quot;&gt;Subversion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;full-frontend-frameworks&quot;&gt;Full Frontend Frameworks&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://getbootstrap.com/&quot;&gt;Twitter Bootstrap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://foundation.zurb.com/&quot;&gt;Zurb Foundation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;grid-systems&quot;&gt;Grid Systems&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://semantic.gs/&quot;&gt;Semantic Grid System&lt;/a&gt; *&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://unsemantic.com/&quot;&gt;Unsemantic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;templating-languages&quot;&gt;Templating Languages&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://handlebarsjs.com/&quot;&gt;Handlebars&lt;/a&gt; *&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mustache.github.io/&quot;&gt;Mustache&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://haml.info/&quot;&gt;HAML&lt;/a&gt; - &lt;em&gt;Haml is mostly used in Ruby on Rails projects, but serves as a good example for an indentation-based language.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;development-tools&quot;&gt;Development Tools&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.mamp.info/en/&quot;&gt;MAMP&lt;/a&gt; *&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://livereload.com/&quot;&gt;LiveReload&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://cssrefresh.frebsite.nl/&quot;&gt;CSSRefresh&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gruntjs.com/&quot;&gt;Grunt&lt;/a&gt; *&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://gulpjs.com/&quot;&gt;Gulp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://incident57.com/codekit/&quot;&gt;Codekit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/marak/Faker.js/&quot;&gt;Faker.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://lorempixel.com/&quot;&gt;Lorem Pixel&lt;/a&gt; *&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;static-site-generators&quot;&gt;Static Site Generators&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://octopress.org/&quot;&gt;Octopress&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://middlemanapp.com/&quot;&gt;Middleman&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;organized-development-approaches&quot;&gt;Organized Development Approaches&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://oocss.org/&quot;&gt;OOCSS&lt;/a&gt; *&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://smacss.com/&quot;&gt;SMACSS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://bem.info/method/&quot;&gt;BEM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://bradfrostweb.com/blog/post/atomic-web-design/&quot;&gt;Atomic Design&lt;/a&gt; *&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Craft Your First Impression</title><link>https://robertnealan.com/craft-your-first-impression/</link><guid isPermaLink="true">https://robertnealan.com/craft-your-first-impression/</guid><description>A few weeks ago I received a cold email from a local San Francisco startup called Mighty Spring asking me to demo their product.</description><pubDate>Mon, 09 Jun 2014 18:31:57 GMT</pubDate><content:encoded>&lt;p&gt;A few weeks ago I received a cold email from a local San Francisco startup called &lt;a href=&quot;http://www.mightyspring.com/&quot;&gt;Mighty Spring&lt;/a&gt; asking me to demo their product. If you work in tech and have an internet presence you get used to receiving these things all the time (and generally saving them to the metaphorical circular filing cabinet&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, but the simplicity and attention to details in this particular case left such a great first impression that I felt it’s worth sharing.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://robertnealan.com/content/images/2014/Jun/Screenshot-2014-06-09-13-41-07.png&quot; alt=&quot;alt&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;Right off the bat they address me by name. This might seem like an obvious detail (especially given how easy it is to use mailing list merge tags), but you’d be surprised how emails I receive that even bother to do this much. Even better, he immediately tells me how he happened upon my contact info:&lt;/p&gt;
&lt;p&gt;“I just found your profile on Github…”&lt;/p&gt;
&lt;p&gt;He’s no longer a stranger who found my email through some shady email list purchase but instead a compadre who at the very least knows the existence of Github – a major nexus of the developer community and something that I maintain a profile for the purpose of people finding my work&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1-2&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;. The second half, “…and am hoping to get your feedback on my startup, Mighty Spring,” doesn’t yet try to sell me on why this startup is going to change my life, but instead appeals to my emotion and &lt;em&gt;&lt;strong&gt;asks&lt;/strong&gt;&lt;/em&gt; for my help.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;*slow clap&lt;/em&gt;*&lt;/p&gt;
&lt;p&gt;With only 21 words they’ve already addressed me by my name, told me how they found me, and asked for my help; and, in the next 33 words they manage to tell me what the startup is, how it’s going to benefit my life, and oh yeah, by the way – it’s free. If this is a product that has any appeal to a potential customer (most people who work full time positions), at this point I have to imagine their only question would be, “Why wouldn’t I sign up?”&lt;/p&gt;
&lt;h4 id=&quot;a-little-magic&quot;&gt;A Little Magic&lt;/h4&gt;
&lt;p&gt;Lastly, this isn’t just a normal invite, this is a &lt;em&gt;beta invite&lt;/em&gt;. That in itself unfortunately isn’t that meaningful since the early days of Gmail save in special circumstances&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1-3&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, but again when I clicked the link I didn’t just land up on a signup page, but instead landed on a page that already knew who I am.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://robertnealan.com/content/images/2014/Jun/Screenshot-2014-06-04-17-46-23.png&quot; alt=&quot;Screenshot of Mightyspring.com&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;At first I was confused, but then I realized they used the same trick I used to rickroll all my friends back in the day. While the link appears to be &lt;a href=&quot;https://www.mightspring.com/lumen/&quot;&gt;https://www.mightspring.com/lumen/&lt;/a&gt;, in reality that’s the text of the anchor tag and the real URL is: &lt;a href=&quot;https://www.mightyspring.com/lumen/?email=robertnealan@gmail.com&quot;&gt;https://www.mightyspring.com/lumen/?email=robertnealan@gmail.com&lt;/a&gt;. This is the oldest trick in the book, but really can add a hint of magic to the experience for those who either don’t code for a living or just aren’t paying that close of attention. It’s the little details that make a big first impression.&lt;/p&gt;
&lt;p&gt;All in all, the email took me about 7 seconds to read at a leisurely pace, and I’m already sold on trying it out. While I personally don’t have much use for a passive recruiting given that I’m happily self-employedd at &lt;a href=&quot;http://www.atomidesign.com/&quot;&gt;Atomi Design&lt;/a&gt;, I’ll still be giving it a go to see how well they follow through on their promises and whether it’s worth recommending to friends.&lt;/p&gt;
&lt;p&gt;Remember – you only have one chance to make a first impression, and with this style of email outreach you have the advantage of being able control the situation. Take your time to &lt;em&gt;craft&lt;/em&gt; your message and test it out before going public. Think it’s good? Wait a day and read it again. Good now? Pitch it to the next person who gets on the elevator and see how they respond. Lastly, be concise. Time is money, and most of us have a severe shortage of time these days. If you send a lengthy essay about your startup chances are most people aren’t going to read it.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Thanks owed to &lt;a href=&quot;http://clement.poisson.me/&quot;&gt;Clement Poisson&lt;/a&gt; for proofreading.&lt;/p&gt;
&lt;hr&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;I’m looking at you Dribbble… &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-2&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1-3&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1-3&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content:encoded></item><item><title>Life is (Finding) Meaning</title><link>https://robertnealan.com/life-is-finding-meaning/</link><guid isPermaLink="true">https://robertnealan.com/life-is-finding-meaning/</guid><description>I&apos;ve only now just finished listening to Derek Siver&apos;s latest conference talk &quot;The Meaning of Life&quot;, and can only encourage everyone else to watch (or listen…</description><pubDate>Sun, 04 May 2014 16:27:05 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://farm7.staticflickr.com/6183/6054999467_f7b952e799_b.jpg&quot; alt=&quot;The empty expanses of the Utah/Nevada desert along Highway 50&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;/p&gt;
&lt;p&gt;I’ve only now just finished listening to Derek Siver’s latest conference talk “&lt;a href=&quot;http://sivers.org/ml&quot;&gt;The Meaning of Life&lt;/a&gt;”, and can only encourage everyone else to watch (or listen to) it as soon as possible.&lt;/p&gt;
&lt;p&gt;As someone whose life work exists on a series of computer hard drives it hits pretty close to home. I regularly question what I’d do if a massive solar flare hit Earth and wiped out every electronic known to man. I mean sure, my skills as a designer/developer are pretty damn valuable right now, but when everything’s reset back to the 1850’s would that skillset really matter? Should I be developing practical skills like hunting and fire building instead? It’s enough to give anyone an mid-life crisis.&lt;/p&gt;
&lt;p&gt;Either way, my main point in writing is that while I loved hearing Sivers so casually questioning the meaning of life with his children’s storybook reading voice (seriously), I unfortunately was disappointed by his ending. After working through the questions of “Life is Time”, “Life is Memory”, and “Life is Learning”, he concludes that we all inevitably assign our own meaning to these different questions; and therefore apparently life is (just) life.&lt;/p&gt;
&lt;p&gt;While I don’t necessarily disagree with this statement, I think there’s a better answer than the one he gave - one hidden right in plain site throughout his entire presentation:&lt;/p&gt;
&lt;p&gt;Life is (Finding) Meaning&lt;/p&gt;
&lt;p&gt;To some this might seem like a disappointing cop-out to a question for which we all want a singular clear answer, but I see it as a beautiful symbol of the unique quality of being human. While other species seem to exist purely to reproduce, we instead explore, invent, and question why we exist, and in doing so (hopefully) eventually find our own reason to persist. Whether that’s a religion, your spouse, or rock climbing in a remote mountain range hours from any sort of civilization, the meaning of life for yourself is whatever you find it to be.&lt;/p&gt;
</content:encoded></item><item><title>Web Designers Code</title><link>https://robertnealan.com/web-designers-code/</link><guid isPermaLink="true">https://robertnealan.com/web-designers-code/</guid><description>When I moved to San Francisco in 2012 I knew I wanted to get a job as a designer at a startup, but had never before dealt with the issue of needing to…</description><pubDate>Tue, 11 Mar 2014 00:14:14 GMT</pubDate><content:encoded>&lt;p&gt;When I moved to San Francisco in 2012 I knew I wanted to get a job as a designer at a startup, but had never before dealt with the issue of needing to categorize myself into a certain role. In architecture there might be different types of designers (architect, landscape, etc), but they all overlap into a mesh of interdisciplinary collaboration that requires each person to be knowledgeable in the other person’s fields, regardless of their day-to-day responsibilities.&lt;/p&gt;
&lt;p&gt;Despite the oddity of having these arbitrary categories (especially at small startups), I applied to a few jobs as UI/UX designer and surprisingly got interviews within a week at all but one company (who interviewed me ~9 months later), got a lot of questions about whether or not I could do X or Y type of design, and landed a full time position at couple year old startup. At the time I didn’t know why I was having such a great response rate, but looking back I realized it was due to one thing:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I was a designer who could accurately code my designs.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;As a self taught designer/developer who never had anybody telling me what to learn or not to learn, this only seemed like common sense. If I’m passionate about my designs then why would I hand them off to someone who’s passion is in programming, not the tedious time-sink of HTML/CSS?&lt;/p&gt;
&lt;p&gt;Unfortunately the CTO at the time didn’t share this passion and I watched as designs were hackily assembled by a group of “full stack” developers, most of which who neither enjoyed nor cared about frontend presentation development, all with a hodge-podge of Bootstrap CSS and an over-abundance of bloated legacy CSS. While I pushed for media queries to be used to create a unified UI/UX across all devices, they were instead used to create an entirely different “mobile experience” and as an excuse to to throw “mobile app” and “responsive” onto the long list of marketing buzzwords.&lt;/p&gt;
&lt;p&gt;Let’s be honest, HTML/CSS is rarely fun and coding out your own designs probably isn’t that exciting to you, but as a designer you’re likely the one who most cares your designs being built accurately in their final medium, and as such you need to be able to take control of their execution. In some cases this means translating designs from PSD to HTML yourself or as is the case more and more often at &lt;a href=&quot;http://atomidesign.com/&quot;&gt;Atomi Design&lt;/a&gt; - designing directly &lt;em&gt;in the browser&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Regardless of how you setup your own workflow, the important thing is being able to take control of your designs from conceptualization through implementation. Even if aren’t coding frontend designs yourself, you need to have that knowledge as it helps inform the way you work and enables to start that discussion with the person who is coding it.&lt;/p&gt;
&lt;p&gt;TL;DR: If you call yourself web designer and you aren’t coding your designs, you better start.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Shameless Plug:&lt;/strong&gt;&lt;br&gt;
I’ve started a Meetup community called &lt;a href=&quot;http://dwc.io/&quot;&gt;Designers Who Code&lt;/a&gt; that focuses on the intersection of design and development. We’re having a &lt;a href=&quot;http://www.meetup.com/Designers-Who-Code/events/169900622/&quot;&gt;Designer Drinkup&lt;/a&gt; on Wednesday, March 12th at Bloodhound in SoMa, and will be announcing upcoming workshops at our office in SoMa soon. If you’re in the San Francisco area and enjoy good beer and good company be sure to come check it out!&lt;/p&gt;
&lt;hr&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;This is likely a topic for a larger discussion, but after having just finished our first project sans-Photoshop we’d like to think it still has a place in our workflow as a place for “digital sketches”. Full page PSD mockups are out, but working in different analog and digital mediums always helps shake up the old design thinking. &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content:encoded></item><item><title>The Most Important Part</title><link>https://robertnealan.com/the-most-important-part/</link><guid isPermaLink="true">https://robertnealan.com/the-most-important-part/</guid><description>While doing some research on OOCSS vs OOSCSS I stumbled across one by Chris Hansen at Pivotal Labs titled Why we don’t use OOCSS (but we should).</description><pubDate>Mon, 16 Dec 2013 18:25:44 GMT</pubDate><content:encoded>&lt;p&gt;While doing some research on OOCSS vs OOSCSS I stumbled across one by Chris Hansen at Pivotal Labs titled &lt;a href=&quot;http://pivotallabs.com/why-we-dont-use-oocss-but-we-should/&quot;&gt;Why we don’t use OOCSS (but we should)&lt;/a&gt;. I have my own hesitations and thoughts regarding pure OOCSS, but was dumbstruck by one of his reasons for not using it:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;HTML and CSS are just not as important as the server code or javascript for a web developer.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&quot;the-part-your-customers-see-isnt-as-important&quot;&gt;The Part Your Customers See Isn’t As Important?&lt;/h3&gt;
&lt;p&gt;Let’s be honest, building out HTML/CSS templates can be pretty mundane at times, so to all the developers who grumble when they have to tediously build out a pixel perfect frontend - I understand. It’s actually one of the many reasons I believe all designers should learn to code their designs themselves.&lt;/p&gt;
&lt;p&gt;Unfortunately, it seems like this attitude extends beyond minor discontent and instead is an industry-wide attitude that the frontend is less important the innerworkings of your application, when I’d argue the exact opposite.&lt;/p&gt;
&lt;p&gt;Yes, the backend is still &lt;em&gt;extremely&lt;/em&gt; important, but most of your customers likely neither understand nor care how it actually works, so long as it does what it says it does. Unless your product is something targeted at the development community or some holy-grail with no competitor (Hint: It probably isn’t), chances are your customers are both consciously and subconsciously forming opinions about your product based on &lt;em&gt;how it looks&lt;/em&gt;. When one of your customers inevitably runs into a bug (I promise they will), if it looks polished there’s a much better chance they’ll be forgiving and report the issue to you instead of switching to a competitor’s product. Better yet, if you respond promptly and work to help them through the issue and/or patch the bug there’s a good chance you can turn a negative situation into a positive memory of great service for your customer.&lt;/p&gt;
&lt;p&gt;On the other hand, when one of your customers runs into a bug and your application looks like a POS, they’re going to assume that’s because it is a POS.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Feel free to voice your thoughts over on &lt;a href=&quot;https://news.ycombinator.com/item?id=6917559&quot;&gt;HackerNews&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>MVP, not MVPOS</title><link>https://robertnealan.com/mvp-not-mvpos/</link><guid isPermaLink="true">https://robertnealan.com/mvp-not-mvpos/</guid><description>If you live and work in the tech world, then &quot;lean&quot; or &quot;agile&quot; just might have been your first words.</description><pubDate>Mon, 18 Nov 2013 16:48:41 GMT</pubDate><content:encoded>&lt;p&gt;If you live and work in the tech world, then “lean” or “agile” just might have been your first words.&lt;/p&gt;
&lt;p&gt;Every meetup, conference, and startup in a 50 mile radius is talking about what it means to be a lean startup, and I have to say it’s been a great improvement over old-fashioned waterfall workflows. Unfortunately, another phrase that goes hand-in-hand with the lean/agile movement is the ever-present concept of the “MVP”, otherwise known as the Minimum Viable Product.&lt;/p&gt;
&lt;p&gt;In theory it’s a great idea - inputting the minimum amount of time necessary to validate a product/feature - but like many great ideas it seems to be frequently bastardized in practice and reinterpreted as what I like to call MVPOS, or Minimum Viable Piece of Shit.&lt;/p&gt;
&lt;p&gt;Yes, I understand you want to move quickly; and yes, I do think you should be doing the minimum amount necessary to validate your idea. However, that is no excuse for it to look and function terribly (or not function at all). Save time on things that don’t scale [1] long-term but can be manually processed for the purposes of testing, but don’t cut corners on the things that directly affect the end-users’ perceivable quality of your product.&lt;/p&gt;
&lt;p&gt;Short of some weekend hackathon you did with your buddies or an internal tool your company uses that took off unexpectedly, every feature of any product you intend to sell or monetize should strive to be as polished as reasonably possible and function just as your end-user expects it should. Don’t be one of those startups that delivers broken features with the excuse, “It’s just the MVP., we’ll fix it later.”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Man up, admit it isn’t good enough, and fix it now.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Otherwise, you’re missing the entire point of the MVP in the first place - to iterate quickly on small features based on customer feedback and measurable data. If it doesn’t work right in the first place, the only feedback you’ll get is likely what you already know.&lt;/p&gt;
&lt;p&gt;Share your thoughts on &lt;a href=&quot;https://news.ycombinator.com/item?id=6755207&quot;&gt;Hacker News&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;1. If you havn’t read Paul Graham’s &lt;a href=&quot;http://paulgraham.com/ds.html&quot;&gt;Do Things That Don’t Scale&lt;/a&gt;, do yourself a favor and check it out.&lt;/p&gt;
</content:encoded></item><item><title>Be Honest</title><link>https://robertnealan.com/be-honest/</link><guid isPermaLink="true">https://robertnealan.com/be-honest/</guid><description>My friend Nathan will tell you I just hate people (jokingly, I think), but when it comes to business you can&apos;t beat around the bush.</description><pubDate>Fri, 15 Nov 2013 20:28:13 GMT</pubDate><content:encoded>&lt;p&gt;My friend Nathan will tell you I just hate people (jokingly, I think), but when it comes to business you can’t beat around the bush. Is someone’s work not up to par? Tell them they need to step things up. Is the client not holding up their end of the work? Sit them down and (politely) talk about what they and you can do to communicate or work together better.&lt;/p&gt;
&lt;p&gt;Sometimes it’s going to be awkward and sometimes it’s going to take some time to fix. And yes, one day you’ll probably inadvertently burn a bridge or two, but more often than not it saves a lot of pain and headache that’ll come from avoiding the reality of the situation until it’s too late.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Pipe in on &lt;a href=&quot;https://news.ycombinator.com/item?id=6741976&quot;&gt;Hacker News&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>Stop Freelancing</title><link>https://robertnealan.com/stop-freelancing/</link><guid isPermaLink="true">https://robertnealan.com/stop-freelancing/</guid><description>I&apos;ve been &quot;freelancing&quot; part time for the better part of the past 4 years and full time for the past 8 months, and if there&apos;s one thing I&apos;ve learned it&apos;s that…</description><pubDate>Wed, 13 Nov 2013 18:42:32 GMT</pubDate><content:encoded>&lt;p&gt;I’ve been “freelancing” part time for the better part of the past 4 years and full time for the past 8 months, and if there’s one thing I’ve learned it’s that telling people you freelance will garner responses that manage to combine a jealousy of your freedom and a subtle tone that silently says,&lt;/p&gt;
&lt;p&gt;“A freelancer? That’s cute.”&lt;/p&gt;
&lt;p&gt;So what did I do? I stopped freelancing and started my own company. I came up with a business name[1], filed for a business license, and as of recent finally even got myself a desk with a fancy “Suite” address in a coworking building.&lt;/p&gt;
&lt;p&gt;While the transition to me seamlessly occured over the course of several months, to the clients I pitched and worked with it was a sudden and jarring difference. Potential leads increased in quantity (and quality), a higher ratio of those leads converted to clients, and the level of control I had over the actual working relationship with clients improved exponentially. Behind the scenes barely anything has truly changed, but by presenting myself as a company it gave a much more professional image than that of some kid “webmaster” working from his parent’s basement[2].&lt;/p&gt;
&lt;p&gt;Remember, you’re not a no-strings-attached temporary employee, you’re an expert in your field whom clients come to because they want the best product possible and can trust to guide them in the best direction possible.&lt;/p&gt;
&lt;p&gt;I’m not saying there aren’t plenty of talented, extremely professional freelancers out there (there are tons), but my experience has been that being a “freelancer” sets the unfortunate tone that you need your client, whereas in reality they are the one who needs you to help tell them how to make their business successful.&lt;/p&gt;
&lt;p&gt;Talk about it over on &lt;a href=&quot;https://news.ycombinator.com/item?id=6727378&quot;&gt;Hacker News&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;1. Some people might want to continue to use their personal name, which is fine. Just be sure to position it as a company, not you. The difference between “Designer John Smith” and “John Smith Design Studio” can’t be underestimated when viewed by a prospective client.&lt;br&gt;
2. No, I don’t work from my parent’s basement.&lt;/p&gt;
</content:encoded></item><item><title>WordPress is Great, WordPress is Terrible</title><link>https://robertnealan.com/wordpress-is-great-wordpress-is-terrible/</link><guid isPermaLink="true">https://robertnealan.com/wordpress-is-great-wordpress-is-terrible/</guid><description>The blogging community has been flourishing for years with WordPress at the lead, but to anyone involved it&apos;s obvious that there&apos;s room for improvement.</description><pubDate>Fri, 01 Nov 2013 21:54:17 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;The blogging community has been flourishing for years with Wordpress at the lead, but to anyone involved it’s obvious that there’s room for improvement.&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;the-community&quot;&gt;The Community&lt;/h3&gt;
&lt;p&gt;First off, let’s just get out front that it now powers an estimated sixty million, or eighteen percent of websites, on the internet.&lt;/p&gt;
&lt;p&gt;Holy shit.&lt;/p&gt;
&lt;p&gt;Now while I won’t argue that something is great because it’s popular (I’m looking at you preppy high school kids), it still doesn’t mean that its widespread use is any less impressive. A quick look at the source of the top 30 articles on HackerNews at the time of writing this shows that at least 9 are powered by Wordpress. First impressions suggest that Wordpress is probably more pervasive in our cat-meme browsing lives than any other platform out there.&lt;/p&gt;
&lt;p&gt;As every platform with more than ten users has started holding a conference if only for publicity’s sake (really Box/Dropbox/Trello/etc?), Wordpress has impressively held over 200 of their own Wordcamp’s worldwide since 2006. What’s impressive isn’t that Wordpress itself organized 200+ events (I’d label that as insanity), but that almost all of these events were organized by the community itself.&lt;/p&gt;
&lt;h3 id=&quot;so-whats-the-problem&quot;&gt;So what’s the problem?&lt;/h3&gt;
&lt;p&gt;John O’Nolan, one of the designers of the Wordpress UI stated,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What started out as a humble blogging platform targeted at enabling digital publishing for the masses, has evolved into a fully-fledged website CMS.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The problem is that Wordpress has long since deviated from being the pure blogging platform it started as, and in doing so has introduced a lot of confusion into it’s product direction. After years of its users hacking it to be more CMS-like it finally embraced this ideal, but years after its acceptance it still remains only CMS-like. Rather than growing into the open source CMS power house it should have been, it’s instead stuck in an awkward adolescent stage where anything is possible but never quite feels right. I can’t recall the last time I had to tell a client, “Wordpress can’t do that,” but sadly I find myself walking away unproud of the code I’ve left behind.&lt;/p&gt;
&lt;p&gt;Like a public school multi-purpose room, it can do anything, but is great for nothing in particular.&lt;/p&gt;
&lt;h3 id=&quot;content-is-king&quot;&gt;Content is King&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;There’s too much stuff everywhere, too much clutter, too many (so many) options getting in the way of what I really want to do: publish content.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is one of the opening lines that leads O’Nolan to introduce his new “pure blog” platform, Ghost. While I so far love Ghost (I’m placing my bet on it with this blog), I think he missed the point that “publish[ing] content” should be the focus of every site, not just simple blogs.&lt;/p&gt;
&lt;p&gt;While the dashboard has visually stood the test of time with some grace, it doesn’t help the fact that it continues to have a steep learning curve for the casual user. Looking at the dashboard for a recent client site, I can quickly count at least 23 sidebar/header links without even getting into dropdown menus or the dashboard homepage content.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://robertnealan.com/content/images/2013/Oct/wordpress_screenshot.jpg&quot; alt=&quot;Wordpress Dashboard&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;&gt;&lt;br&gt;
&lt;em&gt;Why is my theme name, number of widgets, Wordpress version, and spam comments given a first-class location as soon as I log into the dashboard?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For my client’s sake I’ve thankfully created a custom user role that gives them access to only the things necessary for most employees, but again it’s another fix to an issue that shouldn’t exist. Why are Appearance, Plugins, Users, Tools, and Settings all separate top-level items? At the end of the day these are all “Settings” that aren’t relevant to the normal content management process and should be organized as such.&lt;/p&gt;
&lt;h3 id=&quot;security&quot;&gt;Security&lt;/h3&gt;
&lt;p&gt;With great power comes great responsibility, and Wordpress is no exception. With 60 million websites and an aging codebase susceptible to common attacks, it’s not uncommong ot hear about hacked Wordpress sites. I myself have had several occasions where old clients call asking why their description on Google is a bunch of gibberish about credit cards, only to find that a hidden block of text had been injected into their page from some foreign base64 encoded line within their theme or the core files.&lt;/p&gt;
&lt;p&gt;The introduction of poorly written plugins brings even more risk of common attacks like an SQL injection. If anything, Wordpress should probably take the route of auto-escaping any inputs unless explicitly disabled on a case-by-case basis.&lt;/p&gt;
&lt;h3 id=&quot;the-loopoh-god-the-loop&quot;&gt;“The Loop…oh god, the loop”&lt;/h3&gt;
&lt;p&gt;A decade ago PHP was one of the most promising languages out there, but now it’s largely the subject of regular ridicule. While its been making great strides at modernizing itself since v5.3 (now on v5.5), it still has a long way to go compared to its younger, more nimble (and less stable) competitors. Given that PHP is making such big steps to modernize you’d think Wordpress would be right there with it, but instead we get a cop out on their inconsistent “Requirements” page:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We’re very aware that the latest versions of PHP and MySQL aren’t right for everyone, and that sometimes hosts can be slow or hesitant to upgrade their customers since upgrades to PHP and MySQL historically have broken applications.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Being conscious of not breaking your user’s websites is admirable, but when you’re supporting a version of an actively developed language that’s now 6 years old, it starts to raise some concerns.&lt;/p&gt;
&lt;p&gt;A large portion of the PHP community (and development world as a whole) accepted the benefits of separating logic from the view with languages like Twig/Handlebars/etc, yet we still have a muddled method of writing templates using Wordpress’ own PHP-based template tags. While I’m not much interested in arguing whether or not PHP is a templating language in its own right, with inconsistent Wordpress functions all mixed inside the god-forsaken the_loop() it becomes one big hack of if/while/else statements and “Wordpress PHP” that becomes near-impossible to consistently maintain long-term.&lt;/p&gt;
&lt;h3 id=&quot;a-proposal-for-the-future&quot;&gt;A Proposal for the Future&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Modularize the core.&lt;/strong&gt; Don’t need a feature? Then don’t include it. Take some cues from the likes of node.js’ require and Rails 4’s separation of core features into modular gems. No need for a blog? Then stop including post-style functionality and instead just include pages with base templates that can be manipulated based on flexible sets of rules. Don’t need commenting? No problem.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Integrate the community.&lt;/strong&gt; No, really integrate them. Wordpress has one of the most active communities out there and they’re actively building the great plugin ecosystem that makes Wordpress so successful. Take a serious look at the “indispensable plugins” - the ones that are used on almost every website - and integrate them into the Wordpress core as optional modules. There’s no reason we should be installing the same breakable third-party plugins on every Wordpress site we build…I’m looking at you Gravity Forms and Advanced Custom Fields.&lt;/p&gt;
&lt;p&gt;Don’t get me wrong, Wordpress is still a great platform to build for small client sites for many reasons not listed here, but if it wants to continue to remain as relevant as it has been it needs to start looking toward the future.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Share your thoughts on &lt;a href=&quot;https://news.ycombinator.com/item?id=6656816&quot;&gt;HackerNews&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>Doing It Live</title><link>https://robertnealan.com/doing-it-live/</link><guid isPermaLink="true">https://robertnealan.com/doing-it-live/</guid><description>After months of my phone asking, &quot;Are you going to write 1000 words tonight?&quot;, I sadly only have half a dozen partial posts.</description><pubDate>Thu, 31 Oct 2013 17:14:59 GMT</pubDate><content:encoded>&lt;p&gt;After months of my phone asking, “Are you going to write 1000 words tonight?”, I sadly only have half a dozen partial posts. I kept myself convinced that building a backlog of potential posts was the right choice so I’d still have something to post when I get busy, but ultimately that’s just an excuse to be lazy. Instead, I’m going to stop talking about it with myself and do it live. It’s tough to stay motivated, and it’s terrifying to put yourself out there, but as they say, “no risk, no gain” (that is a saying, right?).&lt;/p&gt;
&lt;p&gt;I don’t want to make a grand statement about how this is a “relaunch” of my blog, because it isn’t - it’s just a continuation minus the old content because it’s no longer relevant to what I hope to express. Some of the old stuff will inevitably find itself regurgitated in one way or another, but sometimes starting with a clean slate is the only way to start again at all.&lt;/p&gt;
&lt;p&gt;I’ve written blogs before - it shouldn’t be that difficult, right?&lt;/p&gt;
&lt;p&gt;…right?&lt;/p&gt;
</content:encoded></item></channel></rss>