1. Play-By-Play: Layout

    July 9, 2010 by Craig

    I want to use HAML for my templates. I already have it installed; all I need to do now is convert the scaffolded ERB layout.

    html2haml app/views/layouts/application.html.erb app/views/layouts/application.haml
    

    One other thing I like to do is have the <title> and topmost <h1> tags have the same content. This is generally considered (by the SEO black-magicians) to be good SEO practice. It’s easily achieved by having a @page_title variable set by each view, and then by having the layout display it in title and header.


  2. Play-By-Play: Heroku Setup

    June 7, 2010 by Craig

    Setting up the project is easy enough:

    heroku create softcraft-bakery
    

    Heroku creates a git repo for each project. I want to keep my main git repo on github.

    Add the heroku remote:

      git remote add heroku git@heroku.com:softcraft-bakery.git
      git push heroku master
    

    That gives me:

    -----> Heroku receiving push
     !     Heroku push rejected, no Rails or Rack app detected.
    
    This is caused by rails files being in a subdirectory of my git project. I don't want to mess around trying to figure out how to support an unexpected configuration, so I'll move everything up a level:
    

    rm README rm .gitignore git mv bakery/* . git commit -a -m "Moved rails files up a level" git push heroku

    Output:

    -----> Heroku receiving push -----> Gemfile detected, running Bundler -----> Bundler works best on the Bamboo stack. Please migrate your app: http://docs.heroku.com/bamboo Unresolved dependencies detected; Installing... Fetching source index from http://rubygems.org/ Resolving dependencies Installing abstract (1.0.0) from system gems Installing actionmailer (3.0.0.beta3) from rubygems repository at http://rubygems.org/ /usr/local/lib/ruby/site_ruby/1.8/rubygems/installer.rb:186:in `install': actionmailer requires Ruby version >= 1.8.7 (Gem::InstallError) from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/source.rb:42:in `install' from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/installer.rb:30:in `run' from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/installer.rb:18:in `each' from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/installer.rb:18:in `run' from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/installer.rb:6:in `install' from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/cli.rb:60:in `install' from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/vendor/thor/task.rb:33:in `send' from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/vendor/thor/task.rb:33:in `run' from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/vendor/thor/invocation.rb:109:in `invoke' from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/vendor/thor/invocation.rb:116:in `call' from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/vendor/thor/invocation.rb:116:in `invoke' from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/vendor/thor.rb:137:in `start' from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/vendor/thor/base.rb:378:in `start' from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/vendor/thor.rb:124:in `start' from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/bin/bundle:11 from /usr/local/bin/bundle:19:in `load' from /usr/local/bin/bundle:19 FAILED: Have you updated to use a 0.9 Gemfile? http://docs.heroku.com/gems#gem-bundler

    Now I have to set the Heroku "stack" (runtime environment & versions):
    heroku stack:migrate bamboo-ree-1.8.7
    

    Success!


  3. Play-by-Play: Rails Setup

    June 5, 2010 by Craig

    I still don’t have an official name for this project, so I’ll call it “bakery” in the interim.

    rails bakery
    git add bakery
    git commit -a -m "Basic Rails install"
    rails server
    

    This is new: there’s a single execution point for rails tasks. It’s nice to not have to type script/... all the time

    Fire up http://0.0.0.0:3000/ and see that it’s working.

    Gem Updates

    Update haml/sass:

    sudo gem update haml
    

    Add “gem haml” to Gemfile (another new feature).

    Update Ryan Bates’ Nifty Generators. They’re nifty. Especially when generating.

    sudo gem install nifty-generators
    

    Add “gem nifty-generators” to the Gemfile.

    Also update autotest and shoulda

    Hello World

    Time to get a Hello World going. It’s not working until I see Hello World.

    First, unpack the gems. How do I do that again?

    rake -T gem
    /Users/craig/Documents/SoftCraft/projects/bakery/rails/bakery/db/schema.rb doesn't exist yet. Run "rake db:migrate" to create it then try again. If you do not intend to use a database, you should instead alter /Users/craig/Documents/SoftCraft/projects/bakery/rails/bakery/config/boot.rb to limit the frameworks that will be loaded
    

    Fair enough.

    rake db:migrate
    (in /Users/craig/Documents/SoftCraft/projects/bakery/rails/bakery)
    
    rake -T gem
    (in /Users/craig/Documents/SoftCraft/projects/bakery/rails/bakery)
    rake rails:freeze:gems  # The rails:freeze:gems is deprecated, please use bundle install instead
    

    More Rails 3 changes. Looks like freezing isn’t necessary any more. That’s good; I never liked it anyway.

    Now, I need a “Hello World” page. That means I need a HomeController for the root route.

    rails generate controller Home
    

    Now I need a view. Since Home is a singleton controller, that’s the show view. Whip up Add views/home/show.haml and dump in Hello World.

    Now I need a route. In the new Rails 3 routing DSL that’s done by:

    root :to => "home#show"
    

    Lastly, I need to delete public/index.html.

    Hit localhost:3000 and it works!

    Shoulda

    Looks like Shoulda isn’t Rails 3 compatible yet.

    DEPRECATION WARNING: RAILS_ROOT is deprecated! Use Rails.root instead. (called from join at /Users/craig/.bundle/ruby/1.8/bundler/gems/shoulda-b8b6cad61981d47356de06c2a5586e281938c94e-rails3/lib/shoulda/autoload_macros.rb:40)
    /Users/craig/.bundle/ruby/1.8/bundler/gems/shoulda-b8b6cad61981d47356de06c2a5586e281938c94e-rails3/lib/shoulda/autoload_macros.rb:40:in `join': can't convert # into String (TypeError)
    	from /Users/craig/.bundle/ruby/1.8/bundler/gems/shoulda-b8b6cad61981d47356de06c2a5586e281938c94e-rails3/lib/shoulda/autoload_macros.rb:40:in `autoload_macros'
    

    I go to report this bug. Of course, when I register with RailsPlugins, I get this:

    We are sorry to say that something in our code went bang!

    Screw it, I’ll avoid Shoulda in the interim. Instead, I’ll create a regular Test::Unit controller test.


  4. Play-by-Play: Ruby, Rails, and Heroku Versions

    June 4, 2010 by Craig

    First, update to macports 1.8.2.

    Ruby Update

    sudo port install ruby
    

    I’m going to get 1.8.7 p249

    • p249 “has marshaling bugs that crash Rails 3.0.0
    • Get RVM to help manage the versions.
      bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )
      if [[ -s "$HOME/.rvm/scripts/rvm" ]]  ; then source "$HOME/.rvm/scripts/rvm" ; fi
      source ~/.rvm/scripts/rvm
      rvm notes
      

      Add to .profile:

      for profile in .bash_profile .bashrc ; do echo 'if [[ -s "$HOME/.rvm/scripts/rvm" ]]  ; then source "$HOME/.rvm/scripts/rvm" ; fi' >> $HOME/$profile done
      

      Is this necessary? Should it be in .bash_profile? (Probably not as it references .bash_profile). I’m still fairly new to UNIX and so don’t know my profile consequences off by heart.

    I’m not going to get into ruby 1.9 as Rails 3 isn’t stable on 1.9.1 (1.9.2 only) and Heroku only supports 1.9.1.

    Rails 3

    I’m preferring Rails 3 as:

    • It’s definitely the way of the future.
      • There’s quite a few new APIs — meaning old ones will be abandoned. Rails doesn’t sit still.
      • The API appears to be improved all the way around; it’s more fun to use.
    • It should be stable & released by the time I’m ready to launch.

    But which ruby version should I be using? All seem to have potential for issues. I’ll run 1.8.7@249 and see if it works.

    Rubygems

    RubyGems update, attempt 1:

     gem update --system
     Updating RubyGems
     /opt/local/lib/ruby/site_ruby/1.8/rubygems/spec_fetcher.rb:245: [BUG] Segmentation fault
     ruby 1.8.7 (2010-01-10 patchlevel 249) [i686-darwin9]
    Abort trap
    

    I didn’t sudo, and it gave me a segfault instead of a real error :-(
    Attempt #2, this time with sudo:

     sudo gem update --system
    Password:
    Updating RubyGems
    Updating rubygems-update
    Successfully installed rubygems-update-1.3.7
    Updating RubyGems to 1.3.7
    Installing RubyGems 1.3.7
    RubyGems 1.3.7 installed
    Successfully uninstalled gemcutter-0.1.6
    Successfully uninstalled gemcutter-0.3.0
    ...
    

    Update Rails

    gem install rails --pre
    ...
    Installing ri documentation for rails-3.0.0.beta3...
    File not found: lib
    

    Found the issue here. How did we ever develop software before Google?
    This might not be a big deal after all.

    Heroku

    I’m going to try Heroku for deployment/hosting.
    First, I need Bundler:

    sudo gem install bundler
    /opt/local/lib/ruby/site_ruby/1.8/rubygems/spec_fetcher.rb:254: warning: getc is obsolete; use STDIN.getc instead
    

    I hate warnings.

    Next is the Heroku gem:

     
    sudo gem install heroku
    

    Time to read up on the Heroku quickstart.


  5. Play-by-Play: Initial Git

    June 3, 2010 by Craig

    Time to set up a GitHub project. Github is, at the very least, a good offsite storage system for the source code.

    cd "/Users/craig/Documents/SoftCraft/projects/bakery/"
    mkdir rails
    cd rails
    touch README
    touch .gitignore
    gitx
    git add .
    git commit -a -m "Initial commit"
    git remote add origin git@github.com:softcraft-development/bakery.git
    git push origin master
    

    And we’re in business!

    Update .git/config with a couple of nice features:

    [alias]
      undo = reset --hard HEAD
      wipe = clean -f -d
    

    While I’m at it, I’ll update my copy of git too.


  6. Play-by-Play: Units of Measurement

    June 2, 2010 by Craig

    Ok, time to get down to coding.

    (Actually, I started coding a month ago. I’ve been keeping a development log since the start; I’m just getting to posting it now.)

    I’ll be dealing with measurements quite a bit for ingredients and nutritionals, so I’ll want a measurement library.
    Google up “Ruby Measurement.”
    ruby-measure looks like what I want, but it’s undocumented. That’s a deal-breaker.

    Google “ruby units of measurement”
    Found ruby-units.
    Its old; last updated Oct 2006. That’s a bad sign.
    (Update: I eventually found the github project; it was last updated in March of 2010.)
    The documentation appears to be OK.
    Can it do density calculations? (Divide mass by volume to get density).
    It looks like it’s worth looking into.


  7. Play-by-Play: Fixed and Unknown Costs

    June 1, 2010 by Craig

    Unlike the variable costs, some costs are roughly constant regardless of how many customers you have. Paying for these costs is why it’s so important to have high margins and high customer volume; there’s a hurdle to overcome before the business is bottom-line profitable.

    Legal

    Legal costs aren’t much fun but they are necessary. I’m estimating roughly $1000 per year in basic legal costs. If I actually get sued then it’s another ball game entirely. The lesson here is “Don’t Get Sued.” Also, there’s roughly another $1000 in one-time legal fees during incorporation.

    Insurance

    Liability and business insurance are good safety nets to have; they will hedge against potentially catastrophic losses. I’m estimating $2000 per year based on some personal liability quotes I’ve received already.

    Accounting

    I do all my own accounting and taxes for my sole-proprietor consulting business, but corporate accounting makes me shudder. $1000 a year paid to a professional accountant is plenty, assuming that I have someone else do the actual bookkeeping. I’m fine with doing that myself for the short term.

    Graphic & User Interface Design

    I’m not the worst designer in the world, but I’m a long way from being great. Having a pleasing and usable interface is critical to any modern product. I’m going to budget $1000 for the initial design, with more as the business & feature set grows.

    Not the Whole Story

    There are other costs that I’m intentionally leaving out.

    Cost to Acquire a Customer

    This is a fancy way to say “advertising.” You have to get your product into the minds of your potential customers, and doing so will incur some cost. Word-of-mouth is by far the best and cheapest way to accomplish this, but it’s also the hardest — especially when you’re first starting out. Google AdWords is the easy route, but lately I’ve been hearing rumblings about how it’s not really all it’s cracked up to be. I’ve got some other ideas too; I’ll save those for another post.

    The take away here is that it’s very hard for me to estimate what these costs will be in advance. Remember that the goal here is not just getting people to visit the site, but turning them into paying customers. Lots of companies have gone broke before figuring out how to do that effectively.

    Support Costs

    Customers need help — or eventually they won’t be your customers any more. The trouble is that it’s hard gauge how much money you’ll need to spend to keep your customers satisfied. It’s a combination of the number of customers you have, the fraction that experience trouble, and the time you need to spend to resolve the troubles. This is why user experience & interface design are so important; your application needs to be easy to use so that you’re not burning time, money, and support on frustrated users.

    For the time being, I’m going to handle all support myself via email. Doing it myself isn’t very cost effective but it is low-risk in terms of cash. When the business gets big enough to warrant it I’ll look at hiring someone else to handle it; then I can concentrate on more value-adding activities.

    Development

    This is the big one. The tradeoff for the amazingly high profit margin on software is the amazingly high cost to create the product in the first place. I’ve already sunk “several thousands” of dollars into this project and it’s not even off the ground yet.

    The trick here is that, as long as I’m the one who is doing the development, those costs are all phony. All I’m really spending is my time. I’m not emptying my wallet for someone else and I’m not paying taxes (yet) on the work I’m doing. My spent time isn’t valueless, but it’s a long ways off from risking my house and retirement as startup capital.

    What Am I Missing?

    These costs are just the ones off the top of my head. I’m deliberately not over-analyzing the business model because the unknown aspects are so big. However, if you’ve got a important point that I’ve missed, please feel free to share.


  8. Play-by-Play: Variable Costs and Margins

    May 30, 2010 by Craig

    I did the revenue analysis; now it’s time for the expenses.

    Variable Costs

    These are expenses that are directly proportional to the number of customers you have. More customers = more variable costs.

    Hosting

    For a cloud-based web application, the costs are pretty small. Heroku charges dyno can handle around 10 to 50 customers per second. Given that I’m only expecting 250 non-heavy-duty customers total, the variable costs should be tiny. I’d guess that the app could be hosted for less than $100/month, or $1200 a year. The cost per customer is about $5 per year. Chump change.

    Payment Fees

    I’ll need a merchant account to accept credit cards. I have some quotes for roughly 15 cents + 3% per transaction + $30/month (though the actual amounts vary a bit with provider, volume, and monthly fee). That’s about $4700/year, though with this sort of volume I could probably get a lower transaction fee for lower overall costs. It’s also about $19 per customer per year.

    Billing

    Over and above the merchant account fees are the payment gateway fees. I’m looking at Chargify as it has a good reputation. It costs $50 for up to $500 users; for my 250 users that’s $0.20/user… basically not worth considering.

    Gross Margin

    So if revenue per customer is about $520 per year, and the variable costs per customer are $25 per year, then the gross yearly margin per customer is $495. The margin rate is an astonishing 95%. For reference, a lot of businesses run on margins of 20% or less; really high-volume ones often have margins in the low single digits. That’s the beauty of software: once you build the thing, it costs nearly nothing to supply it to your customers.

    Next up: fixed costs.


  9. Play-by-Play: Revenue Model, Indecently Exposed

    May 28, 2010 by Craig

    I want to publish some analysis regarding the costs of running this business/application. However, to make any real impact, I have to publish the revenue numbers too. I originally said I wasn’t going to do that, but I think it’s worth doing so now given my next post. That, and Teflon Ted said I’d be uncool if I didn’t.

    Answers to My Questions

    Q: How much on ingredients does the bakery spend?

    Depending on the quality of ingredients anywhere from $1000.00 – $5000.00 per week

    Q:How much of the overall waste could be eliminated through better
    planning (via the product we want to build)?

    I would say that there is always waste, any more than 10% can be very detrimental to a small bakery, especially on a daily basis.
    I think if done properly and the bakery is actually planning and following their projections the waste could be brought down to 3-5 %

    Running the Numbers

    Conservatively: $1000 in ingredients per week * 5% minimum reduction in waste = $50/week in potential savings to the customer. That’s about $2600/year.

    Multiply $2600 by some number A, which is the percentage of this savings that you can successfully extract from the customer. I’ve been ballparking this number at 20% for no good reason other than the result seems palatable to me. $2600 * 20% = $520/year, or $43/month.

    There are about 25,000 bakeries in Canada and the US. Multiply this by some number B, which is your customer conversion rate. I’ve been using B = 1% as a suitably low number. 25,000 * 1% = 250 customers, which seems pretty attainable.

    250 customers * $520/year = $130,000.

    The real revenue number is 65 million * AB (minimum). Increase A and B to increase the total revenue.

    That’s a brief look at the revenue side. Next come the expenses.


  10. Play-by-Play: The Architecture

    May 25, 2010 by Craig

    A pay-as-you-go service goes hand-in-hand with a web-based application; it’s much harder to make a viable one-time-purchase web service or a pay-as-you-go desktop application. This choice of architecture has several benefits of its own:

    • Lower (nearly zero) maintenance for the customer. There’s no software to install and no servers to operate.
    • Easier compatibility concerns for the developer. Modern web development is very consistent across platforms (assuming you choose not to support Internet Explorer 6 or less. Even if you target modern Windows exclusively (and that probably means abandoning the huge XP installed base), desktop software has to contend with a huge number of variables for each local installation.
    • Easier distribution of changes, fixes, and enhancements. This is critical for any agile & responsive business.
    • Greater possibility for interaction with the customer. You get a certain amount of feedback automatically, just through usage logs.

    Of course, there are some major downsides:

    • The customer must have a useful Internet connection at their place of work. My domain expert says that this isn’t much of an obstacle; most bakeries have them anyway for things like email. Still, it will be useful to keep offline / non-browser modes in mind: I’m thinking of printed sheets and smartphone apps as future directions.
    • The application won’t be able to take advantage of some features on the local computer. This has been getting less important over the years, but there’s still a few technologies that simply won’t work through a browser. Scanner support is probably the biggest one I can think of. However, that’s probably not important for this particular product.

    One of the biggest advantages though is that my own personal strengths lie with web-based application development. This is a big factor on a small, speculative project like this. However, it should not be the deciding factor; if the product and market do not fit the developer, then you need to either change developers or change products.

    I’ll be using a cloud-based hosting service to start out with. Cloud-based services offer the greatest scalability. In the early days of an application, this means scaling down rather than up; there won’t necessarily be enough traffic to warrant a full-size server (even a virtual server). A cloud service will also scale up nicely through the first phase of growth. After a certain level of traffic, a full server will become more cost effective — but that’s quite a ways off (and getting further away by the year). Since traffic effectively means revenue, migrating to a new server platform will be one of those “good problems to have”.

    In my next post, I put some real numbers against the architecture.