Skip to content

Up all night… again.

As Saturday night becomes early Sunday morning, I find myself frantically tying up loose ends in order to prepare for the “UI integration” phase of KitchenPC, which marks the final coding phase before the private beta release.  I spent the evening tracking down resolutions to a few of those elusive bugs that I’ve been putting off for far too long now.  The ones of interest are:

HTML special codes were being double-escaped

This seems like it should be easy to fix, but for HTML purification, I was using an open-source project called AntiSamy.  When I started, this project was the only one I could find that was a viable white-list approach to purifying HTML and preventing XSS attacks.  There was a few major features missing (like validation of inline CSS styles,) but I was able to construct the input HTML using TinyMCE to not rely on those features.  However, for some reason certain HTML character codes would get escaped, regardless of what the allow-list said.  HTML text that included   would be allowed, but anything else, such as → would get turned into the super annoying →.  WTH?  After putting this off long enough, I decided to track down the issue but instead found the entire project is now pretty much abandoned.  Before I could dig up the source and try to fix this myself, I ran across the recently updated Microsoft AntiXSS Library.  This library, previously part of the Exchange Server SDK (which would actually reference Exchange Server DLLs that I don’t have!), was since released as an open-source, free-to-use library for sanitizing HTML and HTML fragments.  It took all of about 5 minutes to switch my code over, and it works absolutely beautifully!  The one problem was that I had to go through several dozen existing recipes and clean them up by hand.

Archive support for recipes

Now that anyone can edit any recipe, I got scared and decided I should probably archive recipe versions.  Luckily, this was a pretty easy feature to implement.  It required a new table with a recipe id and a text field.  Every time a recipe is updated, I serialize the old version of the recipe as text and stick it in the table.  This will eventually lead to an ability to see old versions of the recipe, highlight differences, and roll back to previous versions similar to most Wiki software out there.  For now, it’s just a safeguard so that I will have some way (albeit hacky) to restore recipes that get corrupted due to accidental user interference or malicious play.  This feature makes me feel a bit better about allowing users to edit any recipe they wish.

Fixed invalid conversion data in database

This one has been annoying me for quite some time.  Sometimes when the user created a shopping list from a recipe, the web service would throw an exception as the form the ingredient was used in could not be converted into the form it’s purchased in.  There was really no good way to enforce this integrity through database schema design, so these errors had to be tracked down manually.  Fortunately, I found a good way to find them all at once, and keep the database clean.  For recipe modeling, I keep certain recipe and ingredient “relationships” in memory in a giant graph.  This graph stores ingredients in their purchased form, but reads every recipe usage up front when the site app loads.  I’ve modified this code to log an error if it runs into any conversion problems.  The code it calls is basically the same code path as adding a recipe to the shopping list.  Furthermore, I’ve been doing performance tests on a database with 10,000 “randomized” recipes.  These tests have exposed invalid conversion data on ingredients that were not even being used on the production DB.  I’ve managed to track these all down and fix them, so there shouldn’t be any such annoying bugs for beta.

Misc bugs that don’t depend on the new UI

I’ve also fixed a few smaller bugs, made some KitchenPC Mobile improvements, and a few finishing touches here and there.  The bugs I have left (and there’s only 6 of them at this point) all will have to wait until the new UI integration.  They are all marked as “Minor” bugs.

KitchenPC Modeling Engine is done!

This is also huge news.  The modeler is now code-complete and running lightning fast.  Generating a model with 10,000 recipes in the database takes about 2 seconds, and the results are excellent.  The overall algorithm design was pretty basic (I had that working in one night), but the hard part turned out to be how to really “define” success.  Computers will do exactly what you tell them, so it really helps if you know what you want them to do.  A lot of variables come into play here, which assume a knowledge of what the user really wants out of this feature.  For example, would a user prefer to use more of their pantry items if this also meant they had to buy more ingredients at the store?  Or are users incredibly cheap and want to buy as few new things as possible, even if they won’t get complete usage out of all their pantry items.  Someday, I believe the meal planner will have an “Advanced” section to allow the user to control these variables, but for beta I have to make a few assumptions about what the user really wants.  I’m really glad I didn’t end up contracting this work out to someone who doesn’t know or care about my users.

Waiting on the UI

On Friday, my Polish guys surprised me by finishing a day early on the final modifications to the prototypes (which are basically Photoshop mockups of each page.)  I’ve signed off on all these changes, and “cutting” (the process of slicing up the bitmap images into HTML) will begin Monday.  I’m hoping the designers will be able to provide me with HTML as each page is completed, which will allow me to work in parallel with them.  I considered putting up a few “teaser” screen shots of the finalized KitchenPC UI, but decided to unleash the final design in all its glory when it goes online.

Final steps

I expect the UI integration to take a week or two, and there will no-doubt be a few last minute bugs to address.  However, the next big step is going to be deciding on a place for KitchenPC to live.  I’m still bouncing back between Amazon EC2 and Rackspace CloudServers, but in reality if I don’t like my decision, I can always move later (it’s just a beta.)

I’d love to say the hard part is over, and it kind of is; getting a product you’re proud of up on the Internet is a huge step, and I really think people are going to enjoy what I’ve created.  I think it will be by far the best meal planning tool available on the Internet (Sorry Monki boy,) and the meal modeling features are just something that hasn’t been done before.  I can’t think of anything I should have done differently or any major regrets with the overall design of the product.  It’s simply going to rock!  I’m more proud of this than any product I worked on at Microsoft during my 12 year career there.

After KitchenPC goes live online, I’ll begin shifting my focus to the business side of things.  This is foreign territory to me, but hugely exciting.  The first step, of course, is to actually find 1,000 beta users.  Rather than just picking 1,000 people off the streets of the Internet, I’d like to do something a bit more intelligent and find a way to target my 1,000 to people who will really use the product and deliver valuable feedback.  Invites will of course go out to the 280+ people who took the survey, and I’ll probably give anyone who asks a few invite codes, but I’ll be spending some time over the next week or so figuring out the best approach for finding this beta group.

During the beta, I’ll be looking at usage metrics, studying how the server performs under certain loads, and addressing any performance problems critical to making possible a wider deployment.  These numbers will also give me an idea of costs associated per user, which is a must for any business plan.  Luckily, my site isn’t hugely data intensive so I expect PostgreSQL to quietly yawn as users explore the site.  This will also be my chance to see if I made any hugely wrong assumptions about the product, and consider the need for any major redesign.

I’ll also be trying to get a bit of media attention, perhaps from the likes of TechCrunch or what-not.  Issuing a formal press-release is probably a good idea, though timing is questionable on that one.  This blog will start to take a turn as well.  I’ll be talking more about future business plans for KitchenPC (such as my visions for revenue generation,) and detailing my adventures trying to get the word out.  Stay tuned!

Stress, Party of One?

Lately, the stress of starting a business has really been getting to me.

Combined with the seemingly endless delays and the “to-do” list items that appear to multiply like a pack of bunnies during mating season, I thought I’d take a moment to write a more emotional blog posting.  I worked at Microsoft for over a decade, and during that time, I never really grew beyond the role of a code monkey.  Mind you, I was an awesome code monkey.  I knew the web back when no one thought web applications would catch on, and every new technology and three-letter-acronym came easy to me.  However, part of the reason I quit was because my career just wasn’t progressing to the point where I’d be proud to allow that role to someday define my life.

The other reason I quit was because I wanted to take a risk while I was still a young, single guy.  Staying at Microsoft, I’d always make a pretty decent salary with a small raise most every year, and perhaps a nice fat bonus when I did really well.  The young Microsoft days of stock splits and people buying new Ferraris with their options were long gone.  It was now a blue chip company, the GE of software (as my good friend Ken once pointed out to me.)  I’m sure my contributions to the company made Microsoft millions in revenue, however if the product were to fail, I’d be shielded from that risk.

Starting a business of your own means you might lose your entire life savings, or become a billionaire, or anywhere in between.  That prospect called to me, as I have the utmost faith in the market being fair.  The market will decide if I make millions, or if my product sucks.  Microsoft managers trying to advance their own careers and argue amongst themselves like wild hyenas about who should get promotions don’t even enter into the equation anymore.  Let me rephrase, I’m not sure exactly what goes on in those calibration meetings, but I’m quite sure it’s the kind of jungle savagery that would be worthy of its own reality TV show.

However, I’m finding out the world of startups probably makes those calibration meetings look like an episode of Mr. Rogers.  Here’s some lessons I’ve learned so far, and I’m still at the beginning of this journey.

No one but you really gives a rat’s ass about your company

Sure you may have friends that like to ask how things are going, or tell you what a great idea you have, but when you count on them for help you really can’t expect much.  Take, for example, the algorithm I’m developing to plan meals based on available ingredients.  This is something well out of my comfort zone, but luckily for me, I know several candidates well-suited for this sort of problem solving.  Unfortunately, calling in favors is like pulling teeth from an aligator.  Emails are seldom returned, and everyone is too busy to spend more that a few minutes.  I’m at the point where I’m damaging friendships by even pushing the issue anymore.  In other words, no one is going to do your work for you.  Okay, well what about paying them?  I tried hiring two coders from other countries, and neither of those came through.  I don’t have the money to hire a real software engineer full time at this point.  In the end, I had to just step up and tackle the problem myself.  This was less than ideal since I have so many other things to worry about these days.  I’ve moved “sleeping” to the “would be nice” priority.

You are not your own typical user, I don’t care what you say

Though I did start this company to address my own interests in meal planning and recipe management, I have absolutely no inkling of an idea on how the product is really going to be used.  The most valuable lesson I learned here is that the typical customer has absolutely no understanding of your vision.  KitchenPC is not a recipe database, that would be boring to make.  The power of KitchenPC relies on an extremely high level of data integrity within recipes.  Ingredients must be expressed accurately, contain realistic metadata on forms and conversion ratios, and result in accurate shopping lists.  The meal planner relies on these conversions to generate results as well.  However, I’ve learned recently this makes sense pretty much only to me.  Out of the three people I hired on GetACoder.com to enter recipes, only one is actually doing any work.  The other two dropped off the face of the planet right after I accepted their bid.  Looking at the recipes being entered, it’s apparent that data quality is going to be one of the, if not the, top challenge to overcome before I can realize my vision.  For example, authors of recipes don’t really care about representing the recipe in a way where the backend engine can make sense of it.  As long as it looks understandable to humans on the screen, they’re happy.  For this reason, I see ingredients hacked up to overcome ingredient database deficiencies.  Most often, the prep note (which is intended to describe a preparation action to be taken against the ingredient,) is used to clarify the meaning of the ingredient itself.  I even found one recipe that called for “Hamburgers: 1” and the prep note was “Hamburger buns”.  Well how the hell am I going to generate a shopping list if the database doesn’t even know the recipe requires hamburger buns?  Magic?  Am I coding this site in Magic#?  Apparently, in an ideal world, I’d have an army of OCD recipe enterers who have an intricate understanding of the inner workings of KitchenPC and have a burning desire to craft each recipe to perfection.  In reality, I’ll probably have thousands of junk recipes that don’t make any sense and don’t result in accurate shopping lists or efficient utilization within the meal planner.

Entrepreneurs are clueless

We all think we have a great business vision and it looks great on paper.  However, no matter how much research you do, no matter how many customer studies you do, no matter how much planning you spend, you really have no idea if people are going to like your work until you just get something out there.  Customer driven development is the hot thing now, however I’m still convinced the best strategy is to focus on the basics, get something working up on the web, and see if it goes anywhere.  Any customer research you do (and I’ve done a ton) will always be tainted by your own personal bias.  I really need people to want to do meal planning online, so I’m going to attempt to find data that back up my wish.  Turns out, those data are not hard to find.  However, until I get a basic version of the website online and see users coming back for more, all my customer research is really meaningless.  I think this stage is probably the most frustrating for me anyway, as I still have no idea if there’s any real demand for what I’m doing.  Oh I’m sure I could get a few hundred people to use the site and really love it, but that would only make for a nice part time hobby as I look around for a new job to pay the bills.  As I claimed in my Kitchen Monki article, I’m a lot more afraid that no one has a need for this site than my customers satisfying their meal planning needs through one of my competitors.  I’m a smart guy, I’ll just go build a better product than my competitor.

So what are you doing about all this?

Getting stressed out about the situation is human, with so much on the line, I don’t ever remember a time at Microsoft where I was this stressed, this busy, or had this much of a drive to go after the right customer solutions.  As far as if the product succeeds or not, who cares?  It will or it won’t.  The point is, I’m going to launch my best attempt at KitchenPC and see where it goes.  If the entire thing is a complete swing and a miss, hopefully I’ll know that sooner than later and can move on.  If a few people latch on, then the problem becomes how to attract more of those people.  If a bunch of people sign up and then never come back again, the problem is figuring out what they expected to get out of the site and why they were disappointed.  Having a real product out there is a far better tool for gathering customer feedback than any survey, user group, or cherry picked piece of data; no matter when Steven Blank tells you.

As for data quality, it’s something I’ve been shifting the majority of my focus on to the past few days.  My GetACoder hire has entered about 200 recipes so far, and she’s doing an awesome job.  When she started, my goal was to get recipes into my site.  I thought my site was basically done (minus the non-Polished UI, yes bad pun) and I just needed data.  After a few dozen recipes, it became quite apparent that my current implementation was nowhere close to good.  True, adding the custom ingredients helped a lot, but this only hides the fact that the recipe entering process is flawed and constrained.  To my surprise, the customer behavioral research I’ve acquired over the past few days far outweighs the value of the new recipes in the database.

I’ve done two things to help mitigate this issue, both in the form of new features.  First, the ability to create ingredient sections is a must-have.  Who knew?  Especially in cakes; which ingredients were necessary for the cake and which were necessary for the frosting?  This resulted in very messy recipes, using the same ingredient multiple times in different forms.  The author ended up using the prep note to clarify what component of the recipe the ingredient would be used for, which resulted in strange ingredient listings such as “Eggs: 3 (yolks separated, for the frosting).”  Users can now divide ingredients into sections and have an ingredient list for the cake and another one for the frosting.  This was perhaps the first feature implementation I’ve done based exclusively on watching a real, live user use the product.

The second new feature targets data quality directly.  No one can actually build Wikipedia on their own, an effort that huge has to be crowd sourced.  I feel the biggest threat to KitchenPC data quality will be users who type in bad recipes and don’t maintain them, or then leave the site and never come back, resulting in orphaned recipes.  I’ve taken a new direction with the site, and have decided to make every recipe editable by anyone else.  This is a risky decision, but it makes the site behave more like a Wiki than a recipe database where everyone only owns their own content.  Quality control can now be crowd sourced, and flaws with individual recipes can be corrected by a hopefully more intelligent hive mind.  As far as the actual implementation, users can decide if their recipe will be “publicly editable” or not, which gives me the control to re-evaluate this decision later on, but for the beta version of the site, all recipes will be editable by anyone else.  I’m sure I’ll be spending a lot of time going through recipes and making corrections myself.  I just hope I can find a way to counter malicious Internet ruffians who like to edit a bunch of recipes to include advertisements for their new web cam site.  Oh well, one problem at a time.

I think the main takeaway for other aspiring entrepreneurs is to really focus on the core essence of what your product is.  Don’t try to be everything for everyone, but build something simple and get it out there fast.  Only by doing this can you really test your idea.  I think the Steven Blanks of the world have a valid point with regards to customer driven development and finding out who your customer is first, but these points are much more applicable to a business idea that depends on significant financial backing to even get off the ground.  If KitchenPC took $20 million dollars to build, required a payroll of ten full time employees, and needed dozens of high-end web servers to run even for a month, then you bet your ass customer research would be worth the time and effort.  However, I think for some ideas, just get something up on the web and try to get some people to use it.  Evolve the idea from there, and maybe one day it will reach the point where you can make some money off of it.

The second take-away is starting a business is not for the faint of heart.  Almost nothing goes right, everything is a complete pain, nothing is done on time, and your biggest problems will be things you never even thought of.  Infinite patience and infinite perseverance would definitely come in handy.  However, it’s an up hill battle and you have to ignore the statistics and just enjoy the ride.  If you’re thinking about quitting your job and pursuing some little Internet idea you have, be sure you’re ready for the long haul.  Trust me, it’s not as easy as you think.

So what’s left?

I’ve been getting asked a lot lately, “So when will KitchenPC be done?”  Well, the answer to that question is the subject of a rather protracted conversion.  However, perhaps due to my Project Server background, I’ve decided to organize a simple “To-Do” list outlining what’s left.  There’s of course a few various minor bugs to work out, but here are the three main items left to be tackled before a more public, beta version of the site can go online.

Finalize Site UI

Right now, the alpha version of the site is absolutely atrocious.  I feel sorry for those who’ve volunteered to use the site in its prenatal form, however the main goal of the alpha release was to stabilize the backend platform.  I believe it’s never a good idea to finalize a UI until you really have to, as you never know what features will end up making it into beta.  For example, I started out with a lot more social networking features (subscriptions, user walls, forums, etc) – all these things were dropped (well, postponed) so I could focus on KitchenPC’s core essence as a meal planning tool.  Had I developed flashy UI for those features, a lot of time would have been wasted.  Also, a lot of the graphics and icons for the site were blatantly ripped off of Google image searches or stolen from other sites just to act as place holders.  Right now, I don’t even think I could legally put the site online!

Luckily, my guys from Poland are hard at work on finalizing the front-end design.  What I’ve seen looks completely awesome, and I can’t wait to have the full HTML code delivered.  I estimate this should happen within the next two weeks or so, and I will probably spend about a week integrating their templates in with my existing code base.  Since no features are changing, this is simply swapping out bad HTML with the new, polished Polish HTML.

Recipe Modeling

You’ve heard me talking a lot about this, but it’s mostly all vaporware right now.  Yes, I admit it.  I don’t actually have a meal modeling algorithm.  For those who have no idea what I’m talking about, the meal modeler will provide KitchenPC with the ability to generate a meal plan automatically using the ingredients you have available, while attempting to incorporate your likes and dislikes into the results.  A couple months ago, I hired a guy from Bangladesh to help with this effort.  However, the initial prototype had some serious flaws, and then the project was delayed even further due to a family illness.  At that point, I decided to hire a new guy from China to take over the project.  However, this guy still has yet to deliver anything.  His estimates keep on increasing like a Fibonacci sequence (“I’ll be done in 2 days, no 3, no 5, no 8.”)  I have little hope he’ll end up coming through, and I’ve given him an ultimatum that if he doesn’t deliver on his latest estimate, he’s out.

In the mean time, I’ve decided to take a crack at the algorithm myself.  I developed a basic prototype this week and the results look very promising!  The code is a bit too slow, but I’ve been using Antz Profiler to track down some of the bottlenecks and I have some ideas for improvements.  The results it generates are very realistic and definitely good enough for a 1.0 version.  In any case, I believe I’ll have a working recipe modeling engine by the end of next week.

Data Entry

I’ve come to the conclusion that my site won’t really be taken seriously without at least 10,000 recipes.  For this reason, I’ve posted some jobs on GetACoder.com for data entry people.  The going rate seems to be about 5 or 6 cents per recipe, which means I can fill my database with 10,000 recipes for five or six hundred bucks.  I hired my first two data entry people (both from the US) today, and will hire more as needed.  Having 10,000 recipes online is not a requirement for getting the site online, but it’s something I’ll be managing while working on the first two issues.  Hopefully I can have a few thousand recipes at launch, and keep these guys around for a while entering recipes during beta.

Ok so when can I use it?

Keep in mind the private beta will be open to about 1,000 people, mostly to allow me to “scale up” as needed and test server load and all that stuff.  I don’t want the site totally crashing due to too many users.  However, chances are you can get a beta invite if you know me, or if you’re a fan of the blog, or just ask.  I still have high hopes that I can get a beta out this month.  As for when the site will be “for real” public, this will depend on scalability (I might send out more and more invite codes as I increase capacity) and user feedback during the beta trials.  Hopefully I can get the site launched and open to the public some time this year.  Is that soon enough?

Monki See Monki Do

Recently, I ran across a brand new web site called Kitchen Monki.  This site offers a one-stop shop for meal planning and recipe management, and I have to say at first glance it looks like they are off to a fantastic start.  For meal planning, their grocery list generation really works well and combines ingredients correctly.  As someone who’s implemented this functionality, I have to give them kudos for making this work so well.

It’s pretty apparent that they ran across a lot of the same design challenges as I did.  For example, being able to work with multiple recipes at the same time requires some sort of mechanism to generate temporary lists.  On KitchenPC, I call this the clipboard.  Users can add a bunch of recipes to the clipboard, then work with that clipboard as a whole; create aggregated shopping lists, drag some on to the calendar, etc.  Kitchen Monki implements something similar called the “queue.”  When viewing a recipe, you can enqueue recipes or “de-queue” them.  Both the queue and clipboard are intended to solve the same problem; allow the user to browse the site collecting recipes, then work with that set using the site’s meal planning tools.

They also have a meal calendar.  It only shows a single day at a time, but each day is organized by section (breakfast, lunch, snack, appetizer, dinner and dessert.)  I had considered this approach but decided a more freeform solution might be more popular.  From the meal planner page, you can drag recipes from your queue onto one of the sections.  This seems to be designed for planning a single day at a time, rather than my approach of planning an entire week at once.  Based on my survey, about 65% of people will plan meals days in advance.

Kitchen Monki also agrees with my decision to support custom ingredients.  When typing in an ingredient, it attempts to auto-complete the ingredient for you.  If no matches are found, it displays what you typed with the word “Custom:” in front.  Coincidently, this is nearly identical to how mine works.  Ingredients don’t have different form types, which makes me curious how they aggregate ingredient amounts across forms.  I have a feeling my ingredient aggregation still might be a little bit more accurate, but I’d have to dig in to their site more to find out.  This probably doesn’t matter too much if all the user does is print out a list for the store, but since I have some more advanced meal planning tools lined up, super accurate ingredient aggregation is a higher priority for me.

It’s apparent that Kitchen Monki is more geared towards managing your own collection of recipes, as recipes can be made private or shared only with certain people.  These are features I’ve been considering, but probably won’t be introduced until I find enough user demand.  Right now, all KitchenPC recipes are public.  Kitchen Monki also plays well in the Web 2.0 world, allowing users to share recipes on social networking sites.  They also have solid Facebook integration, allowing users to login with their Facebook account and “Like” a recipe.  The latter feature is something I’ve been meaning to do.

I do really enjoy the branding efforts behind Kitchen Monki.  It’s a bit more playful of a site, using a cartoon monkey clad in a chef’s hat and oven mits.  They carry the simian theme throughout the site, also using bananas to rate recipes.  I think one drawback of the name is the misspelling of monkey.  When talking about the site verbally, you would have to explicitly point out, “Yes check out KitchenMonki.com, that’s monkey with an i at the end.”  However, domain names are hard to come by these days so there’s probably not a lot to be done there.

I also find the user interface a little bit cluttered.  Performing simple actions (such as adding a meal to the calendar or generating a shopping list) takes multiple mouse clicks or spans multiple pages.  Working with the recipe queue is a bit cumbersome, even I have a few ideas on how to get rid of the need for my clipboard.  Hopefully they’ll get their UI ironed out over the next few revisions.  Good UI design is not an easy task.  I think they have the features users want, so long as those users are willing to learn how to use the site.

Though Kitchen Monki is competition, I’m glad I ran across the site.  It shows that other entrepreneurs are thinking about the need for better online meal planning tools, and the success of Kitchen Monki means that there’s a viable market demand for this sort of site.  I would much rather face other competitors in this space than face defeat through complete lack of demand for my site.

One area that I think KitchenPC will stand out over Kitchen Monki is helping cooks maximize their ingredients and minimize waste.  Kitchen Monki has no concept of a pantry, it doesn’t know what ingredients I have and am trying to use, and it doesn’t have the ability to help me generate a meal plan that will focus on using my available ingredients and analyzing my trends and ratings to come up with recipes that I’ll like.  I think these features put me in a slightly different market than Kitchen Monki.  Whereas Kitchen Monki is more of a data management tool for organizing your recipes (the author equates himself to the “iTunes of recipes”,) KitchenPC is more of a meal planning tool designed to help you figure out what to cook.  This means the recipe management tools of KitchenPC will not be as well developed because, well, that’s not my goal.  It also means the meal planning tools of Kitchen Monki will not be as well developed because, well, that’s not their goal.

It’ll be interesting to see where Kitchen Monki goes, I wish them tons of success.

KitchenPC Goes Mobile!

Over the weekend, I created a very basic mobile version of the website.  It was interesting thinking about what exactly a mobile site would need to offer, as the user scenarios are a little different from someone using the site on a desktop computer.  Obviously, achieving feature parity with the full site would be both massively time consuming and completely unnecessary.  I decided to jot down some quick notes about what I think people are looking for from a mobile version of KitchenPC.

Shopping Lists

This is an obvious one.  Users might use KitchenPC to track their shopping lists, similar to using a magnetic white board on the fridge.  The ability to quickly access their shopping list from a mobile phone while at the grocery store could be a huge benefit.  This was one of the high priority features for KitchenPC Mobile.

Pantry

This one was less obvious, but I could see it come in handy for the user who was obsessed with storing their inventory in KitchenPC.  How often have you asked yourself “Hmm, do I have any cumin?” while at the grocery store.  Now, I think the user who would actually maintain a personal pantry in KitchenPC would be rare, but the ability to access a user defined pantry might come in handy for other reasons.  Users might use this feature to track perishable items that they’re trying to get rid of, and use it as more of a “to use” list rather than a full inventory.  Either way, it needs to be accessible from the mobile site.

Cookbook

Providing access to the user’s cookbook is pretty important, though it also mandates the need to build a mobile version of the recipe viewer.  However, this is no problem.  I can see a few uses for this feature.  For example, while at the grocery store, users might find themselves with a craving for a certain salmon recipe but not remember all the ingredients.  Likewise, perhaps at a pot luck someone might ask you how you made that fantastic fruit salad.  You could quickly pull up the recipe on your phone.  Providing quick access to the cookbook (for those of you who don’t know, the cookbook is basically analogous to the user’s favorite recipes or “bookmarks”) could come in handy.

Calendar

I’d rate calendar access as a lower priority, but I decided to add this in anyway.  The big scenario I can think of is if you forgot to generate a shopping list with your upcoming meal plan before heading to the store.  Perhaps you have a big dinner planned for this weekend and use your calendar to track the dishes you’ll be making.

Recipe Search

Though most recipe searching would be done on the main site, I just didn’t feel the mobile site would be complete without the ability to search the database for recipes.  My search options are not as “advanced” as the main site, for example you can only filter by one tag at a time and there’s no ingredient filter, but it’s better than nothing.  The most common scenario would be the user who wants to find a recipe that they hadn’t added to their cookbook.

Recipe Viewer

The recipe viewer is a dumbed down version of the one on the full site, but it provides the basics.  You can see each ingredient (which are also hyperlinks to search for other recipes with that ingredient), the method, prep time, cook time, servings, average rating, author and tags.  The latter two also provide hyperlinks to search for other recipes with those properties.  The recipe viewer allows you to quickly generate a shopping list for the recipe, add it to your cookbook, rate the recipe, and see comments on the recipe.  There’s no ability to create a new comment, but that might be something I implement down the road.

What’s missing?

The mobile site is really designed with a read-only approach in mind.  It’s intended for users who want to check information, not contribute data to the site.  There’s no ability to create new recipes or edit recipes.  You also don’t have much control over your shopping list, cookbook or pantry.  You can create a new shopping list from a recipe, but not edit or remove individual items.  There’s no ability to remove an item from your cookbook.  The calendar is also read only, and there’s no way to add a recipe to your calendar.  More advanced calendar features (such as generating a shopping list from a calendar range) are a super high priority, I just wasn’t able to get to them in the first round.  I’ll probably depend on direct user feedback to influence my decisions on what to implement next, and what features need to be thought out more.

However, I think this is a pretty good first attempt at a mobile site and it only took me about a day to create.  Furthermore, I think this site will act as somewhat of a feature spec when designing mobile apps, such as those for the iPhone, Android and Windows Mobile platforms.

Power vs Usability: Part II

As a follow-up to my recent post titled “Power vs Usability: The Never Ending War“, I thought I’d write a bit about the changes that I’ve implemented recently to address the issues discussed.  It’s fairly easy to agree that the “Do Nothing Approach” just won’t cut it.  There will of course be missing ingredients, and there will of course be users inconvenienced by this fact.  I can’t expect these users to happily report these problems, as they’re more likely to just close their browsers.  In the Dot-Com-Startup world, you really have one chance to wow your customer and keep them coming back for more, and a user who types in half a recipe and then can’t find “plum marmelade” will not be wowed (except for “wow, this sucks”) and will definitely not be coming back for more.

The “Oh, Did We Mess Up?” approach is not all that much better.  As mentioned, it doesn’t actually solve the user’s problem, it simply presents a bug-reporting form that turns users into testers, and assumes they have some sort of active interest in making my site better.  It still presents the deal-breaker scenario where a user enters half a recipe and cannot save it.  It’s this scenario that I’ve determined is the critical issue to resolve.

Redesigning my database to allow recipes to reference non-existant ingredients or ingredient forms was also a design change that I found highly discouraging.  It’s a lot of code and a lot of design changes that target a hopefully seldom used scenario, and these changes ripple through most of the product (shopping lists, meal planning, displaying data throughout the site, etc.)  The approach I found best was one that was isolated to recipe entry and had little or no changes anywhere else within the product, which meant no database changes.

Over the past three days, I’ve implemented a design that I feel acknowledges the root pain point while not warranting a major design overhaul for the entire site.  This solution allows for recipe entry using custom ingredients or custom forms, however stores these recipes in “limbo” until the database can be updated to represent them correctly.  The user can enter their recipe as they see fit, however a process will take place on the backend to manually approve this recipe before it will actually exist in the database.  The process goes something like this:

  1. User enters a recipe requiring “plum marmelade”, which does not exist in the database.
  2. When typing in this ingredient, KitchenPC will see no exact matches exist and display an option at the bottom of the dropdown titled “Custom: plum marmelade”.
  3. The user selects this, and the rest of the ingredient input switches to a freeform mode, where the user can type in any amount and any unit.
  4. When the user is finished with their recipe entry, they click Save.
  5. On the backend, KitchenPC detects the custom ingredient usage and aborts the normal saving code path.  Instead, the Recipe object is serialized and added to the “PendingRecipes” table.  A message is displayed to the user to indicate this.
  6. Later on, this “pending recipe” will be processed through human intervention.  Either “plum marmelade” will be added to the ingredients table and the recipe will be linked to the newly created ingredient, or if the ingredient indeed existed and the user was in error, the recipe will be corrected.  After the links are fixed up, the recipe will be published as normal under the user’s context.

The mechanism also allows the modification of an existing recipe to use a custom ingredient in the same way.  The altered recipe will be serialized with its existing recipe id, and added to the pending recipe queue.

In the case of a missing form of an existing ingredient (for example, say “goat cheese” was missing the “by slice” form), the user can now choose a “Custom” option in the forms dropdown and type any amount they’d like.  When this happens, the recipe once again goes through the pending recipe queue before being published.

This overall approach has a few advantages.  First and foremost, the user is not prevented from entering their recipe.  The fact that the recipe will not appear right away simply acts as a deterrent for users to use custom ingredients or forms where it’s not actually necessary.  In fact, the UI for using custom ingredients was purposely made harder to use.  There is no shortcut key for selecting a custom ingredient, the user must tab to it or select it with the mouse.  This is in contrast to existing ingredients, which have numbered shortcut keys.

The second advantage is this defines a workflow for reporting missing ingredients and improving the database.  The user doesn’t have to click on a special button to “report a missing ingredient”, they simply use the ingredient in their recipe and the database will be improved as a result.  There may come a time where custom ingredients and forms are a thing of the past and the database has pretty much any consumable food product known to man, but for now, this provides a viable approach for dealing with missing data.

I don’t yet have any backend tools for easily dealing with the pending recipes, however I imagine this is something I’ll be able to get to before beta.  This might be a web based “admin” tool that only I have access to, or even a simple command line tool that can be run on any machine with access to the database.

I’m pretty happy with the solution and am glad I took the time to really deal with this problem from the user’s point of view.  I think the site will be overall better for it, and it just goes to show that it doesn’t matter how perfect your architecture is; if you annoy the user, they’ll be going elsewhere.

This Iced Tea is Tea-Riffic!

I really dig Tazo Iced Tea, especially the “Giant Peach” flavor.  It’s made with real (organically grown) cane sugar, tastes great, and I can pronounce all the ingredients on the bottle.  However, I find it surprisingly difficult to find this stuff.  The QFC located near-by my house is where I frequent for my grocery shopping needs.  After discovering I liked this tea so much, the next time I came back I bought all three bottles on the shelf.  Weeks passed, and the inventory was never replenished.  In fact, they were using the slot labled “TAZO GNT PCH” for another brand of tea, which remained untouched by customers for quite some time (I’m O.C.D. so I notice and remember exact product configurations on a shelf.)  Several weeks later, they got five more bottles in.  I immediately bought all five.  Well over a month passed, and the slot remained empty, with other products being replenished.  After quite some time, they finally got more in and I promptly deprived them of their inventory in full once more.  However, the last time I stopped by this QFC, they got a brand new shipment in and this time it was two whole slots dedicated to Tazo Giant Peach iced tea as far back as the eye could see.  More than I could possibly fit in my basket!

I’d like to think QFC was looking at historical trends of customer behavior and I tilted the results to warrant larger Tazo Iced Tea orders.  Either way, this is a fantastic example of converting customer metrics into usable data to maximize profits.  Lesser used features should be cast aside to make way for those with proven customer use.  I write this post as I sip on an ice cold Tazo Giant Peach tea.

Power vs Usability: The Never Ending War

Sometimes there exists a disconnect between usability and power, and visions of flawless code design don’t bode well for actual human interaction.  I talked a bit about this concept in my article, “We all want to be normal[ized].”  The idea in this article was that KitchenPC is predicated on the concept of ingredient normalization.  Rather than each recipe containing its own ingredient data, recipes point to a finite set of available ingredients.  These two approaches are at war with each other, as both cannot be achieved simultaneously, and each has its own strengths and weaknesses.  Ingredient normalization has some incredibly powerful advantages, for example the ability to accurately represent relationships between recipes that use a common ingredient.  It’s this ability that KitchenPC takes advantage of to deliver features such as ingredient aggregation and conversions across forms.  It’s this ability that makes possible ingredient blacklisting, trend analysis on favorite ingredients, and recipe modeling.  However, this design comes at a huge disadvantage in terms of usability.

A database design that allowed users to enter any ingredient they want (as most recipe websites employ) would allow for incredibly simple recipe entry; simply type stuff.  We could even have a simple auto-complete mechanism that would guess what the user is typing, but not limit the user to a set of finite choices.  Not limiting the user to a certain form of ingredient (such as cheese must always be in weight, shredded, melted, or diced) adds the flexibility required to easily import recipes from other sources, such as many of the popular recipe aggregators out there that simply link to other recipe websites.

Until recently, I’ve been fine with my “power over usability” approach, since to my knowledge no one has really done this before and I wanted to try to do it right and gain some competitive advantages.  Plus, the entire business plan depends on this approach, and changing it would basically send me back to the early stages of the drawing board.

As of lately, my mind has been hijacked by Polish designers pressing me on usability issues and thus liberating the right side of my brain to stand up for the people.  It’s become apparent that I might have to step up and be the long-awaited “coding diplomat” and attempt to divise a strategy that can offer a middle ground between these two waring factions.

Right now, I can think of three possible avenues to explore.

The Do Nothing Approach

Ooo, I like the sound of that.  Doing nothing is easy, and makes me want to go take a nap.  Or perhaps go watch “Burn Notice.”  The idea here is that my design is fine the way it is, and though it can cause headaches in the short term, eventually the data necessary will exist and problems will be rare.  After, say, ten thousand recipes are entered and missing ingredients or forms are noticed and corrected, the idea of a custom ingredient or form would almost be completely unnecessary.  After all, a very small percentage of users even ever enter a recipe on a recipe website, so this feature should take a back seat to the potential awesomeness of the rest of the site.

Furthermore, these headaches are expected during a beta period of any product, and early adopters are used to running into a few hassles here and there.  I fully expected to spend a lot of time entering in recipes, and am even considering outsourcing this data entry to anyone who could use the work.  Part of this effort will result in the completion of a deadly accurate and finely tuned ingredient database that will address the needs of 99.9% of users entering recipes in the future.

The “Oh, Did We Mess Up?” Approach

This approach requires doing the minimal work to feign interest in the user’s dilemma, but not really solving their problem.  One implementation of this approach would be to put a small link in the ingredient picker that says “Cannot find an ingredient?  Click here”.  The link would result in some sort of reporting form the user could fill out to let us know that something is missing.  After submitting the form, the user would be promised the ingredient would be added to the database within 24 hours.  I’d have a team of some sort of trained circus monkeys responding to these reports around the clock (ok, it would probably be me doing that.)

This approach is a bit more friendly, and acknowledges that our database is not perfect and we are striving to fix that.  It’s a bit of a turn-off to the user as they may have entered half a recipe and now have to wait a day to complete their work, most likely having to start all over again at that point.  However, the details in implementing such a system are minimal and don’t affect any existing architecture.

The Hybrid Database Approach

This approach truly admits defeat by requiring me to rip apart half my database schema and invent the concept of a custom ingredient.  Since data integrity is crucial to my database design (and one of the strengths of PostgreSQL at that), the idea of a recipe ingredient usage that doesn’t point to an ingredient entity makes me cringe.  Being able to represent an ingredient usage against a non-existant ingredient would be hacky at best, and the very need for this design means admitting the impossibility of an accurate ingredient database, ever.  However, it’s an option to consider as it potentially could result in an awesome usability experience.  One approach is to link such recipe ingredient usages to a “Custom” ingredient entity that would be in the database, but hidden from any UI.  The ingredient usage row in the database would contain an optional field for the custom ingredient name as entered by the user.  When a recipe is displayed with this ingredient usage, the code would be special cased to display the user entered ingredient name.

With this approach, I would have the ability to filter for recipes that point to this special custom ingredient entity, fix my database, and then re-link the recipe to the newly entered “real” ingredient.  This would happen seamlessly within 24 hours, potentially by said circus simians, and during that time, certain aggregation features wouldn’t be available with these recipes.

This approach has a major implementation cost, especially so late in the game, and a big test cost as well.

So, Which One?

Hmmm, I’ll have to get back to you on that.  And here you were thinking I had all the answers!  I’ve been thinking the “Do Nothing” idea is less and less of an option, however I’m not quite sure if I’m ready to start on a major database re-architecture until I really understand the nature of how the product is used.  One idea is to hold off a bit on this, until the private beta stage.  We can see how common missing ingredients are, and how users respond to various levels of frustration related to these limitations.  The idea of this level of re-design is also scary during a beta period, since the idea of beta is usually “Ok I think I have this working, now you guys test it”, so part of me is tempted to just get this redesign out of the way now and not have to worry about it again.

I apologize for this blog post resembling more of a brain dump than any actionable items or finalized opinion, but it’s something I’ve been thinking about all week so thought it best to get it out there and potentially hear from other people who might have faced similar challenges.

Web Two-Point-Oh-No!

First off, I whole heartily apologize for the lame blog post title.  Not only is it a bad pun, it’s misleading given the topic of this post, which is to chronicle my efforts integrating KitchenPC in with Facebook Connect, Facebook’s single-signon approach.  It seems if you want to be a real Web 2.0 website, not only do you need to use the right fonts, but you also need the “Log in with Facebook” button.  This realization was the catalyst of yesterday’s headaches.

The second reason, and arguably more important, for this post is to feebly attempt to organize the chaos of information out on the web that one must grudgingly wade through to untangle the mess that are the Facebook APIs.  I’m hoping this post will help out someone like me, who until yesterday didn’t know the first thing about integrating in with Facebook or providing a single sign-in mechanism.  To make matters worse, since I’m using the .NET Framework (which is all but unsupported by Facebook), there exists only the most brief and usually contradictory information across blogs, various CodePlex projects, and other web based bulletin boards.

Most people who begin investigating Facebook integration with a .NET based backend will stumble across this site almost immediately.  This is Facebook’s attempt to provide links to various APIs developed for Facebook.  There’s a few out there (mostly unstable, alpha code that hasn’t been changed in a year or more), but it seems that the main one is the Facebook Developer Toolkit library that is supported by Microsoft, though written by a third party contracting firm called Clarity Consulting.  Unfortunately, they don’t have the clarity required to write a coherent API or document anything they’ve done.  Most APIs in their documentation are left completely blank or just place holders for examples that may never come.  Maybe they should use a Wiki, which might encourage others to update it.

The sample is fairly easy to setup, which assumes you’ve created a Facebook application, and takes only minor tinkering to get working.  One thing I noticed is that people like to confuse the terms API Key and Application ID.  Often, they are merged into one super-ambiguous term such as “Application Key”.  The API Key is an alphanumeric (actually hex value) string, and the Application ID is a numeric value (apparently a 64-bit number).  The example refers to this key, mostly using the incorrect terms, so you have to guess which one they mean.  I’ll just go over the “Connect” sample, which is available in the Samples.zip file here.

Once you open the solution file in Visual Studio, the two files of importance are Default.aspx (which contains some script to edit), and Default.aspx.cs (which contains everything else.)  In Default.aspx, at the bottom of the page you’ll find the following line of Javascript:

FB.init(“9a6e2f9bf3b0be5b695e95d8a6f71f34”, “xd_receiver.htm”);

This initializes the Facebook framework, and also does stuff like transform that funky <fb:login-button> tag into an actual button.  The first parameter will be your API key (the hex one) of your Facebook application.  If you accidentally type in your Application ID (numeric), the logon still works but the session will not be valid and Facebook Developer Toolkit is not nice enough to report any useful error to you.  IsConnected() just returns false and explains no reason why.  This was about ten minutes of hair pulling for me.

Next, edit the Default.aspx.cs file.  Under the Private Members region, there’s two constants (no, not death and taxes) – APPLICATION_KEY (there’s that damn made up name again!) and SECRET_KEY.  Your APPLICATION_KEY is your API Key, which is the same value you have in your script file.  The SECRET_KEY is obviously the Application Secret, which you don’t even tell your best friend.  Once you set this up, stuff should work.  Oh wait, no it won’t.

One thing you’ll have to keep in mind if you’re developing locally is your URLs for redirects might not match.  If your local development machine is running on localhost, and your application’s “Connect URL” is something else, you’ll see an error when clicking on the Login button.  There’s two theories on how to fix this.

  • Fake out your dev machine by editing the HOSTS file to point yourdomain.com to 127.0.0.1.  Since all the redirection is through client-side script and Facebook itself doesn’t actually hit your server, this should work fine.  For me it’s a bit hacky and requires developers to mess around with junk.
  • Create two Facebook applications.  One points to http://localhost/ as the Connect URL and one points to your production site.

I went with the latter route.  I have a “KitchenPC” application which points to kitchenpc.com, and a “KitchenPC Development” application, which is hidden, that points to http://localhost.  Also, I use port 80 for my development web server; if you use another port, that will have to be in your Connect URL as well.

Ok, now everything should work.  When you login to Facebook and trust the application, the page will display various information it obtained through your account.  This is a great start!  However, if you actually want to do anything useful, this is where the headaches will begin.

The first thing I wanted to do was retrieve the email address from Facebook so I could check if the user already had an account on KitchenPC, and ask the user if they wished to link to that Facebook account.  There’s also a way to do this with comparing email hash values but I decided to avoid this approach.  Since the email address is not provided by default, you have to ask for this permission explicitly.  The FDT documentation only provided one example on how to prompt the user for permissions, and this involved using a Facebook client side control that pops up a prompt asking for the permission.  However, I wasn’t too thrilled about the idea of having yet another prompt after the user logs on to then ask for more permissions.  I wanted to grant email access when the application is first installed on the user’s account, as I’d seen before on other sites;  something like this:

I knew this was possible, but I had to resort to the Facebook documentation (which assumes you’d use PHP for a task like this) to figure out the deal.  One of the first things I noticed is that all the Facebook SDK samples used different syntax.  For one, FB.Init() took a different signature.  Theirs looked like this:

FB.init({appId: ‘xxxxxxxxx’, status: true, cookie: true, xfbml: false});

Next, their <fb:login-button> had all sorts of neat features, such as a “perms” attribute that would ask for explicit permissions (exactly what I needed!), had the ability to override the text, and other features I might desire.  However, none of these attributes worked for me when I tried.  Upon digging into this more, I noticed they also included a different Javascript file.  Instead of the FeatureLoader.js.php file that the FDT sample was using, they used a file called all.js.  This seemed to be the key.  When I started using the new file, my Facebook Login control now worked and asked for the permissions I wanted, and allowed me to use other featured from Facebook’s documentation.  Now the problem is the FDT no longer worked.  Even with valid session cookies, ConnectSession.IsConnected() returned false.  After a little debugging, I noticed the cookies that Facebook created after logging in were different if I included the all.js file, versus the working FeatureLoader.js.php.  Upon a bit more research, a few things were revealed.  First, FeatureLoader.js.php is old and deprecated.  Facebook warns against it, insisting the use of their new Javascript API which is designed around OAuth 2.0.  The FDT is designed around the old Javascript API, which is still supported but most likely not for long.  After digging through the Discussions for the FDT looking for help, it appeared I was not alone.  There were literally a dozen or more posts on this subject.  Some posts were aware of the exact problem and were asking for a timeline on when FDT would support the new APIs, some posters were like me and completely clueless to the fact that there were multiple APIs and what the differences were between them.  Very few of the posts had any answers or even replies.

It seems that support for the .NET FDT is waning, and even Facebook isn’t really backing it.  This means there’s no real .NET support for Facebook, and FDT may or may not eventually get around to supporting the new Javascript library.  Unfortunately, the other .NET libraries for Facebook aren’t much better, mostly abandoned or very unstable.  I did run across one that supported OAuth 2.0 but it had some dependancies on some .NET libraries that I didn’t want to mess with.

After more research, I dug across a blog post that really saved the day!  This was a post by a guy named Nathan Totten who, like me, was grumbling about the lack of .NET support for Facebook, but unlike me, was knowledgable enough to do something about it.  He posted this.

This code is able to deserialize the new OAuth 2.0 cookie and build a valid session.  I pretty much copied and pasted the code into my project as is, and was able to hack together a session object under the debugger.  Be sure the read the comments on his blog post, as they’ll reveal a few more steps to get everything working.  Once this was working, the rest was pretty easy.  ConnectSession.IsConnected() will still return false, as it tries to find the old cookie, but you can mock up a Api object by setting the session manually like so:

Api api = new Api(session);
api.Session.SessionKey = sessionKey;
api.Session.UserId = userId;

The sessionKey and userId of course come from the ConnectService class that Nathan built.  When this is done, you can use the Api object normally or use FQL queries to obtain any information you have permission to from Facebook.  Sure, this is a bit of a hack but it’ll do for now until there’s something better.  I chatted with Nathan a bit over email and apparently his company is working on a new, fully featured .NET API for Facebook.  I wish him luck with this project as there really needs to be a single library that is well maintained, documented, and supported by the community.

The goods news is that now I have the ability to sign on to KitchenPC using a Facebook account, and even link a Facebook account with an existing KitchenPC account.  This framework will also pave the way for features such as publishing KitchenPC content to a Facebook user’s news feed, or “Liking” content on the KitchenPC site.  Ah the joys of Web 2.0-ness.

Tweet!

So I’ve been meaning to set up a Twitter account for KitchenPC for awhile now, as it seems like the trendy Web 2.0 thing to do.  Plus, there’s already been a few Tweets about my blog so it’d be nice to have an at-name for them to point to.  The problem is the @KitchenPC Twitter name was already taken!  This was a bit frustrating because the account was private, had no posts and no followers.  The other day I was reading through Twitter’s terms of use and I noticed there’s actually a clause regarding using trademarks in your Twitter name.  Since KitchenPC is a registered trademark, I figured I’d send Twitter an email asking if they’d transfer the KitchenPC user name over to me.  To my surprise, I got an email this morning saying ‘Sure!” and this was done.

So now I have a Twitter name.

I feel a bit guilty about yanking someone’s Twitter account from them, but hey the account was totally inactive for months.  Otherwise, it’s not something I would have tried.  I hope this is not the start of a trend into corporate bullying for me :)