Written by Bryan Powell. For updates, subscribe to the feed, join the newsletter, or follow me on Twitter.

Heading West

This is my last full week in Huntsville. On July 7, my family and I begin a year-long experiment in the great Pacific Northwest. If you know us well, this news will hardly come as a surprise.

Prior to having our two girls, Amanda and I spent several weeks in Seattle to see if we might like to live there one day. That was more than four years ago. We decided against moving at the time. Looking back, the timing wasn't quite right.

Back in May I booked a last-minute flight to Seattle. We had found a few rental houses and I went to take a closer look. I landed around 8pm and made the 45 minute drive down to Olympia to stay with friends (they were traveling Europe at the time but insisted that I stay at their home).

The next morning, loaded up with coffee and danish from a neighborhood coffee shop, I drove 150 miles north through Seattle to a small city about 30 miles from Canada.

Welcome to Bellingham.

Four years prior, Amanda and I rented a car and set off driving the same route. I don't remember exactly why we decided to do this, but I do remember wanting to get out of the city for a bit.

It was well after dark when we stopped the car to fill up with gas. We breathed the fresh air and remarked on how pretty the area must be during the day. This is the same place I found myself in just a few weeks ago, this time looking to relocate.

Bellingham, Washington Sunset

Bellingham came up a few months ago when researching various areas of the maritime Pacific Northwest. We love Seattle, but things like traffic, cost of living, and distance from nature made us lose interest. The suburbs were ruled out (because suburbs) so we looked out a little further.

For many reasons, Bellingham quickly made it to the top of our list. And on the morning of my 29th birthday, we signed a lease on a house located in a great little neighborhood on the edge of town. Looking back, it's kind of funny how things work out.

I could go on for days about all the factors playing into this decision. Instead, I'll focus on explaining things at a high level. If you want more detail, let's chat over coffee :-)

Personally, we're looking for a fresh perspective. Amanda and I both grew up in Huntsville. The longest we've ever been away are the few weeks we spent in Seattle. Huntsville has its perks, but we've longed to live in a place that's completely different from the one we grew up in. We don't know a single person where we're moving, and that's incredibly exciting.

From the business side, my role at Metabahn won't be changing even a little bit. Instead, I'll be joining our growing ranks of remote employees. The office in Huntsville will continue to exist and we have plans to expand our presence here. We value the relationships we've built and we plan to be just as involved as ever.

While it's true that we aren't moving because of my job, it just so happens that our personal goals align perfectly with the goals of the business. We'll see how things go.

The best way I know to describe this move is that it's an experiment. We don't really know what living in a new city will lead us to. But we couldn't be more excited to find out.

Pakyow Fundamentals 001: Build an App in 9 LOC

For some time now I've wanted to write about the fundamental concepts behind Pakyow. This is the first of a dozen or so posts covering many of the details and considerations that have made their way into the framework's design.

I also recorded a screencast where I ramble through roughly the same content. It's available on the Pakyow YouTube Channel and is a nice supplement for this post.

Here it is, the simplest app you can build in Pakyow:

require 'pakyow-core'

Pakyow::App.define do
  routes do
    default do
      send 'hello'

1 library, 3 dependencies, 9 total lines of code.

And yes, you can tweet it.

Save to a file (e.g. app.rb) and run it:

ruby app.rb

See Installation for details on getting your environment setup.

The app server should start up at localhost:3000. This app is nothing complex — it simply accepts a request at the default / path and returns hello in the response body.

$ curl http://localhost:3000/

Despite its simplicity, there are many things we can learn from this example.

Single Responsibility Libraries

You'll notice that we require pakyow-core rather than pakyow. This is because we only want a portion of the functionality that Pakyow provides. Pakyow consists of 8 different libraries, or gems, each introducing a separate concern.

The primary pakyow gem requires all 8 of the gems. Since we know that this app will only deal with routing, we choose the pakyow-core gem. The core Pakyow gem handles defining the app, routing requests to it, and sending responses.

Single responsibility gems let us start small and only include features in our app when we need them. This keeps apps as lightweight as possible while scaling to meet the requirements of more complex apps (more on this in future posts).

Apps That Grow With You

After requiring core, we define our app.

Pakyow::App.define do

Pakyow is designed to allow every part of the app code to be specified right in the define block. Here we can not only define our routes, but configuration, middleware, and more advanced features like mutators.

While this is an easy place to start, it does start to break down as an app grows larger. Pakyow offers ways to break things out as needed.

Pakyow often provides multiple ways to accomplish the same task. You choose between them based on your needs. For a simple app like this, specifying the routes elsewhere creates more friction than just doing it inline. When the app grows, it's easy to refactor these routes into their own files.

This design decision provides a clear starting point while providing ways to organize code in a larger codebase. You can take it as far as you need to.

Routing Requests

Now that we've defined an app, let's take a closer look at our routes.

default do
  send 'hello'

In Pakyow, a route is responsible for routing a request to a bit of logic. Here we see a single route, called default. This route will match a request to GET /, or the default path.

Pakyow couples the definition of the route with the work to be performed when the route is matched. You see this pattern in other frameworks, like Sinatra. We chose this approach to keep routing concerns in one place.

Consider if we had written the route like this:

default :SomeController, :some_action

SomeController#some_action would look like this:

class SomeController
  def some_action
    send 'hello'

The call to send is a routing concern. Putting it in the controller (away from routing) requires us to keep two bits of information in mind to understand the entire request / response flow. This is bad.

A pattern I like to use when building Pakyow apps is for routes to contain only routing logic and delegate other concerns. Here's an example:

default do
  send SomeService.hello_or_goodbye

Assume that the method on our service object makes some decision about whether it should say "hello" or "goodbye" and returns the appropriate message. We can look at this route and understand everything that happens from request all the way to response. All routing concerns are right in front of us.

Sending Data

Our default route simply sends back hello in the response. This is done through Pakyow's send helper, which accepts a String or IO object (e.g. a File). It sets the content headers and body of the response, then immediately halts execution and returns the response.

Send is one of a handful of helper methods that provide us with tools for dealing with different routing concerns. We'll look at other helpers in the future including error handlers, redirects, and rerouting.

Choosing an App Server

When your app server started up, it probably booted Webrick. This is the default server in Ruby and is part of the standard library. If Pakyow can't find another app server in its environment, it falls back to Webrick.

You can use a different app server by requiring it:

require 'pakyow-core'
require 'puma'


Now the app will boot with Puma instead of Webrick.

Pakyow tries to make sane decisions when things are unspecified, but gives you the power to easily influence or change those decisions. This further reduces friction by letting you deal with things when you want to deal with them, rather than requiring many decisions upfront.

Start with conventions, allow configuration in the future.


We'll build on this 9 line app in the next post and discuss configuration, helpers, and middleware. Thanks for reading!

Pakyow v0.11

Pakyow v0.11 was pushed to RubyGems yesterday. This release introduced some new features like Resources and Binding Parts. It also improves the developer experience by removing the libxml dependency (which can be a pain to install) and adding Dotenv for config management.

v1.0 is the next planned major release. We're setup well to push for 1.0 with a ton of work having focused on improving the framework internals.

You can read the full release announcement on the blog. I also screencasted a walkthrough of some of the new features.

I also want to try something new and include a selfie for every release, wherever I happen to be when I publish the announcement post. Pakyow is a project I plan to keep working on for a long time, so it'll be fun to see how things change. This one was taken at Metabahn HQ:

v0.11 Selfie


Pakyow, Portable View Transformations, and the Distributed Web

I've been doing quite a lot of thinking about IPFS and how Pakyow might fit into the world of distributed web apps. Examples that I've seen lately are built as client-side JavaScript apps, with the underlying source distributed among peers with something like IPFS.

This is interesting, but it requires you to 1) write your app in client-side JavaScript and 2) distribute the source code of your app. Neither of these are necessarily deal-breakers, but I don't like the idea of being forced to do this just to build a distributed web app.

Since Pakyow is a server-side framework implemented in Ruby, how does it fit into this? Eh, I still don't know. But, thinking about it has led me to some interesting realizations. Such as the fact that Pakyow divorces business logic from the rendering of a user-interface.

This separation means that we can render state changes without knowing about the underlying decisions that led to the state change. When the state of a Pakyow app changes, it creates a set of declarative view transformations that can be serialized and passed around.

Given an interpreter and the underlying view template, the transformations can be performed anywhere. Rendering is made completely portable. We could also, in theory, replay the entire state of a UI from beginning to end without having access to the state or the original business logic that created the transformations.

I find this quite profound.

What can we do with this? Well, portable rendering allows views that exist on the client-side to auto-update and reflect new state, without moving any code or state to the client. This concept is at the core of pakyow-ui and ring.js. Might it also have implications for the distributed web?

I considered ending this post with a discussion about embedding the historical state of a Pakyow app in a blockchain, but I honestly don't know enough to sound intelligent about it. Instead, go read Tony Arcieri's post on the dangers of a blockchain monoculture.

Interaction is an Enhancement

Aaron Gustafson for A List Apart:

In February 2011, shortly after Gawker Media launched a unified redesign of its various properties (Lifehacker, Gizmodo, Jezebel, etc.), users visiting those sites were greeted by a blank stare. Not a single one displayed any content. What happened? JavaScript happened. Or, more accurately, JavaScript didn't happen.

He goes on to explain why, in the web, content should always comes first with interaction as a layer on top. It's interesting that this still has to be pointed out, as this was commonly accepted just a few years ago. As browsers continue to improve, developers talk less about progressive enhancement. But as Aaron points out, browser support isn't the primary issue here.

Reading this article reminds me of a talk I gave last year at All Things Open, where I made the case that we're building at least two kinds of things for the web:

  1. Content-Focused: New York Times
  2. Interaction-Focused: Slack

Each of these warrants a different approach. To readers of the New York Times, content is the priority and nothing should stand between them and their content. What about Slack? Content isn't the priority to those users. Slack is a tool for collaboration, not content delivery. Supporting progressive enhancement feels like overkill.

Going further, why do tools like React and Ember even try to support server-side rendering? At best it's an afterthought that's proven to be brittle. It seems these frameworks are building in backwards-compatibility in an attempt to become the "one tool to rule them all".

Consider this — when a user prioritizes content over interaction, using a client-side JavaScript framework that prioritizes interaction might be a poor choice.

Of Patterns and Power: Web Standards Then & Now

Separating structure from style and behavior was the web standards movement's prime revelation, and each generation of web designers discovers it anew. This separation is what makes our content as backward-compatible as it is forward-compatible (or "future-friendly," if you prefer). It’s the key to re-use. The key to accessibility. The key to the new kinds of CMS systems we're just beginning to dream up. It's what makes our content as accessible to an ancient device as it will be to an unimagined future one.

Zeldman nailed it in this recent piece. The style / behavior separation he's preached his entire career drove my decision to separate structure / logic in Pakyow. Markup, even in a templating system, should be expressed in terms of content. Semantics are just as important during development as they are in production.

Web standards is more relevant than ever.

Hiring in Silicon Valley

Zack Holman on how startups interview candidates:

There's such a wild gulf between what gets asked in interviews and what gets done in the gig's daily grind that it's a wonder how startups make it out of the initial incubation phase in the first place.

Just another reason not to do technical interviews.

F*ck Your 90 Day Exercise Window is also well worth a read.

Is it just me or is there a trend emerging?

Pakyow Intros

We added a new category on the Pakyow Forums for the purpose of introducing yourself to the community. Jump over and tell us a few things about yourself. Intros aside, we've had several good discussions happening lately.

The Self-Destruction of Walled Gardens

We talk a lot these days about the open web and rant about how platforms such as Medium are working against it. To some extent this is all true — the rise of platforms has certainly made the web feel more closed than it did 10 years ago.

However, avoiding these platforms is not the answer.

To most consumers, there’s a real advantage in using a platform like Medium instead of figuring out how to build their own solution. And from their point of view, there's little risk. John O'Nolan talks about this in his recent post:

Mainstream, casual consumers will always be attracted to what is easiest, pretty and cost-efficient. And there is nothing wrong with that.

Sure, you can make predictions and point out how you don’t control your content and Medium can put advertising on it at any time. But until they actually do anything like that, predictions are just hearsay. Nothing has happened yet to break user trust. So why immediately default to distrust?

Closed networks like Medium are prevalent for casual bloggers because open alternatives suck for this use-case. If you just want to write something that looks good and can easily be shared with no professional agenda, you shouldn't have to go through the hassle of deploying an application and an entire server.

I agree with this — particularly the last bit. The fact is Medium has enabled more people to contribute to the web. Platforms solve a real problem. Consumers should use them. But for the sake of the open web, platforms like Medium have a responsibility to become open.

Here's what an open platform looks like:

  • Makes it easy for users to leave with their content
  • Provides tools to make that content accessible again

If someone leaves a platform and can't immediately host a navigable version of their content elsewhere, it's not an open platform. I can think of exactly two reasons a platform wouldn't want to become open:

  1. Technical challenges make it hard
  2. Being open is perceived as being bad for business

The first reason is more of an excuse, really. It's easier than ever to create open platforms and give someone the power to easily host their own content. If being open was a priority, the Medium team could make it happen.

If the first reason is an excuse, the second is complete nonsense. In fact, with a long-term view, being a closed platform is in fact bad for business. Dave Winer makes a compelling case for this in his recent post:

Tech is cyclic. First there was an open platform, then silo-makers were able to build something higher level by foreclosing on the openness. Then they stagnate because big companies get stuck in the Way Things Always Have Been, and the users get skilled, a new generation comes along and they see how to make progress outside the silo and enough people use the new open system so it gains traction. It’s always more exciting than the stale corporate silos, so for a while they blossom, until the cycle repeats.

Closed platforms are doomed to the same fate. Being closed is great at first; it gives a platform ultimate control. But the beautiful walled garden soon becomes an echo chamber, masking the platform's increasing irrelevance until it's too late.

I firmly believe that giving users an easy exit strategy is a great catalyst for long-term success. If 10% of a platform's user-base leaves after launching a controversial feature, that's immediate feedback. Whereas Medium would have slightly fewer articles written or more complaining than usual, an open platform would feel the pain and could adapt. Walled gardens make it too easy to ignore user feedback because there's less pain.


Dave Winer recently tweeted that instead of posting to Medium we should post to Tumblr or WordPress.com. I fail to see how those two are more open, but yes let's talk about WordPress.

I have quite a lot of respect for Matt and what the WordPress community has created. It's empowered more contribution and created a more democratic web in the process. Great.

But unlike its open-source counterpart, WordPress.com is not open. As far as I know, there's no easy way to move a blog from WordPress.com onto a standalone server. The best free option they provide is a content export feature, but you're on your own to setup WordPress.

The WordPress platform does offer a "Guided Transfer" service in exchange for a $129 fee. Why can't they automate this process and then make it free? I imagine it's one of the two reasons we discussed earlier, though I'd love to be wrong.

Platforms like Medium and WordPress.com have empowered millions to contribute to the web, but they've dropped the ball on ensuring that these contributions exist well into the future.

This is a missed opportunity.

My team and I are working on an open platform built around our open-source web framework. When someone creates a website on our platform we'll let them export not only their data, but a bootable version of it. Eventually, this feature will also provision a server on a VPS provider (such as DigitalOcean) and move their code to it.

As a community we've spent years fighting vendor lock-in with open-source software. And by now open-source is nearly standard practice. It's about time we fight for open platforms.

Rubocop as a Teaching Tool

Last year I jumped into a project that had started about 9 months earlier. The team had already defined best-practice patterns and decided on preferred syntax. It was also a Node.js project, something I was less familiar with at the time.

Fortunately JSLint was being used as part of the CI build. While frustrating at the beginning, it quickly taught me how the team preferred to write their code. Nobody handed me a style guide. I could write code, run the build, and get immediate feedback.

In about a week I was catching (most) syntax issues without even having to run the build. JSLint effectively taught me the style guide to follow.

When the next Ruby project started, I went looking for a similar tool and found Rubocop. I added it as a build step, just to see the impact it might have. Here are the results:

Rubocop Graph

Each bar represents how many commits out of 10 caused a Rubocop failure.

At first it failed all the time. You can start to see a pretty immediate drop about half way in. This is when we finally fixed the offenses that had already been introduced into the project. There were a lot of these because Rubocop was added after about 2 weeks of development had passed. From that point to present day, there's been a continuous downward trend in the number of offenses per commit.

This points to something interesting. As time has passed, there are fewer offenses introduced into the project that violate the style guide. For myself and the team that I work on, Rubocop has proven to be a pretty good teacher.

Setting Up Rubocop

Installing Rubocop in a Ruby project is easy. Add rubocop to your Gemfile, bundle install and you're ready to roll. If your project has been around for awhile, be prepared for that first run depression to set in. It happens.

To use Rubocop to enforce a style guide, I find it helpful to disable most of the metric cops. Sure, perceived complexity, method length, etc can be important. But in my opinion those are things best dealt with in code reviews rather than being enforced by almighty Rubocop.

In case it's helpful, the full .rubocop.yml from my recent project can be found here.

Lessons Learned

Introducing Rubocop into this project was a positive experience overall. The resulting codebase is both consistent and readable. A word of warning though: get buy-in from the team before you try this. Having a tool pointing things out in your code is annoying. Explain the purpose and ask for feedback.

It worked for us, give it a shot and let me know how it works out!

Replacing Technical Interviews with an Audition

Years ago I asked a candidate for a developer position to solve a variation of the Fizz Buzz problem during an interview. He failed and I moved on, swearing never to do another technical interview again.

I hated the fact that he failed to solve the problem told me nothing about why he failed to solve it. It just made him feel bad without reason, and that made me feel bad too. When the entire point of the technical interview is to better understand the technical abilities of a candidate, this seems like a pretty poor state to leave things in.

Unless your company is named Trivial Programming Puzzle Solver Inc, you won't determine a candidate's abilities during a technical interview (and it doesn't matter if the interview takes place over 30 minutes or over an entire day). As developers, our day-to-day jobs are nothing like a technical interview. The time that we spend working involves a different kind of pressure solving a very different kind of problem. And at good companies, we perform our work without someone else breathing down our necks evaluating our performance.

At Metabahn, we've made the last few hiring decision without performing a single technical interview. And every person hired has worked out well and made big contributions to the company. Here's how we did it.

1. Tell us something interesting

Before we ever talk to a candidate, we ask that they tell us a written story. This is often described as a request in the job posting itself. It doesn't have to be long and it's best if it's non-technical. We want to see what they communicate as well as how good they can do it.

Many candidates are thrown out after this step. We look for things like honesty, personality, and openness -- not a marketing pitch. The fact is, as a developer at Metabahn, you'll spend more time communicating than writing code. As a team, we always err on the side of overcommunicating everything. If you can't communicate, you won't be an effective part of our team.

2. Let's have a real conversation

We actually do perform one or more interviews, they just aren't technical. We'll never ask for a candidate to write some code or solve a problem in front of us. Our interviews tend to be relaxed and enjoyable, because they're just a friendly conversation. We have two main goals with this step:

  1. Make sure our goals as a company are in line with the candidate's personal goals. We want people who work for Metabahn to understand and agree with the vision for the company, while at the same time helping them flourish.

  2. Discover the candidate's specializations, focus, background, and interests. If you've been building embedded systems more than you have websites or web apps, we probably aren't the right company for you.

This interview is just as important for the candidate to learn about us as it is for us to learn about the candidate. If we decide to work together, we're both making huge committments. It has to be a mutual fit.

Need a bigger salary than we can offer? We'll know after this conversation. Have the right background and are interested in building the kinds of websites and apps we build? We'll know that too. Interested in actively impacting the vision and goals of Metabahn? GREAT.

Once we're to this step things are serious. We've narrowed down to one or two candidates for each position and are almost ready to make a decision. How do we pick between them, especially without a technical interview?

3. The technical audition

We take the approach that other companies (such as Automattic) have taken. That is we pay candidates to do real work for us for a small period of time; essentially a technical audition. This gives us real-world metrics to make a decision with. Making the technical audition part of our hiring process is the best decision we've ever made.

To be honest, we stumbled into this approach by accident. It just so happened that early Metabahn employees were contractors first. I was comfortable making a bigger committment to them because I knew the work they could deliver.

So now, we extend an audition to our top candidates. Auditions are a minimum of 10 hours per week for 2 weeks. This is all paid, of course. Candidates don't have to quit their job to audition; nights and weekends are fine.

This gives us a realistic picture of what to expect, perhaps more than other companies because nearly all of our processes are asyncronous. Nearly all team communication happens on Slack and we have one all-hands meeting that takes place on Monday morning (that you don't have to be in person for). Folks are free to work from anywhere whenever they choose. Performance is measured with results, not time spent online or at the office.


This has worked well for us, but it's important to understand this in context of how Metabahn operates as a whole. I fully encourage you to try replacing technical interviews with auditions, but realistically your mileage may vary.

How does your company operate? I'd love to hear from you.

Set Your Agenda

I recently disappeared into the mountains with my family for some long overdue rest. Computers were left at home and devices largely remained off. I didn't check my email for over a week and had my work calls held.

Nothing bad happened. The Metabahn team handled things perfectly. Clients remained happy, important work got done, and I came back to several promising new leads. It's nice to not be a required component all the time.

Stepping away for a few days led to the realization that few things in any given week can be classified as an emergency. Maybe this sounds obvious, but in context of the burnout I felt prior to getting away, it was profound.

The weeks before I left were filled with one emergency after another. I jumped around from task to task, accomplishing little overall, but happy to be averting disaster after disaster. Fortunately these emergencies and so-called disasters were merely exaggerations of reality.

Taking a step back, what is an emergency? The way I defined it, an emergency is a situation that is in contradiction with one's overall goals and vision.

Here's a summary of my goals:

  1. Maintaining my personal health and well-being (physical and mental).
  2. Nurturing healthy relationships with family and friends.
  3. Keeping the company operating smoothly to benefit our clients and ourselves.
  4. Improving our open-source work to empower anyone wanting to build for the web.

Having this list brings a lot of clarity to otherwise difficult situations. For example, if something in the company isn't running smoothly but the first two goals aren't being met, my best option is to focus on the first two goals and delegate the third. That's exactly why I stepped away in the middle of things. And the entire company is better for it.

Set your agenda and stick to it.

The flat company myth.


I've been wanting to write about my experience starting and running Metabahn for some time now. Unfortunately, running a software company is very much at odds with absolutely everything else I could do with my time. So, let me catch you up.


September of 2007 was a busy month. I left the startup I was working at, started Metabahn, and got engaged; in that order. At this point the company was more a cover for my own consulting work; I wasn't all that interested in growing it.

In March of 2008 I found a project to build a web-based tool that would be resold to major financial institutions. I put a lot of work into landing the project, as I knew it would pay the bills for the next few months and give me at least the illusion of stability. When it came through I knew it was too big to do by myself.

I hired my first contractor and we delivered the project on time. This happened to be the first of many sizable projects that dwarfed the amount of effort I could expend. So I kept hiring contractors to help. Overall I have positive memories of this time. It was the single biggest learning experience I've ever had, filled with success and failure alike.

Version 2.0

2012 rolled around and I was beginning to sense change in the air. If you know me reasonably well you know I don't like to stagnate. The company as it was just didn't seem to be challenging enough. Couple that with the momentum we had built and it felt like the right time to try and build a real company, with real employees.


I reached out to a long-time friend about joining as the first employee. He had contracted with us a couple years prior, and I knew he'd be a good fit for the direction I wanted to take the company. We'd talked about working together again, and it seemed like the right time.

Metabahn 2.0 started in May of 2012 when I made the first hire. Today we're at 2.3 with six employees and roughly the same number of contractors who help us out on a consistent basis. We've been bootstrapped from day one and have taken no outside money. 100% of the company is owned either by myself or other employees.


As we hired more folks, I did a lot of thinking about process. My view is if you can't define the problem to solve with a process, don't implement the process. Conversely, if the problem goes away, throw away the process that was being used to solve it. Without these rules you risk becoming bloated, even at a small size.

This led to a really flexible work environment, including flexible hours and unlimited vacation time. To this day, we really only have a single rule:

Don't make decisions that have a negative impact on the team.

Along with this flexibility came the lack of formal organizational structure. It is a fad in the tech industry to have a so-called "flat" company. However, all companies have an implied hierarchy. This is evident when there's a decision to be made.

Let's say some member of the team makes a product decision that causes a negative experience for a large percentage of customers. Someone has to deal with the problem, right? As it turns out, someone always does deal with it.

The biggest problem with flat companies is that when structure is left undefined, a structure will still form, but it won't be the structure you want. Folks will elect themselves to particular positions and start making decisions on behalf of others. So, you still don't avoid the hierarchy and you've also created an unhealthy organization.

When we started growing, I decided to implement structure amounting to a flat hierarchy.


Here's how it works. Write down all the roles that exist in your company. Assign each role to a member of the company and inform them of their responsibility. Then tell them not to play that role unless they need to.

This levels the playing field for day to day operations, effectively creating a flat company. But when a situation arises and a decision needs to be made, it's clear who decision maker is. Just like process, the structure isn't used unless there's a defined problem to solve.

I tend to think of it a bit like sudo in a Unix system.

You can find this pattern in everything we do as a company. Typical project teams consist of three developers; one is chosen to play the role of project owner. Our teams don't require full-time management, so the owner is a developer 80% of the time. When the client calls about a problem, the owner deals with it rather than letting it impact the entire team.

I even think of my job as Sudo CEO. By default, I consider myself to be a developer. I just also have the power to make higher-level decisions when necessary. At our size this works really well. I hope it scales.

Pakyow Platform

A few days ago the Metabahn team rolled out a teaser page for Pakyow Platform, a new project we've been hard at work on the last few months. I couldn't be happier with my team's work on this project and we can't wait to introduce you to it in the near future!

We'll be putting more details on the site over the next few weeks as we get closer to a public rollout. In the meantime, you should join the launch list →

Your template language is killing the web.

I published an article about template languages and how they effect the modern web:

It used to be simple to build things for the web. In some ways this is still the case, but modern realtime apps are driving the complexity factor to new and uncomfortable heights.

You need knowledge of more tools and technologies than ever to build a web app that feels modern. In contemplating this shift, much of the added complexity stems from how we handle the part of the application a user interacts with — the view layer.

This is likely the start of many such articles in which I try to explain some of the more nuanced thinking behind what we're doing with Pakyow and the impending realtime UI libraries.

Read it →