The RND Stack

Last week, ZEIT released a new framework for Universal React applications: Next.js. Unlike previous attempts, Next provides a complete solution for rendering and routing React applications in a single dependency (transitive dependencies notwitstanding, of course). No amount of configuration is required for Webpack, or Babel, or React itself. Furthermore, no convention is imposed on React beyond the way Next.js handles routing. It's an incredibly elegant solution.

On its first day of release, developers piled onto Guillermo, one of the creators of Next.js, to add custom server-side logic. While this will no doubt be a useful feature, I think it continues to miss the point: this is an opportunity to cleanly separate concerns between services, with technologies to match. The advantage of "Universal JavaScript" is not the opportunity to run our UI rendering alongside our business logic. Instead, it is the opportunity for UI Engineering to take complete advantage of the server independent of the business logic.

In short, Next.js is the ideal "front layer" (also referred to as the "presentation layer") solution. [For more discussion of what that entails, see here and here.]

What should we use for business logic and communicating with the database, then? Rails.

Where the front layer can benefit from "just enough" flexibility as provided by Next.js, API tiers are best served by convention. Where the front layer can take risks and dodge the rigor of test coverage (though React and Redux benefit from their rich testing story), the API tier is the primary line of defense against data corruption, leakage, and loss. Rails remains a mature solution in this domain; I know no comprehensive argument that it's done anything but continue to prove this to be true.

Not to leave out some of the nuanced practicalities of these suggestions, I propose the name "RND Stack" for two reasons:

  • This is a stack to start with. The best stack for your application is the one that's already providing value, but the zero-to-sixty story of both Next and Rails is more than sufficient for an expedient start to any project. Where better to do R'n'D than on the RND Stack?
  • The D: Docker. The biggest operational risk to splitting resources across Rails and Node is the deployment environment, whether local or remote. On one hand, maintaining two complete environments (runtimes, OS dependencies, etc.) is a nightmare. On the other, Docker (or any imaging solution) provides a better byte-for-byte identity guarantee than either Gemfile.lock or npm-shrinkwrap.json. On a foot, Docker brings with it a rich suite of tooling for orchestration and management: Terraform, Triton, Kubernetes, etc.

Interested? Let me know. Next up, assuming there's interest? Demo.

Living a Limited Life


Life has limits. You will try to break them, as I have, but they will catch up with you.

Life has limits. Even though God may be limitless, we are called to live within those limits and be Sabbath people.

Life has limits. I pray that will learn this lesson quicker than I have, as I have wasted more time than I care to recount trying to deny these limits, rather than embracing them and living a full life.

Life has limits. Those limits are, indeed, life-giving: God gave us those limits so that we would prune away those things in our lives that spoil and cultivate those things that edify.

Speaking Up

As I've tried to explain before, institutionalized patriarchy and institutionalized white supremacy provide men like Drumpf with a considerable deal of privilege (there's that word again).

On the surface, using "Drumpf" follows the same logic, albeit against the person granted power by those institutions, rather than against those persons marginalized by them. When you refer to a trans person by their deadname, you are deciding to refuse them the fullness of their personhood and their ability to self-identify. Since the deck is stacked in your favor to begin with, the institution agrees with your choice and they're marginalized even further.

On the flip side, referring to a liar, megalomaniac, and terrorist by the name they've chosen to leave behind (for a word that means "in a class above all others", no less) is a similar attempt to pull the same wind out of their own sails. Since the institution favors them in this matter, however, it has little effect: at its worst, this negative feedback loop normalizes the effects of the institution at large, providing equitability of discourse in the general.

James calls out this exact imbalance in chapter 2, verse 6 of his letter: "But you have dishonored the poor man. Are not the rich the ones who oppress you, and the ones who drag you into court?" (ESV, context: The word here is "katadunasteuo", which Strong defines as "to exercise harsh control over one, to use one's power against one, or to oppress one". What power (even "riches") we as cis, white men yield today!

While this is more of my own heart than I typically share over social media, silence is no longer an option. Too many of our marginalized brothers and sisters are being threatened, attacked, and even killed here and abroad because those given privilege by institutions refuse to speak up on their behalf. It's often hard to speak out, but society at large is on our side and will hear us out just as it ignores those beneath its feet.

Whether you agree with me or my methods (or my faith), I implore you to at least meditate on and consider how you and I might "correct oppression" (Is 1:17 ESV, and bring a little more shalom to this world.

God bless you.

Growing Up Gamer

Today's my birthday.

Without a doubt I'll wind up spending it, for the most part, like any other day: working, having lunch with people I love, occasionally flipping through Twitter to see what awful thing is going on for the rest of the world today. And, like any other day, those awful things include the harassment of anyone not simultaneously white, male, and cisgendered for simply existing and having an opinion. This is even worse in the industry I miss to this day being involved in, as female employees of Nintendo in specific and game development in general become the target of harassment for bringing diversity into this "sacred", white-boy-serving medium.

This got me thinking about the following dynamic:

  1. I grew up a gamer.
  2. My parents thought I'd "grow out of it", but that never happened.
  3. I grew up.
  4. I got a job, and can afford, for the most part, to buy any game I want whenever I want—one of many privileges I've been afforded, I guess.
  5. I have less time and patience for games, so I buy fewer of them, not more.
  6. I start to choose game purchases because of the people responsible for them as much as for the content of the game itself.
  7. I had two children.
  8. I only buy games I want to be proud of playing today, prouder still to someday share with my kids.

And that leads me back to the present day:

  1. I don't buy games that objectify anyone, especially those already oppressed due to their gender, race, ethnicity, etc. (It's not satire, it's not art, it's active oppression.)
  2. I don't buy games from Nintendo.
  3. I don't buy games.

I'm 100% sure GamerGate and its ilk don't care. Good.

I'm 100% sure Nintendo doesn't care. Fine.

I'm 100% sure nobody cares about this but me, but I'm 100% sure I'm not alone in my conclusions.

As such, game companies need to adjust if they want our money: more and more gamers are growing up, and we just don't have the time or the patience to deal with their childish, insecure shenanigans anymore. You stand up for what's right, or I spend this money on the other million-and-one things demanding my time and attention. I lose no sleep over missing out on the latest over-sexualized garbage from You-Name-It Studios. On the contrary, not wasting my time with the latest oppressive tire fire means I get specifically to spend more time in bed with my wife instead of on the couch, controller in hand.

So if you'll excuse me, I'll be in the yard chasing my kids. Call me if the industry grows up, too.

P.S. This is purposefully hyperbolic, but less than you'd want or imagine. That said, I know that against all odds, those who don't look like the cast of Indie Game: The Movie have managed to bring to market wonderful, diverse, important art and I love and appreciate every one of them for it more than they'll ever know.

Standards Wanted: Yelp

Earlier today I received another link through another concerned individual to another person fired from Yelp for being human and having human needs. The corporate culture at Yelp clearly values departmental and tribal performance over individual well-being, and it shows in the ways its middle management treats their staff: you're "putting them in a tough spot" when you decide on priorities higher than the tasks they put before you.

We can and should hold companies to higher standards.

Yelp has what's known as a "two-sided market". As a startup, this would have even been referred to as their "two-sided market problem": they need users to get businesses on board, and they need relevant data from businesses to get and "retain" users. The only way they make money is by selling those users to their true customers: those same businesses.

Today, Yelp has "solved" this problem. They're a pervasive influence in the restaurant industry: a pied piper for all the "foodies" (read: would-be food critics that scathe anything outside of their limited worldview) nationwide. They're now publicly traded on the NYSE, and as of right now they seem to be rising slowly to around $20.50 a share (though their cash flow seems to be in the red – big surprise there).

As we all should know by now, this is by no means a permanent position.

As it turns out, individual users have a lot of power over these same platforms in how they choose to spend their time and share their personal information. Every piece of information you share on Facebook and Twitter further strengthens their position, entrenching them in the overall sphere of "social media". So it goes with Yelp and the industry of gleaning values from those that spend countless hours contributing to their database of reviews and ratings. The inverse is true as well: enough users discontinuing use of Yelp in lieu of the growing list of alternatives (even for other monopolies like Apple and Google) is the strongest motivating force for such a lifeless juggernaut.

That's a good enough argument for me. I'm not sure I'll miss the foodies anyway.

Why I Follow Who I Follow (on Twitter)

TL;DR: If I follow you on Twitter, I find what you say important for me to hear. If I don't follow you on Twitter, that means almost nothing, and you should not take that personally. For all you know, I may consider you one of my closest friends.

For all intents and purposes, I use Twitter incorrectly: I read every post, often scrutinizing the nuances involved and the ways in which this post might challenge one of my assumptions. Because of this method I might invest more of my time on Twitter considering a single idea than most people seem to spend on a single visit. Twitter is more than a social network: it has become a tool of my profession, and it remains a part of my daily work to invest in that network.

Currently, however, I am drowning under waves of rich debate.

Rich debate? On Twitter? Yes. It's there, if you're willing to follow the right people. Consider a conversation between Michael Jackson and Marco Rogers: Marco called Michael out publicly for posing a naïve question from a position of relative privilege, and the two struggled with the situation for the better part of a day. While I hope both men grew from the encounter, I know I did, and I'm sure other third parties did, too. (For posterity, here is the "offending" post and Marco's considered response.)

Unless I want to spend all of my time reading thoughts and conversations like these and no time contributing my own ideas, I need to be a little ruthless, culling my list of follows down dramatically. I've thought about going "write-only" (only posting, never reading), and I know that works for some, but the growth begotten by that nuance and debate remains important to me. As a result, I need to ensure I follow a group of people that, together:

  • Challenge my assumptions
  • Broaden my perspective
  • Check my privilege
  • Help my growth
  • Brighten my day
  • Empower my faith
  • Improve my profession

These are co-dependent needs, and I hope to discover a group of people that can (whether they know this or not) meet these needs with me while reducing the cognitive burden of keeping up with all the nuance and debate Twitter users present on a daily basis.

Addendum: The "Do you know them?" Challenge

My wife once asked me that question, and I challenged myself to be able to answer "yes" by meeting everyone on my Twitter follows in the real world. While I still look forward to seeking out a few more people I've "met" through Twitter, I expect I'll wind up following far fewer people on that list, from celebrities like Wil Wheaton, Chris Kluwe, and Kenji Lopez-Alt to "normal folk" like Fabian Giesen, Caitie McCaffrey, and Kelly Sommers.

That said, far more unfollows will be people I do know and have already met, and that's hard.

SSH-Agent and Windows

During my day job I use a Windows laptop to make working with a number of .NET projects easier. That said, I've not completely abandoned Node as a platform, nor do I wish to leave Bash behind. Ergo, I wind up using msysgit to emulate a Bash-like environment for Windows. To make things even easier, I use ConEmu to provide a tabbed interface around msysgit. The final piece of the problem is that I have multiple git accounts with their own SSH key (one GitHub for Enterprise, and one Github), and each of these keys has a passphrase.

The naive approach is to just add eval $(ssh-agent -s) to the top of my .bashrc file. The Problem is that this requires a separate ssh-add call for every tab, requiring me to enter my passphrase in every tab. This pretty-well defeats any ease-of-use I was originally looking for.

Screenshake on Tweet

A fun little bookmarklet I made for @tha_rami and @legobutts. It applies screenshake to Twitter every time you press the Tweet button.

Geographical Closure


It was a strange feeling to return to the world I grew up in. After several episodes of completely leaving my world and moving to a new one, taking such a large step backward was anathema to such an extreme defense mechanism. I know I left these places behind to try and bury some version of myself along with it, so exhuming any portion of that past self seemed disagreeable at best.

Nevertheless, Carlisle is the place Jess fell in love with, and I can't argue with that.

Perfectly Imperfect Bash

A quick and dirty nerdy reflection on some Perfectly Imperfect Bash I just wrote while exploring the skip-worktree flag in Git:

git ls-files -v | grep 'S ' | xargs -n 1 git update-index --no-skip-worktree

To the uninitiated:

Motivation: "The Gap"

In a moment of Fantastic Inspiration, I was presented with an elegant solution to a problem so many makers have: motivation.

More specifically, a co-bootstrapper and friend was concerned that he felt unmotivated to come home after a day of programming and continue programming on our product. Coincidentally, I've been having motivational problems with my day job. In a random moment of inspiration, I decided to see if the motivational issues were the same, coining the issue itself "The Gap".

The Best Password Database: Your Mind

In the wake of Heartbleed, one particularly interesting side effect kept surfacing: users of Lastpass were encouraged to regenerate all "important" (read: All) passwords. 1Password, on the other hand, announced that they weren't affected. I think it's great that these password security options are promoting good practices. That said, OpenSSL's bug today is Agile's bug tomorrow. It's still software, and it's inevitable for it to become vulnerable someday.

My "Annual" Snowman, 2014 Edition

This is my "annual" snowman for 2014. He's about 7 feet tall; I'm slightly in front of him. His arms are a bit hard to see, but one goes out to his walking stick, and the other is raised to his left, waving to the passing cars.

Wipe that snow off your shoulder, Mr. Snowman.

Overwhelming Uncertainty


On a completely different track from my thoughts on Insufficient Uncertainty, today I'm fighting off Overwhelming Uncertainty. Michael Lopp, a.k.a. Rands, introduced me to the concept of "entropy surfing" through his Trickle Theory post. The post is worth a full read, but here's the ending from this well-written analysis of software development:

Insufficient Uncertainty

I've started working on a game with simultaneously-executed turns. It's meant to be as simple as possible: the first version only allowed for two decisions per turn with only four choices per decision.

Any time you iterate on a concept, you need to know where to iterate and why you're iterating there. Do it scientifically: build a theory, make a related change, make a measurement, and check your theory. This game wasn't fun at first (just reading the sentence above might make that obvious), so I needed to iterate. Time for that theory.

Unit Testing over SMB in Visual Studio


Though I've recently upgraded computers, my old Drobo is still attached to the old machine, shared through Windows (SMB) with the new machine. I've been working on getting CS-RESP wrapped up in support of a Unity project, and wanted to start testing it.


After reading all the MSDN documentation I could on using the Test Explorer, I could not get the tests load for the life of me. I tried writing the test classes by hand, deleting them and generating a second time, restarting, you name it. Though common error cases were diligently called out on MSDN, my problem was not. Test Explorer remained empty, and I had no way of running my tests. Even Assert.AreEqual(1, 2); was passing...

Café Bombón

In lieu of a Café Cubano, a Café Bombón will always suffice. I bet the reverse is true, too. When made well, both are rich, creamy, and just sweet enough to satisfy.

No Brakes Valet

When we couldn't find anything to play on the 360 and Nidhogg seemed a little too challenging, I broke out the @PlayOuya with my folks. No Brakes Valet was immediately accessible and a lot of fun. It's shaping up to be a party favorite.

Silicon Valley's "Meritocracy"


I can't find the Tweet anymore, but I know someone from my network (I think it was @raganwald) posted something to the effect of:

Silicon Valley is a meritocracy for sufficiently cronyistic values of "meritocracy".

That phrase has stuck with me since, mostly because it explains one of several issues I had with Silicon Valley. Silicon Valley's barrier of entry rivals that of AAA game development, and every AAA game development job on the planet is either a dead end or it requires a shipped title. Good luck jumping that one.

Cross-Country Road Trip


Growing up in an era when flying is cheaper, safer, and easier than alternative transportation methods, I've never before had the occasion or opportunity to partake in a cross-country road trip. This means that at less than a year old you've joined in something I've missed out on for twenty-seven years.

It's been epic:

Old Friends, New Places


An Old Friend is such a wonderful, rare sight in my life. Not that I'm opposed to making friends with the elderly, but I assume that you can assume that I'm not referring to the old and wise; rather, I'm referring to those friends I haven't seen "in a while".

Thoughts on Git

A few thoughts on Git workflows:

  • I tend to prefer simple, low-friction workflows in general, but this is amplified greatly for Git. In my experience, complex wastes time, whether in the form of continual education to newcomers (who can't self-educate due to its complexity) or fixing problems that arise (due to the almost certain fragility that joins complexity in the fun). For this reason I've regularly attempted (and usually succeeded) to instill a workflow closer to GitHub than git-flow. Check out those links to see the differences for yourself. One simple difference is that git-flow all but requires its own tooling to manage the complexity. GitHub's simpler flow is just branching.

The Next Big Hunch

My belief (which could definitely be considered non-standard in the Valley) is that what we call a "hunch" is really just God prodding us along our way. Because of this belief, any time I get one of those "I can feel it in my bones", solid hunches, I explore obsessively. If the feeling continues as I get deeper into the exploration, I know this is what He wants me to do, and it becomes a part of my life.

Deploying Wordpress to Openshift

Even though I have moved to Jekyll for this blog, Wordpress remains an extremely powerful and user-friendly blogging engine. If it weren't for its PHP nature, I'd probably still be using it. But I digress. While most of my in-development Node apps run on Heroku, for my latest Wordpress project I decided to give OpenShift a try. (My decision may have been influenced by working with ex-Makara and ex-RedHat folks at [StrongLoop][ls], but they didn't solicit this post.)

OpenShift provides an example Wordpress project this method relies heavily on, but I wanted to diverge from this method by managing the Wordpress code as a separate Git repository. That is, the OpenShift app server is the only remote for any OpenShift-specific code, and GitHub provides the remote for everything else: Wordpress core, plugins, themes, etc.

Commentary on a Pull Request

Open source projects thrive on the existence of active contributors. The best contributors, typically leading to the best projects, are those using the software in question to solve real, interesting problems with the software while running into either insufficiencies in its feature set or bugs with the existing features. The process follows that these same good programmers, rather than simply complain about the issue they face, dig into the source code they've been freely given in an effort to solve these issues themselves. Since these are grateful, effective programmers, they decide to give back to the community at large, submitting a pull request (or similar); should the matriarchs and patriarchs of the microcosm around the open source project agree with the solution presented, it becomes law, folded into the rest of the software, ready to be distributed to its users lest they face the same issue.

Sublime & GitHub


My Sublime Text User settings are now on GitHub. View the README for further instruction.


Why Sublime? Because it makes my day (which is spent predominantly reading and editing code) so much easier. Why store my personal settings on GitHub? Much better question:

Getting Started with ZeroMQ

A surprisingly frequent topic of discussion with me is ZeroMQ, especially regarding how to get started using ZeroMQ. Along with that usually comes some desire for starting into distributed systems architecture, programming, or the like.

I cannot recommend The Guide enough. It's well-written, topical, and (most importantly) enjoyable.

"Welcome to Jekyll!"

UPDATE: I'm not longer using Jekyll, but static site generation remains my jam.

Why thank you, Jekyll. I certainly feel welcome.

After using both Wordpress and home-rolled solutions, I've decided to switch to Jekyll, a "blog-aware" static site generator. With Nodepaper, I decided to move away from a db-based CMS to one based on flat Markdown files. I agree with the makers of Jekyll that it's backward, and I, too, have lost a lot of content from bad hosts.

So it's on to Jekyll and Github Pages, and I'm enjoying the process so far. The idea that a new theme or theme inspiration is just a fork away is exciting. That a correction or comment can be made by Issue (or even a Pull Request) seems ideal and forward-thinking.

Jekyll is not for everyone; it's for makers.

Field notes

  • Jekyll could use a jekyll add command (or similar) to start a new blog post. Not that it's hard to run subl `date "+%Y-%m-%d"`, but I prefer not to make choices (like what key to press) when the answers are obvious (See: game design). I'll update if I can learn enough Ruby to submit a pull request.
  • jekyll serve --watch doesn't provide a lot of information about formatting errors, which is ironic as it's intended to be used during development. While you don't want a big, fat stack trace every time you save if you save as often as I do, it is inconvenient (if minorly so) to have to restart the server to get the stack traces you do want.
  • Maruku is the default Markdown processor. I'm not a Ruby programmer, but I understand RDiscount to be better. It should probably be the default, as it produces far better output based on the kind of Markdown I write.

The Pebble & I

My phone and I have had a touch-and-go relationship ever since we met. I hated when it would interrupt my life, so I would leave it on my desk or otherwise out of sight; I'm away from my desk enough that those trying to reach me had difficulty doing so, and I would hate that, too. There seemed to be no middle ground:

  • If the phone is ringing, it needs to be loud to be consistently heard, making it innevitably interrupting.
  • If the phone is on silent, I'll never hear it, making me unacceptably unreachable.
  • If the phone is on vibrate and in my pocket, it's close, but unreliable. But maybe that's something.

Enter Pebble

The Pebble is a smartwatch that connects to my Galaxy Nexus via Bluetooth, and my phone can send it notifications and receive basic input for everything from Phone and Messaging to Spotify and Calendar. I'd found my middle ground.

How I make the most of it

To really capitalize on this, my phone is set to Silent permanently, and I configured the Pebble to receive all available notification types. Aside from the occasional loss of connection1:

  1. Notifications are extremely reliable. I know people can reach me.
  2. I never have to check my phone. See #1.
  3. If I can hear the notification sound, it's not my phone. (For instance, when I'm at home I know it's for my wife, not me. With three Nexus devices, that got confusing.) See #2.
  4. The vibrate is subtle enough that most people don't seem to notice or care. A quick glance to my watch and I can tell if it's urgent.

1 I guarantee this will improve. Pebble isn't even done shipping pre-orders, and the only bug in the connection has to do with the Android client app not tearing down the Bluetooth connection completely when it loses it. It's a really quick fix - just twiddle the Bluetooth on your phone Off-On, and the connection will be reestablished immediately. The process should take 5 seconds tops on a 4.x Android phone, as the Bluetooth settings are available via the shortcut in the Notification Tray.