Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Web Development with CoffeeScript and Sass

10,935 views

Published on

Twin Cities Code Camp 11 talk.

Published in: Technology, Design
  • Be the first to comment

Web Development with CoffeeScript and Sass

  1. 1. Web Development with Sass and CoffeeScript Brian P. HoganBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  2. 2. Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  3. 3. What about you?Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  4. 4. Web pages run on CSS and JavaScriptBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  5. 5. CSS feels limited and repetitiveBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  6. 6. and many people don’t really understand JavaScriptBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  7. 7. Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  8. 8. We need to use better tools to build modern web apps.Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  9. 9. CoffeeScript lets us write complex JS with simpler syntax.Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  10. 10. Sass gives us extensions to CSS.Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  11. 11. Sass + CoffeeScript + automated workflowBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  12. 12. CoffeeScriptBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  13. 13. It’s more of a new syntax than a new language.Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  14. 14. Some jQuery $(function() { $("a#get").click(function(e) { .get("/ajax/get", {name: "John",time: "2pm"}, function(data) { $("#result").html(data); } ); }); });Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  15. 15. in CoffeeScript $ -> $("a#get").click (e) -> $.get "/ajax/get", {name: "John", time: "2pm"}, (data) -> $("#result").html(data)Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  16. 16. CoffeeScript borrows from Python and Ruby syntax.Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  17. 17. CoffeeScript uses significant whitespace for scope.Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  18. 18. CoffeeScript compiles to regular, plain old JavaScript.Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  19. 19. Declaring variables and objects var box, colors, firstName, lastName; firstName = "Homer" firstName = "Homer"; lastName = "Simpson" lastName = "Simpson"; colors = ["Green", "Blue", "Red"] colors = ["Green", "Blue", "Red"]; box = box = { height: 40 height: 40, width: 60 width: 60, color: red color: red };Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  20. 20. JavaScript functions // function declaration. Visible anywhere (hoisting) (function hello(name){ alert("Hello " + name + "!"); } // function expression, visible to the scope of the var var hello = function(name){ alert("Hello " + name + "!"); }Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  21. 21. Function declaration in CoffeeScript hello -> alert "Hello" hello (name) -> alert "Hello #{name}" -> (thin arrow)Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  22. 22. CoffeeScript uses function expressions. hello (name) -> alert "Hello #{name}!" var hello = function(name){ alert("Hello " + name + "!"); } #{} interpolates strings.Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  23. 23. New syntax means new features.Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  24. 24. a jQuery example $(function() { var displayError, displaySuccess, url; $("form").submit(function(event) {}); event.preventDefault(); url = $(this).attr("href"); $.ajax({ url: url + ".js", success: function(data, status, xhr) { displaySuccess($("#form")); }, error: function(xhr, status, error) { displayError(error); } }); displaySuccess = function(form) { var element; element = $("<p>Thanks for signing up!").addClass("success"); element.insertAfter(form); form.hide(); }; displayError = function(error) { $("#notice").attr("html", error); }; });Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  25. 25. jQuery $(function(){}) $ -> $("form").submit (event) -> event.preventDefault() url = $(this).attr "href" $.ajax url: url + ".js" success: (data, status, xhr) -> displaySuccess($("form")) error: (xhr, status, error) -> displayError error displaySuccess = (form) -> element = $("<p>Thanks for signing up!").addClass("success") element.insertAfter form form.hide() displayError = (error) -> $("#notice").attr "html", errorBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  26. 26. jQuery event handler $ -> $("form").submit (event) -> event.preventDefault() url = $(this).attr "href" $.ajax url: url + ".js" success: (data, status, xhr) -> displaySuccess($("form")) error: (xhr, status, error) -> displayError error displaySuccess = (form) -> element = $("<p>Thanks for signing up!").addClass("success") element.insertAfter form form.hide() displayError = (error) -> $("#notice").attr "html", errorBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  27. 27. jQuery $.ajax $ -> $("form").submit (event) -> event.preventDefault() url = $(this).attr "href" $.ajax url: url + ".js" success: (data, status, xhr) -> displaySuccess($("form")) error: (xhr, status, error) -> displayError error displaySuccess = (form) -> element = $("<p>Thanks for signing up!").addClass("success") element.insertAfter form form.hide() displayError = (error) -> $("#notice").attr "html", errorBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  28. 28. success and error callbacks $ -> $("form").submit (event) -> event.preventDefault() url = $(this).attr "href" $.ajax url: url + ".js" success: (data, status, xhr) -> displaySuccess($("form")) error: (xhr, status, error) -> displayError error displaySuccess = (form) -> element = $("<p>Thanks for signing up!").addClass("success") element.insertAfter form form.hide() displayError = (error) -> $("#notice").attr "html", errorBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  29. 29. -> leaves (this) scope alone. $ -> $("form").submit (event) -> event.preventDefault() url = $(this).attr "href" $.ajax url: url + ".js" success: (data, status, xhr) -> displaySuccess($("form")) error: (xhr, status, error) -> displayError error displaySuccess = (form) -> element = $("<p>Thanks for signing up!").addClass("success") element.insertAfter form form.hide() displayError = (error) -> $("#notice").attr "html", errorBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  30. 30. =>Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  31. 31. => binds this to the function body $ -> $("form").submit (event) -> event.preventDefault() url = $(this).attr "href" $.ajax url: url + ".js" success: (data, status, xhr) => displaySuccess($(this)) error: (xhr, status, error) -> displayError error displaySuccess = (form) -> element = $("<p>Thanks for signing up!").addClass("success") element.insertAfter form form.hide() displayError = (error) -> $("#notice").attr "html", errorBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  32. 32. ComprehensionsBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  33. 33. Simple iteration alert color for color in ["red", "green", "blue"] var colors = ["red", "green", "blue"]; for (i = 0, length = colors.length; i < length; i++) { var color = colors[i]; alert(color); }Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  34. 34. “for in” people = [ {name: "Homer", age: 42} {name: "Bart", age: 10} ] for person in people alert "#{person.name} is #{person.age} years old"Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  35. 35. That’s just the beginning.Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  36. 36. Existential operator (?) total ?= 0 if (typeof total !== "undefined" && total !== null) { total; } else { total = 0; };Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  37. 37. Object-oriented JavaScriptBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  38. 38. Classes var Person, p; Person = (function() { function Person(options) { this.firstname = options.firstname; this.lastname = options.lastname; this.age = options.age; } Person.prototype.fullname = function() { return "" + this.firstname + " " + this.lastname; }; return Person; })(); p = new Person({ firstname: "Brian", lastname: "Hogan" }); alert(p.fullname());Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  39. 39. Classes var Person, p; Person = (function() { function Person(options) { this.firstname = options.firstname; this.lastname = options.lastname; class Person this.age = options.age; constructor: (options) -> } @firstname = options.firstname Person.prototype.fullname = function() { @lastname = options.lastname return "" + this.firstname + " " + this.lastname; @age = options.age }; return Person; fullname: -> })(); "#{@firstname} #{@lastname}" p = new Person({ firstname: "Brian", lastname:="Hogan" p new Person }); alert p.fullname() alert(p.fullname());Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  40. 40. We can even extend classes! class basicWindow constructor: -> class mainWindow extends basicWindow @window = Ti.UI.createWindow({ constructor: -> backgroundColor: "#F5F5ED" super }) @window.backgroundColor = "#fff" open: -> @window.open()Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  41. 41. How do we use it? In the web browser itself via Node.js With Ruby, via GuardBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  42. 42. In the browser? <script language="text/coffeescript"> people = [ {name: "Homer", age: 42} {name: "Bart", age: 10} ] for person in people do (person) -> alert "#{person.name} is #{person.age} years old" </script> <script src="coffee-script.js"></script> (this is slow.)Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  43. 43. With Node.js Install Node.js Install npm npm install -g coffee-script coffee --compile --output js/ coffee/ coffee -o js/ -cw coffee/Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  44. 44. Ruby and Guard Install Ruby gem install guard-coffeescript In our project guard init coffeescript guardBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  45. 45. Guard watches input folders for changes and writes output files.Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  46. 46. Guard works with Sass too.Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  47. 47. Sass Syntactically Awesome StylesheetsBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  48. 48. Sass gives CSS everything programmers want.Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  49. 49. CSS .sidebar { color: #000; border: 1px solid #000; } .sidebar p { margin-bottom: 20px; } .sidebar ul { margin-bottom: 10px; } .sidebar h1 { margin-bottom: 0; } .main{ color: #000; }Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  50. 50. CSS .sidebar { color: #000; border: 1px solid #000; } .sidebar p { margin-bottom: 20px; } .sidebar ul { margin-bottom: 10px; } .sidebar h1 { margin-bottom: 0; } .main{ color: #000; }Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  51. 51. CSS .sidebar { color: #000; border: 1px solid #000; } .sidebar p { margin-bottom: 20px; } .sidebar ul { margin-bottom: 10px; } .sidebar h1 { margin-bottom: 0; } .main{ color: #000; }Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  52. 52. Sass to the rescue!Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  53. 53. Variables! $measure: 20px $color: #ce4dd6 .sidebar background-olor: $color border: 1px solid lighten($color, 20%) p margin-bottom: $measure ul margin-bottom: $measure / 2 h1 margin-bottom: 0Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  54. 54. Variables and helper functions! $measure: 20px $color: #ce4dd6 .sidebar background-olor: $color border: 1px solid lighten($color, 20%) p margin-bottom: $measure ul margin-bottom: $measure / 2 h1 margin-bottom: 0Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  55. 55. Scope with nesting $measure: 20px $color: #ce4dd6 .sidebar background-olor: $color border: 1px solid lighten($color, 20%) p margin-bottom: $measure ul margin-bottom: $measure / 2 h1 margin-bottom: 0Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  56. 56. Indented Sass SCSS $measure: 20px $measure: 20px; $color: #000 $color: #000; .sidebar .sidebar{ color: $color color: $color; border: 1px solid $color border: 1px solid $color; p p{ margin-bottom: $measure margin-bottom: $measure; } ul margin-bottom: $measure / 2 ul{ margin-bottom: $measure / 2; h1 } margin-bottom: 0 h1{ margin-bottom: 0; } }Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  57. 57. But wait... there’s more!Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  58. 58. Modularization _mixins.scss @import "mixins"; @import "reset"; @import "base"; _reset.scss @import "fonts"; _base.scss _fonts.scssBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  59. 59. Reusable Functions (mixins) blockquote { @mixin rounded($radius){ width: 225px; border-radius: $radius; padding: 15px 30px; -moz-border-radius: $radius; margin: 0; -webkit-border-radius: $radius; position: relative; } background: #faa; @include rounded(20px); } .button { cursor: pointer; color: #000; text-decoration: none; @include rounded(12px); }Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  60. 60. Mixins + Interation + Variables @mixin shadow($x, $y, $offset, $color) @each $prefix in "", -moz-, -webkit-, -o-, -khtml- #{$prefix}box-shadow: $x $y $offset $colorBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  61. 61. Mixins + Interation + Variables @mixin shadow($x, $y, $offset, $color) @each $prefix in "", -moz-, -webkit-, -o-, -khtml- #{$prefix}box-shadow: $x $y $offset $color box-shadow: 5px 5px 5px #dddddd; -moz-box-shadow: 5px 5px 5px #dddddd; -webkit-box-shadow: 5px 5px 5px #dddddd; -o-box-shadow: 5px 5px 5px #dddddd; -khtml-box-shadow: 5px 5px 5px #dddddd; }Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  62. 62. Create well-organized folders and libraries of stylesheets.Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  63. 63. or use Compass. http://compass-style.org/Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  64. 64. Compass has helpers @import compass @include box-shadow(#ddd 5px 5px 5px) box-shadow: 5px 5px 5px #dddddd; -moz-box-shadow: 5px 5px 5px #dddddd; -webkit-box-shadow: 5px 5px 5px #dddddd; -o-box-shadow: 5px 5px 5px #dddddd;}Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  65. 65. How do we use it? via Sass via a supported IDE With Ruby, via GuardBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  66. 66. with Sass Install Ruby $ gem install sass $ sass --watch sass:stylesheetsBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  67. 67. Ruby and Guard Install Ruby gem install guard-sass In our project guard init sass guardBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  68. 68. Using Sass and CoffeeScript togetherBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  69. 69. Mindscape Web Workbench http://www.mindscapehq.com/products/web-workbenchBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  70. 70. Ruby and Guard Install Ruby gem install guard-sass guard- coffeescript In our project guard init sass guard init coffeescript guardBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  71. 71. Let’s talk deploymentBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  72. 72. Rails 3.1 and CapistranoBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  73. 73. Asset PackagingBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  74. 74. So instead of this... <link rel="stylesheet" href="stylesheets/layout.css"> <link rel="stylesheet" href="stylesheets/style.css"> <script src="javascripts/jquery-1.7.0.min.js"></script> <script src="javascripts/app.js"></script>Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  75. 75. ...let’s do this: <link rel="stylesheet" href="assets/app.css"> <script src="assets/app.js"></script>Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  76. 76. Ruby + Guard + Jammit Install Ruby $ gem install guard-jammitBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  77. 77. Sass, CoffeeScript, Jammit watch Sass files for changes Place output css in tmp/ folder watch CoffeeScript files for changes Place output js in tmp/ folder Use Jammit to combine them.Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  78. 78. config/assets.yml stylesheets: app: - tmp/app.css - tmp/style.css javascripts: app: - javascripts/jquery-1.6.4.js - tmp/app.jsBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  79. 79. Guardfile guard "coffeescript", :input => "coffeescripts", :output => "tmp" guard "sass", :input => "sass", :output => "tmp" guard "jammit" do watch(/^javascripts/(.*).js/) watch(/^stylesheets/(.*).css/) watch(/^tmp/(.*).js/) watch(/^tmp/(.*).css/) endBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  80. 80. Jammit places files in public/assets <link rel="stylesheet" href="assets/app.css"> <script src="assets/app.js"></script>Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  81. 81. Deploy with Rake SERVER = "yourhost.com" USERNAME = "yourusername" REMOTE_FOLDER = "/home/#{USERNAME}/yourhost.com" REMOTE_FOLDER = 22 require net/scp desc "compile CSS, js files" task :compile do require guard Guard.setup Guard::Dsl.evaluate_guardfile Guard::guards.each{|guard| guard.run_all} end desc "Deploy web site" task :deploy => :compile do Net::SSH.start(SERVER, USERNAME, {:port => PORT} ) do |ssh| ssh.sftp.rmdir File.join(REMOTE_FOLDER, "public") ssh.scp.upload! "public", REMOTE_FOLDER, :recursive => true end endBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  82. 82. qedproject https://github.com/napcs/qedprojectBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  83. 83. qedproject Install Ruby gem install qedproject qedproject myapp -c -s -a -l jquery creates app with Sass, CoffeeScript, Asset packaging, and jQuery Sets up Guard and a simple Rake file for deploymentBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  84. 84. DemoBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  85. 85. Short syntax Nested Selectors Catch errors at compile time Variables List Mixins Comprehensions Composition ClassesBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  86. 86. With asset packagingand automated deployment...Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  87. 87. ...CoffeeScript and Sass make developers happy.Brian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682
  88. 88. Questions? http://pragprog.com/book/wbdev/web- development-recipesBrian P. Hogantwitter: @bphoganwww.webdevelopmentrecipes.com Rate this talk at http://spkr8.com/t/8682

×