Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial Commit

  • Loading branch information...
commit 4b169b02fb1c2b699548345a1db38634119e937c 1 parent 275e4d8
@Jarred-Sumner Jarred-Sumner authored
Showing with 2,274 additions and 18 deletions.
  1. +17 −14 .gitignore
  2. +30 −0 Gemfile
  3. +138 −0 Gemfile.lock
  4. +1 −0  Procfile
  5. +0 −4 README.md
  6. +66 −0 README.rdoc
  7. +7 −0 Rakefile
  8. BIN  app/assets/images/1-background.png
  9. BIN  app/assets/images/2-background.png
  10. BIN  app/assets/images/3-background.png
  11. BIN  app/assets/images/4-background.png
  12. BIN  app/assets/images/background.png
  13. BIN  app/assets/images/bullet.png
  14. BIN  app/assets/images/rails.png
  15. +19 −0 app/assets/javascripts/application.js
  16. +6 −0 app/assets/javascripts/jquery.details.js
  17. +10 −0 app/assets/javascripts/jquery.textchange.js
  18. +28 −0 app/assets/javascripts/preorder.js.coffee
  19. +14 −0 app/assets/stylesheets/application.css
  20. +48 −0 app/assets/stylesheets/checkout.css.scss
  21. +23 −0 app/assets/stylesheets/footer.css.scss
  22. +19 −0 app/assets/stylesheets/header.css.scss
  23. +33 −0 app/assets/stylesheets/homepage.css.scss
  24. +56 −0 app/assets/stylesheets/homepage/call_to_action.css.scss
  25. +21 −0 app/assets/stylesheets/homepage/faq.css.scss
  26. +50 −0 app/assets/stylesheets/homepage/key_points.css.scss
  27. +28 −0 app/assets/stylesheets/homepage/other_points.css.scss
  28. +47 −0 app/assets/stylesheets/homepage/press.css.scss
  29. +96 −0 app/assets/stylesheets/homepage/stats.css.scss
  30. +8 −0 app/assets/stylesheets/main.css.scss
  31. 0  app/assets/stylesheets/preorder.css.scss
  32. +232 −0 app/assets/stylesheets/primitives.css.scss
  33. +48 −0 app/assets/stylesheets/reset.css
  34. +50 −0 app/assets/stylesheets/share.css.scss
  35. +63 −0 app/assets/stylesheets/variables.css.scss
  36. +3 −0  app/controllers/application_controller.rb
  37. +42 −0 app/controllers/preorder_controller.rb
  38. +2 −0  app/helpers/application_helper.rb
  39. +17 −0 app/helpers/preorder_helper.rb
  40. 0  app/mailers/.gitkeep
  41. 0  app/models/.gitkeep
  42. +68 −0 app/models/order.rb
  43. +4 −0 app/models/user.rb
  44. +22 −0 app/views/layouts/_footer.html.erb
  45. +14 −0 app/views/layouts/application.html.erb
  46. +1 −0  app/views/preorder/_copyright.html.erb
  47. +6 −0 app/views/preorder/_footer.html.erb
  48. +13 −0 app/views/preorder/_google_analytics.html.erb
  49. +5 −0 app/views/preorder/_header.html.erb
  50. +20 −0 app/views/preorder/checkout.html.erb
  51. +6 −0 app/views/preorder/checkout/_sidebar.html.erb
  52. +71 −0 app/views/preorder/homepage/_faqs.html.erb
  53. +51 −0 app/views/preorder/homepage/_key_points.html.erb
  54. +6 −0 app/views/preorder/homepage/_middle_reserve.html.erb
  55. +20 −0 app/views/preorder/homepage/_other_points.html.erb
  56. +8 −0 app/views/preorder/homepage/_press.html.erb
  57. +4 −0 app/views/preorder/homepage/_show_dont_tell.html.erb
  58. +53 −0 app/views/preorder/homepage/_stats.html.erb
  59. +3 −0  app/views/preorder/homepage/_value_proposition.html.erb
  60. +6 −0 app/views/preorder/index.html.erb
  61. +26 −0 app/views/preorder/share.html.erb
  62. +8 −0 app/views/preorder/share/_facebook_js.html.erb
  63. +1 −0  app/views/preorder/share/_twitter_js.html.erb
  64. +4 −0 config.ru
  65. +24 −0 config/application.rb
  66. +6 −0 config/boot.rb
  67. +25 −0 config/database.yml
  68. +5 −0 config/environment.rb
  69. +37 −0 config/environments/development.rb
  70. +67 −0 config/environments/production.rb
  71. +37 −0 config/environments/test.rb
  72. +3 −0  config/initializers/amazon_flexible_payments.rb
  73. +7 −0 config/initializers/backtrace_silencers.rb
  74. +15 −0 config/initializers/inflections.rb
  75. +5 −0 config/initializers/mime_types.rb
  76. +3 −0  config/initializers/rails_config.rb
  77. +7 −0 config/initializers/secret_token.rb
  78. +8 −0 config/initializers/session_store.rb
  79. +14 −0 config/initializers/wrap_parameters.rb
  80. +5 −0 config/locales/en.yml
  81. +11 −0 config/routes.rb
  82. +80 −0 config/settings.yml
  83. 0  config/settings/development.yml
  84. 0  config/settings/production.yml
  85. 0  config/settings/test.yml
  86. +9 −0 db/migrate/20121004072615_create_users.rb
  87. +26 −0 db/migrate/20121004072706_create_orders.rb
  88. +45 −0 db/schema.rb
  89. +7 −0 db/seeds.rb
  90. +2 −0  doc/README_FOR_APP
  91. 0  lib/assets/.gitkeep
  92. 0  lib/tasks/.gitkeep
  93. 0  log/.gitkeep
  94. +26 −0 public/404.html
  95. +26 −0 public/422.html
  96. +25 −0 public/500.html
  97. 0  public/favicon.ico
  98. +5 −0 public/robots.txt
  99. +6 −0 script/rails
  100. 0  test/fixtures/.gitkeep
  101. +27 −0 test/fixtures/orders.yml
  102. +7 −0 test/fixtures/users.yml
  103. 0  test/functional/.gitkeep
  104. +19 −0 test/functional/preorder_controller_test.rb
  105. 0  test/integration/.gitkeep
  106. +12 −0 test/performance/browsing_test.rb
  107. +13 −0 test/test_helper.rb
  108. 0  test/unit/.gitkeep
  109. +4 −0 test/unit/helpers/preorder_helper_test.rb
  110. +7 −0 test/unit/order_test.rb
  111. +7 −0 test/unit/user_test.rb
  112. 0  vendor/assets/javascripts/.gitkeep
  113. 0  vendor/assets/stylesheets/.gitkeep
  114. 0  vendor/plugins/.gitkeep
View
31 .gitignore
@@ -1,16 +1,19 @@
-*.rbc
-*.sassc
-.sass-cache
-capybara-*.html
-.rspec
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+#
+# If you find yourself ignoring temporary files generated by your text editor
+# or operating system, you probably want to add a global ignore instead:
+# git config --global core.excludesfile ~/.gitignore_global
+
+# Ignore bundler config
/.bundle
-/vendor/bundle
-/log/*
-/tmp/*
+
+# Ignore the default SQLite database.
/db/*.sqlite3
-/public/system/*
-/coverage/
-/spec/tmp/*
-**.orig
-rerun.txt
-pickle-email-*.html
+
+# Ignore all logfiles and tempfiles.
+/log/*.log
+/tmp
+
+config/settings.local.yml
+config/settings/*.local.yml
+config/environments/*.local.yml
View
30 Gemfile
@@ -0,0 +1,30 @@
+source 'https://rubygems.org'
+
+gem 'rails', '3.2.8'
+
+group :development do
+ gem 'sqlite3'
+end
+
+group :production do
+ gem 'thin'
+ gem 'pg'
+end
+
+# Gems used only for assets and not required
+# in production environments by default.
+group :assets do
+ gem 'sass-rails', '~> 3.2.3'
+ gem 'coffee-rails', '~> 3.2.1'
+ gem 'therubyracer', :platforms => :ruby
+ gem 'uglifier', '>= 1.0.3'
+end
+
+# jQuery
+gem 'jquery-rails'
+
+# Kickstarter's awesome Amazon Flexible Payments gem
+gem 'amazon_flex_pay'
+
+# Configuration File
+gem 'rails_config'
View
138 Gemfile.lock
@@ -0,0 +1,138 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ actionmailer (3.2.8)
+ actionpack (= 3.2.8)
+ mail (~> 2.4.4)
+ actionpack (3.2.8)
+ activemodel (= 3.2.8)
+ activesupport (= 3.2.8)
+ builder (~> 3.0.0)
+ erubis (~> 2.7.0)
+ journey (~> 1.0.4)
+ rack (~> 1.4.0)
+ rack-cache (~> 1.2)
+ rack-test (~> 0.6.1)
+ sprockets (~> 2.1.3)
+ activemodel (3.2.8)
+ activesupport (= 3.2.8)
+ builder (~> 3.0.0)
+ activerecord (3.2.8)
+ activemodel (= 3.2.8)
+ activesupport (= 3.2.8)
+ arel (~> 3.0.2)
+ tzinfo (~> 0.3.29)
+ activeresource (3.2.8)
+ activemodel (= 3.2.8)
+ activesupport (= 3.2.8)
+ activesupport (3.2.8)
+ i18n (~> 0.6)
+ multi_json (~> 1.0)
+ amazon_flex_pay (0.9.13)
+ activesupport (>= 3.0.14)
+ multi_xml (~> 0.2.0)
+ rest-client (~> 1.6.1)
+ arel (3.0.2)
+ builder (3.0.3)
+ coffee-rails (3.2.2)
+ coffee-script (>= 2.2.0)
+ railties (~> 3.2.0)
+ coffee-script (2.2.0)
+ coffee-script-source
+ execjs
+ coffee-script-source (1.3.3)
+ daemons (1.1.9)
+ erubis (2.7.0)
+ eventmachine (1.0.0)
+ execjs (1.4.0)
+ multi_json (~> 1.0)
+ foreman (0.60.2)
+ thor (>= 0.13.6)
+ hike (1.2.1)
+ i18n (0.6.1)
+ journey (1.0.4)
+ jquery-rails (2.1.3)
+ railties (>= 3.1.0, < 5.0)
+ thor (~> 0.14)
+ json (1.7.5)
+ libv8 (3.3.10.4)
+ mail (2.4.4)
+ i18n (>= 0.4.0)
+ mime-types (~> 1.16)
+ treetop (~> 1.4.8)
+ mime-types (1.19)
+ multi_json (1.3.6)
+ multi_xml (0.2.2)
+ pg (0.14.1)
+ polyglot (0.3.3)
+ rack (1.4.1)
+ rack-cache (1.2)
+ rack (>= 0.4)
+ rack-ssl (1.3.2)
+ rack
+ rack-test (0.6.2)
+ rack (>= 1.0)
+ rails (3.2.8)
+ actionmailer (= 3.2.8)
+ actionpack (= 3.2.8)
+ activerecord (= 3.2.8)
+ activeresource (= 3.2.8)
+ activesupport (= 3.2.8)
+ bundler (~> 1.0)
+ railties (= 3.2.8)
+ rails_config (0.3.1)
+ activesupport (>= 3.0)
+ railties (3.2.8)
+ actionpack (= 3.2.8)
+ activesupport (= 3.2.8)
+ rack-ssl (~> 1.3.2)
+ rake (>= 0.8.7)
+ rdoc (~> 3.4)
+ thor (>= 0.14.6, < 2.0)
+ rake (0.9.2.2)
+ rdoc (3.12)
+ json (~> 1.4)
+ rest-client (1.6.7)
+ mime-types (>= 1.16)
+ sass (3.2.1)
+ sass-rails (3.2.5)
+ railties (~> 3.2.0)
+ sass (>= 3.1.10)
+ tilt (~> 1.3)
+ sprockets (2.1.3)
+ hike (~> 1.2)
+ rack (~> 1.0)
+ tilt (~> 1.1, != 1.3.0)
+ sqlite3 (1.3.6)
+ therubyracer (0.10.2)
+ libv8 (~> 3.3.10)
+ thin (1.5.0)
+ daemons (>= 1.0.9)
+ eventmachine (>= 0.12.6)
+ rack (>= 1.0.0)
+ thor (0.16.0)
+ tilt (1.3.3)
+ treetop (1.4.10)
+ polyglot
+ polyglot (>= 0.3.1)
+ tzinfo (0.3.33)
+ uglifier (1.3.0)
+ execjs (>= 0.3.0)
+ multi_json (~> 1.0, >= 1.0.2)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ amazon_flex_pay
+ coffee-rails (~> 3.2.1)
+ foreman
+ jquery-rails
+ pg
+ rails (= 3.2.8)
+ rails_config
+ sass-rails (~> 3.2.3)
+ sqlite3
+ therubyracer
+ thin
+ uglifier (>= 1.0.3)
View
1  Procfile
@@ -0,0 +1 @@
+web: bundle exec rails server thin -p $PORT -e $RACK_ENV
View
4 README.md
@@ -1,4 +0,0 @@
-selfstarter
-===========
-
-Roll your own crowdfunding
View
66 README.rdoc
@@ -0,0 +1,66 @@
+# Selfstarter
+Selfstarter makes it easy to roll your own crowdfunding site. To get started, fork this repository and change around ```config/settings.yml``` to suit your needs.
+
+## Background
+
+[Kickstarter rejected us](http://techcrunch.com/2012/10/07/the-story-of-lockitron-crowdfunding-without-kickstarter/), so we made our own crowdfunding for [Lockitron](https://lockitron.com). Feel free to [give us feedback](mailto:hello@lockitron.com)!
+
+Over the past week, a lot of people asked us for help with building their own crowdfunding app. This is it.
+
+Selfstarter is starting point. We made some specific choices with Selfstarter for Lockitron and we recommend you tailor it for your project:
+
+* We use Amazon Payments for payments. You can use Stripe or WePay. We used Kickstarter's awesome ```amazon_flex_pay``` gem.
+* We collect multi-use tokens from customers with Amazon Payments - this let's us collect payment information without charging the customer until we are ready to ship
+* Selfstarter doesn't come with any authentication, administration, mailers or analytics tools. We recommend adding a basic set of these so that you can message backers and manage orders.
+
+## Getting Started
+
+First you'll need to fork and clone this repo
+
+Let's get all our dependencies setup:
+```bash
+bundle install --without production
+```
+
+Now let's create the database:
+```bash
+rake db:migrate
+```
+
+Let's get it running:
+```bash
+rails s
+```
+
+### Customizing
+
+While it is *just* a skeleton, we did make it a little quicker to change around things like your product name, the colors, pricing, etc.
+
+To change around the product name, tweet text, and more, open this file:
+
+```
+config/settings.yml
+```
+
+To change around the colors and fonts, open this file:
+
+```
+app/assets/stylesheets/variables.css.scss
+```
+
+To dive into the code, open this file:
+
+```
+app/controllers/preorder_controller.rb
+```
+
+### Deploying to Production
+
+We recommend using Heroku, and we even include a ```Procfile``` for you. All you need to do is run:
+
+```bash
+gem install heroku
+heroku create
+git push heroku master
+heroku run rake db:migrate
+```
View
7 Rakefile
@@ -0,0 +1,7 @@
+#!/usr/bin/env rake
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require File.expand_path('../config/application', __FILE__)
+
+Selfstarter::Application.load_tasks
View
BIN  app/assets/images/1-background.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/assets/images/2-background.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/assets/images/3-background.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/assets/images/4-background.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/assets/images/background.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/assets/images/bullet.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  app/assets/images/rails.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
19 app/assets/javascripts/application.js
@@ -0,0 +1,19 @@
+// This is a manifest file that'll be compiled into application.js, which will include all the files
+// listed below.
+//
+// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
+// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
+//
+// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
+// the compiled file.
+//
+// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
+// GO AFTER THE REQUIRES BELOW.
+//
+//= require jquery
+//= require jquery_ujs
+//= require jquery-ui
+//= require jquery.details
+//= require jquery.textchange
+//= require preorder
+//= require_tree .
View
6 app/assets/javascripts/jquery.details.js
@@ -0,0 +1,6 @@
+(function(b){var d="open"in document.createElement("details"),e;b.fn.details=function(a){"open"===a&&(d?this.prop("open",!0):this.trigger("open"));"close"===a&&(d?this.prop("open",!1):this.trigger("close"));"init"===a&&e(b(this));if(!a){if(!d)return this.hasClass("open");var c=!1;this.each(function(){if(this.open)return c=!0,!1});return c}};e=function(a){a=a.not(".details-inited").addClass("details-inited");a.filter(".animated").each(function(){var a=b(this),d=a.children("summary").remove(),e=b("<div>").addClass("details-wrapper").append(a.children());
+a.append(e).prepend(d)});d||(a.each(function(){var a=b(this);a.children("summary").length||a.prepend("<summary>Details</summary>")}).children("summary").filter(":not(tabindex)").attr("tabindex",0).end().end().contents(":not(summary)").filter(function(){return 3===this.nodeType&&/[^\t\n\r ]/.test(this.data)}).wrap("<span>").end().end().filter(":not([open])").prop("open",!1).end().filter("[open]").addClass("open").prop("open",!0).end(),b.browser.msie&&9>b.browser.msie&&a.filter(":not(.open)").children().not("summary").hide())};
+b(function(){b("body").on("open.details","details.animated",function(){var a=b(this),c=a.children(".details-wrapper");c.hide();setTimeout(function(){c.slideDown(a.data("animation-speed"))},0)}).on("close.details","details.animated",function(){var a=b(this),c=a.children(".details-wrapper");setTimeout(function(){a.prop("open",!0).addClass("open");c.slideUp(a.data("animation-speed"),function(){a.prop("open",!1).removeClass("open")})},0)});if(d)b("body").on("click","summary",function(){var a=b(this).parent();
+a.prop("open")?a.trigger("close"):a.trigger("open")});else if(b("html").addClass("no-details"),b("head").prepend('<style>details{display:block}summary{cursor:pointer}details>summary::before{content:"\u25ba"}details.open>summary::before{content:"\u25bc"}details:not(.open)>:not(summary){display:none}</style>'),b("body").on("open.details","details",function(a){b(this).addClass("open").trigger("change.details");a.stopPropagation()}).on("close.details","details",function(a){b(this).removeClass("open").trigger("change.details");
+a.stopPropagation()}).on("toggle.details","details",function(a){var c=b(this);c.hasClass("open")?c.trigger("close"):c.trigger("open");a.stopPropagation()}).on("click","summary",function(){b(this).parent().trigger("toggle")}).on("keyup","summary",function(a){(32===a.keyCode||13===a.keyCode&&!b.browser.opera)&&b(this).parent().trigger("toggle")}),b.browser.msie&&9>b.browser.msie)b("body").on("open.details","details",function(){b(this).children().not("summary").show()}).on("close.details","details",
+function(){b(this).children().not("summary").hide()});e(b("details"))})})(jQuery);
View
10 app/assets/javascripts/jquery.textchange.js
@@ -0,0 +1,10 @@
+/*!
+ * jQuery TextChange Plugin
+ * http://www.zurb.com/playground/jquery-text-change-custom-event
+ *
+ * Copyright 2010, ZURB
+ * Released under the MIT License
+ */
+ (function(a){a.event.special.textchange={setup:function(){a(this).data("lastValue",this.contentEditable==="true"?a(this).html():a(this).val());a(this).bind("keyup.textchange",a.event.special.textchange.handler);a(this).bind("cut.textchange paste.textchange input.textchange",a.event.special.textchange.delayedHandler)},teardown:function(){a(this).unbind(".textchange")},handler:function(){a.event.special.textchange.triggerIfChanged(a(this))},delayedHandler:function(){var c=a(this);setTimeout(function(){a.event.special.textchange.triggerIfChanged(c)},
+ 25)},triggerIfChanged:function(a){var b=a[0].contentEditable==="true"?a.html():a.val();b!==a.data("lastValue")&&(a.trigger("textchange",[a.data("lastValue")]),a.data("lastValue",b))}};a.event.special.hastext={setup:function(){a(this).bind("textchange",a.event.special.hastext.handler)},teardown:function(){a(this).unbind("textchange",a.event.special.hastext.handler)},handler:function(c,b){b===""&&b!==a(this).val()&&a(this).trigger("hastext")}};a.event.special.notext={setup:function(){a(this).bind("textchange",
+ a.event.special.notext.handler)},teardown:function(){a(this).unbind("textchange",a.event.special.notext.handler)},handler:function(c,b){a(this).val()===""&&a(this).val()!==b&&a(this).trigger("notext")}}})(jQuery);
View
28 app/assets/javascripts/preorder.js.coffee
@@ -0,0 +1,28 @@
+Selfstarter =
+ firstTime: true
+ validateEmail: ->
+ # The regex we use for validating email
+ # It probably should be a parser, but there isn't enough time for that (Maybe in the future though!)
+ if /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/.test($("#email").val())
+ $("#email").removeClass("highlight")
+ $("#amazon_button").removeClass("disabled")
+ else
+ $("#email").addClass("highlight") unless Selfstarter.firstTime
+ $("#amazon_button").addClass("disabled") unless $("#amazon_button").hasClass("disabled")
+ init: ->
+ $("#email").bind "textchange", ->
+ Selfstarter.validateEmail()
+ $("#email").bind "hastext", ->
+ Selfstarter.validateEmail()
+ # The first time they type in their email, we don't want it to throw a validation error
+ $("#email").change ->
+ Selfstarter.firstTime = false
+$ ->
+ Selfstarter.init()
+ $("#email").focus()
+
+
+
+
+
+
View
14 app/assets/stylesheets/application.css
@@ -0,0 +1,14 @@
+/*
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
+ * compiled file, but it's generally better to create a new file per style scope.
+ *
+ *= require_self
+ *= require reset
+ *= require main
+ */
View
48 app/assets/stylesheets/checkout.css.scss
@@ -0,0 +1,48 @@
+.main_content
+{
+ width: 560px;
+ float: left;
+ h3
+ {
+ margin-bottom: 30px;
+ color: #4b4b4b;
+ line-height: 1;
+ }
+ p
+ {
+ line-height: 1.5;
+ }
+ #checkout
+ {
+ #email
+ {
+ padding: 15px;
+ border-radius: 10px;
+ border: 1px solid #CCC;
+ width: 350px;
+ outline: none;
+ }
+ .invalid
+ {
+ border: 1px solid orange;
+ }
+ #amazon_button
+ {
+ margin-top: 5px;
+ padding: 15px;
+ border: none;
+ }
+ }
+}
+
+.sidebar
+{
+ float: right;
+ width: 300px;
+ p
+ {
+ font-size: 18px;
+ margin-bottom: 30px;
+ line-height: 1.3;
+ }
+}
View
23 app/assets/stylesheets/footer.css.scss
@@ -0,0 +1,23 @@
+.footer
+{
+ padding: 40px 0;
+ ul
+ {
+ float: left;
+ }
+ li
+ {
+ margin-bottom: 10px;
+ }
+ a
+ {
+ font-size: 18px;
+ color: #525252;
+ font-family: $primary_font, $secondary_font, $tertiary_font;
+ }
+ p
+ {
+ float: right;
+ font-size: 18px;
+ }
+}
View
19 app/assets/stylesheets/header.css.scss
@@ -0,0 +1,19 @@
+#lockitron_header
+{
+ border: none;
+ a
+ {
+ border: none !important;
+ font-size: inherit !important;
+ }
+}
+#header
+{
+ width: 100%;
+ padding: 26px 0;
+ -moz-box-shadow: 0px 1px 3px 0px #acacac;
+ -webkit-box-shadow: 0px 1px 3px 0px #acacac;
+ box-shadow: 0px 1px 3px 0px #acacac;
+ background: #fcfcfc;
+ position: relative;
+}
View
33 app/assets/stylesheets/homepage.css.scss
@@ -0,0 +1,33 @@
+@import "homepage/stats";
+@import "homepage/call_to_action";
+@import "homepage/key_points";
+@import "homepage/other_points";
+@import "homepage/press";
+@import "homepage/faq";
+
+#tweet_button
+{
+ margin-top: 5px;
+}
+
+.fb-like
+{
+ margin-left: 5px;
+ float:left;
+}
+
+#video
+{
+ float: left;
+ width: 512px;
+ height: 385px;
+ background: #fff;
+ -moz-box-shadow: 0 2px 6px rgba(0,0,0,.39); /* drop shadow */
+ -webkit-box-shadow: 0 2px 6px rgba(0,0,0,.39); /* drop shadow */
+ box-shadow: 0 2px 6px rgba(0,0,0,.39); /* drop shadow */
+ img:hover
+ {
+ opacity: 0.5;
+ cursor: pointer;
+ }
+}
View
56 app/assets/stylesheets/homepage/call_to_action.css.scss
@@ -0,0 +1,56 @@
+#reserve_container
+{
+ float: left;
+ padding-top: 20px;
+ border-top: 1px solid #fff;
+ -moz-box-shadow: 0 -1px 0 #cbcbcb; /* drop shadow */
+ -webkit-box-shadow: 0 -1px 0 #cbcbcb; /* drop shadow */
+ box-shadow: 0 -1px 0 #cbcbcb; /* drop shadow */
+ margin-top: 30px;
+ text-align: center;
+ p
+ {
+ color: #8b8a8a;
+ font-size: 18px;
+ line-height: 1.4;
+ }
+ #ship_date
+ {
+ color: #4c4c4c;
+ font-size: 22px;
+ font-family: $primary_font, $secondary_font, $tertiary_font;
+ line-height: 1.3;
+ display: block;
+ margin: 0 auto;
+ width: 300px;
+ }
+ #price
+ {
+ color: #4c4c4c;
+ font-size: 22px;
+ font-family: $primary_font, $secondary_font, $tertiary_font;
+ line-height: 1.3;
+ display: block;
+ margin: 0 auto 10px auto;
+ width: 300px;
+ }
+}
+.reserve
+{
+ margin: 0 auto;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ padding: 20px 0;
+ width: 274px;
+ font-size: 32px;
+}
+
+#middle_reserve
+{
+ padding: 60px;
+ h2
+ {
+ margin-bottom: 26px;
+ }
+}
+
View
21 app/assets/stylesheets/homepage/faq.css.scss
@@ -0,0 +1,21 @@
+#faqs {
+ padding-bottom: 30px;
+ border-bottom: 1px solid #dfdfdf;
+ ul {
+ margin-top: 50px;
+ float: left;
+ width: 50%;
+ li
+ {
+ width: 400px;
+ margin: 0 49px 30px 0;
+ padding-left: 18px;
+ background: url(image_path("bullet.png")) no-repeat left 8px;
+ p {
+ margin-top: 10px;
+ line-height: 1.4;
+ font-size: 18px;
+ }
+ }
+ }
+}
View
50 app/assets/stylesheets/homepage/key_points.css.scss
@@ -0,0 +1,50 @@
+.big_wrapper {
+ border-bottom: 1px solid #d2d2d2;
+ background: #fff;
+}
+.big_wrapper .wrapper {
+ padding: 35px 0;
+}
+
+.point_copy {
+ width: 440px;
+ h3 {
+ margin: 20px 0 30px 0;
+ }
+}
+
+h3 {
+ font-size: 42px;
+ font-family: $primary_font, $secondary_font, $tertiary_font;
+ color: #292929;
+ line-height: 1.3;
+}
+
+.point_copy p, #other_points li p {
+ line-height: 1.5;
+}
+
+#one {
+ background: url(image_path("1-background.png")) no-repeat bottom left;
+ height: 320px;
+ width: 936px;
+}
+
+#two {
+ background: url(image_path("2-background.png")) no-repeat bottom left;
+ height: 320px;
+}
+
+#three {
+ background: url(image_path("3-background.png")) no-repeat bottom left;
+ height: 320px;
+}
+
+#four {
+ background: url(image_path("4-background.png")) no-repeat bottom left;
+ height: 320px;
+}
+
+.right {
+ margin-left: 500px;
+}
View
28 app/assets/stylesheets/homepage/other_points.css.scss
@@ -0,0 +1,28 @@
+#other_points
+{
+ li
+ {
+ width: 400px;
+ float: left;
+ margin: 0 120px 50px 0;
+ padding-top: 60px;
+ }
+ #section-1 {
+ background: url(asset-path("", "images")) no-repeat center top;
+ }
+ #section-2 {
+ background: url(asset-path("", "images")) no-repeat center top;
+ margin-right: 0px;
+ }
+ #section-3 {
+ background: url(asset-path("", "images")) no-repeat center top;
+ }
+ #section-4 {
+ background: url(asset-path("", "images")) no-repeat center top;
+ margin-right: 0px;
+ }
+ h4 {
+ width: 400px;
+ text-align: center;
+ }
+}
View
47 app/assets/stylesheets/homepage/press.css.scss
@@ -0,0 +1,47 @@
+#logos {
+ padding: 40px 0;
+ background: #f3f3f3;
+ -moz-box-shadow: 0px 1px 3px 0px #acacac;
+ -webkit-box-shadow: 0px 1px 3px 0px #acacac;
+ box-shadow: 0px 1px 3px 0px #acacac;
+ li
+ {
+ float: left;
+ margin: 0 16px;
+ a {
+ display: block;
+ height: 48px;
+ opacity: 0.2;
+ text-indent: -10000px;
+ }
+ a:hover {
+ opacity: 1;
+ }
+ }
+ #awesomeblog a
+ {
+ background: url(image-path("")) no-repeat left center;
+ width: 176px;
+ }
+ #coolpaper a
+ {
+ background: url(image-path("")) no-repeat left center;
+ width: 109px;
+ }
+ #nicemag a
+ {
+ background: url(image-path("")) no-repeat left center;
+ width: 149px;
+ }
+ #readcrunch a
+ {
+ background: url(image-path("")) no-repeat left center;
+ width: 81px;
+ }
+}
+
+
+
+
+
+
View
96 app/assets/stylesheets/homepage/stats.css.scss
@@ -0,0 +1,96 @@
+#backing
+{
+ float: left;
+ width: 383px;
+ margin: 20px 0 0 40px;
+ #backers
+ {
+ border-left: none;
+ padding-left: 0;
+ ul
+ {
+ float: left;
+ }
+ }
+ #days {
+ border-right: none;
+ padding-right: 0;
+ }
+ ul {
+ text-align: center;
+ }
+ .stats
+ {
+ margin: 0 auto;
+ color: #3f3f3f;
+ font-size: 24px;
+ display: block;
+ display: inline-block;
+ font-family: $primary_font, $secondary_font, $tertiary_font;
+ border-right: 1px solid #cbcbcb;
+ padding-right: 26px;
+ padding-left: 26px;
+ text-align: left;
+ span
+ {
+ color: #868686;
+ font-size: 18px;
+ margin-top: 5px;
+ display: block;
+ font-family: $primary_font, $secondary_font, $tertiary_font;
+ }
+ }
+}
+#progress_bg
+{
+ margin-top: 20px;
+ float: left;
+ height: 40px;
+ -moz-box-shadow: 0 1px 1px rgba(0,0,0,.41); /* drop shadow */
+ -webkit-box-shadow: 0 1px 1px rgba(0,0,0,.41); /* drop shadow */
+ box-shadow: 0 1px 1px rgba(0,0,0,.41); /* drop shadow */
+ -webkit-border-radius: 30px;
+ -moz-border-radius: 30px;
+ border-radius: 30px;
+ width: 383px;
+ background: #dbdbdb;
+ #progress
+ {
+ height: 40px;
+ -moz-box-shadow: 0 1px 1px rgba(0,0,0,.59); /* drop shadow */
+ -webkit-box-shadow: 0 1px 1px rgba(0,0,0,.59); /* drop shadow */
+ box-shadow: 0 1px 1px rgba(0,0,0,.59); /* drop shadow */
+ background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGxpbmVhckdyYWRpZW50IGlkPSJoYXQwIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwJSIgeTE9IjEwMCUiIHgyPSI1MCUiIHkyPSIwJSI+CjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiMxMzkyZGMiIHN0b3Atb3BhY2l0eT0iMSIvPgo8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwNjlkZjQiIHN0b3Atb3BhY2l0eT0iMSIvPgogICA8L2xpbmVhckdyYWRpZW50PgoKPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNoYXQwKSIgLz4KPC9zdmc+); /* gradient fill */
+ background-image: -moz-linear-gradient(90deg, #1392dc 0%, #069df4 100%); /* gradient fill */
+ background-image: -o-linear-gradient(90deg, #1392dc 0%, #069df4 100%); /* gradient fill */
+ background-image: -webkit-linear-gradient(90deg, #1392dc 0%, #069df4 100%); /* gradient fill */
+ background-image: linear-gradient(90deg, #1392dc 0%, #069df4 100%); /* gradient fill */
+ -webkit-border-radius: 30px;
+ -moz-border-radius: 30px;
+ border-radius: 30px;
+ min-width: 2%;
+ width: 100%;
+ max-width: 100%;
+ display: inline-block;
+ }
+ #progress_text
+ {
+ margin: 0 auto;
+ width: 100%;
+ font-size: 14pt;
+ display: inline-block;
+ color: white;
+ text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.37);
+ text-align: center;
+ position: relative;
+ top: -35px;
+ }
+}
+.small
+{
+ height: 20px !important;
+ #progress
+ {
+ height: 20px !important;
+ }
+}
View
8 app/assets/stylesheets/main.css.scss
@@ -0,0 +1,8 @@
+@import "variables";
+@import "primitives";
+@import "header";
+@import "footer";
+
+@import "homepage";
+@import "share";
+@import "checkout";
View
0  app/assets/stylesheets/preorder.css.scss
No changes.
View
232 app/assets/stylesheets/primitives.css.scss
@@ -0,0 +1,232 @@
+
+/* For modern browsers */
+.clearfix:before,
+.clearfix:after
+{
+ content:"";
+ display:table;
+}
+.clearfix:after
+{
+ clear:both;
+}
+/* For IE 6/7 (trigger hasLayout) */
+.clearfix {
+ zoom:1;
+}
+
+ code
+ {
+ border: 1px solid #CCC;
+ padding: 1px;
+ vertical-align: middle;
+ font-family: "Consolas", "Inconsolata", "Meslo", "Inconsolata-dz", monospace;
+ text-shadow: none;
+ font-size: 10pt;
+ }
+
+html, body {
+ width: 100%;
+}
+
+body {
+ background: $body_background;
+}
+
+.disabled
+{
+ opacity: 0.65;
+ pointer-events: none;
+}
+
+form
+{
+ margin-top: 15px;
+}
+
+body, input, textarea
+{
+ font-size: $font_size;
+ font-family: $primary_font, $secondary_font, $tertiary_font;
+ color: $text_color;
+ text-shadow: $text_shadow;
+ -webkit-font-smoothing: antialiased;
+}
+
+a
+{
+ text-decoration: none;
+ color: $link_color;
+}
+
+a:hover
+{
+ text-decoration: underline;
+}
+
+i
+{
+ font-style: italic;
+}
+
+
+
+
+// Used in the FAQ
+details, summary
+{
+ outline: none;
+}
+summary
+{
+ text-decoration: none;
+ color: $summary_color;
+ user-select: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ font-size: 20px;
+ line-height: 1.3;
+
+}
+summary:hover
+{
+ text-decoration: underline;
+ cursor: pointer;
+}
+details summary::-webkit-details-marker { display:none; content: ""; }
+// Styling the polyfill for browsers that don't support details/summary tags
+.no-details details { display: block }
+.no-details details > summary::before { content:none }
+.no-details details.open > summary::before { content:none }
+
+
+
+h1 {
+ margin: 0 auto;
+ margin-left: 380px;
+ width: 174px;
+ font-family: Helvetica;
+ font-size: 42px;
+ font-weight: bold;
+ color: $h1_color;
+ letter-spacing: -.05em;
+ float: left;
+ a
+ {
+ color: $h1_color;
+ text-decoration: none;
+ }
+ a:hover
+ {
+ color: $h1_color;
+ text-decoration: none;
+ }
+}
+
+h2 {
+ font-family: $primary_font, $secondary_font, $tertiary_font;
+ font-size: 45px;
+ color: $h2_color;
+ margin-bottom: 50px;
+}
+
+h4 {
+ font-size: 36px;
+ color: $h4_color;
+ margin-bottom: 30px;
+}
+
+h5 {
+ font-family: $primary_font, $secondary_font, $tertiary_font;
+ margin-bottom: 10px;
+ color: $h5_color;
+}
+
+.wrapper {
+ width: 935px;
+ margin: 0 auto;
+}
+
+.center {
+ text-align: center;
+}
+
+.gray_background
+{
+ width: 100%;
+ padding: 50px 0;
+ background: $gray_background_top_color; /* Old browsers */
+ background: -moz-linear-gradient(top, $gray_background_top_color 0%, $gray_background_middle_color 50%, $gray_background_bottom_color 100%); /* FF3.6+ */
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,$gray_background_top_color), color-stop(50%,$gray_background_middle_color), color-stop(100%,$gray_background_bottom_color)); /* Chrome,Safari4+ */
+ background: -webkit-linear-gradient(top, $gray_background_top_color 0%,$gray_background_middle_color 50%,$gray_background_bottom_color 100%); /* Chrome10+,Safari5.1+ */
+ background: -o-linear-gradient(top, $gray_background_top_color 0%,$gray_background_middle_color 50%,$gray_background_bottom_color 100%); /* Opera 11.10+ */
+ background: -ms-linear-gradient(top, $gray_background_top_color 0%,$gray_background_middle_color 50%,$gray_background_bottom_color 100%); /* IE10+ */
+ background: linear-gradient(to bottom, $gray_background_top_color 0%,$gray_background_middle_color 50%,$gray_background_bottom_color 100%); /* W3C */
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='$gray_background_top_color', endColorstr='$gray_background_bottom_color',GradientType=0 ); /* IE6-9 */
+ border-bottom: 1px solid $gray_background_border_color;
+}
+
+.button:hover {
+ text-decoration: none;
+ color: $button_hovered_color;
+}
+
+.button:active {
+ background: $button_active_background;
+ border: 1px solid $button_active_border;
+}
+
+.blue_button {
+ display: block;
+ color: $button_color; /* text color */
+ text-shadow: 0 -1px 1px $button-text_shadow_color; /* drop shadow */
+ -moz-box-shadow:
+ 0 1px 1px $button_box_shadow_color /* drop shadow */,
+ inset 0 -1px $button_box_shadow_inset_color /* inner shadow */;
+ -webkit-box-shadow:
+ 0 1px 1px $button_box_shadow_color /* drop shadow */,
+ inset 0 -1px 1px $button_box_shadow_inset_color /* inner shadow */;
+ background-image: $button_top_gradient; /* gradient fill */
+ background-image: -moz-linear-gradient(90deg, $button_top_gradient 0%, $button_bottom_gradient 100%); /* gradient fill */
+ background-image: -o-linear-gradient(90deg, $button_top_gradient 0%, $button_bottom_gradient 100%); /* gradient fill */
+ background-image: -webkit-linear-gradient(90deg, $button_top_gradient 0%, $button_bottom_gradient 100%); /* gradient fill */
+ background-image: linear-gradient(90deg, $button_top_gradient 0%, $button_bottom_gradient 100%); /* gradient fill */
+ -webkit-border-radius: $button_border_radius;
+ -moz-border-radius: $button_border_radius;
+ border-radius: $button_border_radius;
+ font-family: $primary_font, $secondary_font, $tertiary_font;
+}
+.blue_button:hover {
+ -moz-box-shadow:
+ 0 1px 1px $button_box_shadow_color /* drop shadow */,
+ inset 0 -1px 1px $button_box_shadow_inset_color /* inner shadow */;
+ -webkit-box-shadow:
+ 0 1px 1px$button_box_shadow_color /* drop shadow */,
+ inset 0 -1px 1px $button_box_shadow_inset_color /* inner shadow */;
+ box-shadow:
+ 0 1px 1px $button_box_shadow_color /* drop shadow */,
+ inset 0 -1px 1px $button_box_shadow_inset_color /* inner shadow */;
+ background-image: $button_ie9_gradient_hover; /* gradient fill */
+ background-image: -moz-linear-gradient(90deg, $button_top_gradient_hover 0%, $button_bottom_gradient_hover 100%); /* gradient fill */
+ background-image: -o-linear-gradient(90deg, $button_top_gradient_hover 0%, $button_bottom_gradient_hover 100%); /* gradient fill */
+ background-image: -webkit-linear-gradient(90deg, $button_top_gradient_hover 0%, $button_bottom_gradient_hover 100%); /* gradient fill */
+ background-image: linear-gradient(90deg, $button_top_gradient_hover 0%, $button_bottom_gradient_hover 100%); /* gradient fill */
+ text-decoration: none;
+}
+
+.blue_button:active {
+ -moz-box-shadow:
+ 0 1px 1px $button_box_shadow_color /* drop shadow */,
+ inset 0 3px 5px $button_box_shadow_inset_color /* inner shadow */;
+ -webkit-box-shadow:
+ 0 1px 1px $button_box_shadow_color /* drop shadow */,
+ inset 0 3px 5px $button_box_shadow_inset_color /* inner shadow */;
+ box-shadow:
+ 0 1px 1px $button_box_shadow_color /* drop shadow */,
+ inset 0 3px 5px $button_box_shadow_inset_color /* inner shadow */;
+ background-image: $button_ie9_gradient_active /* gradient fill */;
+ background-image: -moz-linear-gradient(90deg, $button_top_gradient_active 0%, $button_bottom_gradient_active 100%); /* gradient fill */
+ background-image: -o-linear-gradient(90deg, $button_top_gradient_active 0%, $button_bottom_gradient_active 100%); /* gradient fill */
+ background-image: -webkit-linear-gradient(90deg, $button_top_gradient_active 0%, $button_bottom_gradient_active 100%); /* gradient fill */
+ background-image: linear-gradient(90deg, $button_top_gradient_active 0%, $button_bottom_gradient_active 100%); /* gradient fill */
+}
View
48 app/assets/stylesheets/reset.css
@@ -0,0 +1,48 @@
+/* http://meyerweb.com/eric/tools/css/reset/
+ v2.0 | 20110126
+ License: none (public domain)
+*/
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+}
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+ display: block;
+}
+body {
+ line-height: 1;
+}
+ol, ul {
+ list-style: none;
+}
+blockquote, q {
+ quotes: none;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+ content: '';
+ content: none;
+}
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
View
50 app/assets/stylesheets/share.css.scss
@@ -0,0 +1,50 @@
+#share_container
+{
+ #congrats
+ {
+ padding: 70px 0;
+ h2
+ {
+ margin-bottom: 24px;
+ }
+ p
+ {
+ margin-bottom: 30px;
+ font-size: 24px;
+ }
+ }
+ #share
+ {
+ margin: 0 auto;
+ text-align: center;
+ margin: 0 auto;
+ #facebook_button_container
+ {
+ margin: 0 auto;
+ display: inline-block;
+ }
+ #pin_button_container
+ {
+ margin: 0 auto;
+ display: inline-block;
+ position: relative;
+ top: 1px;
+ .pin-it-button
+ {
+ }
+ }
+ #tweet_button_container
+ {
+ margin: 0 auto;
+ display: inline-block;
+ }
+ }
+ #order_id
+ {
+ margin: 0 auto;
+ margin-top: 15px;
+ padding: 0px;
+ opacity: 0.3;
+ z-index: 9999;
+ }
+}
View
63 app/assets/stylesheets/variables.css.scss
@@ -0,0 +1,63 @@
+// Hi!
+// Please change around the settings as you need. These are all the defaults
+// These only affect the primitives -- inputs, divs, h1-h5, etc (not classes/IDs, with one exception)
+
+// If you have any questions, create a GitHub issue, or email me us -- hello@lockitron.com
+
+$body_background: #E6E6E6;
+
+// Right now, we don't really use h1 and h2's correctly.
+// We'll fix it soon!
+
+$h1_color: #323232;
+$h2_color: #4B4B4B;
+$h4_color: #292929;
+$h5_color: #4B4B4B;
+
+$text_color: #6B6B6B;
+$link_color: #0008D6;
+$text_shadow: 0 1px 0px #fff;
+$font_size: 22px;
+
+// Lockitron uses ProximaNova Regular, but that costs money, so we're defaulting to Helveitca Neue instead.
+$primary_font: "Helvetica Neue";
+$secondary_font: "Helvetica";
+$tertiary_font: "Arial";
+
+// Gray background is a gradient -- top == 0%, middle == 50%, bottom == 100%
+$gray_background_top_color: #F6F6F6;
+$gray_background_middle_color: #FAFAFA;
+$gray_background_bottom_color: #FAFAFA;
+
+// The bottom border on the gray backgrounds
+$gray_background_border_color: #C4C4C4;
+
+// Button colors/background/border
+$button_color: white;
+$button_hovered_color: #0088d6;
+$button_active_background: #FAFAFA;
+$button_active_border: #C8C8C8;
+
+// This only affects .blue_button, which is the "Reserve Now" button you see on Lockitron's homepage
+$button_text_shadow_color: rgba(0,0,0,.37);
+$button_box_shadow_color: rgba(255,255,255,.92);
+$button_box_shadow_inset_color: rgba(0,0,0,.22);
+$button_border_radius: 10px;
+
+// Default State
+$button_ie9_gradient: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGxpbmVhckdyYWRpZW50IGlkPSJoYXQwIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwJSIgeTE9IjEwMCUiIHgyPSI1MCUiIHkyPSIwJSI+CjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiMwZTk2ZTQiIHN0b3Atb3BhY2l0eT0iMSIvPgo8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMmEwZmEiIHN0b3Atb3BhY2l0eT0iMSIvPgogICA8L2xpbmVhckdyYWRpZW50PgoKPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNoYXQwKSIgLz4KPC9zdmc+);
+$button_top_gradient: #0E96E4;
+$button_bottom_gradient: #02A0FA;
+
+// Hover State
+$button_ie9_gradient_hover: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGxpbmVhckdyYWRpZW50IGlkPSJoYXQwIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwJSIgeTE9IjEwMCUiIHgyPSI1MCUiIHkyPSIwJSI+CjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiMyZGE0ZTkiIHN0b3Atb3BhY2l0eT0iMSIvPgo8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMyMWFlZmYiIHN0b3Atb3BhY2l0eT0iMSIvPgogICA8L2xpbmVhckdyYWRpZW50PgoKPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNoYXQwKSIgLz4KPC9zdmc+);
+$button_top_gradient_hover: #2DA4E9;
+$button_bottom_gradient_hover: #21AEFF;
+
+// Active State
+$button_ie9_gradient_active: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGxpbmVhckdyYWRpZW50IGlkPSJoYXQwIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjUwJSIgeTE9IjEwMCUiIHgyPSI1MCUiIHkyPSIwJSI+CjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiMwMzlmZjciIHN0b3Atb3BhY2l0eT0iMSIvPgo8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMzlmZjciIHN0b3Atb3BhY2l0eT0iMSIvPgogICA8L2xpbmVhckdyYWRpZW50PgoKPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNoYXQwKSIgLz4KPC9zdmc+);
+$button_top_gradient_active: #039FF7;
+$button_bottom_gradient_active: #039ff7;
+
+// FAQ Entry
+$summary_color: #0088D6;
View
3  app/controllers/application_controller.rb
@@ -0,0 +1,3 @@
+class ApplicationController < ActionController::Base
+ protect_from_forgery
+end
View
42 app/controllers/preorder_controller.rb
@@ -0,0 +1,42 @@
+class PreorderController < ApplicationController
+ skip_before_filter :verify_authenticity_token, :only => :ipn
+
+ def index
+
+ end
+
+ def checkout
+
+ end
+
+ def prefill
+ @user = User.find_or_create_by_email!(params[:email])
+ @order = Order.prefill!(:name => Settings.product_name, :price => Settings.price, :user_id => @user.id)
+
+ # This is where all the magic happens. We create a multi-use token with Amazon, letting us charge the user's Amazon account
+ # Then, if they confirm the payment, Amazon POSTs us their shipping details and phone number
+ # From there, we save it, and voila, we got ourselves a preorder!
+ @pipeline = AmazonFlexPay.multi_use_pipeline(@order.uuid, :transaction_amount => Settings.price, :global_amount_limit => Settings.charge_limit, :collect_shipping_address => "True", :payment_reason => Settings.payment_description)
+ redirect_to @pipeline.url("#{request.scheme}://#{request.host}/preorder/postfill")
+ end
+
+ def postfill
+ unless params[:callerReference].blank?
+ @order = Order.postfill!(params)
+ end
+ # "A" means the user cancelled the preorder before clicking "Confirm" on Amazon Payments.
+ if params['status'] != 'A' && @order.present?
+ redirect_to :action => :share, :uuid => @order.uuid
+ else
+ redirect_to root_url
+ end
+ end
+
+ def share
+ @order = Order.find_by_uuid(params[:uuid])
+ end
+
+ def ipn
+ end
+
+end
View
2  app/helpers/application_helper.rb
@@ -0,0 +1,2 @@
+module ApplicationHelper
+end
View
17 app/helpers/preorder_helper.rb
@@ -0,0 +1,17 @@
+module PreorderHelper
+ def like_button(width = 70, show_faces = false)
+ raw "<div class=\"fb-like\" data-send=\"false\" data-width=\"#{width}\" data-layout=\"box_count\" data-show-faces=\"true\"></div>"
+ end
+ def pin_it_button
+ image_url = URI.encode("#{request.scheme}://#{request.host}#{image_path(Settings.product_image_url)}")
+ raw "<a href='http://pinterest.com/pin/create/button/?url=#{encoded_root_url}&media=#{image_url}' class='pin-it-button' count-layout='vertical'><img border='0' src='//assets.pinterest.com/images/PinExt.png' title='Pin It' /></a>"
+ end
+ def tweet_button
+ tweet_text = "I'm #{Settings.primary_stat_verb} number #{number_with_delimiter @order.number, :delimiter => ","} #{Settings.tweet_text}!"
+ raw "<a href='https://twitter.com/share?url=/' id='tweet_button' class='twitter-share-button twitter-button' data-url=#{request.scheme}//#{request.host}' data-via='#{Settings.product_name}' data-lang='en' data-count='vertical' data-text=\"#{tweet_text}\">Tweet</a>"
+ end
+
+ def encoded_root_url
+ raw URI.encode "#{request.scheme}://#{request.host}/preorder"
+ end
+end
View
0  app/mailers/.gitkeep
No changes.
View
0  app/models/.gitkeep
No changes.
View
68 app/models/order.rb
@@ -0,0 +1,68 @@
+class Order < ActiveRecord::Base
+ attr_accessible :address_one, :address_two, :city, :country, :number, :state, :status, :token, :transaction_id, :zip, :shipping, :tracking_number, :name, :price, :phone, :expiration
+ attr_readonly :uuid
+ before_validation :generate_uuid!, :on => :create
+ belongs_to :user
+ self.primary_key = 'uuid'
+
+
+ # This is where we create our Caller Reference for Amazon Payments, and prefill some other information.
+ def self.prefill!(options = {})
+ @order = Order.new
+ @order.name = options[:name]
+ @order.user_id = options[:user_id]
+ @order.price = options[:price]
+ @order.number = Order.next_order_number || 1
+ @order.save!
+
+ return @order
+ end
+
+ # After authenticating with Amazon, we get the rest of the details
+ def self.postfill!(options = {})
+ @order = Order.find_by_uuid!(options[:callerReference])
+ @order.token = options[:tokenID]
+ if !@order.token.blank?
+ @order.address_one = options[:addressLine1]
+ @order.address_two = options[:addressLine2]
+ @order.city = options[:city]
+ @order.state = options[:state]
+ @order.status = options[:status]
+ @order.zip = options[:zip]
+ @order.phone = options[:phoneNumber]
+ @order.country = options[:country]
+ @order.expiration = Date.parse(options[:expiry])
+ @order.save!
+
+ @order
+ end
+ end
+
+ def self.next_order_number
+ Order.order("number DESC").limit(1).first.number.to_i + 1 if Order.count > 0
+ end
+
+ def generate_uuid!
+ self.uuid = SecureRandom.hex(16)
+ end
+
+ # Implement these three methods to
+ def self.goal
+ Settings.project_goal
+ end
+
+ def self.percent
+ (Order.current.to_f / Order.goal.to_f) * 100.to_f
+ end
+
+ # See what it looks like when you have some backers! Drop in a number instead of Order.count
+ def self.current
+ Order.count
+ end
+
+ def self.revenue
+ Order.current.to_f * Settings.price
+ end
+
+ validates_presence_of :name, :price, :user_id
+end
View
4 app/models/user.rb
@@ -0,0 +1,4 @@
+class User < ActiveRecord::Base
+ attr_accessible :email
+ has_many :orders
+end
View
22 app/views/layouts/_footer.html.erb
@@ -0,0 +1,22 @@
+<div class="footer">
+ <div class="wrapper clearfix">
+ <ul>
+ <li>
+ <a href="#" %>/faq">Help & FAQs</a>
+ </li>
+ <li>
+ <a href="#">Press & Media</a>
+ </li>
+ <li>
+ <a href="http://blog.lockitron.com/">Blog</a>
+ </li>
+ <li>
+ <a href="#">Privacy Policy</a>
+ </li>
+ <li>
+ <a href="/account/login">Login</a>
+ </li>
+ </ul>
+ <p>© 2009-2012 Apigy Inc. All rights reserved. Patents pending.</p>
+ </div>
+ </div>
View
14 app/views/layouts/application.html.erb
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en" xml:lang="en" xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
+<title><%= Settings.product_name %></title>
+ <%= stylesheet_link_tag "application" %>
+ <%= javascript_include_tag "application" %>
+</head>
+<body>
+ <%= render 'header' %>
+ <%= yield %>
+ <%= render 'footer' %>
+</body>
+</html>
View
1  app/views/preorder/_copyright.html.erb
@@ -0,0 +1 @@
+<p>© You. Made by the guys at <a href="https://lockitron.com">Lockitron</a>. MIT License.</p>
View
6 app/views/preorder/_footer.html.erb
@@ -0,0 +1,6 @@
+<div class="footer">
+ <div class="wrapper clearfix">
+ <%= render 'copyright' %>
+ </div>
+</div>
+<%= render 'google_analytics' %>
View
13 app/views/preorder/_google_analytics.html.erb
@@ -0,0 +1,13 @@
+<script type="text/javascript">
+
+ var _gaq = _gaq || [];
+ _gaq.push(['_setAccount', '<%= Settings.google_id %>']);
+ _gaq.push(['_trackPageview']);
+
+ (function() {
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+ })();
+
+</script>
View
5 app/views/preorder/_header.html.erb
@@ -0,0 +1,5 @@
+<div id="header">
+ <div class="wrapper clearfix">
+ <h1 id="lockitron_header"><a href="/"><%= Settings.product_name %></a></h1>
+ </div>
+</div>
View
20 app/views/preorder/checkout.html.erb
@@ -0,0 +1,20 @@
+<div class="gray_background">
+ <div class="wrapper clearfix">
+ <div class="main_content">
+ <h3>Check out</h3>
+ <p>
+ Let your backers know how their payment information will be handled.
+ <br />
+ <br />
+ Enter your email address below.
+ </p>
+ <%= form_tag "/preorder/prefill", :id => "checkout" do %>
+ <%= email_field_tag "email", nil, :placeholder => "hello@lockitron.com", :required => "required", :id => "email" %>
+ <%= hidden_field_tag "preorder", true %>
+ <%= hidden_field_tag "quantity", params[:quantity] %>
+ <%= submit_tag "Checkout", :class => "blue_button disabled", :id => "amazon_button" %>
+ <% end %>
+ </div>
+ <%= render 'preorder/checkout/sidebar' %>
+ </div>
+</div>
View
6 app/views/preorder/checkout/_sidebar.html.erb
@@ -0,0 +1,6 @@
+<div class="sidebar">
+ <h5>When will I be charged?</h5>
+ <p>
+ We recommend that you only charge backers when you can ship, otherwise your payment provider won't be happy.
+ </p>
+</div>
View
71 app/views/preorder/homepage/_faqs.html.erb
@@ -0,0 +1,71 @@
+<div class="gray_background" id="faqs">
+ <div class="wrapper clearfix">
+ <h4>Frequently Asked Questions</h4>
+ <ul>
+ <li class=''>
+ <details class=''>
+ <summary class=''>How do I setup Amazon Payments?</summary>
+ <p>You'll need to <a href="https://payments.amazon.com/sdui/sdui/accountstatus">create an Amazon Seller Central account</a>. Afterwards, get your access key and secret key from the "Integration" tab on your AWS account. <a href="https://payments.amazon.com/sdui/sdui/helpTab/Checkout-by-Amazon/Advanced-Integration-Help/Using-Your-Access-Key">Click here for more info</a>.
+ <br />
+ <br />
+ Once you have your access key and secret key, head over to <code>config/settings.yml</code>. Change <code>amazon_access_key</code> and <code>amazon_secret_key</code> appropriately.</p>
+ </details>
+ </li>
+ <li>
+ <details class=''>
+ <summary>Can I use another payments provider?</summary>
+ <p>Of course. We haven't built in support for other providers, but we recommend that you take a look at <a href="https://stripe.com">Stripe</a> or <a href="https://wepay.com">WePay</a>.</p>
+ </details>
+ </li>
+ <li>
+ <details class=''>
+ <summary>How do I edit the FAQ?</summary>
+ <p>The faq is a partial located in <code>app/views/preorder/homepage/_faq.html.erb</code> The <code>summary</code> tag is the title, the <code>p</code> is the body. Make sure to add an <code>li</code> tag for each FAQ entry.</p>
+ </details>
+ </li>
+ <li>
+ <details class=''>
+ <summary>How do I change around the images, product name, etc?</summary>
+ <p>The best way is in <code>config/settings.yml</code>. It has variables for several different parts, the YouTube video, the product name, the call to action button ("Fork Now"), and several more.
+ </p>
+ </details>
+ </li>
+ </ul>
+ <ul class='col2'>
+ <li>
+ <details class=''>
+ <summary>How do I change the CSS?</summary>
+ <p>Head over to <code>app/assets/stylesheets/variables.css.scss</code>. It makes it easy to change around the elements used throughout the HTML.
+ <br />
+ <br />
+ Alternatively, you can dive right into the CSS, have a look at <code>app/assets/stylesheets/main.css.scss</code>.</p>
+ </details>
+ </li>
+ <li class=''>
+ <details class=''>
+ <summary>Why did you release this?</summary>
+ <p>Hardware startups are less welcome on Kickstarter than they were 6 months ago. We needed to roll our own kickstarter, so we did. Other hardware startups probably will too, so we made it easier for them by open sourcing our way of doing it.</p>
+ </details>
+ </li>
+ <li class=''>
+ <details class=''>
+ <summary class=''>What software stack does this use?</summary>
+ <p>It's a Ruby on Rails app that makes heavy use of SCSS, Kickstarter's wonderful <code>amazon_flex_pay</code> gem, and a hint of CoffeeScript.</p>
+ </details>
+ </li>
+ <li class=''>
+ <details class=''>
+ <summary class=''>How do I deploy it?</summary>
+ <p>We recommend using Heroku. We include a Procfile for you, so all you need to do is:
+ <p>
+ <p>Install the <a href="https://toolbelt.heroku.com/">Heroku Toolbelt</a></p>
+ <p>Run <code>heroku create</code> in Selfstarter's folder</code></p>
+ <p>Run <code>git push heroku master</code> in Selfstarter's folder</p>
+ </p>
+ </p>
+ </details>
+ </li>
+ </ul>
+ </div>
+</div>
+
View
51 app/views/preorder/homepage/_key_points.html.erb
@@ -0,0 +1,51 @@
+<div class="big_wrapper">
+ <div class="wrapper" id="one">
+ <div class="point_copy">
+ <h3>
+ What is Selfstarter?
+ </h3>
+ <p>
+ Selfstarter is an open source starting point for building your own ad-hoc crowdfunding site. It was put together by <a href="https://lockitron.com">Lockitron</a> after they were <a href="http://techcrunch.com/2012/10/07/the-story-of-lockitron-crowdfunding-without-kickstarter/">turned down from Kickstarter</a>.
+ <p>
+ </div>
+ </div>
+</div>
+
+<div class="big_wrapper">
+ <div class="wrapper" id="two">
+ <div class="point_copy right">
+ <h3>
+ How do I use it?
+ </h3>
+ <p>
+ Selftstarter is a starting point for you to build your own solution. It is set up to collect reservations using Amazon Payments, but you can choose you own provider too.
+ <p>
+ </div>
+ </div>
+</div>
+
+<div class="big_wrapper">
+ <div class="wrapper" id="three">
+ <div class="point_copy">
+ <h3>
+ It's just a skeleton
+ </h3>
+ <p>
+ We've kept Selfstarter really simple, but that also means that you should beef it up with your own authentication, administration and product management code.
+ <p>
+ </div>
+ </div>
+</div>
+
+<div class="big_wrapper">
+ <div class="wrapper" id="four">
+ <div class="point_copy right">
+ <h3>
+ Let's get started
+ </h3>
+ <p>
+ Most of what you need to get started is in the Readme. Selfstarter is based on Ruby on Rails, and we've tried to break up all of the different parts in a sensible fashion.
+ <p>
+ </div>
+ </div>
+</div>
View
6 app/views/preorder/homepage/_middle_reserve.html.erb
@@ -0,0 +1,6 @@
+<div class="big_wrapper">
+ <div class="wrapper center" id="middle_reserve">
+ <h2><%= Settings.ships %></h2>
+ <a href="/preorder/checkout" class="blue_button reserve"><%= Settings.middle_reserve_text %></a>
+ </div>
+</div>
View
20 app/views/preorder/homepage/_other_points.html.erb
@@ -0,0 +1,20 @@
+<div class="gray_background">
+ <ul class="wrapper clearfix" id="other_points">
+ <li id="section-1">
+ <h4>Section 1</h4>
+ <p>Morbi tempus dapibus egestas. Nullam accumsan dolor ut purus ornare congue. Phasellus ac commodo neque. Quisque non ligula lacus, id hendrerit eros.</p>
+ </li>
+ <li id="section-2">
+ <h4>Section 2</h4>
+ <p>Vivamus nec posuere mauris. Suspendisse mi sem, egestas ac tristique ac, varius ac lectus. Sed porttitor dolor adipiscing mauris sagittis.</p>
+ </li>
+ <li id="section-3">
+ <h4>Section 3</h4>
+ <p>Curabitur dolor elit, placerat et malesuada et, tristique vel nulla. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
+ </li>
+ <li id="section-4">
+ <h4>Section 4</h4>
+ <p>Curabitur ac mi elit, nec tempor odio. Nam sollicitudin, sapien sit amet elementum pretium, turpis mi fermentum nisl, ac vehicula purus lacus non velit.</p>
+ </li>
+ </ul>
+</div>
View
8 app/views/preorder/homepage/_press.html.erb
@@ -0,0 +1,8 @@
+<div id='logos'>
+ <ul class="wrapper clearfix">
+ <li id="awesomeblog"><a href=""></a></li>
+ <li id="coolpaper"><a href=""></a></li>
+ <li id="nicemag"><a href=""></a></li>
+ <li id="readcrunch"><a href=""></a></li>
+ </ul>
+</div>
View
4 app/views/preorder/homepage/_show_dont_tell.html.erb
@@ -0,0 +1,4 @@
+<div class="gray_background">
+ <%= render 'preorder/homepage/value_proposition' %>
+ <%= render 'preorder/homepage/stats' %>
+</div>
View
53 app/views/preorder/homepage/_stats.html.erb
@@ -0,0 +1,53 @@
+<div class="wrapper clearfix">
+ <div id="video">
+ <iframe width='512' height='385' src="<%= Settings.youtube_embed_url %>?autohide=1&showinfo=0&rel=0&autoplay=0"></iframe>
+ </div>
+
+ <div id="backing">
+ <ul>
+ <li class="stats" id="backers">
+ <%= number_with_delimiter Order.current, :delimiter => "," %>
+ <span><%= Settings.primary_stat %></span>
+ </li>
+ <li class="stats">
+ <%= number_to_currency Order.revenue, :precision => 0 %>
+ <span>of <%= number_to_currency Settings.project_goal.to_f * Settings.price.to_f, :precision => 0 %></span>
+ </li>
+
+ <% if Settings.expiration_date.present? %>
+ <li class="stats" id="days">
+ <%= distance_of_time_in_words_to_now(Settings.expiration_date).gsub(/\D/, "") %>
+ <span><%= distance_of_time_in_words_to_now(Settings.expiration_date).gsub(/\d/, "").gsub("about", "") %> left</span>
+ </li>
+ <% else %>
+ <li class="stats" id="days">
+ &infin;
+ <span>days left</span>
+ </li>
+ <% end %>
+ </ul>
+
+ <% if Order.current < Order.goal %>
+ <div id='progress_bg' class='small'>
+ <div id='progress' class='' style='width: <%= Order.percent %>%;'>
+ </div>
+ </div>
+ <% else %>
+ <div id="progress_bg">
+ <div id="progress">
+ </div>
+ <div id='progress_text'><%= Order.percent %>% <%= Settings.progress_text %></div>
+ </div>
+ <% end %>
+
+ <div id="reserve_container">
+ <p id="ship_date"><%= Settings.ships %></p>
+ <a href="/preorder/checkout" class="blue_button reserve"><%= Settings.call_to_action %></a>
+ <p id="price"><%= Settings.price_human %></p>
+ <p><%= Settings.dont_give_them_a_reason_to_say_no %></p>
+ <%= like_button %>
+ </div>
+
+ </div>
+
+</div>
View
3  app/views/preorder/homepage/_value_proposition.html.erb
@@ -0,0 +1,3 @@
+<div class="wrapper center">
+ <h2><%= Settings.value_proposition %></h2>
+</div>
View
6 app/views/preorder/index.html.erb
@@ -0,0 +1,6 @@
+<%= render 'preorder/homepage/show_dont_tell' %>
+<%= render 'preorder/homepage/key_points' %>
+<%= render 'preorder/homepage/other_points' %>
+<%= render 'preorder/homepage/middle_reserve' %>
+<%= render 'preorder/homepage/faqs' %>
+<%= render 'preorder/homepage/press' %>
View
26 app/views/preorder/share.html.erb
@@ -0,0 +1,26 @@
+<div class="gray_background" id='share_container'>
+ <div class="wrapper center" id="congrats">
+ <h2>
+ Hooray! You've just reserved a <%= Settings.product_name %>!
+ </h2>
+ <p>Congratulations, you're <%= Settings.primary_stat_verb %> number <span id="backer_number"><%= number_with_delimiter @order.number, :delimiter => "," %></span>, in supporting <%= Settings.product_name %>. Share the great news!</p>
+ <br />
+ <br />
+ <div id="share" class="clearfix">
+ <div id='pin_button_container'>
+ <%= pin_it_button %>
+ </div>
+ <div id='tweet_button_container'>
+ <%= tweet_button %>
+ </div>
+ <div id='facebook_button_container'>
+ <%= like_button(450, true) %>
+ </div>
+ </div>
+ <div id="order_id">Reservation ID: <%= @order.uuid %>. You can bookmark or print this page for your records.</div>
+ </div>
+
+</div>
+
+<%= render 'preorder/share/twitter_js' %>
+<%= render 'preorder/share/facebook_js' %>
View
8 app/views/preorder/share/_facebook_js.html.erb
@@ -0,0 +1,8 @@
+<div id="fb-root"></div>
+<script>(function(d, s, id) {
+ var js, fjs = d.getElementsByTagName(s)[0];
+ if (d.getElementById(id)) return;
+ js = d.createElement(s); js.id = id;
+ js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=<%= Settings.facebook_app_id %>";
+ fjs.parentNode.insertBefore(js, fjs);
+}(document, 'script', 'facebook-jssdk'));</script>
View
1  app/views/preorder/share/_twitter_js.html.erb
@@ -0,0 +1 @@
+<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="https://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
View
4 config.ru
@@ -0,0 +1,4 @@
+# This file is used by Rack-based servers to start the application.
+
+require ::File.expand_path('../config/environment', __FILE__)
+run Selfstarter::Application
View
24 config/application.rb
@@ -0,0 +1,24 @@
+require File.expand_path('../boot', __FILE__)
+
+require 'rails/all'
+
+if defined?(Bundler)
+ Bundler.require(*Rails.groups(:assets => %w(development test)))
+end
+
+module Selfstarter
+
+ class Application < Rails::Application
+
+ # --- Standard Rails Config ---
+ config.time_zone = 'Pacific Time (US & Canada)'
+ config.encoding = "utf-8"
+ config.filter_parameters += [:password]
+ config.active_record.whitelist_attributes = true
+ # Enable the asset pipeline
+ config.assets.enabled = true
+ # Version of your assets, change this if you want to expire all your assets
+ config.assets.version = '1.0'
+ # --- Standard Rails Config ---
+ end
+end
View
6 config/boot.rb
@@ -0,0 +1,6 @@
+require 'rubygems'
+
+# Set up gems listed in the Gemfile.
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+
+require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
View
25 config/database.yml
@@ -0,0 +1,25 @@
+# SQLite version 3.x
+# gem install sqlite3
+#
+# Ensure the SQLite 3 gem is defined in your Gemfile
+# gem 'sqlite3'
+development:
+ adapter: sqlite3
+ database: db/development.sqlite3
+ pool: 5
+ timeout: 5000
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+test:
+ adapter: sqlite3
+ database: db/test.sqlite3
+ pool: 5
+ timeout: 5000
+
+production:
+ adapter: sqlite3
+ database: db/production.sqlite3
+ pool: 5
+ timeout: 5000
View
5 config/environment.rb
@@ -0,0 +1,5 @@
+# Load the rails application
+require File.expand_path('../application', __FILE__)
+
+# Initialize the rails application
+Selfstarter::Application.initialize!
View
37 config/environments/development.rb
@@ -0,0 +1,37 @@
+Selfstarter::Application.configure do
+ # Settings specified here will take precedence over those in config/application.rb
+
+ # In the development environment your application's code is reloaded on
+ # every request. This slows down response time but is perfect for development
+ # since you don't have to restart the web server when you make code changes.
+ config.cache_classes = false
+
+ # Log error messages when you accidentally call methods on nil.
+ config.whiny_nils = true
+
+ # Show full error reports and disable caching
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+
+ # Don't care if the mailer can't send
+ config.action_mailer.raise_delivery_errors = false
+
+ # Print deprecation notices to the Rails logger
+ config.active_support.deprecation = :log
+
+ # Only use best-standards-support built into browsers
+ config.action_dispatch.best_standards_support = :builtin
+
+ # Raise exception on mass assignment protection for Active Record models
+ config.active_record.mass_assignment_sanitizer = :strict
+
+ # Log the query plan for queries taking more than this (works
+ # with SQLite, MySQL, and PostgreSQL)
+ config.active_record.auto_explain_threshold_in_seconds = 0.5
+
+ # Do not compress assets
+ config.assets.compress = false
+
+ # Expands the lines which load the assets
+ config.assets.debug = true
+end
View
67 config/environments/production.rb
@@ -0,0 +1,67 @@
+Selfstarter::Application.configure do
+ # Settings specified here will take precedence over those in config/application.rb
+
+ # Code is not reloaded between requests
+ config.cache_classes = true
+
+ # Full error reports are disabled and caching is turned on
+ config.consider_all_requests_local = false
+ config.action_controller.perform_caching = true
+
+ # Disable Rails's static asset server (Apache or nginx will already do this)
+ config.serve_static_assets = false
+
+ # Compress JavaScripts and CSS
+ config.assets.compress = true
+
+ # Don't fallback to assets pipeline if a precompiled asset is missed
+ config.assets.compile = false
+
+ # Generate digests for assets URLs
+ config.assets.digest = true
+
+ # Defaults to nil and saved in location specified by config.assets.prefix
+ # config.assets.manifest = YOUR_PATH
+
+ # Specifies the header that your server uses for sending files
+ # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
+ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx