Bootstrapping with Meteor.js
Getting to first revenues with $90 and 18 months of my time
Four years ago I didn’t know the difference between git and Github. Eighteen months ago I was at best a front-end hack (note the missing “er”). Last week our startup, Kyn, brought in its first revenues in the form of a $1,000 check. What follows is a quasi-technical discussion of how I went from a morsel of an idea and limited html/css/jQuery skills to generating first revenues with an MVP written using Meteor.
- If you’re a rapid prototyping fan and miss the Rails of 2005, Meteor just might be your new BFF.
- If you’re a designer with html/css/jQuery familiarity and want to move beyond static sites, Meteor just might be your BFF.
- If you want to focus on validating assumptions rather than recruiting a unicorn technical co-founder, Meteor just might be your new BFF.
Context: What is Kyn, today?
The Problem: The charitable world is woefully inefficient.
The Mission: Democratize philanthropy.
The Opportunity: $30 trillion will change generational hands over the next 40 years. Every service provider in the wealth advisory industry from the for-profit side (wealth managers) to the non-profit side (philanthropy advisors) is freaking out because their dying clients (their words) don’t require any digital tools, but the next generation does. Kyn provides those tools.
The idea starts with a problem
Disclaimer: While I’m a huge fan of agile and lean startup methodologies, I’m not a purist in either. With my solo projects I mash up bits from each and in the process bastardize them both. So if something in this discussion doesn’t follow proper Agile or Lean Startup principles, you’re right. It’s my own flavor.
The core problem I started with was the same as it is today: the charitable world is woefully inefficient. I spent a few weeks dissecting the problem from a few different angles, did some quick secondary research to create a few user stories (as a ___ I want ___ so that ___), and then “got out of the office” to begin the customer discovery journey. I told myself on this next startup I’d spend at least three months talking to people before opening up Sublime Text. I was an industry outsider and had much to soak up.
Jumping ahead a bit, I quickly realized that the context I was operating in was essentially a three-sided marketplace. For those of you familiar with building marketplaces, there’s a huge chicken and egg problem to overcome. Two-sided marketplaces are hard to pull off, so I knew I had my work cut out for me. At this point I had already sold everything I owned, moved in with my dad, and got personal expenses down to in-it-for-the-long-haul levels ($1,500/mo), so my financial runway was decent. I was all-in. Gulp.
Assumption One — No code required
For you lean startup fans, our major assumptions roughly correlated to each of the three sides of the marketplace. Within each side, we needed to figure out how to engage that particular side, which market segment/user profile to go to market with, and what utility/feature/app they were asking for, even if they weren’t asking for it.
Our first assumption was focused on the “grant-seeker” side of the marketplace…the nonprofits. This was the easiest assumption to validate. No mockups, no code, just a bunch of coffees, Hangouts, and phone conversations. The response was unanimous: if I could get the donors in the marketplace, the nonprofits would follow.
Assumption Two — the HTML Email
The second assumption was a bit trickier. In my experience you can’t always rely on direct feedback no matter how good you are at asking the right questions. For this one I needed metrics. I needed some html. Time to open up Sublime Text.
I crafted an HTML email with a single call-to-action and sent it to a number of people representing various user segments in the second side of the marketplace. At this point it was clear my true customer was actually the third side of the marketplace (not the second), and all I needed from the second side was some data from them. I’d use that data to build a knowledge-bank, and we would in turn use that knowledge bank to build tools to engage the third side.
The email call-to-action represented the second side’s willingness to share the data in question. A clicked button = a validated engagement assumption.
I used Mozilla Thunderbird to send the HTML emails manually. These were largely cold emails and I wanted to include a personalized intro to each specific recipient. Thunderbird allows you to do that easily.
The result of the initial email experiment: an overwhelming majority clicked the call-to-action, and an overwhelming majority of them actually went back to my email to respond directly with additional, positive feedback. With this quantitative and qualitative validation, I was confident I knew how to engage the second side of the marketplace.
Next Stop: Jekyll
At this point I was creating quite a bit of content as each email was personalized (e.g. they included a nonprofit name, image, description, etc). It was time to create a template to speed up the content creation process and figure out how best to expand the landing page into a multi-page engagement process that we could start testing. This engagement sequence was largely targeting the third side of the marketplace.
My gut told me this third side was the make-or-break side of the marketplace, and thus, the most important to validate. For those of you that speak VC, this third side was the one seeking a pain killer not a vitamin.
Focusing on UI and UX
I had recently moved a personal site over to Jekyll (thanks for the free hosting Github!) so I decided Jekyll was likely the path of least resistance (and did I mention free?). I had never actually written any true programming logic in the past, just static html/css/jQuery, so the built-in Liquid templating engine was an additional plus. I would soon write my first bit of logic…a simple ‘for’ loop.
Like many before me, I hacked the /posts feature in Jekyll to serve as a mock database. This allowed me to focus on the messaging and the workflow of the new landing pages. Ain’t no rake db:migrate to deal with in these parts!
For anyone that calls UI or UX their domain but has never written server-side code nor dabbled with a database-driven site, Jekyll was a great gateway drug for me. There are loads of Jekyll boilerplate templates out there to get you started, and with Github for Mac you have no excuse for not following a proper development workflow so that any experienced developer/frientor can jump in immediately and contribute.
Time to move on
The Jekyll hackery worked decently for awhile, but even with all the 3rd party analytics tools I couldn’t really get the granular user-level activity data I needed. Further, I was overusing jQuery to fake a dynamic site and creating a poor user experience in the process. It became increasing clear I was outgrowing Jekyll.
Well hello, Meteor
Meteor’s tech stack: Meteor
Our tech stack for the Rails app was Rails > MySql > AWS/EC2 > Nginx. I didn’t feel all that comfortable anywhere in that stack. With Meteor, this gets simplified down to: Meteor. Yes, that’s only one word. The database is essentially built-in as is the web server, and the icing on the cake was that hosting is free as well (I’ve still only spent $10 total at this point on Kyn).
Community — OMG how cool are these people
Another HUGE draw of Meteor was its incredibly active community. Sure it was the new hotness and all, but it was clear the community members weren’t there just to check out a new fad. You’ll find amazingly helpful folks all over the Internets, be it StackOverflow, the meteor-talk Google group, and IRC if that’s your thing.
Quick test app
Before I finalized the decision to build in Meteor, I wanted to kick the tires a bit. Rather than building an app by following a tutorial in one of the many great beginner resources available, I decided to simply fork an existing project and start morphing it to something I’d find useful. On a summer Sunday and subsequent Monday morning coffee shop session, I built a basic CRUD app and could both pull and send data to a 3rd party API (Github source | demo ). Most importantly, I was comfortable that Meteor was approachable and the right framework to build out the Kyn MVP.
Meteor it is — Time to build
The data model
So Meteor it is. But where to start? The logical first step was moving the view templates over, but having run product teams using MVC frameworks in the past, I knew the importance of fleshing out the data model first. Problem was, from a technical perspective, I was primarily a front-end guy. I had no idea where to start even thinking about a data model.
“I” becomes “we”
Kyn was a solo venture at this point. I prefer to work with others (startups are hard and nearly impossible to pull off on your own), but anyone I’d consider for a co-founder role (i.e. someone I trusted and worked well with) was either busy with family, had just taken a sweet role at [insert well-funded startup here], or was otherwise unavailable. I knew I still had some de-risking to do, and that came in the form of validating one if not both of the remaining assumptions. My focus would be there instead of recruiting a technical co-founder.
Developers should get paid for their time, and since I didn’t have any money, we figured out an equity deal and a limited time commitment. He’d mainly focus on reviewing my code, serving as a technical mentor, and if time permitted, jumping on Nitrous to do a little pair programming to help me through the occasional code problem. I treated him like a full co-founder, sharing how I developed the go-to-market strategy, how I crafted my invite emails, how I thought about the roadmap, how I segmented the market, and every other business/hustle aspect. I knew I was going to learn a ton from him from a technical perspective, and I wanted to make sure I was sharing the 17 years of experience I had built up on the business side. Win win.
Repo access granted, Slack rooms set up, and Jenkins wired in. Time to get to work.
Sample code — Teach a man to fish
We kicked it off with a great discussion around the data model and he offered to set up the Meteor file structure, transfer over the view templates, and write a few of the first database queries to get me going in the right direction.
Rather than creating a full CRUD app, my colleague, being the smart lean startuper he is, realized our MVP really only needed the ‘R’ (Read) to validate our next assumption. The ‘C’ (Create) would be handled manually for the time being, leveraging the Meteor.startup feature to seed the db from JSON (see images below). In the case we did actually need a proper “Create” form we could leverage a 3rd party admin tool, Houston, to create additional records more quickly than hand-coding in JSON. His read-only approach saved us from unnecessarily creating a bunch of input forms (that may ultimately be scrapped) as well as dodging the security complexity that goes along with creating such user-submitted forms.
Here’s the general code structure with v0.1 (see if you can deduce which code was mine and which was my mentor’s):
I can’t express how amazingly beneficial this step was. I conceptually understood Meteor’s publish/subscribe model, but actually implementing it from scratch was another thing. I probably could have pulled it off on my own by leveraging one of the many sample apps available and the Meteor community, but at the cost of valuable time. With the foundational code in the repo, I was now armed with the building blocks for an app I could tweak to my heart’s content. Best yet, I had a technical mentor to pick me up when I stumbled.
NoSQL — well aren’t you refreshing
I spent the next few months building, soliciting feedback, iterating, rinse, repeat. As the code base grew the data model did as well. At times I struggled with this. Should I make a new collection? Should I start looking into the publish-with-relations package and reactive joins? But each time I started going down this rat hole I’d remember what another of my technical advisors said: “You’re not trying to optimize for 1m concurrent users. You’re optimizing for the right first one or two”.
The great thing about NoSQL, I would discover, is that if you’re ever in doubt with what to do with a new data field, just insert a new document. Though we do have three collections currently, for the longest time we had a single, albeit decently large collection…and nary a user noticed. Optimize for the right first one or two.
I’ll be the first to admit I’m a Meteor fanboy. It was, and continues to be, the right tool for the job. But it’s not all puppies and sunshine, so let’s take a moment to discuss some of its shortcomings I noticed along the way.
Alpha — syntax is here today, changed tomorrow
Meteor is still in alpha (currently 0.8.3 as of this writing), so I knew going with Meteor meant having to be flexible and patient as new releases came out. Stuff was going to break, and it did. Syntax would change with major releases prompting the need for reactive editing before updating. Further, big portions of my app are dependent on third party packages, and while most of these package maintainers are quick to update, a few have lagged. Nothing insurmountable, but something to keep in mind. Thankfully, they are closing in on v1.0.
Meteor vs. Rails — it’s a numbers game
I now have a number of amazing mentors and technologists on my technical advisory board. Three of the four are advanced-to-expert-level Rubyists. Thus, I have three Rubyists that would be more than happy to bang out a few lines of code for me (give a man a fish). The bulk of my advisors don’t know “the Meteor way” so I don’t really have a resource to just bang out some code for me. And trust me, there were many times I wished someone would just show me the code. In the end though, grinding through some of these problems on my own with the help of the amazing Meteor community will absolutely make me a better web builder in the end.
No SSL (picky picky)
Meteor offers free hosting and they do allow custom domains. Totally f’n awesome. But, I needed to accept online payments and the only way I could have done that using Stripe and Meteor was to purchase an SSL cert and start paying a PaaS for hosting. Being the cheapskate I am, I opted to create a Sinatra app and host it on Heroku for free. As long as you don’t want a custom domain, Heroku is SSL enabled by default.
Stripe has a play-by-play tutorial for doing so for those interested in going this route. It’s a bit wonky to send someone to a URL containing ‘herokuapp.com’, but beggars can’t be choosers.
About eight weeks ago I realized I was doing a good job building, but what I really needed was to get out of Sublime Text and double down on the hustle side of the table. In this process (and with a little bit of dumb luck on the timing front), I came across a partner that loved what we were building and wanted to help us get it out of the garage. They sent a check for $1k.
I wish I had a nanny-cam to film the 15 minutes following my receipt of the email notifying me of the contribution. I was first and foremost humbled to have such an Awesome partner on my team now. I was also ecstatic to finally get out of the proverbial garage and relieved that all the conversations, iterations, commits and self-questioning over the prior eighteen months were indeed on the right track to helping make the world a better place. Relief. Elation.
With the $1k in house, we’ll be purchasing a wildcard SSL cert and moving off Meteor’s free hosting. We need to start developing our user/accounts model and thus will be sending sensitive information over the wire. There’s no way we’d do this without SSL in place. Plus, we can finally move Stripe to Meteor and our own domain. It’s time to put the big boy pants on.
In addition to the 18 months of my time, the direct expenditures were as follows:
- Old domain + renewal (getkyn.com): $20
- New domain (kyn.me): $10
- Google Apps: $5/mo x 8 mo = $40
- Landing page image = $20
- TOTAL: $90
We do use a number of online services, but all are no additional cost to us. I use my personal Github account (been a paying customer for four years now), Slack gave us a $250 early adopter credit, we now use Codeship instead of Jenkins and are on their free 100-builds-a-month plan, and our kanban/PM tool (Waffle) is currently free during beta.
So have we outgrown Meteor?
The short answer is no. We still have a lot of work to do to validate our last assumption, and thus, a lot of iterating on the current prototype. We see no reason to change frameworks now.
Our core asset is the Giving Graph we’re creating, so we’ll continue to flirt with non-MongoDB solutions. Neo4j seems to be gaining traction in the graph database world and I’m pleased to see some work being done to integrate it with Meteor. That said, the change to a new framework and/or new database will hopefully never be mine to make…it’ll be the sole responsibility of whomever eventually becomes Kyn’s Head of Technology ☺
There are lots of ways to launch a web app these days. Some use cash to hire a team. Others go to coder school and learn enough to get to MVP. I decided to surround myself with a group of amazing technologists and see if I couldn’t write most of the code myself.
Regardless of your method of getting there, there is absolutely no better feeling than someone in the world writing you a check to continue building what you’re building. So go forth…code...launch!
Get in touch: I’ve glossed over a number of details. I’m an open book, so if you’d like to dive deeper into the details of anything in this post I’m happy to share. My favorite mentors always give experience, not advice, so if my experience can help inform a decision you’re about to make on your own journey I’m glad to share. My email is chad at kyn dot me.