Trevor O2018-02-15T01:17:53+00:00http://trevoro.net/Trevor Otrevoro@gmail.comService Bubbles2016-04-05T00:00:00+00:00http://trevoro.net/2016/service-bubbles<p>Lots of the discussion surrounding conversational interfaces is centered on text
and the kinds of interactions that medium will enable. The idea is by starting
with a system that enables organic behaviour, you allow your service to address
generic needs and requirements. The behaviour that people exhibit in your UI
allow you to learn, and that learning leads to augmentation. With text, that
interaction is augmented by layering in some kind of domain specific language or
if you’re lucky a system that understands natural language.</p>
<p>Today, those languages and commands are being interpreted using chat bots.
Having a bot that can respond to certain types of commands or intercept words
and trigger an action are becoming commonplace on platforms like Slack, but have
existed for a really long time on IRC channels.</p>
<p>Underlying all of this is the need and desire to achieve some kind of outcome.
Conversational interfaces provide a generalized way to achieve a goal. In this
world, the UI allows you to accomplish something, but can also represent the
outcome itself.</p>
<p><img src="/img/magic.jpg" alt="" /></p>
<p>While text is an incredibly powerful tool for asking for information, it’s a
very limiting tool for conveying results. In many of these instances we want to
return images. But images are also limiting in their own way. While they can
describe data that is very dense, they’re also fixed and non-interactive; it’s
impossible to transform or interact with an image in the same way that even a
rudimentary weather app would provide.</p>
<p>Instead of popping out to email to get your ticket, we want to bring the data
forward. What we should be able to achieve is an element you can interact with,
delivered in-line, as a response to our question, or a prompt to our user.</p>
<h3 id="a-new-chat-primitive">A new chat primitive</h3>
<p>The solution to this problem is a new primitive for chat we call service
bubbles. A service bubble is an interactive widget that appears in-line with
traditional text, images, and video. By adding this 4th mode of interaction, we
give conversational interfaces the flexibility of text and the density of
images, all in a tidy package.</p>
<p>If we apply this to our earlier example, your flight details can be delivered as
a ticket bubble in line, which you can scrub through for flight details and
present to the airline.</p>
<p>At Bench our customers routinely connect businesses financial accounts. Adding a
new account through a conversational interface using text would expose sensitive
information. But with a service bubble we’re able to capture and keep this
interaction self-contained to the widget, and then have that bubble represent
the state of the connection after we’re done. In this way, our UI not only
represents the tool designed to achieve an outcome, but it represents the
outcome as well.</p>
<iframe src="/chat-demo.html" style="border: 0 none; width: 100%; height: 600px;"></iframe>
<p>Today some modes of this exist, but they require you to leave the chat
interface. You can send links to forms or directly into some state of an
application where you can take these actions, but this type of behaviour limits
the user experience. Another massive loss is the separation of history, by
breaking up what you did into separate tools, when you really want the history
of your chat to update in response to state.</p>
<p>The major benefit of chat is having a free flowing conversation which allow
people and machines to respond where appropriate. By implementing the service
bubble concept, we can provide users with the powerful organic behaviour that
text provides, with rich interactions of specialized applications.</p>
SSH Authentication with Github Teams2015-04-03T00:00:00+00:00http://trevoro.net/2015/ssh-authentication-with-github<p><strong>tl;dr</strong>: You can authenicate SSH access using Github Teams.
<a href="http://github.com/trevoro/sshauth">Here’s the project on Github</a>.</p>
<p>OpenSSH version 6.6 introduced this nifty config option that makes it possible
to run a command that will produce a users <code>authorized_keys</code> file. This
means that instead of manually managing your <code>authorized_keys</code> file on a
server you could just write a command that does it for you. You could collapse
a directory layout so that keys are kept per file, hit a remote endpoint or API,
or something else creative.</p>
<p>For a simple experiement I thought it would be neat to use the Github Teams API
in order to create “groups” that are allowed to SSH into boxes.</p>
<p>The idea is simple enough: Create a team in your Github Organization called
“ssh” or something, and then get all the SSH keys for the users in that team.
This way, when you need to revoke access to a machine you can just remove
someone from the “ssh” group and you’re done.</p>
<p>The <code>AuthorizedKeysCommand</code> option in SSH is just a first pass. If the keys it
returns are not present for a user, it will continue to use the default
<code>authorized_keys</code> file. That means you could have a backup or master key on all
the servers, but individual user keys could still be fetched from Github.</p>
<p>This has a few problems obviously. Github only allows 5000 requests / hour which
means if someone is trying to brute-force your server and you don’t have
something like <a href="http://denyhosts.sourceforge.net/ssh_config.html">denyhosts</a>
installed then you’ll burn through your request limit. It also essentially gives
people at Github access to all your servers, so it’s not for the paranoid.</p>
<p>All the code is at <a href="http://github.com/trevoro/sshauth">github.com/trevoro/sshauth</a></p>
Simple Event Tracking with Google Analytics2013-11-18T00:00:00+00:00http://trevoro.net/2013/data-attributes-for-google-analytics<p>We use Google Analytics to do some event tracking. Specifically, we’re using the
new analytics.js library which is in private beta. It’s pretty clean and the API
for it is really nice.</p>
<p>Custom event tracking in Analytics.js involves tracking 3 mandatory and two
optional values attached to some element. Mostly for this exercise I wanted to
do click tracking of some navigational elements.</p>
<p>A custom event sent to GA involves a simple call</p>
<pre><code>ga('send', 'event', 'category', action', 'label', 'value');
</code></pre>
<p>It also accepts an object as the second argument.</p>
<pre><code>ga('send', {
'hitType': 'event', // required
'eventCategory': 'button', // required
'eventAction': 'click', // required
'eventLabel':'label',
'eventValue: 'value'
};
</code></pre>
<p>It would be nice to attach some custom information to each one of these
navigation clicks. That means we either need to tag all these elements with IDs
then write some custom functions each, or a function generator. Or we can use
the HTML <code>data</code> attribute to create event tag information. Something along the
lines of this</p>
<pre><code>&lt;a data-label="navbar" data-value="signup" href="http://signup.example.com"&gt;signup&lt;/a&gt;
</code></pre>
<p>In fact, we can make all of the event data part of the element itself</p>
<pre><code>&lt;a data-category="button" data-action="click" data-label="navbar" data-value="signup"&gt;...&lt;/a&gt;
</code></pre>
<p>Then we can use some javascript to generate event handlers for these element
clicks.</p>
<pre><code>$('a[data-category]').each(function(idx, ele) {
var e, data;
e = $(ele);
data = e.data();
if (data.cateogry === 'button') {
e.on('click', clickTracker(data))
}
});
</code></pre>
<p>Now someone who knows HTML can go and start tracking events without having to
write much code</p>
Monitoring the Modern Web2013-09-17T00:00:00+00:00http://trevoro.net/2013/monitoring-the-modern-web<p>APM measures and analyzes performance and patterns at different layers. Whether
you’re using server APM to monitor the behavior of virtual or physical
infrastructure, or NPM to monitor your network transactions, the goal is
usually to identify how performance issues affect real users.</p>
<p>Instead of inferring user experience through server logs and database response
times, some offerings opt to monitor how applications behave from the client’s
perspective. This can be accomplished using servers that behave like real
users, or by monitoring the users themselves. Monitoring a real user is the
most accurate portrayal of application performance, and can provide a business
with real context about how application performance is affecting users.</p>
<p>Today, real-user monitoring simply involves measuring how long it took to load
a web page.</p>
<p>In this model, a server renders a webpage which is then sent over the internet
to a browser, which then renders the content. External assets like scripts,
styles, and images are loaded either from cache or from their respective
locations. You just measure how long that takes, and report it back to a
central location. There are two different ways to get those measurements: The
time it took to load the HTML and render it in a page with non-blocking assets,
or you can use the W3C NavTiming API.</p>
<p>The page load technique is quite simple. You use JavaScript to insert a
Date.now() at the top, then attach a callback for the “window.onload” event to
calculate the difference.</p>
<p>The W3C NavTiming technique is very similar, but it makes use of functionality
for reporting navigation timing built directly into the browser. The NavTiming
breakdown displays measurements on DNS lookups, TCP overhead, how long it took
to fetch the page, and how long before the load event fires. Without a doubt,
the NavTiming technique offers more granularity and a more accurate
representation of what the user would actually experience. NavTiming isn’t
widely supported yet, so you may not get a good sample size with this
technique.</p>
<p>Unfortunately, both techniques fall flat when it comes to monitoring other
critical elements like AJAX requests. That’s a pretty critical observation,
because it turns out AJAX is how we enable all the rich functionality that a
user expects, and how most applications have actually dealt with the problem of
slow page loads!</p>
<p>Enter the Web App</p>
<p>In a modern web appplication, you don’t browse from page-to-page. You load the
page once, and each click or keypress results in data being loaded from a
server and rendered locally. AJAX is everywhere, and is the key to enabling a
rich, “more native” experience. It can also be much faster than loading a new
page. This technique is extremely popular, so much so that several frameworks
have been written in order to make writing these applications faster and
easier. The list of companies deploying these “single-page apps” continues to
grow.</p>
<p>The real-user monitoring techniques used before are still useful, but only for
when you first load the application. If you only measure page load times, then
you end up with an incomplete view of what’s actually happening to your
end-users while they use your app. A good metaphor is “Looking under the lamp
post because that’s where the light is”.</p>
<p>What’s critical in the world of modern web applications, is to monitor ongoing
application usage. That means monitoring AJAX requests throughout the entire
users session. In order to make that actionable, you also need to monitor other
contextual information about where a user is in your application, what they’re
doing, what they did, and who they are.</p>
<p>Monitoring applications from the client also means that you can detect edge
cases that weren’t planned for during a synthetic benchmark run. Timing view
rendering and profiling real-world utilization can help identify performance
issues for your most active users.</p>
<p>Does a user have 1000x more data than your average?</p>
<p>How does that affect their performance?</p>
<p>How do long response times affect utilization?</p>
<p>Being able to measure and monitor every aspect of a client’s application is
critical. Those details power-up real-user monitoring in a way that lets you
pinpoint performance and issues, and really enhance the user experience.</p>
Git Shell Prompt2013-08-20T00:00:00+00:00http://trevoro.net/2013/git-branch-ps1<p><strong>Update</strong> A few people have asked me for a repo so I’ve created a <a href="https://github.com/trevoro/clean.sh">clean.sh
project</a> on Github.</p>
<p>If you’re a developer then the tools you use from day to day forms a good part
of your experience. Something I like to know quickly in a shell is whether or
not my PWD is in a git repo or not. I also find it useful to know if I’m in
master or a different branch.</p>
<p>That can be accomplished quickly by setting your PS1 to include a single
character that tells you whether or not you’re in a git repo. I use a <code>+</code> sign
to indicate that the current path is part of a git repo, and that its part of
the master branch. For other branches then I use the <code>*</code> token. I dont
necessarily care which branch it is. For that I still use <code>git branch</code>, but at
least I know I’m not on master.</p>
<pre><code>WHITE="\[\033[1;37m\]"
GREEN="\[\033[0;32m\]"
RESET="\[\033[00m\]"
BGRAY="\[\033[01;36m\]"
_git_branch() {
branch=$(git branch --no-color 2&gt; /dev/null | sed -e '/^[^*]/d')
if [ "${branch}" == "* master" ] ; then
echo "+"
elif [ "${branch}" ] ; then
echo "*"
else
echo " "
fi
}
PS1="${GREEN}\h${BGRAY}:\W${WHITE}\$(_git_branch)\$ ${RESET}"
</code></pre>
<p>Here’s what you’ll see if you’re on master</p>
<pre><code>tethys:caliper-app+$
</code></pre>
<p>And if you’re on a different branch…</p>
<pre><code>tethys:caliper-app*$
</code></pre>
<p>And if you’re not in a git repo</p>
<pre><code>tethys:~ $
</code></pre>
Retooling the Web2013-08-15T00:00:00+00:00http://trevoro.net/2013/retooling-the-web<p>Just a few years ago, anyone who wanted to get started with building apps needed
to at least work with Linux, database and web servers, and deployment tooling.
Cloud computing introduced some easy to use abstractions to these components in
the form of Infrastructure and Platforms as Services.</p>
<p>Time has pushed abstractions further up the stack, to a point where developers do
not need to know or care about implementation details of the OS, database, or
how the pages are served. Backend services like <a href="https://parse.io">Parse</a>,
<a href="https://firebase.com">Firebase</a>, and <a href="http://kinvey.com">Kinvey</a> are the latest
components in this trend.</p>
<p>So far the biggest driver behind these BaaS services has been native-mobile. But an <strong>API first
approach leads to clients everywhere</strong> - including desktop &amp; mobile web.</p>
<h3 id="enter-the-single-page-app">Enter the Single-page App</h3>
<p><a href="http://en.wikipedia.org/wiki/Single-page_application">Single-page apps</a> are an
awesome way to create a rich experience for your web site. You basically send
the entire ‘app’ to the client on page load, and then subsequent interactions or
changes in the application state occur locally in the browser. When changes need to be retrieved or stored
on a server, that state can be updated through using an API that either you own,
or that a BaaS provides.</p>
<p>Because of how they work, Single-page apps encourage &amp; enable you to think in clear
terms of ‘Storage’ and ‘Client’. Those developers won’t ever need to touch the
backend, or the API - just consume it.</p>
<h3 id="the-client-server-web">The Client Server Web</h3>
<p>As the distinction between Client and Server continues, we’ll end up with two sets of
specialized developers: Those focused on the backend, and those focused on the
client. A <strong>client focused</strong> web app developer probably won’t
need or recognize many of the existing tools and services. An <a href="http://yeoman.io/">entirely new set of
tools</a> have already been created focused <em>specifically on modern</em> web
apps.</p>
<p>We’re only at the beginning of a major shift in how we build the web.
More and more services are going to focus specifically on this new set of modern
web developers to help them build applications faster.</p>
Generating IDs in Unix2013-08-12T00:00:00+00:00http://trevoro.net/2013/generating-ids-in-unix<p>Sometimes I’ve found it handy to be able to generate unique IDs directly from
the command line. The easiest and most unique tool to use is <code>uuidgen</code>.
UUIDs are 122 bits in length; so colossal that the chances of a <a href="http://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates">collision are
incredibly low</a>.</p>
<p>The <code>uuidgen</code> tool generates version 4 UUIDs which is just a random sequence of
128 numbers and letters.</p>
<pre><code>$ uuidgen
6445B35A-BBD6-412C-B782-5B732DCF5919
</code></pre>
<p>UUIDs are probably what you want, but they’re really a PITA to read out to
someone, say over the phone. They’re also ugly to look at.</p>
<h3 id="generating-friendlier-ids">Generating Friendlier IDs</h3>
<p>For a recent project I was working on I wanted a smaller ID.
Luckily <code>openssl</code> can generate and hash random data which we can truncate with
<code>printf</code></p>
<pre><code>$ id=$(openssl rand 1000 | openssl sha1) &amp;&amp; printf "%s${id:0:8}\n"
7cb6c62b
</code></pre>
<p>That’s a bit nicer, but it definitely comes with tradeoffs. The tradeoff being
you have a higher chance of collisions. The range <code>[a-z0-9]</code> gives us 36 possibilties (base 36)
and 36<sup>8</sup> gives us 2.82 x 10<sup>12</sup> which <strong>looks</strong> like a lot but
you have to make sure it still fits your use case. IE, not instant messaging but
maybe for a build environment.</p>
What's your timezone?2013-08-06T00:00:00+00:00http://trevoro.net/2013/whats-your-timezone<p>Why do we care what timezone a user is in?</p>
<p>Well beause we have to show them dates that are relevant to them where they
live. Unfortunately you hit a weird scenario where someone is traveling and they
have to update their timezone settings, just because they decided to hop on a
plane that week. Fortunately operating systems on laptops and mobile devices all
adjust timezones automatically whenever they connect to the internet. So we have
the ability to stop asking people what timezone they’re in by relying on the
<strong>time on the device</strong>. Here’s a method that works well.</p>
<p>It turns out you can get around that problem pretty easily by <strong>always storing
your date data in GMT</strong>, and <strong>making all requests AJAX requests in GMT</strong>.</p>
<p>We then have some view rendering to take care of. Luckily,
the browser already knows what timezone the user is currently in, so we can make
use of the <code>getTimezoneOffset()</code> function to calculate the date to display
locally. We can also use either a <code>data-time</code> tag in an element with a class or
just use the new <code>&lt;time&gt;</code> tag.</p>
<p>Put something like this in your view.</p>
<pre><code>...
&lt;time datetime="2013-07-31T05:05Z"&gt;&lt;/time&gt;
...
</code></pre>
<p>Then ensure you have something to go through those elements and show the local
time. I’m using straight javascript here, but you could easily write a jQuery
plugin to do the same thing.</p>
<pre><code>var times = document.getElementsByTagName('time')
function prettyTime(dateString) {
if (!dateString)
return;
var d = new Date(dateString);
return d.toDateString();
}
for (var i = 0; i &lt; times.length; i++) {
var t, d;
t = times[i];
d = t.getAttribute('datetime')
t.innerHTML = prettyTime(d);
}
</code></pre>
<p>Now the GMT offset is always <strong>per device</strong> and not <strong>per account</strong>.</p>
<p><a href="http://jsfiddle.net/trevoro/T4wRq/">Check out the fiddle</a></p>
Tell Me I'm Pretty2013-08-01T00:00:00+00:00http://trevoro.net/2013/tell-me-im-pretty<p>One of the best parts about the scientific method is that negative results are
celebrated as much as positive ones. While a negative result is sometimes less
of a joyous occasion, having an answer is regarded as better than not
knowing at all. Being impartial and viewing results without prejudice is the
hallmark of a great researcher.</p>
<p>Unfortunately though, even great scientists are guilty of selectively
interpreting or ignoring unfavourable data. The same thing happens to anyone
with an idea they feel passionate about. This is due to <strong>confirmation bias</strong> - the
tendency for people to favor information that confirms their beliefs whether or not
the information is true.</p>
<h3 id="remove-emotion--ask-better-questions">Remove Emotion &amp; Ask Better Questions</h3>
<p>As entrepreneurs, this happens all too often. We search for information that
confirms our initial idea, rather than contradicts it. Some great entrepreneurs
understand this and search for a much wider variety of solutions to a problem.
It sometimes helps to envision opposing solutions to your idea, then figure out
what makes your solution or idea still work. This is why <strong>confirming your idea
properly</strong> with a good customer development strategy <strong>is so essential</strong>.</p>
<p>Here are a few things that might help you overcome confirmation bias</p>
<h4 id="understand-motivation">Understand Motivation</h4>
<p>When you’re consuming information or discussing an idea, think about who is
telling you something and why. You should be especially nervous if only one
realistic suggestion is given.</p>
<h4 id="remove-emotion">Remove Emotion</h4>
<p>Is someone totally in love with their idea? To be fair, passion sells product,
but love oversells and hate denounces. It’s important to understand the costs
and benefits of strategies and solutions before you go and implement them. Be
aware of the <a href="http://youarenotsosmart.com/2011/06/10/the-backfire-effect/">backfire
effect</a>.</p>
<h4 id="groupthink">Groupthink</h4>
<p>Does everyone in a group agree? You should <a href="http://www.psysr.org/about/pubs_resources/groupthink%20overview.htm">probably be
concerned</a>. Given a large
enough group of people, you’ll always have a dissenting voice. That voice should
be listened to, and their opinion should be taken seriously. You dont want a
group that’s too large (design by committee - hurray) but you should be able to
be challenged in your opinion and be able to defend your decision.</p>
<h4 id="hindsight-bias">Hindsight Bias</h4>
<p>Are you looking through a lens of your past decisions? Its important to
understand that <a href="http://en.wikipedia.org/wiki/Hindsight_bias">hindsight bias</a>
plays an important part in how we make decisions.</p>
<p>You have to prepare yourself for surprises. The good kind and the bad kind. I
consider preparing yourself for the worst and hoping for the best a “best
practice”. When you understand that a flop or a failure is a possibility, you can
plan around the situation a lot better than had you gone into something with blind
optimism.</p>
Getting Started With Manta2013-07-31T00:00:00+00:00http://trevoro.net/2013/getting-started-with-manta<p>Manta is a powerful new type of object store from the same folks that invented Node.js.
The cool part is that Manta <em>isnt just an object store</em> - it’s an <strong>object store with built-in compute</strong>.
That means that you can run code and other familiar commands against the objects directly on the server.
I’ll walk you through setting up Manta, and a simple example of where you could use the compute job functionality.
It’s assumed you have already setup a <a href="https://https://sso.joyentcloud.com/signup">Joyent account</a> and have <a href="http://nodejs.org">node.js</a> installed
on your machine.</p>
<h3 id="install-manta">1. Install Manta</h3>
<pre><code>$ npm install -g manta
</code></pre>
<h3 id="set-your-environment-variables">2. Set your Environment Variables</h3>
<p>You can find these on your <a href="https://my.joyentcloud.com/main/#!/storage">dashboard page</a>.
Just copy and paste them into your <code>.bashrc</code> then source with <code>. ~/.bashrc</code></p>
<pre><code>export MANTA_URL=https://us-east.manta.joyent.com
export MANTA_USER=your_user_name
export MANTA_KEY_ID=fd:f8:08:22:11:b2:ef:db:87:09:c0:2b:4b:fd:99:f7
</code></pre>
<h3 id="upload-a-file">3. Upload a File</h3>
<p>At this point you should be ready to upload a file. Manta includes command
line utilities for listing, creating, and destroying files and directories.
Let’s use <a href="https://us-east.manta.joyent.com/trevoro/public/beer.jpg">this sample file</a></p>
<pre><code>$ mput /$MANTA_USER/public/beer.jpg -f beer.jpg
$ wget https://us-east.manta.joyent.com/$MANTA_USER/public/beer.jpg
</code></pre>
<p>You’re done!</p>
<h3 id="that-was-easy">That was easy!</h3>
<p>Manta is pretty easy to use, but that’s really only the beginning. It’s got tons
of powerful functionality built into it. That functionality comes in the form of
map reduce jobs which you can easily run with a single shell command.</p>
<p>Let’s start with a simple example.</p>
<h3 id="create-a-thumbnail">Create a Thumbnail</h3>
<pre><code>$ mfind /$MANTA_USER/public | \
mjob create -w -m 'convert $MANTA_INPUT_FILE -resize 100x jpeg:- | mpipe ${MANTA_INPUT_OBJECT%.*}-100x.jpg'
81e40938-d33c-42da-ab61-33527360e366
added 1 inputs to 81e40938-d33c-42da-ab61-33527360e366
$ wget https://us-east.manta.joyent.com/$MANTA_USER/public/beer-100x.jpg
</code></pre>
<p><a href="https://us-east.manta.joyent.com/trevoro/public/beer-100x.jpg">check out the result</a></p>
<h3 id="lets-think-at-scale">Let’s think at Scale</h3>
<p>That’s a simple one-liner that will create thumbnails for <em>all</em> of your images,
which is pretty amazing considering the alternative would be to list all your
images, download them, convert them, then put them back. If you have 100’s of
millions of images in your object store, then that old process can take days.</p>
<p>With manta it just takes a few seconds.</p>
<h3 id="lets-clean-it-up-a-little">Let’s Clean it up a little</h3>
<p>That little goober shows how powerful Manta can be. But we’re going to make this
a tiny bit fancier. What if you need 4 differerent thumbnails? Writing that all
out on the command line might get a little ugly. At the end of the day though,
youre just running code that would run on any server, like a shell script or a
node app, etc.</p>
<p>Luckily we can submit these scripts as arguments to our map reduce jobs in Manta.
These files are called <a href="http://apidocs.joyent.com/manta/jobs-reference.html#assets-assets-property">assets</a>.</p>
<p>Here’s an example shell script we’ll use as our asset</p>
<pre><code>#!/usr/bin/env bash
sizes=( 128 256 512 )
for i in "${sizes[@]}" ; do
convert $MANTA_INPUT_FILE -resize ${i}x jpeg:- | \
mpipe "${MANTA_INPUT_OBJECT%.*}-${i}x.jpg
done
</code></pre>
<p>Lets upload it as an asset</p>
<pre><code>$ mput -f thumb.sh /$MANTA_USER/stor/thumb.sh
</code></pre>
<p>And create our job again</p>
<pre><code>$ mfind /$MANTA_USER/public | \
mjob create -w -s /$MANTA_USER/stor/thumb.sh \
-m 'bash /assets/$MANTA_USER/stor/thumb.sh'
</code></pre>
<p>Now we have 3 thumbnails</p>
<pre><code>$ mls /$MANTA_USER/public
beer-128x.jpg
beer-256x.jpg
beer-512x.jpg
beer.jpg
</code></pre>
<h3 id="thats-just-the-beginning">Thats just the beginning</h3>
<p>This is a simple example that hopefully shows you what Manta can do. The
<a href="http://apidocs.joyent.com/manta">documentation is pretty extensive</a> and they’re on <a href="http://freenode.net">irc.freenode.net</a> under <code>#manta</code>
if you have any questions.</p>
One Line2013-02-18T00:00:00+00:00http://trevoro.net/2013/one-line<p>Most new applications today are built up out of many 3rd party components and
glued together with some business rules. This means that any 3rd party service
is highly incentivized to make integrating their service as easy as possible.
Often times we end up reducing that down to a simple statement like</p>
<p>“Just one line of Javascript is all it takes!”</p>
<p>Most of the time that’s all it takes, and you’ve got a new customer.</p>
<p>Unfortunately it’s not that simple.</p>
<p>One line for a developer is 2-3 minutes of effort.
One line for a business is 2-3 months of change requests, releases,
product meetings, sprint planning, regression testing and hopefully a production
deployment. Thats <em>after</em> you finally get approval from legal, and a finance
department, because you only have so much discretionary income to be able to
spend on “3rd party tools that dont help the bottom line”.</p>
<p>Just something to keep that in mind when you write your “super easy to plug in” service.</p>
In Defense of the Intrapreneur2011-07-12T11:19:03+00:00http://trevoro.net/2011/in-defense-of-the-intrapreneur<p>I read a rather <a href="http://www.chubbybrain.com/blog/intrapreneur-entrepreneur-no-similarity/">harsh criticism</a>
on Hacker News today about “Intrapreneurs”. The Intrapreneur is an “Internal
Entrepreneur” who starts up new projects, ideas, etc, but from within an
established company. I personally feel this criticism is rather misguided. The
key to the argument was that Intrapreneurs take no risk, and therefore do not
deserve to be associated with any deviation of the word “Entrepreneur”.
<strong>Update</strong>: My colleague <a href="http://twitter.com/#!/bcantrill">Bryan</a> has also
written his thoughts on the subject. You can read them
<a href="http://dtrace.org/blogs/bmc/2011/07/12/in-defense-of-intrapreneurialism/">here</a>.</p>
<p>As an entrepreneur who has done both, here’s why you’re wrong. You can follow
along with the <a href="http://www.chubbybrain.com/blog/intrapreneur-entrepreneur-no-similarity/">original
article</a>
if you care at all.</p>
<p><strong>“Intrapreneurs take no REAL risk”</strong> - Entrepreneurs take great risks at the
benefit of great possible reward. A successful entrepreneur can make his entire
career by taking a chance. You’re confusing someone who drives internal product
direction with someone who just shoves paper all day. Innovative products that
come out of companies (like the iPod, Motorola Razr, Kinect, etc) were all
driven by internal entrepreneurs. You may feel that the term “entrepreneur” is
being trodden upon by these lowly individuals who have chosen not to go
bankrupt. Sometimes that’s just not an option. But an entrepreneur by definition
is someone who works on a new idea and is held accountable. Have you ever failed
a multi-million dollar project? That’s a risk and responsibility very few people
are willing to take.</p>
<p><strong>“Little Accountability”</strong> - Entrepreneurs blame all sorts of things when their
startups fail. The market conditions weren’t right. We couldn’t get enough
investment. Johnny should have written our webapp in Python instead of PHP. At
the end of the day, that’s not an “intrapreneur” vs entrepreneur issue. That’s a
goddamned character flaw. Intrapreneurs rarely get a second or third chance to
start over. Entrepreneurs usually flee with their tail between their legs. In
either case, it takes balls to do it over again.</p>
<p><strong>“Little Upside”</strong> - 10k in bonus money? If you come up with the next iPhone
and you get stuck with a 10K bonus then you’re an idiot - not a hesitant
entrepreneur. Stock options, bonuses, a career, a significantly higher salary.
Again, this is a risk vs reward scenario. For many serial entrepreneurs, they
aren’t in it “for the money” they’re in it for the experience. Building
something new is (and arguably should be) its own reward. The money is a bonus.</p>
<p><strong>“Intrapreneurs dont call the shots”</strong> - If you’ve started or a project that
would be significant enough to justify calling yourself an “intrapreneur” then
by definition you’re calling the shots. How many entrepreneurs are great at
press releases anyway? I can tell you straight up that the number is pretty low.
Sometimes having an entire department to spruce up some product documentation
would be nice. Is the process a pain - sure. But if i’ve built something good
enough this issue is moot.</p>
<p><strong>“Scarcity of Resources”</strong> - Yes. Yes there is. It’s called a budget. Sometimes
you go over your budget and you have to beg for more money. I’m not saying it’s
glamorous. It’s certainly not as “glamorous” as asking a VC for more money, but
it’s real. Just because you work for a big company, doesn’t mean you get to piss
that money away on catered lunches and sparkling water.</p>
<p><strong>“Knowing, Not Doing”</strong> - It’s incorrect (if not downright delusional) to
believe that after raising money internally an “Intrapreneur” can sit back and
watch everything magically happen. Again - we come back to risk vs reward. No VC
is going to throw their money into a project that has no traction with an
inexperienced team. But many times, a kick-ass team and a great idea, and a
track record will get you seed financing in the millions of dollars range.
You’re wrong.</p>
<p><strong>“Intrapreneurs piggy back on a Brand”</strong> - Companies of the size you’re
describing as so massive that the “shared resources” benefit is not really a
benefit at all. It’s more of a cost. The brand very often has nothing to do with
the quality of a product. It gives you a little bit of marketing money, but at
the end of the day that doesn’t necessarily result in sales. Most recent example
of this is the Blackberry Playbook. All the marketing money in the world won’t
save them from the fact that nobody cares about having Flash if the thing
doesn’t have email. Bad products are not made good by means of a logo. Startup
or not.</p>
<p><strong>“Luxury to Specialize”</strong> - Yes. The Marketing, Finance or Tech people have
specific functions. But by your very definition, they’re not “Intrapreneurs” if
they just go to work and do their very specific pigeon-holed jobs. That’s called
“Having a job” and there’s nothing wrong with it. If you want to start up a new
idea at your company, you have to learn a whole bunch of other “Entreprenerial”
skills. How to sell your idea, how to write a presentation, how to socialize
with people who decide if you get your money or not, how to run a team, etc. If
you’re an entrepreneur who is worrying about writing contracts, and how to do
all your taxes then you’re doing it wrong.</p>
How to do Prototype Validation in Javascript2010-11-24T09:42:48+00:00http://trevoro.net/2010/how-to-do-prototype-validation-in-javascript<p>I hacked together a quick model for a prototype REST API written in Node.js, and wanted to validate an object prior to saving it to a database. I didn’t want or need some wacky full blown ORM but I did want to ensure that the records I was storing were consistent.</p>
<p>Validating in Javascript can be done in many ways but this is a method I came up with after a couple iterations. Let’s take a look at the code.</p>
<div class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">PictureValidations</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="sr">/^[A-Za-z0-9_-]{8,64}$/</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="nx">type</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">type</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="sr">/^(jpeg|png|gif|bmp)$/</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">type</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="nx">tags</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">tags</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="nx">i</span> <span class="k">in</span> <span class="nx">tags</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="p">(</span><span class="sr">/^[A-Za-z0-9]+$/</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">tags</span><span class="p">[</span><span class="nx">i</span><span class="p">])))</span> <span class="p">{</span> <span class="k">return</span> <span class="kc">false</span> <span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">exports</span><span class="p">.</span><span class="nx">Picture</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">name</span> <span class="o">||</span><span class="s2">&quot;unassigned&quot;</span> <span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">tags</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">tags</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">description</span> <span class="o">=</span> <span class="nx">options</span><span class="p">.</span><span class="nx">description</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">created_on</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">exports</span><span class="p">.</span><span class="nx">Picture</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">valid</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">validations</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">PictureValidations</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">valid</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="nx">v</span> <span class="k">in</span> <span class="nx">validations</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">valid</span> <span class="o">=</span> <span class="nx">validations</span><span class="p">[</span><span class="nx">v</span><span class="p">](</span><span class="k">this</span><span class="p">[</span><span class="nx">v</span><span class="p">]);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">valid</span> <span class="o">==</span> <span class="kc">false</span><span class="p">)</span> <span class="p">{</span> <span class="k">break</span> <span class="p">;</span> <span class="p">}</span> <span class="c1">// stop checking on first failure</span>
<span class="p">};</span>
<span class="k">return</span> <span class="nx">valid</span>
<span class="p">}</span></code></pre></div>
<h3 id="how-it-works">How it works</h3>
<p>We’ve defined a new Object called Picture which has all the properties associated with it, as well as some defaults.</p>
<p>We also specify another object called PictureValidations which contains a bunch of functions. Each function is named after the properties in the Picture that we want to validate. Each function will return either True or False when it is called with the valid() method which has been added to the Picture prototype. The key is the line that says:</p>
<pre><code>valid = validations[v](this[v]);
</code></pre>
<p>This is storing the status returned from the function in the validations Object we’ve instantiated with the value of the current objects properties (this).
It will then check to see whether or not it passed or failed.</p>
<p>The nice thing about this method is that you can write a function that does just about anything to determine whether or not something is valid.</p>
<p>Anyway, it seems to work, but I’d appreciate any feedback!</p>
How to learn Node.js from Scratch2010-11-23T19:26:09+00:00http://trevoro.net/2010/how-to-learn-node-js-from-scratch<p>Server-side Javascript has appealed to me for <a href="http://trevoro.ca/blog/2009/02/05/why-serverside-javascript-matters/">quite a awhile</a>, and while watching from the sidelines was interesting, I still <a href="http://trevoro.ca/blog/2010/07/15/layerboom-acquired-by-joyent/">never had the time</a> to really get my feet wet and see how the language really worked. That changed after joining Joyent, of course. We’re the proud home of Node.js, and it would be wrong unforgivable if I didn’t know how to write JS.</p>
<p>It turns out that learning Javascript has been quite fun, and really easy. There are numerous resources on the internet for learning how to manipulate the DOM, and do ridiculous stuff with JQuery. But I’ve never been a UI person. I’m a server and network guy, through and through. It turns out, the hardest part about learning Javascript is finding decent documentation. Most of my learning experience has been through reading other peoples wacky, sometimes incomprehensible code, and then going through lists of tutorials that I wrote for myself. Breaking things seems to be the best way to learn how to write stuff. I also was able to rely on some of my brilliant co-workers who are full time software engineers.</p>
<p>Here’s a list of resources I found helpful, which don’t necessarily show up at the top of your Google search results.</p>
<h3 id="nodetutshttpnodetutscom--"><a href="http://nodetuts.com/">NodeTuts</a></h3>
<p>A decent list of tutorials as screencasts. They can be a little on the long side, but there are a few gems. Check out the one about learning how Sys.pump (util.pump) works. Once you understand how it works you’ll kind of be blown away at how easily you wrote something so powerful</p>
<h3 id="nodejs-documentationhttpnodejsorgdocs--"><a href="http://nodejs.org/docs/">Node.Js Documentation</a></h3>
<p>The API documentation for node is extremely well written, a testament to <a href="https://github.com/ry">Ryan’s</a> <a href="http://en.wikipedia.org/wiki/Benevolent_Dictator_For_Life">Benevolent Dictator for Life</a> mentality, which is a really good thing.</p>
<h3 id="crockford-on-javascripthttpjavascriptcrockfordcom--"><a href="http://javascript.crockford.com/">Crockford on Javascript</a></h3>
<p>Douglas Crockford has a ton of really well written examples, standards, “best practices”, and videos. If you’re interested, check out “Javascript - The Good Parts” <a href="http://yuiblog.com/blog/2007/06/08/video-crockford-goodstuff/">post</a>, hosted on the Yahoo! developer network (Mirror please…)</p>
<h3 id="mozilla-developer-network-javascript-referencehttpsdevelopermozillaorgenjavascriptreference--"><a href="https://developer.mozilla.org/en/JavaScript/Reference">Mozilla Developer Network Javascript Reference</a></h3>
<p>I don’t know why this wasn’t the first result I found when I searched for things like “Javascript Object” or “Javascript Array”, but this is the best resource that explains what the native objects are, what methods they include, and provides some decent examples on their usage. A MUST read.</p>
<h3 id="learning-advanced-javascripthttpejohnorgappslearn"><a href="http://ejohn.org/apps/learn/">Learning Advanced Javascript</a></h3>
<p>John Resig is putting together a book on the Secrets of Javascript, and it has something to do with Ninjas. But this part of the book is available for people to read today, and it’s pretty cool. After you nail down a lot of the style, prototyping, and closure stuff, be sure to check out this list of examples on advanced JS.</p>
Layerboom Acquired by Joyent!2010-07-15T07:12:05+00:00http://trevoro.net/2010/layerboom-acquired-by-joyent<p>I’m happy to announce that my company <a href="http://layerboom.com">Layerboom</a> has been acquired by <a href="http://www.joyent.com">Joyent</a>, a leading provider of Cloud Computing services and solutions. Here’s the <a href="http://gigaom.com/2010/07/15/joyent-buys-layerboom-to-offer-enterprises-easier-transition-to-the-cloud/">press announcement</a>.</p>
<p>Layerboom &amp; Cloud Computing is something I’ve been working on for 2 years but I’ve been thinking about cloud since school. Startups require quite a bit of sacrifice, and this definitely wasn’t an exception. I had to give up a lot for the opportunity to try and for that reason I have a ton of people to thank. Most of you I’ve thanked in person already, but here it is again for ‘the record’.</p>
<p>A big thanks to our Investors for taking a chance on a couple guys with a laptop and an idea, and a big congratulations to the rest of the guys on the <a href="http://layerboom.com">Layerboom</a> team for being persistent, forward thinking, and above all a pleasure to work with.</p>
<p>I also have to thank my Friends for being really supportive and putting up with my bullshit over the last 2 years; You’re like family to me and in case there was any doubt, you’re worth more to me than anything.</p>
<p>As part of our deal I’ve taken a job at Joyent and I’m really happy to be working for a company with excellent leadership and vision . We can’t wait to show everyone the projects we’re working on!</p>
<p>ps We’re hiring, so if you’re a developer and you’re looking for a killer opportunity <a href="&#109;&#097;&#105;&#108;&#116;&#111;:&#116;&#114;&#101;&#118;&#111;&#114;&#111;&#064;&#106;&#111;&#121;&#101;&#110;&#116;&#046;&#099;&#111;&#109;">send me</a> an email.</p>
Hosting Apocalypse2008-10-16T00:00:00+00:00http://trevoro.net/2008/hosting-apocalypse<p>If you run a managed hosting company then your time is officially ‘up’. You
won’t survive the coming hosting Apocalypse. Here’s why.</p>
<p>There are a few companies you may have heard of building large compute grids for
consumption by the general public. They’re calling them their Cloud Computing
products. IBM is building BlueCloud, Microsoft is building the Mesh, Amazon
already has EC2, and Google has AppEngine. AppEngine is in a slightly different
category than the others and the BlueCloud details are sparse, but they’re still
worth mentioning. Of more immediate interest are Amazon and Microsoft’s
solutions.</p>
<p>Microsoft is currently building their famous 300,000 server Data Center in
Chicago. That’s roughly 3 times the number of servers that Google has. Microsoft
has also announced several other Data center projects - each worth about $500
Million. It’s fair to say that that’s a lot of computing power, and it’s not all
for MSN - Microsoft is planning on providing their platform in the cloud.</p>
<p>The real question is what Amazon will do when the Windows Cloud comes online.
Microsoft has enough money in the bank to provide their 300,000 servers to
customers for <em>years</em> without earning a single cent. That implies they can offer
services at super low rates; Low enough to at least compete with Amazon’s EC2,
which will support the Windows Server OS in fall 2008.</p>
<p>What happens with two huge cloud hosting companies get into a price war?</p>
<p>In the interest of self preservation they won’t make their services commodities
- at least right away. But it won’t even matter. When you’re as big as Amazon,
Microsoft, Google or IBM, you can afford to buy servers in such massive
quantities that you could make money selling compute time for 10$ a month. The
hosting space will change forever, because Amazon will eventually drop their
prices by an <em>order of magnitude</em> and that has dire implications for the rest of
the Mom’n’Pop hosting companies.</p>
<p>If thousands of companies can’t compete with Microsoft or Amazon on price, and
they can’t compete in terms of convenience, then why would anyone use them? If
you have to buy individual servers, or even servers by the rack, then you’re not
going to get the price you need to be able to compete. You also don’t have
access to the handful of specialized individuals and hardware required to make
things work on such a grand scale.</p>
<p>The only answer is for all the smaller players to band together - to create a
Federated Hosting environment, where together they can provide services that
begin approaching levels of service and power that the Big 4 will offer.</p>
<p>Either way, we’re in an interesting period in the industry. Computing and the
infrastructure of technology has become such a requirement for the economy that
it will eventually become a general utility. The real question is who will be
around.</p>
Function as a Service2008-07-15T00:00:00+00:00http://trevoro.net/2008/function-as-a-service<p>Websites have gone from hand-typed static pages, to massive applications with
every feature under the moon. Most applications have some secret sauce that does
magical things in the background - whether that be the ability to handle massive
amounts of volume, reduce the barrier to entry into a market, or just keep users
engaged by providing endless amounts of quick short updates.</p>
<p>Take Amazon as an example. Amazon operates their environment as a bunch of
different groups, each running different services within the same company. S3,
EC2, Payment Services. They’re all independent, highly scalable functions, tied
together in the application we call Amazon.com.</p>
<p>Companies and startups are starting to break this operational model open, and
putting those individual functions online for everyone. They’re building
services that do something really well - or rather that do one thing really
really well. They’re companies that focus on a specific function or feature and
are open enough so creative people can say “I’m going to take this, this, and
this - mix it in a pot and voila!”.</p>
<p>Do you want to build your own Twitter? Find an SMS gateway, Cloud Computing Host
and XMPP service provider.</p>
<p>Do you want to build an interesting RSS/ATOM service? Find an RSS aggregator
service and pour on some glue - see what sticks.</p>
<p>It’s Function as a Service world (to use an already overused description).
Eventually cloud companies will realize that doing one thing really <em>really</em>
well is tremendously valuable. Why does everyone have to build their own DNS
service? Why does everyone have to build their own hosting system? What about
Enterprise Storage, Authentication, SMS Gateways, Massively scalable XMPP
services? How come I have to do that myself? Can 10,000 messages sent through a
jabber server be worth a dollar? I think it can (maybe the math needs adjusting
but you get my point). We’re all really just building a massive computer called
the internet, only with each big trend we replace ‘The Internet’ with something
else. First it was ‘The Web’, then it was ‘Web 2.0′, and now its ‘The Cloud’.</p>
<p>The fact of the matter remains - the further along we go the more tightly knit
the internet becomes, and that means that theres opportunity for programmable
white label services to propel us further and faster.</p>
Pull to Push - RSS to XMPP2008-02-04T00:00:00+00:00http://trevoro.net/2008/pull-to-push<p>You and your friend are standing alone in a room. You’re interested in what your
friend has to say, but he’s normally a pretty quiet guy, so every minute or so
you ask him.</p>
<p>“Hey. What’s on your mind”</p>
<p>“Nothing”, he responds.</p>
<p>This goes on for a few hours until your friend responds with</p>
<p>“I had a great idea for a blog post!”</p>
<p>Now you can start your conversation.</p>
<p>Now its not so bad in this circumstance. There are only two people involved, but
it’s not what you would consider the normal way to have a conversation. Lets
place another 10 people in the room, all talking to each other the same way, and
things get noisy very quickly.</p>
<p>RSS has been around for awhile, and with the exception of ATOM its generally
regarded as the standard for syndicating content. But RSS is a dirty hack.
Constant polling from tons of locations and clients means an unnecessary amount
of data and strain on servers, not to mention wasted bandwidth (And we love our
precious bandwidth). So rather than have millions of clients poll millions of
servers, what’s the better solution? We want to push data to clients as it
becomes available.</p>
<p>Let’s imagine our ideal circumstance.</p>
<p>There are no more pull mechanisms being used online. Every user and website is
having its content updated based not on timers and countdowns, but rather
changes and actions are being taken based on events that happen somewhere else
online. You write a twitter post, but it also updates your Jakiu, your Facebook
status and some other set of widgets. Someone writes an article, and rather than
the information being syndicated over RSS, the update is pushed directly into
the browsers of subscribers all over, or updated on an aggregate website like
Popurls.</p>
<p>There’s no sense distinguishing between clients. A client can be a browser, an
instant messaging system, a daemon on a server somewhere, a website, a widget, a
cell phone. The possibilities are literally limitless. What we need to get to
this point is a transition mechanism, and the first and best place to start is
by creating a service that converts RSS feeds into XMPP style messaging. The
most popular clients that are available to end-users are going to be what they
have already - Browsers and IM Clients. Firefox plugins would allow you to keep
your data in a list. A website would allow you to retrieve your list whenever
you wanted, a cell phone to get certain information on the go.</p>
<p>It’s interesting and exciting, because it means that mediums where polling
mechanisms aren’t feasible can start to participate in more connected way, and
applications can speak to each other in a more natural fashion.</p>