<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link rel="hub" href="http://tumblr.superfeedr.com/" xmlns:atom="http://www.w3.org/2005/Atom"/><description>A tumblog by Ryan Probasco.</description><title>bitdrift</title><generator>Tumblr (3.0; @bitdrift)</generator><link>http://bitdrift.com/</link><item><title>Another day, another gift (from our users) (Taken with Instagram...</title><description>&lt;img src="http://24.media.tumblr.com/tumblr_m2e1xviuDi1qdg04ro1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Another day, another gift (from our users) (Taken with &lt;a href="http://instagr.am"&gt;Instagram&lt;/a&gt; at Pinterest)&lt;/p&gt;</description><link>http://bitdrift.com/post/20987939590</link><guid>http://bitdrift.com/post/20987939590</guid><pubDate>Thu, 12 Apr 2012 15:46:42 -0700</pubDate></item><item><title>Optimus Prime’s mind &lt;= 1.44 MB? (Taken with...</title><description>&lt;img src="http://24.media.tumblr.com/tumblr_m255ohHSXa1qdg04ro1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Optimus Prime’s mind &lt;= 1.44 MB? (Taken with &lt;a href="http://instagr.am"&gt;instagram&lt;/a&gt;)&lt;/p&gt;</description><link>http://bitdrift.com/post/20692948484</link><guid>http://bitdrift.com/post/20692948484</guid><pubDate>Sat, 07 Apr 2012 20:29:05 -0700</pubDate></item><item><title>#pinning (Taken with Instagram at Pinterest)</title><description>&lt;img src="http://24.media.tumblr.com/tumblr_m1ojanO83l1qdg04ro1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;#pinning (Taken with &lt;a href="http://instagr.am"&gt;Instagram&lt;/a&gt; at Pinterest)&lt;/p&gt;</description><link>http://bitdrift.com/post/20156304533</link><guid>http://bitdrift.com/post/20156304533</guid><pubDate>Thu, 29 Mar 2012 21:03:59 -0700</pubDate><category>pinning</category></item><item><title>BBQ &amp; Evrhet @Pinterest (Taken with Instagram at Pinterest)</title><description>&lt;img src="http://24.media.tumblr.com/tumblr_m1ns1iuKAz1qdg04ro1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;BBQ &amp; Evrhet @Pinterest (Taken with &lt;a href="http://instagr.am"&gt;Instagram&lt;/a&gt; at Pinterest)&lt;/p&gt;</description><link>http://bitdrift.com/post/20123789828</link><guid>http://bitdrift.com/post/20123789828</guid><pubDate>Thu, 29 Mar 2012 11:15:18 -0700</pubDate></item><item><title>Original Site (Taken with instagram)</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_m1nmbkFHOa1qdg04ro1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Original Site (Taken with &lt;a href="http://instagr.am"&gt;instagram&lt;/a&gt;)&lt;/p&gt;</description><link>http://bitdrift.com/post/20119358896</link><guid>http://bitdrift.com/post/20119358896</guid><pubDate>Thu, 29 Mar 2012 09:11:44 -0700</pubDate></item><item><title>Lighthouse (Taken with Instagram at Santa Cruz Harbor)</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_lset7d7APV1qdg04ro1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Lighthouse (Taken with &lt;a href="http://instagr.am"&gt;Instagram&lt;/a&gt; at Santa Cruz Harbor)&lt;/p&gt;</description><link>http://bitdrift.com/post/10908223908</link><guid>http://bitdrift.com/post/10908223908</guid><pubDate>Sat, 01 Oct 2011 15:59:37 -0700</pubDate></item><item><title>Parking Lot Palms (Taken with instagram)</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_lrupthOJ9K1qdg04ro1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Parking Lot Palms (Taken with &lt;a href="http://instagr.am"&gt;instagram&lt;/a&gt;)&lt;/p&gt;</description><link>http://bitdrift.com/post/10468185531</link><guid>http://bitdrift.com/post/10468185531</guid><pubDate>Tue, 20 Sep 2011 19:34:29 -0700</pubDate></item><item><title>The Right Opportunity</title><description>&lt;p&gt;As they say in that commercial (you know the one I&amp;#8217;m talking about): &amp;#8220;life comes at you fast.&amp;#8221; Less than 8 weeks ago, I had no idea what &lt;a href="http://pinterest.com/bitdrift"&gt;Pinterest&lt;/a&gt; was, let alone imagined that I&amp;#8217;d be packing up the family and moving to California before the end of July. If you ask my friends, I&amp;#8217;m sure they&amp;#8217;ll tell you this was no surprise; moving to the bay area is something I&amp;#8217;ve been talking about for years. But still, I can&amp;#8217;t help but feel a little shocked that I&amp;#8217;m writing this post from Palo Alto instead of Provo today.&lt;/p&gt;

&lt;p&gt;If you&amp;#8217;re a startup guy like me, you probably have a hard time imagining yourself at a larger more established company (even if that company is as cool as Facebook or Google). The term &amp;#8216;startup&amp;#8217; gets thrown around a lot these days and young companies come in all shapes and sizes. In my case, I was looking for a startup that met a few specific requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Early but not without funding&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m prepared to take a risk, but being a parent means I&amp;#8217;m not the only one taking the risk anymore. This may not apply to everyone, but for those with families, it&amp;#8217;s a big deal. It reminds me of something &lt;a href="http://www.paulgraham.com/notnot.html"&gt;Paul Graham wrote&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&amp;#8220;Another way to decrease the risk is to join an existing startup instead of starting your own. Being one of the first employees of a startup is a lot like being a founder, in both the good ways and the bad.&amp;#8221;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The earlier you join a startup, the more impact you&amp;#8217;ll be able to have. I&amp;#8217;ve only been at Pinterest for 3 weeks and I&amp;#8217;ve already experienced this personally. One of my first tasks was to add a feature that makes it possible for users pin videos. We launched the feature last Monday and nearly 20,000 videos have been pinned so far. I&amp;#8217;m quite certain that nothing I&amp;#8217;ve ever done in my life has touched so many people in such a short amount of time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Great team with a strong sense of direction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I can&amp;#8217;t overstate how important this was to me. There were several good signs that helped me feel good about joining Pinterest. One that stands out to me was how careful the founders have been about publicity. In an era where so many startups seem to be overly focused on the fundraising game, it&amp;#8217;s refreshing to meet a group of founders who haven&amp;#8217;t forgotten their users. Pinterest is under-hyped for a reason (for now anyway).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Great product with adoring customers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I knew Pinterest was something special the moment I first saw it. Now that I&amp;#8217;m on the team I realize that even more. We get fan mail pretty much every day. And not just simple &amp;#8216;thank you&amp;#8217; notes, either; these are long gushing love letters. We have the best users ever.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exciting technical challenges&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This one caught me off guard. I knew that joining an early stage startup would present new technical challenges. What I didn&amp;#8217;t realize was just how much I would learn and how quickly I would be thrust into the thick of it. I feel like I&amp;#8217;m drinking from the firehose, but there&amp;#8217;s honestly nothing I&amp;#8217;d rather be doing at this point in my career. Pinterest is growing so quickly right now that it&amp;#8217;s giving me opportunities to work on things I&amp;#8217;d only ever dreamed of before.&lt;/p&gt;

&lt;p&gt;As you can probably tell, I&amp;#8217;m pretty excited about the opportunity to help turn Pinterest into something millions of people use and appreciate. I&amp;#8217;ll do my best to post more as the site grows.&lt;/p&gt;

&lt;p&gt;Oh, and if you&amp;#8217;re looking for a great opportunity to work with amazing people on an exciting problem for the best users in the world, &lt;a href="http://pinterest.com/about/jobs/"&gt;apply here&lt;/a&gt;. :-)&lt;/p&gt;</description><link>http://bitdrift.com/post/8984689982</link><guid>http://bitdrift.com/post/8984689982</guid><pubDate>Mon, 15 Aug 2011 21:42:00 -0700</pubDate></item><item><title>Video Pins</title><description>&lt;p&gt;My second &amp;#8216;visible&amp;#8217; contribution since joining Pinterest is now live (the first was the new &amp;#8220;Pin It&amp;#8221; button for websites)! Almost 15,000 videos have been pinned since the feature was launched on Monday. More details on the Pinterest blog:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://blog.pinterest.com/post/8670310296" class="tumblr_blog"&gt;pinterest&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Today, we’re excited to introduce a brand new feature at Pinterest: Video Pins! If you’ve ever wanted to pin a DIY tutorial, a cooking lesson, a music video, or just a Beluga whale enjoying a Mariachi Band, now you can.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://pinterest.com/pin/95722047/"&gt;&lt;img src="http://media.tumblr.com/tumblr_lpn0x0HFXL1qek6n0.png"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Just push the very same &lt;a title="Pin It Button" href="http://www.pinterest.com/about/goodies"&gt;Pin It button&lt;/a&gt; you have installed in your bookmarks bar whenever you see a YouTube video. We are hard at work adding support for other video sites. &lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;&lt;/blockquote&gt;</description><link>http://bitdrift.com/post/8879779212</link><guid>http://bitdrift.com/post/8879779212</guid><pubDate>Sat, 13 Aug 2011 14:52:30 -0700</pubDate></item><item><title>"Why do companies brag about how many employees they have? They want to spotlight their..."</title><description>“Why do companies brag about how many employees they have? They want to spotlight their inefficiencies and poor leverage?”&lt;br/&gt;&lt;br/&gt; - &lt;em&gt;&lt;a href="http://twitter.com/#!/venturehacks/status/98164863951585280"&gt;&lt;a href="http://twitter.com/#!/venturehacks/status/98164863951585280"&gt;http://twitter.com/#!/venturehacks/status/98164863951585280&lt;/a&gt;&lt;/a&gt;
&lt;a href="http://venturehacks.com/articles/scale"&gt;&lt;a href="http://venturehacks.com/articles/scale"&gt;http://venturehacks.com/articles/scale&lt;/a&gt;&lt;/a&gt;&lt;/em&gt;</description><link>http://bitdrift.com/post/8368678966</link><guid>http://bitdrift.com/post/8368678966</guid><pubDate>Mon, 01 Aug 2011 20:11:11 -0700</pubDate></item><item><title>Antelope Canyon (Taken with instagram)</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_ln0j79ZWEM1qdg04ro1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Antelope Canyon (Taken with &lt;a href="http://instagr.am"&gt;instagram&lt;/a&gt;)&lt;/p&gt;</description><link>http://bitdrift.com/post/6672467621</link><guid>http://bitdrift.com/post/6672467621</guid><pubDate>Sat, 18 Jun 2011 18:09:09 -0700</pubDate></item><item><title>Pendleton Round-Up (Taken with instagram)</title><description>&lt;img src="http://24.media.tumblr.com/tumblr_lm6z662oUJ1qdg04ro1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Pendleton Round-Up (Taken with &lt;a href="http://instagr.am"&gt;instagram&lt;/a&gt;)&lt;/p&gt;</description><link>http://bitdrift.com/post/6128420476</link><guid>http://bitdrift.com/post/6128420476</guid><pubDate>Thu, 02 Jun 2011 19:06:06 -0700</pubDate></item><item><title>Fork your own project on GitHub</title><description>&lt;p&gt;I was a little surprised to discover that &lt;a href="http://github.com"&gt;GitHub&lt;/a&gt; doesn&amp;#8217;t allow you to fork your own projects as simply as you can fork someone else&amp;#8217;s (if you don&amp;#8217;t believe me, check out &lt;a href="http://support.github.com/discussions/repos/2086-forking-my-own-project"&gt;this post&lt;/a&gt;). Fortunately it&amp;#8217;s pretty simple as long as you can come up with a different name for your new project.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s assume we have an existing project called &amp;#8216;foo&amp;#8217; and we want to create a fork called &amp;#8216;bar&amp;#8217;.&lt;/p&gt;

&lt;p&gt;First, create a new project on GitHub called &amp;#8216;bar&amp;#8217;.&lt;/p&gt;

&lt;p&gt;Next, clone foo using the name &amp;#8216;bar&amp;#8217;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git clone git@github.com:YOURNAME/foo.git bar
Initialized empty Git repository in /projects/bar/.git/
remote: Counting objects: 3618, done.
remote: Compressing objects: 100% (1503/1503), done.
remote: Total 3618 (delta 2629), reused 2922 (delta 2075)
Receiving objects: 100% (3618/3618), 7.31 MiB | 1.23 MiB/s, done.
Resolving deltas: 100% (2629/2629), done.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Next, edit your Git config file and replace the origin URL with your new URL:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ cd bar
$ vim .git/config
[remote "origin"]
    fetch = +refs/heads/*:refs/remotes/origin/*
    url = git@github.com:YOURNAME/bar.git #replace foo with bar
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Optionally add your original repo as an upstream source:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git remote add upstream git@github.com:YOURNAME/foo.git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Finally, push your new repository up to GitHub:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git push -u origin master
Counting objects: 3618, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (949/949), done.
Writing objects: 100% (3618/3618), 7.31 MiB | 646 KiB/s, done.
Total 3618 (delta 2629), reused 3618 (delta 2629)
To git@github.com:YOURNAME/bar.git
 * [new branch]      master -&amp;gt; master
Branch master set up to track remote branch master from origin.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now you can push/pull from your new repo (bar) as expected. You should also be able to merge upstream changes using the following command (although I haven&amp;#8217;t tried this yet):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git fetch upstream
$ git merge upstream/master
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;#8217;s really all there is to it. :-)&lt;/p&gt;</description><link>http://bitdrift.com/post/4534738938</link><guid>http://bitdrift.com/post/4534738938</guid><pubDate>Mon, 11 Apr 2011 14:45:00 -0700</pubDate><category>github</category><category>git</category><category>fork</category></item><item><title>Old Linoleum (Taken with instagram)</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_liw9cb3jpM1qdg04ro1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Old Linoleum (Taken with &lt;a href="http://instagr.am"&gt;instagram&lt;/a&gt;)&lt;/p&gt;</description><link>http://bitdrift.com/post/4219576621</link><guid>http://bitdrift.com/post/4219576621</guid><pubDate>Wed, 30 Mar 2011 20:31:25 -0700</pubDate></item><item><title>Don't try this at home (just get Embedly)</title><description>&lt;p&gt;&lt;a href="http://bitdrift.com/post/3449584110/beaten-to-the-punch-convore-vs-banterly"&gt;Launching Banterly&lt;/a&gt; last week was a thrill. It was unbelievably fun meeting so many new people from all over the world through my own personal creation. Everyone was so friendly and supportive and I honestly loved every minute of it (even the parts where I was frantically fixing bugs). It was an experience I won&amp;#8217;t soon forget and hope to repeat.&lt;/p&gt;

&lt;p&gt;Not long after I launched, the guys at &lt;a href="http://embed.ly/"&gt;Embedly&lt;/a&gt; started a discussion suggesting that I check out their &lt;a href="http://www.oembed.com/"&gt;oEmbed&lt;/a&gt; service. The moment I saw it, I knew it was exactly what I had been looking for. The only annoying part was that I hadn&amp;#8217;t discovered it several weeks ago when I first started working on embedded media in Banterly. So, for that reason, I decided to do a little demonstration and offer a little praise in hopes that others looking for a solution to their embedding woes might not waste time trying to roll their own (like I did).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don&amp;#8217;t DIY&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s start with what NOT to do. Don&amp;#8217;t try to do media embedding yourself. For starters, there are simply too many different sites out there, each with slightly different methods of exposing their data (Embedly supports more than 160 providers for free or 185 for a &lt;a href="https://pro.embed.ly/"&gt;reasonable subscription fee&lt;/a&gt;). Doing it myself, it took two days to get support for images, YouTube, and the most simple &lt;a href="http://ogp.me/"&gt;OpenGraph&lt;/a&gt; meta tags (which was extremely flimsy since no complete HTML parsers exist for &lt;a href="http://nodejs.org/"&gt;Node&lt;/a&gt; yet).&lt;/p&gt;

&lt;p&gt;Additionally, doing it yourself means downloading unknown content from unknown sources at the whim of your users&amp;#8212;not exactly the kind of thing you want to expose yourself to when all you want is to embed content on your site. In fact, I almost cut the feature before launch because I was afraid malicious users might discover it and use it to abuse the system, but then I thought&amp;#8212;&amp;#8216;why not?&amp;#8217; and left it in anyway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;embedly-node&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can use Embedly to embed media from both server side and client side (via &lt;a href="http://github.com/embedly/embedly-jquery"&gt;jQuery&lt;/a&gt;). I chose to use the server side module (&lt;a href="http://github.com/embedly/embedly-node"&gt;embedly-node&lt;/a&gt;) in order to reduce the number of requests I have to make to the Embedly API and to keep page load times fast for users. Using the embedly-node module on &lt;a href="http://github.com/"&gt;GitHub&lt;/a&gt; (use npm install embedly), I ended up with something similar to the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var Embedly = require("embedly");
var embedly = new Embedly.api({
    //key: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX", // Embedly Pro Key                                                                             
    user_agent: 'Mozilla/5.0 (compatible; myapp/1.0; me@example.com)'
});

// Do initial comment text processing
// 1. Parse URLs from comment text
// 2. Render HTML comment by replacing parsed URLs with anchor tags
// 3. Save rendered comment HTML to the database
// 4. Send rendered comment HTML to connected clients (via WebSocket)

...

// 5. Try to get additional content from Embedly
if (urls) {
    // Using Embedly oEmbed API
    embedly.oembed({
        params: {
        urls: urls // Can send single URL also.
    },
    complete: function(e, objs) {
        for (var i in objs) {
            // Returned if the URL content is not supported on free tier 
            if (objs[i].type == "error") continue;

            // Some embed types don't contain a URL
            objs[i].url = objs[i].url || urls[i]; 

            // Render and replace the previously rendered link
            html = html.replace(getLink(urls[i]), render(objs[i]));
        }

        // Only save and send to clients if the HTML has changed
        if (comment.html != html) {
            // Update the rendered HTML in the database
            comment.html = html;
            comment.save(function() {
                // Send updated comment HTML to connected clients (via WebSocket)
                ...
            });
        }
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Sending the initial HTML to connected clients immediately (rather than waiting for Embedly) helps keep the UI fast and responsive while users are chatting. Once Embedly returns, new HTML is sent out to clients to replace the initial comment markup. In my tests, I found Embedly to be quite fast at returning embed data, but its speed will always be limited by how fast the URL host can return its own content, so it&amp;#8217;s much more reasonable to keep the updates separate.&lt;/p&gt;

&lt;p&gt;A simplified version of my render function looks like this (would be admittedly much cooler with a template):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;function render(obj) {
    if (obj.type == "photo") {
        // Just an image (only works with pro account)
        // image dimensions are available as obj.height and obj.width
        var html = "&amp;lt;img src='"+obj.url+"' width='500'/&amp;gt;";
        return html;
    } else if (obj.type == "video") {
        var html = "";
        // Add thumbnail
        if (obj.thumbnail_url)
            html += "&amp;lt;a href='"+obj.url+"' target='_blank'&amp;gt;&amp;lt;img src='"+obj.thumbnail_url+"' width='100'/&amp;gt;&amp;lt;/a&amp;gt;";
        // Add title link
        if (obj.title)
            html += "&amp;lt;a href='"+obj.url+"' target='_blank'&amp;gt;&amp;lt;h6&amp;gt;"+obj.title+"&amp;lt;/h6&amp;gt;&amp;lt;/a&amp;gt;";
        // Add an explicit link
        html += "&amp;lt;a href='"+obj.url+"' target='_blank'&amp;gt;"+obj.url+"&amp;lt;/a&amp;gt;";
        // Add description
        if (obj.description)
            html += "&amp;lt;p&amp;gt;"+obj.description+"&amp;lt;/p&amp;gt;";
        // Wrap it up
        return "&amp;lt;div class='oembed'&amp;gt;"+html+"&amp;lt;/div&amp;gt;";
    }
    // Just a normal link
    return "&amp;lt;a href='"+obj.url+"' target='_blank'&amp;gt;"+obj.url+"&amp;lt;/a&amp;gt;";
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;In addition to oEmbed, there are also &amp;#8216;preview&amp;#8217; and &amp;#8216;objectify&amp;#8217; which I have yet to explore (maybe I&amp;#8217;ll follow up if I do) but are only available for Pro Embedly users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Thanks guys!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I also think it&amp;#8217;s worth mentioning how helpful the folks at Embedly were during the process (especially Bob Corsaro aka &lt;a href="http://twitter.com/doki_pen"&gt;@doki_pen&lt;/a&gt;). Throughout the experience, they were extremely available (chatting on Banterly and exchanging emails late into the night). They even fixed a bug I found within minutes of reporting it!&lt;/p&gt;</description><link>http://bitdrift.com/post/3553420066</link><guid>http://bitdrift.com/post/3553420066</guid><pubDate>Sun, 27 Feb 2011 15:50:00 -0800</pubDate><category>embedly</category><category>oembed</category><category>node.js</category><category>banterly</category></item><item><title>Beaten to the Punch (Convore vs Banterly)</title><description>&lt;p&gt;I&amp;#8217;ve been working on Banterly ever since I caught the startup bug at &lt;a href="http://startupschool.org/"&gt;Startup School 2010&lt;/a&gt;. It started as a simple last minute idea to apply to &lt;a href="http://ycombinator.com/"&gt;Y Combinator&lt;/a&gt;, but has since evolved into something much more (despite not being accepted).  If you haven&amp;#8217;t seen Banterly yet, go ahead and take a few minutes to check it out. Here&amp;#8217;s a link even: &lt;a href="http://www.banter.ly/"&gt;&lt;a href="http://banter.ly"&gt;http://banter.ly&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;~ Intermission ~&lt;/p&gt;

&lt;p&gt;&lt;img src="http://media.tumblr.com/tumblr_lh1c0pGJat1qd973a.png" alt=""/&gt;&lt;/p&gt;

&lt;p&gt;Either you saw the announcement from Convore (&lt;a href="http://convore.com/"&gt;&lt;a href="http://convore.com"&gt;http://convore.com&lt;/a&gt;&lt;/a&gt;) the week before last, or you don&amp;#8217;t follow startups. If you&amp;#8217;re in the latter group, you should probably just skip the rest of this and go start chatting on Banterly (or I suppose&amp;#8230;Convore). If you&amp;#8217;re in the former, you may have taken one look at Banterly and thought &amp;#8220;meh&amp;#8230;this is just Convore with less features.&amp;#8221; But of course, we hope you thought &amp;#8220;Sweet! This is what Convore should have been.&amp;#8221;&lt;/p&gt;

&lt;p&gt;Regardless, if you&amp;#8217;re an entrepreneur like me, you can probably relate to my story. While it&amp;#8217;s normal to question any idea over the course of its development, it&amp;#8217;s also often a great source of agony and stress for would-be founders. Second guessing yourself is difficult, but even more difficult after getting rejected by Y Combinator.&lt;/p&gt;

&lt;p&gt;However, after experiencing all of the ups and downs of startup-idea self-examination, there&amp;#8217;s one thing that&amp;#8217;s even more agonizing: being beaten to the punch. When I saw the announcement from Y Combinator about Convore less than two weeks ago, I was shattered.&lt;/p&gt;

&lt;p&gt;In researching the space over the months we had discovered many competitors, so discovering someone else was nothing new. What made Convore different was that it was actually GOOD, it had buy-in from Paul Graham &amp;amp; Co., and seemed to get instant respect from people in the know&amp;#8212;all things I felt needed to be in place to make something like Banterly successful.&lt;/p&gt;

&lt;p&gt;Discovering that your &amp;#8216;revolutionary&amp;#8217; product is suddenly a &amp;#8216;me too&amp;#8217; product is a bitter pill to swallow. There&amp;#8217;s nothing like having your idea validated and taken away from you at the same time.&lt;/p&gt;

&lt;p&gt;Somehow I resisted the urge to abandon Banterly (not easy as easy as it sounds) and have been working around the clock ever since to get something presentable ready anyway. Banterly, as we&amp;#8217;re releasing it today, is not perfect and has no shortage of bugs (which I am sure will pop up once people start using the service in greater numbers). I am the sole programmer working on it and have only limited time for it (not to mention learning &lt;a href="http://nodejs.org/"&gt;Node.js&lt;/a&gt; + &lt;a href="http://www.mongodb.org/"&gt;MongoDB&lt;/a&gt;&amp;#8212;both new platforms for me).&lt;/p&gt;

&lt;p&gt;So my question to the community is this: What would you do if you were in my shoes? Would you cut your losses and move on to a new idea (we discovered several while working on Banterly)? Would you ignore Convore and go for it? Would you open source the code?&lt;/p&gt;

&lt;p&gt;I also want to add one more thing. We have nothing but respect for the folks at Convore and we think their service is fantastic. Even if we end up moving on from Banterly, we&amp;#8217;re really happy that Y Combinator decided to support such an awesome team with such a great idea.&lt;/p&gt;</description><link>http://bitdrift.com/post/3449584110</link><guid>http://bitdrift.com/post/3449584110</guid><pubDate>Tue, 22 Feb 2011 12:48:44 -0800</pubDate><category>mongodb</category><category>node.js</category><category>startups</category><category>banterly</category><category>convore</category><category>ycombinator</category></item><item><title>Way to go—Sebadoh! (Taken with instagram)</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_lgn57d05IV1qdg04ro1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Way to go—Sebadoh! (Taken with &lt;a href="http://instagr.am"&gt;instagram&lt;/a&gt;)&lt;/p&gt;</description><link>http://bitdrift.com/post/3304126899</link><guid>http://bitdrift.com/post/3304126899</guid><pubDate>Mon, 14 Feb 2011 20:16:26 -0800</pubDate></item><item><title>Using node-openid with Google + Attribute Exchange</title><description>&lt;p&gt;I&amp;#8217;m afraid the honeymoon with &lt;a href="http://nodejs.org/"&gt;Node.js&lt;/a&gt; may finally be over. That is not to say that I&amp;#8217;m not still enamored with it&amp;#8212;just that I&amp;#8217;ve encountered a few challenges that weren&amp;#8217;t there in the beginning.  These are mostly due to the fact that Node is still a very very young project and much of the support community around it is still emerging. The good news is that it is emerging faster than I think anyone expected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;node-openid&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So I needed &lt;a href="http://openid.net/"&gt;OpenID&lt;/a&gt; support for my project.  A Google search revealed a few incomplete implementations on GitHub.  So I did what any respectable open source community member would do. I started writing one.&lt;/p&gt;

&lt;p&gt;Lucky for me, I didn&amp;#8217;t have to spend much time on my version, because another respectable community member (&lt;a href="https://github.com/havard"&gt;@havard&lt;/a&gt;) released his own version (&lt;a href="https://github.com/havard/node-openid"&gt;node-openid&lt;/a&gt;) just as I was getting mine working with Google. This version was much more complete and true to the spec than I had time for&amp;#8212;so really a win for both me and the community.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Attribute Exchange&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As frustrating as it can be to discover a large missing feature from your platform, what&amp;#8217;s even more frustrating is finding that the implementation doesn&amp;#8217;t work for your needs. I&amp;#8217;m not sure how common this is, but Google additionally allows consumers to request additional properties through &lt;a href="http://openid.net/specs/openid-attribute-exchange-1_0.html"&gt;OpenID Attribute Exchange&lt;/a&gt;, which in this case get piggybacked on top of the main OpenID request. Since I needed the user&amp;#8217;s email address as well, and was only interested in Google, I needed the node-openid to work for this case.&lt;/p&gt;

&lt;p&gt;I briefly considered putting some time into adding Attribute Exchange to node-openid before realizing that it was not a trivial amount of work. The good news is there is an easy way to modify node-openid (you can even just use &lt;a href="https://gist.github.com/777406"&gt;this patch&lt;/a&gt;) so that you can send your own additional parameters with the authenticate request. With the patch applied, your request might look something like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var openid = require("openid");

openid.authenticate.defaultParams["openid.ns.ax"] = "http://openid.net/srv/ax/1.0";
openid.authenticate.defaultParams["openid.ax.mode"] = "fetch_request";
openid.authenticate.defaultParams["openid.ax.required"] = "email";
openid.authenticate.defaultParams["openid.ax.type.email"] = "http://axschema.org/contact/email";

openid.authenticate(
  "http://www.google.com/accounts/o8/id",
  "http://example.com/verify",
  null, false,
  function(url) {
    res.writeHead(302, { Location: authUrl });
    res.end();
  }
);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Strange Queries&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But even that&amp;#8217;s not quite enough to get it working. That&amp;#8217;s because there are two active releases of Node.js at the moment. They are version v0.2 and v0.3. The latest version (v0.3) does not yet support HTTPS when making client requests (but is apparently being worked on). This means it is impossible to use OpenID to authenticate with Google (and likely others) because Google only provides an HTTPS endpoint for OpenID authentication.&lt;/p&gt;

&lt;p&gt;The older version (v0.2) does include HTTPS support but uses a strange parameter parsing strategy that actually tries to parse parameter names with dots (&amp;#8216;.&amp;#8217;) to create a containment hierarchy. This strategy sounds nice on paper, but causes lots of problems when clients send requests that use dots but don&amp;#8217;t conform to the rules, as is the case with OpenID. While you&amp;#8217;d expect the parser to silently fail or ignore the bad parameters&amp;#8212;instead it throws an exception and the request dies making it impossible to even work around.&lt;/p&gt;

&lt;p&gt;For example, in Node.js v0.2 requests that look like this will always fail:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;openid.ns=foo&amp;amp;openid.ns.ext1=bar
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So I submitted &lt;a href="https://gist.github.com/775210"&gt;this patch&lt;/a&gt; which simply prevents the exception from occurring and puts the offending parameters in a special variable called __str__. Unfortunately, since v0.2 is on its way out, the &lt;a href="http://groups.google.com/group/nodejs-dev"&gt;nodejs-dev&lt;/a&gt; guys won&amp;#8217;t be including this patch, so you&amp;#8217;ll have to patch manually. In any case, with the patch applied, the query string above will result in this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{"openid":{"ns":{"__str__":"foo","ext1":"bar"}}} 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And that&amp;#8217;s about it. Break over. Time to code again.&lt;/p&gt;</description><link>http://bitdrift.com/post/2844831736</link><guid>http://bitdrift.com/post/2844831736</guid><pubDate>Thu, 20 Jan 2011 11:17:59 -0800</pubDate><category>node.js</category><category>openid</category><category>node-openid</category><category>google</category></item><item><title>I now own this.  I am a dork. (Taken with instagram)</title><description>&lt;img src="http://24.media.tumblr.com/tumblr_lf8g1uxCiq1qdg04ro1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;I now own this.  I am a dork. (Taken with &lt;a href="http://instagr.am"&gt;instagram&lt;/a&gt;)&lt;/p&gt;</description><link>http://bitdrift.com/post/2814157007</link><guid>http://bitdrift.com/post/2814157007</guid><pubDate>Tue, 18 Jan 2011 11:13:08 -0800</pubDate></item><item><title>Ice is nice (Taken with instagram)</title><description>&lt;img src="http://25.media.tumblr.com/tumblr_lf4lvolN2x1qdg04ro1_500.jpg"/&gt;&lt;br/&gt;&lt;br/&gt;&lt;p&gt;Ice is nice (Taken with &lt;a href="http://instagr.am"&gt;instagram&lt;/a&gt;)&lt;/p&gt;</description><link>http://bitdrift.com/post/2779398586</link><guid>http://bitdrift.com/post/2779398586</guid><pubDate>Sun, 16 Jan 2011 09:28:38 -0800</pubDate></item></channel></rss>

