fixed.html 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <title>There I Fixed It</title>
  6. <meta name="description" content="An amalgamation of dumb ideas that actually turn out to be kind of great.">
  7. <meta name="author" content="David Banham and Sam Gentle">
  8. <meta name="apple-mobile-web-app-capable" content="yes" />
  9. <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
  10. <link href='http://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
  11. <link rel="stylesheet" href="css/reset.css">
  12. <link rel="stylesheet" href="css/main.css">
  13. <link rel="stylesheet" href="css/print.css" type="text/css" media="print">
  14. <link rel="stylesheet" href="lib/css/zenburn.css">
  15. <!--[if lt IE 9]>
  16. <script src="lib/js/html5shiv.js"></script>
  17. <![endif]-->
  18. </head>
  19. <body>
  20. <div class="reveal">
  21. <!-- Used to fade in a background when a specific slide state is reached -->
  22. <div class="state-background"></div>
  23. <!-- Any section element inside of this container is displayed as a slide -->
  24. <div class="slides">
  25. <section>
  26. <h1>There I Fixed It</h1>
  27. <h3 class="inverted">Dumb hacks that end up being great</h3>
  28. <script>
  29. // Delicously hacky. Look away.
  30. if( navigator.userAgent.match( /(iPhone|iPad|iPod|Android)/i ) ) document.write( '<p style="color: rgba(0,0,0,0.3); text-shadow: none;">('+'Tap to navigate'+')</p>' );
  31. </script>
  32. </section>
  33. <section>
  34. <h2>Heads Up</h2>
  35. <p>
  36. This presentation uses a souped-up version of reveal.js
  37. </p>
  38. <p>
  39. Go here on your laptop, smartphone or tablet:
  40. </p>
  41. <img src="https://dl.dropbox.com/u/176051/120715180431.png">
  42. <p><a href="http://www.pinion.gg/sydjs/index.html">http://www.pinion.gg/sydjs/index.html</a></p>
  43. <p><a href="http://bit.ly/Nlf8Aw">http://bit.ly/Nlf8Aw</a></p>
  44. </section>
  45. <section>
  46. <section>
  47. <h2>Who the hell are you?</h2>
  48. <a href="http://www.pinion.gg" class="image">
  49. <img src="http://www.pinion.gg/images/pinion_green_horizontal.png">
  50. </a>
  51. </section>
  52. <section>
  53. <h2>What the hell is this?</h2>
  54. <img src="http://i.chzbgr.com/completestore/2012/2/24/2d633fb0-9205-46f2-9bc1-f508124308aa.jpg">
  55. </section>
  56. <section>
  57. <img src="http://i.chzbgr.com/completestore/2009/12/8/129047925338284784.jpg">
  58. </section>
  59. </section>
  60. <!-- Unql -->
  61. <section>
  62. <section>
  63. <h2>In the beginning.</h2>
  64. <p>
  65. There was SQL.
  66. </p>
  67. <p>
  68. And it was okay.
  69. </p>
  70. </section>
  71. <section>
  72. <h2>And then...</h2>
  73. <p>There was noSQL!</p>
  74. <p>And it scaled and it was all javascripty and all the hipsters loved it and everyone was happy.
  75. </section>
  76. <section>
  77. <h2>But then you want to actually use it</h2>
  78. </section>
  79. <section>
  80. <pre><code contenteditable style="font-size: 18px; margin-top: 20px;">
  81. var request = http.request({
  82. host: 'couchdb.internet.com',
  83. path: '/awesomedb/_all_docs',
  84. auth: 'zer0c00l:God'
  85. });
  86. request.end();
  87. var newrows = []
  88. request.on('response', function (response) {
  89. response.on('data', function (data) {
  90. data.rows.forEach(function(row){
  91. row.value.walkThe = "dinosaur";
  92. newrows.push(row.value);
  93. });
  94. });
  95. });
  96. request.end();
  97. var request = http.request({
  98. host: 'couchdb.internet.com',
  99. method: 'post'
  100. path: '/awesomedb/_bulk_docs',
  101. auth: 'zer0c00l:God'
  102. });
  103. request.write(JSON.stringify({docs:newrows}));
  104. request.end()
  105. </code></pre>
  106. </section>
  107. <section>
  108. <img src="http://c1eatdrinkbettercom.wpengine.netdna-cdn.com/files/2012/05/nope.jpg">
  109. </section>
  110. <section>
  111. <h2>unql-node</h2>
  112. <p>
  113. <a href="https://github.com/sgentle/unql-node">
  114. https://github.com/sgentle/unql-node
  115. </a>
  116. </p>
  117. <p>It's like SQL for NoSQL</p>
  118. <img src="http://geekspodcast.com/geekpress/wp-content/uploads/2009/07/yo_dawg-230x300.jpg">
  119. </section>
  120. <section>
  121. <h2>Deletin' stuff</h2>
  122. <pre><code contenteditable style="font-size: 18px; margin-top: 20px;">
  123. > delete from checkins where username.match(/\d{4}$/) && timestamp > (new Date()).getTime()-1000*60*60*24*7
  124. </code></pre>
  125. </section>
  126. <section>
  127. <h2>Why don't we take all the data...</h2>
  128. <pre><code contenteditable style="font-size: 18px; margin-top: 20px;">
  129. > create collection nag_old_users
  130. > insert into nag_old_users select {username: username, email: email} from user where last_login < (new Date()).getTime()-1000*60*60*24*7
  131. </code></pre>
  132. <h2>And put it over here!</h2>
  133. </section>
  134. <section>
  135. <h2>Want to see my awesome LALR recursive descent parser?</h2>
  136. <img src="http://ic.pics.livejournal.com/ontinia/10827199/5144/original.jpg">
  137. </section>
  138. <section>
  139. <h2>Nope!</h2>
  140. <pre><code contenteditable style="font-size: 18px; margin-top: 20px;">
  141. handle /delete from (\S+)(?: where (.*))?/, (db, expr, cb) ->
  142. query = "update #{db} set _deleted = true"
  143. query += " where #{expr}" if expr
  144. processExpr query, cb
  145. </code></pre>
  146. </section>
  147. <section>
  148. <h2>There I fixed it.</h2>
  149. <img src="http://i.chzbgr.com/completestore/2009/12/4/129043939908502110.jpg"</img>
  150. </section>
  151. </section>
  152. <section>
  153. <section>
  154. <h2>noDB</h2>
  155. <p>So you want to add some persistence to your simple web app.</p>
  156. </section>
  157. <section>
  158. <p>Okay so just require that each user have a couch installation.</p>
  159. <p>Or make redis a dependency. Probably include some build scripts or something to make it easier since it's the only thing in the app that needs to be compiled.</p>
  160. <img src="http://upload.wikimedia.org/wikipedia/commons/thumb/7/72/ER_Diagram_MMORPG.png/539px-ER_Diagram_MMORPG.png">
  161. <p>Maybe it would be easier to build SQLite?</p>
  162. </section>
  163. <section>
  164. <h2>Nope!</h2>
  165. <img src="https://dl.dropbox.com/u/176051/nopenopenope.jpeg">
  166. </section>
  167. <section>
  168. <h2>noDB</h2>
  169. <p>SQL < noSQL < noDB</p>
  170. </section>
  171. <section>
  172. <h2>Super simple</h2>
  173. <pre><code contenteditable style="font-size: 18px; margin-top: 20px;" class="javascript">
  174. var users = JSON.parse(fs.readFileSync('data/users.json'))
  175. users.push({name: "newguy"});
  176. fs.writeFileSync('data/users.json', JSON.stringify(users));
  177. res.send('success');
  178. </code></pre>
  179. </section>
  180. <section>
  181. <h2>Session storage too!</h2>
  182. <pre><code contenteditable style="font-size: 18px; margin-top: 20px;" class="javascript">
  183. var store = new express.session.MemoryStore;
  184. store.sessions = JSON.parse(fs.readFileSync('data/sessions.json'));
  185. setInterval(function(){
  186. fs.writeFileSync('data/sessions.json', JSON.stringify(store.sessions));
  187. }, 2000);
  188. </code></pre>
  189. </section>
  190. <section>
  191. <h2>It's basically Redis</h2>
  192. <small>It's not really</small>
  193. </section>
  194. <section>
  195. <h2>But it is:</h2>
  196. <ul>
  197. <li>Deployable</li>
  198. <li>Dependency free</li>
  199. <li>Easily backed up</li>
  200. <li>Debuggable</li>
  201. </ul>
  202. </section>
  203. <section>
  204. <h2>Databases: Fixed</h2>
  205. <img src="http://i.chzbgr.com/completestore/2009/12/20/129058269966385911.jpg">
  206. </section>
  207. </section>
  208. <section>
  209. <section>
  210. <h2>I would like to make some information available on the internet.</h2>
  211. </section>
  212. <section>
  213. <h2>So find a shared hosting provider or something.</h2>
  214. <p>But they're kind of crappy</p>
  215. </section>
  216. <section>
  217. <h2>So I'll just run my own</h2>
  218. <p>On nginx or express or something!</p>
  219. <p>But load balancing and updates and bugs and oh no.</p>
  220. </section>
  221. <section>
  222. <h2>Oh I know!</h2>
  223. <img src="http://s2.wp.com/wp-content/themes/h4/i/logo-v-rgb.png?m=1308937729g">
  224. </section>
  225. <section>
  226. <img src="https://dl.dropbox.com/u/176051/spidernope.jpeg">
  227. </section>
  228. <section>
  229. <blockquote>
  230. Augh. I wish I could just shove all this right on Akamai
  231. </blockquote>
  232. </section>
  233. <section>
  234. <p>...</p>
  235. </section>
  236. <section>
  237. <p>...</p>
  238. </section>
  239. <section>
  240. <p>...</p>
  241. </section>
  242. <section>
  243. <p>Why not?</p>
  244. </section>
  245. <section>
  246. <h2>Step 0: Generate static site</h2>
  247. <p>Use whatever you want. We really like <a href="http://jade-lang.com/">Jade.</a></p>
  248. </section>
  249. <section>
  250. <pre><code contenteditable style="font-size: 18px; margin-top: 20px;" class="jade">
  251. !!! 5
  252. include includes/head.jade
  253. body
  254. include includes/header.jade
  255. // BEGIN Content
  256. .inner-bg
  257. #content-wrapper
  258. Welcome to zombocom!
  259. </code></pre>
  260. </section>
  261. <section>
  262. <h2>make</h2>
  263. <pre><code contenteditable style="font-size: 18px; margin-top: 20px;">
  264. JADE = $(shell find pages/*.jade)
  265. HTML = $(JADE:.jade=.html)
  266. all: $(HTML)
  267. %.html: %.jade
  268. ./jade/bin/jade < $< --path $< > $@
  269. clean:
  270. rm -f $(HTML)
  271. .PHONY: clean
  272. </code></pre>
  273. </section>
  274. <section>
  275. <h2>Rackspace == Akamai</h2>
  276. <p>It's cheap. 18c per GB</p>
  277. <p>You don't have to deal directly with Akamai. Keep your soul!</p>
  278. <p><a href="http://www.rackspace.com/cloud/public/files/">http://www.rackspace.com/cloud/public/files/</a></p>
  279. </section>
  280. <section>
  281. <h2>Getting it there</h2>
  282. <p>There's a node library for that.</p>
  283. <p><a href="https://github.com/nodejitsu/node-cloudfiles">https://github.com/nodejitsu/node-cloudfiles</a></p>
  284. </section>
  285. <section>
  286. <p>There's also some tooling for that.</p>
  287. <p><a href="https://github.com/PinionTech/cloud-loader">https://github.com/PinionTech/cloud-loader</a></p>
  288. <pre><code contenteditable style="font-size: 18px; margin-top: 20px;">
  289. coffee cloud-loader.coffee -x localDir cloudContainer
  290. </code></pre>
  291. </section>
  292. <section>
  293. <h2>Deep magic</h2>
  294. <pre><code contenteditable style="font-size: 18px; margin-top: 20px;">
  295. curl -i -X GET -H "X-Auth-User: pinion" -H "X-Auth-Key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" "https://auth.api.rackspacecloud.com/v1.0"
  296. curl -X POST -H "X-Container-Meta-Web-Index: index.html" -H "X-Auth-Token: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" "https://storage101.dfw1.clouddrive.com/v1/MossoCloudFS_ad499859-aaed-43c6-813b-5e1c545f85cf/pinion-www
  297. </code></pre>
  298. </section>
  299. <section>
  300. <h2>Relax</h2>
  301. <p>Never ever care about whether your website is up.</p>
  302. <p>Go do something useful instead.</p>
  303. <br />
  304. <p>Yeah, it's harder to do pretty URLs.</p>
  305. </section>
  306. <section>
  307. <h2>So fixed</h2>
  308. <img src="http://i.chzbgr.com/completestore/2009/12/19/129057249545630776.jpg">
  309. </section>
  310. </section>
  311. <section>
  312. <section>
  313. <h2>It's not always the right thing to just fix it</h2>
  314. </section>
  315. <section>
  316. <h2>But sometimes it is</h2>
  317. <img src="http://i.chzbgr.com/completestore/2009/12/22/129060139339845620.jpg">
  318. </section>
  319. </section>
  320. <section>
  321. <h1>ALL FIXED</h1>
  322. <h3 class="inverted">BY David Banham and Sam Gentle</h3>
  323. <img src="http://i.chzbgr.com/completestore/2009/12/22/129059992995261245.jpg">
  324. </section>
  325. </div>
  326. <!-- The navigational controls UI -->
  327. <aside class="controls">
  328. <a class="left" href="#">&#x25C4;</a>
  329. <a class="right" href="#">&#x25BA;</a>
  330. <a class="up" href="#">&#x25B2;</a>
  331. <a class="down" href="#">&#x25BC;</a>
  332. </aside>
  333. <!-- Presentation progress bar -->
  334. <div class="progress"><span></span></div>
  335. </div>
  336. <script src="lib/js/head.min.js"></script>
  337. <script>
  338. var multiplex = {
  339. id: 'e754f2af1a284921'
  340. , secret: null
  341. , url: 'revealjs.jit.su'
  342. };
  343. var notes = false;
  344. head.ready( function() {
  345. // Fires when a slide with data-state=customevent is activated
  346. Reveal.addEventListener( 'customevent', function() {
  347. console.log( '"customevent" has fired' );
  348. } );
  349. // Fires each time a new slide is activated
  350. Reveal.addEventListener( 'slidechanged', function( event ) {
  351. // event.previousSlide, event.currentSlide, event.indexh, event.indexv
  352. } );
  353. // Full list of configuration options available here:
  354. // https://github.com/hakimel/reveal.js#configuration
  355. Reveal.initialize({
  356. controls: true,
  357. progress: true,
  358. history: true,
  359. theme: Reveal.getQueryHash().theme || 'default', // default/neon/beige
  360. transition: Reveal.getQueryHash().transition || 'default' // default/cube/page/concave/linear(2d)
  361. });
  362. // Load highlight.js for syntax highlighting of code samples
  363. head.js( 'lib/js/highlight.js', function() {
  364. hljs.initHighlightingOnLoad();
  365. } );
  366. } );
  367. // Scripts that should be loaded before initializing
  368. var scripts = [];
  369. // If the browser doesn't support classList, load a polyfill
  370. if( !document.body.classList ) {
  371. head.js( 'lib/js/classList.js' );
  372. }
  373. // Load markdown parser if there are slides defined using markdown
  374. if( document.querySelector( '[data-markdown]' ) ) {
  375. scripts.push( 'lib/js/showdown.js' );
  376. scripts.push( 'lib/js/data-markdown.js' );
  377. }
  378. scripts.push( 'js/reveal.js' );
  379. // If we're runnning the notes server we need to include some additional JS
  380. // TODO Is there a better way to determine if we're running the notes server?
  381. if( window.location.host === 'localhost:1947' || notes === true) {
  382. scripts.push( 'socket.io/socket.io.js' );
  383. scripts.push( 'plugin/speakernotes/client.js' );
  384. }
  385. if( multiplex.id !== null ) {
  386. scripts.push( 'socket.io/socket.io.js' );
  387. scripts.push( 'plugin/multiplex/client.js' );
  388. if( multiplex.secret !== null ) {
  389. scripts.push( 'plugin/multiplex/master.js' );
  390. }
  391. }
  392. // Load the scripts and, when completed, initialize reveal.js
  393. head.js.apply( null, scripts );
  394. </script>
  395. </body>
  396. </html>