0:00:17.080,0:00:18.450 BRAD GESSLER: All right. So, while these are, 0:00:18.540,0:00:20.130 these responses are coming in. 0:00:20.130,0:00:23.350 It looks like quite a few people have 0:00:23.360,0:00:27.010 either handcrafted html and css applications. 0:00:27.010,0:00:30.900 I'm not sure if they're single-page application, 0:00:30.900,0:00:34.170 or just deploy straight-up Rails applications 0:00:34.180,0:00:36.380 or all the logic on the server-side. 0:00:36.400,0:00:39.620 So that's good. I, I hope you'll learn 0:00:39.620,0:00:42.390 something new today about how my company, 0:00:42.390,0:00:43.930 Poll Everywhere, which the, 0:00:43.940,0:00:45.150 the product is what you're seeing. 0:00:45.150,0:00:48.060 We're a software as a service company. 0:00:48.060,0:00:51.520 We just sell this to presenters based on audience[br]size. 0:00:51.520,0:00:56.549 So, I'm gonna fire up the slides here. All 0:00:56.549,0:01:00.941 right. My display settings are working, so[br]this is 0:01:00.941,0:01:05.069 good. All right, so Middleman. The missing[br]view in 0:01:05.069,0:01:07.471 the Rails API stack. 0:01:07.500,0:01:10.440 Let's just jump into it. So, as I said 0:01:10.440,0:01:13.240 before, I am Brad Gessler, CTO and co-founder[br]of 0:01:13.240,0:01:15.760 Poll Everywhere. We started this company about[br]six years 0:01:15.760,0:01:19.240 ago now. So, we were mobile first, whatever[br]that 0:01:19.240,0:01:22.550 meant, SMS. So we went through all the pains 0:01:22.550,0:01:25.850 of having to upgrade, if you will, to the 0:01:25.860,0:01:31.520 second vintage of mobile first, which is mobile,[br]basically 0:01:31.520,0:01:34.230 a mobile website. We had a lot of fun 0:01:34.230,0:01:38.560 doing that and, and learning things the hard[br]way. 0:01:38.560,0:01:41.080 But first, what is middleman? How many of[br]you 0:01:41.080,0:01:43.100 have heard of Jekyll in this room? That seems 0:01:43.100,0:01:46.380 to be the, the predominant static website[br]generator. And 0:01:46.380,0:01:48.470 if you go to the Ruby toolbox and you 0:01:48.470,0:01:50.680 ask Ruby toolbox for, hey, what should I use 0:01:50.680,0:01:52.970 to generate a static website? You're going[br]to get 0:01:52.970,0:01:56.950 Jekyll. But it's, it's not like Jekyll, in[br]the 0:01:56.980,0:01:59.590 sense that it uses a lot of the more 0:01:59.590,0:02:03.090 modern, basically RubyGems inside of what[br]you see in 0:02:03.090,0:02:05.620 Rails 4 and Rails 3, which is, the fact 0:02:05.620,0:02:09.239 that it uses tilt to manage all of the 0:02:09.240,0:02:12.591 template and, and sass and all that good stuff. 0:02:12.600,0:02:14.680 So, if you're looking for a tool to build 0:02:14.680,0:02:16.990 a static site, don't be scared off by the 0:02:16.990,0:02:20.700 fact that middleman is catching up with Jekyll.[br]And 0:02:20.720,0:02:23.640 you should feel a lot better about that after 0:02:23.640,0:02:24.730 this talk. 0:02:24.730,0:02:30.490 So, middleman is extraordinarily well-documented.[br]Thomas Reynolds built middleman. 0:02:30.500,0:02:34.080 He's the, the guy behind this. And he also 0:02:34.080,0:02:35.910 built an amazing website with a lot of great 0:02:35.910,0:02:38.620 documentation behind it. So if you go to,[br]I 0:02:38.620,0:02:42.430 believe it's middlemanapp dot com, you can[br]get a 0:02:42.430,0:02:46.120 sense of, of everything that, that this static[br]site 0:02:46.120,0:02:48.030 generator involves. 0:02:48.040,0:02:51.270 Another really nice thing about this static[br]site generator 0:02:51.280,0:02:54.220 is that it's, it's very modular. So it actually 0:02:54.220,0:02:56.250 uses rack in its gut, so if you understand 0:02:56.250,0:02:58.299 rack, you can write a lot of extensions using 0:02:58.300,0:03:01.661 rack, which is kind of crazy. A static site 0:03:01.680,0:03:04.880 generator using rack to, to do certain things. 0:03:04.880,0:03:08.740 And there's also a, an extension framework,[br]where you 0:03:08.740,0:03:11.530 can roll things out, like, a middleman blog,[br]if 0:03:11.530,0:03:15.030 you so please. So, middleman blog in middleman[br]is 0:03:15.030,0:03:18.860 essentially a, a drop and replacement for[br]Jekyll. With 0:03:18.860,0:03:20.810 a few other things. If you're used to writing 0:03:20.820,0:03:22.949 GitHub-flavored markdown, there's a few tweaks[br]that you have 0:03:22.960,0:03:24.871 to make there to, to get that whole thing 0:03:24.871,0:03:26.520 working. 0:03:26.520,0:03:30.770 So, getting started with middleman is actually[br]very similar 0:03:30.780,0:03:33.680 to what it's like getting started in a Rails 0:03:33.680,0:03:37.810 application. You install the gem, you initialize[br]the application, 0:03:37.810,0:03:40.410 it creates all of this boilerplate code. You[br]can 0:03:40.410,0:03:42.910 see from this directory structure you have[br]your configuration 0:03:42.910,0:03:46.870 file, default index.html.erb. You get a layout[br]file and 0:03:46.880,0:03:49.820 then you have all of your assets. Stylesheets[br]and 0:03:49.820,0:03:53.140 JavaScripts. And then you spin up the server,[br]and 0:03:53.140,0:03:56.290 it boots extremely fast. So, in under a second, 0:03:56.290,0:03:59.569 you can hit this server and things are just 0:03:59.600,0:04:01.541 working. 0:04:01.541,0:04:05.130 So, the thing that I like a lot about 0:04:05.130,0:04:07.510 middleman is that it's very easy to come into 0:04:07.510,0:04:11.100 middleman from Rails. I said earlier that[br]this uses 0:04:11.100,0:04:14.049 tilt, so you can bring all the same gems 0:04:14.049,0:04:17.310 and really the same toolset that you hopefully[br]have 0:04:17.320,0:04:20.219 come to love inside of Rails into middleman[br]and 0:04:20.240,0:04:25.461 start using it without too much of a problem. 0:04:25.461,0:04:27.319 So the other interesting thing about middleman[br]is that 0:04:27.320,0:04:31.380 it's multi-environment aware. This is, I pulled[br]this from 0:04:31.380,0:04:34.711 a default middleman configuration from the[br]boilerplate and simplified 0:04:34.711,0:04:36.510 it a bit. But here you, you get an 0:04:36.510,0:04:39.070 idea that in your development environment,[br]you can put 0:04:39.080,0:04:42.610 extensions in there and activate them. Like[br]live reload. 0:04:42.610,0:04:45.280 And you can pull these extensions off of that 0:04:45.280,0:04:49.950 directory that is on the middleman website.[br]And then 0:04:49.950,0:04:52.620 your production environment in middleman is[br]called your build 0:04:52.640,0:04:53.629 environment. 0:04:53.629,0:04:56.951 So, in there, you're going to activate certain[br]extensions, 0:04:56.960,0:05:01.590 like minifying css, JavaScript, having an[br]asset hash so 0:05:01.590,0:05:04.350 that you can basically hash your assets and[br]do 0:05:04.350,0:05:06.400 what you do in Rails where you, you give 0:05:06.420,0:05:09.520 your asset path a, a hash and a path, 0:05:09.520,0:05:12.330 so that you can cache it. 0:05:12.330,0:05:15.290 So, once you have this configuration setup[br]and your 0:05:15.290,0:05:18.090 webpages and stuff are, are ready to go, you 0:05:18.100,0:05:21.220 have to deploy it somehow. And this is another 0:05:21.240,0:05:24.150 area where middleman really shines is that,[br]deployments are 0:05:24.150,0:05:28.010 incredibly easy. It's two steps easy. There[br]is the 0:05:28.010,0:05:29.940 build command, which takes all of the templates[br]and 0:05:29.940,0:05:33.480 files and whatnot, and it basically compiles[br]a bunch 0:05:33.500,0:05:38.130 of html, css, and JavaScript files into a[br]build 0:05:38.130,0:05:40.870 directory. And then the, the best part about[br]it 0:05:40.870,0:05:42.470 is that getting that build directory up to[br]your 0:05:42.470,0:05:45.389 web server is as simple as rsync. Or, if 0:05:45.400,0:05:47.001 you want to throwback to the days of using 0:05:47.001,0:05:51.520 DreamWeaver, you could use FTP to upload it.[br]Or 0:05:51.520,0:05:54.170 SFTP if you're into the whole security thing. 0:05:54.170,0:05:58.100 I developed a, a gem called shart, appropriately,[br]hoping 0:05:58.100,0:06:00.949 that it would make for an awkward IT conversation 0:06:00.960,0:06:03.781 in some corporate environment, where you can[br]deploy your 0:06:03.781,0:06:06.270 middleman website up to an S3 bucket, and[br]you 0:06:06.280,0:06:08.400 can actually set the headers that are going[br]to 0:06:08.400,0:06:13.540 emitted from that S3 bucket. Mostly caching[br]headers on, 0:06:13.540,0:06:15.050 on certain assets. 0:06:15.050,0:06:16.840 So there's a ton of tools you can use, 0:06:16.860,0:06:19.000 and there's a ton of deployment targets that[br]you 0:06:19.000,0:06:21.120 can choose from for middleman. If you do go 0:06:21.120,0:06:23.180 the route of deploying to S3, it's an incredibly 0:06:23.180,0:06:26.910 cheap way to really run your website. You[br]just 0:06:26.910,0:06:29.040 pay a couple cents a month for a, a 0:06:29.040,0:06:33.150 personal website. And it's also incredibly[br]scalable, whenever you're 0:06:33.160,0:06:35.919 deploying to an S3 endpoint. 0:06:35.920,0:06:40.361 So. Yippie. You have a static website. You[br]know, 0:06:40.361,0:06:42.229 why should you care about middleman? How is[br]this 0:06:42.229,0:06:48.000 going to, to help you scale your application? 0:06:48.000,0:06:49.981 Before I dive into that, it's really important[br]to 0:06:49.981,0:06:54.420 kind of understand the place that middleman[br]will have 0:06:54.420,0:06:58.219 in this spectrum of dynacism, is what I call 0:06:58.220,0:07:00.111 it. And it turns out dynacism is not actually 0:07:00.120,0:07:02.930 a word, so. I had to ignore the, the 0:07:02.930,0:07:04.200 spellchecker on this thing. 0:07:04.200,0:07:08.080 And it looks something like this. So the graph 0:07:08.080,0:07:10.930 that you saw earlier was actually a static[br]web 0:07:10.930,0:07:14.410 application. And if you access PollIt dot[br]com slash 0:07:14.410,0:07:16.919 brad on your smart phone, that was another[br]static 0:07:16.940,0:07:18.220 web application. 0:07:18.220,0:07:22.750 So, that's a very dynamic application, though,[br]in that 0:07:22.750,0:07:25.281 the chart has to move and animate and pull 0:07:25.281,0:07:27.640 this data from the server in real time. In 0:07:27.660,0:07:30.070 under, you know, a second, it has to get 0:07:30.070,0:07:32.490 from all of your phones, whether it comes[br]from 0:07:32.490,0:07:34.679 SMS or your smart phone, we have to get 0:07:34.680,0:07:36.441 it up on that graph in a really short 0:07:36.441,0:07:38.300 amount of time. 0:07:38.300,0:07:42.179 So that is arguably a highly dynamic application.[br]And 0:07:42.180,0:07:44.631 we also have to make things really smooth[br]and 0:07:44.640,0:07:47.779 seem very fluid, because that's just what[br]you have 0:07:47.780,0:07:51.351 to do for presentations like this. So as we 0:07:51.360,0:07:56.770 go down the dynacism spectrum, you have your[br]GUI-oriented 0:07:56.770,0:07:57.510 applications. 0:07:57.510,0:08:00.619 So, Google spreadsheets - you're probably[br]very familiar with 0:08:00.640,0:08:03.091 that. Who hasn't used it? You're doing a lot 0:08:03.091,0:08:05.469 of actions, a lot of very short actions, and 0:08:05.480,0:08:08.920 you don't want to build applications where[br]you click 0:08:08.920,0:08:09.960 a button and then you have to wait for 0:08:09.960,0:08:12.950 a response to come back to a server. The, 0:08:12.950,0:08:15.660 basically the functions of the GUI are very[br]tightly-coupled 0:08:15.660,0:08:18.360 with what comes out of that. 0:08:18.360,0:08:20.860 So we kind of start moving down into document-oriented 0:08:20.860,0:08:23.910 web apps, like an invoicing application or[br]Base Camp 0:08:23.920,0:08:25.879 where you can, you start to get into Rails 0:08:25.880,0:08:28.851 territory, where Rails is, it's kind of the[br]sweet 0:08:28.860,0:08:32.889 spot between these highly dynamic applications[br]or these highly 0:08:32.889,0:08:35.140 static applications. 0:08:35.140,0:08:38.250 So moving down into the blogging platform[br]world, you 0:08:38.250,0:08:41.900 may have something like Subtle or PostHaven,[br]that is 0:08:41.900,0:08:44.231 backed by mySQL, but for the most part it's 0:08:44.240,0:08:48.840 just storing these documents in a database[br]server, just 0:08:48.840,0:08:51.980 for the convenience of administering many[br]users in a 0:08:51.980,0:08:54.430 multi-tendency environment. 0:08:54.440,0:08:56.300 And then you go on down to your personal 0:08:56.300,0:08:57.940 blog, and maybe some of you have a GitHub 0:08:57.940,0:09:01.020 site. Maybe you're using Jekyll for that.[br]Maybe you're 0:09:01.020,0:09:04.980 using middleman. All the way down to informational[br]websites, 0:09:04.980,0:09:07.800 like a mom and pop shop or Steve's plumping 0:09:07.800,0:09:08.410 services. 0:09:08.410,0:09:10.519 If somebody wants to make a killing, go out 0:09:10.520,0:09:13.680 there and sell these restaurants that have[br]flash websites, 0:09:13.700,0:09:16.200 sell them on a middleman website so that we 0:09:16.200,0:09:17.971 can get some html out there and have less 0:09:17.980,0:09:21.839 flash on the internet. 0:09:21.840,0:09:24.751 So, where does middleman kind of fit into[br]all 0:09:24.751,0:09:28.380 of this? If you're working on a green-filled[br]application, 0:09:28.380,0:09:30.810 it's pretty easy to get started right away.[br]Kind 0:09:30.810,0:09:33.410 of what you hear about doing today is, you 0:09:33.420,0:09:36.550 build your single page html application over[br]here and 0:09:36.550,0:09:38.819 you build your smaller kind of API off to 0:09:38.840,0:09:41.051 the side using Sinatra or some type of, of 0:09:41.051,0:09:42.750 microframework. 0:09:42.750,0:09:46.400 But, since we've been around as a company[br]for, 0:09:46.400,0:09:50.270 well, since 2008, we actually started out[br]using Rails 0:09:50.270,0:09:53.610 1 point 2, I believe. It was before REST 0:09:53.640,0:09:57.040 was even a thing in Rails. So we had 0:09:57.040,0:10:00.310 this green-filled application. We spin this[br]thing up. It 0:10:00.310,0:10:01.960 was great. We were able to move pretty fast 0:10:01.960,0:10:05.030 inside of this framework. And we just set[br]up 0:10:05.030,0:10:07.930 this application at polleverywhere dot com.[br]The real time 0:10:07.940,0:10:10.350 components we had, I don't know if anybody[br]remembers 0:10:10.350,0:10:14.059 RJS, but that was basically how we would make 0:10:14.060,0:10:17.051 things appear in, in real time on Rails, was 0:10:17.060,0:10:21.400 through these kind of, in retrospect, horrendous[br]helpers that 0:10:21.420,0:10:24.640 would emit JavaScript from the server and[br]run on 0:10:24.640,0:10:25.830 your web page. 0:10:25.830,0:10:28.190 So, we got a lot of mileage out of 0:10:28.190,0:10:30.490 that. But it wasn't, it wasn't really enough.[br]We 0:10:30.500,0:10:33.380 needed something that was more visually appealing[br]than just 0:10:33.380,0:10:36.710 updating some numbers on a table. So that's[br]when 0:10:36.710,0:10:39.800 we turned to flex, because they happened to[br]have 0:10:39.800,0:10:43.650 this bar chart library that everything updated[br]in real 0:10:43.650,0:10:45.260 time. There was just a lot of stuff that 0:10:45.260,0:10:46.920 worked out of the box. 0:10:46.920,0:10:49.380 And it also just happened, out of sheer dumb 0:10:49.380,0:10:54.290 luck, that flash was installed on 99-some-odd-percent[br]of, just 0:10:54.300,0:10:56.980 all machines out on the internet. But even[br]more 0:10:56.980,0:11:00.300 compelling is that you could embed a flash[br]asset 0:11:00.300,0:11:04.819 into a PowerPoint slide because of good-old[br]ActiveX. 0:11:04.820,0:11:06.911 So we did this kind of weird hack where 0:11:06.920,0:11:10.550 we would embed these swifts that we would[br]generate. 0:11:10.550,0:11:13.189 These Flex applications, and we would actually[br]embed them 0:11:13.189,0:11:15.971 into a PowerPoint slide and send those out[br]up 0:11:15.980,0:11:17.720 on the server so that people could download[br]these 0:11:17.740,0:11:21.930 polls embedded right into PowerPoint slides.[br]So whenever they 0:11:21.930,0:11:24.759 opened it, nothing really had to be loaded[br]up 0:11:24.760,0:11:28.020 over the conference wifi connections in their[br]slide. The 0:11:28.020,0:11:30.330 swift application would just connect out to[br]our Rails 0:11:30.330,0:11:33.581 app and start pulling data out of it. 0:11:33.581,0:11:36.730 So we initially had this flex application[br]in the 0:11:36.730,0:11:41.830 same code repository as we did our Rails application. 0:11:41.860,0:11:44.060 So as we started to build more customers,[br]things 0:11:44.060,0:11:47.180 became more complex, and we were able to afford 0:11:47.180,0:11:49.390 a contractor who came in and just started[br]shredding 0:11:49.390,0:11:50.889 it on this Flex app and really making a 0:11:50.900,0:11:53.900 lot of progress. To the point where we started 0:11:53.900,0:11:57.331 getting annoyed at just how many commit messages[br]that 0:11:57.331,0:11:59.280 he would have in our, I believe it was 0:11:59.280,0:12:02.440 actually SVN at the time. So we broke that 0:12:02.440,0:12:05.269 out into a, a separate application. And we[br]were 0:12:05.269,0:12:08.481 able to move a lot quicker, in the fact 0:12:08.481,0:12:10.069 that we got to separate deployments. 0:12:10.080,0:12:11.981 So, we had this contractor working over here[br]on 0:12:11.981,0:12:13.660 the Flex app, and he was able to deploy 0:12:13.660,0:12:15.880 those Swift assets out to production. And[br]meanwhile the 0:12:15.880,0:12:19.199 Rails app team was able to do their work 0:12:19.200,0:12:21.770 and, kind of, push their updates out through[br]a 0:12:21.780,0:12:24.301 separate release cycle. And, of course, at[br]the time, 0:12:24.301,0:12:27.180 it was a lot easier for Flex to work 0:12:27.180,0:12:30.550 with XML, so we had a very fashionable XML 0:12:30.550,0:12:31.750 API. 0:12:31.750,0:12:35.259 So, time went on, and mobile started to change. 0:12:35.260,0:12:38.621 It wasn't just about SMS anymore. So we had 0:12:38.621,0:12:41.870 to think about the smart phone thing that[br]was, 0:12:41.870,0:12:44.390 that was taking off. Really it was the advent 0:12:44.420,0:12:46.180 of the iPhone. 0:12:46.180,0:12:49.170 So, having a lot of really good luck in 0:12:49.170,0:12:52.600 the past with frameworks, including Rails[br]and, and some 0:12:52.600,0:12:55.230 of the visual components that Flex gave us,[br]naturally 0:12:55.230,0:13:00.240 we gravitated towards using jQuery mobile.[br]And the other 0:13:00.240,0:13:02.559 thing, dot mobe extension, was this thing[br]that I 0:13:02.560,0:13:07.391 saw on RailsCasts about this new-fangled way[br]to kind 0:13:07.400,0:13:09.230 of say, hey, this dot mobe format is gonna 0:13:09.240,0:13:11.560 serve up this, this mobile stuff that's kind[br]of 0:13:11.560,0:13:13.050 like html. 0:13:13.050,0:13:16.790 So, it turned out that was a really bad 0:13:16.790,0:13:20.620 idea. The way that jQuery mobile worked got[br]us 0:13:20.620,0:13:22.620 about 80% of the way there, but the other 0:13:22.620,0:13:26.879 20% was just extraordinarily painful. The[br]jQuery mobile framework 0:13:26.880,0:13:30.901 was extremely opinionated. It wanted data[br]in a certain 0:13:30.901,0:13:32.220 way. It wanted the DOM to be structured a 0:13:32.240,0:13:34.610 certain way. It felt kind of clunky and we 0:13:34.610,0:13:36.650 just felt like we were kind of stuck inside 0:13:36.650,0:13:40.260 of the, the jQuery mobile world. 0:13:40.280,0:13:43.590 So, our team had to, had to do some 0:13:43.600,0:13:46.180 soul searching on this front. And what we[br]decided, 0:13:46.180,0:13:48.880 at the time, was, you know, instead of trying 0:13:48.880,0:13:52.209 to pick a framework, let's actually focus[br]at the 0:13:52.209,0:13:55.101 specific problems that we're trying to solve,[br]and let's 0:13:55.101,0:13:57.540 focus on picking libraries. 0:13:57.540,0:14:00.569 So, that made our thinking a lot more clear, 0:14:00.569,0:14:03.250 and we were able to pick exactly what we 0:14:03.250,0:14:06.821 needed it. Or, yeah, pick exactly what we[br]need, 0:14:06.821,0:14:08.619 and bring it in our application where we needed 0:14:08.620,0:14:09.261 it. 0:14:09.261,0:14:11.320 So, at the time, as well, there was still 0:14:11.340,0:14:14.600 a lot going on in the JavaScript MVC world. 0:14:14.600,0:14:16.829 You had sproutcore was one, was one of the 0:14:16.829,0:14:20.101 frameworks that we looked at. And that was[br]not 0:14:20.101,0:14:23.379 really that good-looking in terms of where[br]we came 0:14:23.400,0:14:25.001 from with jQuery mobile. 0:14:25.001,0:14:28.790 So, we decided to go full speed ahead and 0:14:28.790,0:14:31.730 use backbone.js, which was, I think, at version[br]point 0:14:31.740,0:14:33.380 eight at the time. And we knew that we 0:14:33.380,0:14:35.790 would probably be swapping out libraries,[br]because the space 0:14:35.790,0:14:38.060 was still maturing very rapidly, and there[br]were a 0:14:38.060,0:14:41.030 lot of changes. So this approach really let[br]us 0:14:41.030,0:14:43.809 hand-pick the libraries we need and swap them[br]out 0:14:43.820,0:14:45.941 as something else kind of pulled ahead of,[br]you 0:14:45.941,0:14:48.280 know, another library. 0:14:48.280,0:14:50.740 So we ended up with this single page mobile 0:14:50.740,0:14:53.940 application that we built entirely inside[br]of middleman. So 0:14:53.940,0:14:57.259 middleman was handling all of the assets that,[br]that 0:14:57.260,0:14:59.820 this application was using. And it uses kind[br]of 0:14:59.820,0:15:02.991 the standard sprockets pipeline that, that[br]you have in 0:15:03.000,0:15:05.600 Rails. So whenever you build this thing, we[br]have 0:15:05.600,0:15:08.149 three files. We upload it to our EngineX server, 0:15:08.149,0:15:11.791 and we were pretty happy with how this stuff 0:15:11.800,0:15:15.639 ends up working out on production, especially[br]for deployments. 0:15:15.640,0:15:18.111 So, if you go down this route of building 0:15:18.111,0:15:21.250 these single-page web applications, one thing[br]that you need 0:15:21.260,0:15:25.620 to be very aware of is CORS. So whenever 0:15:25.620,0:15:28.779 you went to the pollit dot com single-page[br]site 0:15:28.780,0:15:32.291 on your phone, that was actually making a[br]AJAX 0:15:32.291,0:15:36.490 request to our polleverywhere dot com host[br]to an 0:15:36.490,0:15:38.530 API endpoint on there. 0:15:38.540,0:15:40.370 So in order to do that without CORS is 0:15:40.380,0:15:43.440 you get all these cross-domain errors for[br]AJAX. But 0:15:43.440,0:15:45.899 what CORS lets you do is, the pollit dot 0:15:45.900,0:15:49.241 com host says, hey, polleverywhere dot com,[br]I'm from 0:15:49.241,0:15:51.560 a different domain. I want to make these types 0:15:51.560,0:15:55.399 of HTTP requests. A GET request, a POST request, 0:15:55.400,0:15:57.520 and, oh, by the way, I want access to 0:15:57.520,0:16:00.171 these headers. So our polleverywhere dot com[br]service says, 0:16:00.171,0:16:02.530 OK, you're on our whitelist, polleverywhere[br]dot com, so 0:16:02.540,0:16:05.360 here you go. Here's the data. Great. You want 0:16:05.360,0:16:08.940 to POST something. I'll accept that request.[br]And if 0:16:08.940,0:16:12.820 another domain tried to access it, it would[br]just 0:16:12.820,0:16:15.480 give them the cross-domain error. 0:16:15.480,0:16:17.399 So that's how we, we got around that issue. 0:16:17.400,0:16:20.541 And then another really great thing about[br]the way 0:16:20.541,0:16:22.959 that we deploy this mobile app is, it's really 0:16:22.960,0:16:26.411 easy to deploy this to a CDN. You actually 0:16:26.411,0:16:29.449 have these assets that you can push out to 0:16:29.460,0:16:32.770 other servers. So you can't really do that[br]with 0:16:32.770,0:16:34.890 a Rails app, per se. You can't just take 0:16:34.890,0:16:37.111 it and stick it over here on this file 0:16:37.120,0:16:39.610 system on this server without having to boot[br]a 0:16:39.620,0:16:43.600 bunch of stuff and go through all that. 0:16:43.600,0:16:47.250 So another interesting kind of feature of[br]that is 0:16:47.250,0:16:49.769 that you can deploy to floppy discs. So when's 0:16:49.769,0:16:54.320 the last time that anybody's seen one of these? 0:16:54.340,0:16:56.431 And we have these readers here. You pick these 0:16:56.431,0:16:59.400 up for about fifteen bucks off of Amazon.[br]And 0:16:59.400,0:17:01.180 what I'm actually going to do is a live 0:17:01.180,0:17:05.119 hardware demo. Possibly the only one at RailsConf.[br]And 0:17:05.119,0:17:09.829 let's plug this in. The really surprising[br]thing, to 0:17:09.829,0:17:15.732 me, was that Mac OS actually recognizes floppy[br]drives. 0:17:15.740,0:17:21.689 So let's plug this guy in here. Op. 0:17:21.920,0:17:28.920 Devices. I think that's devices. Oh, I got[br]to 0:17:32.520,0:17:39.520 put the disc in. All right. So you can 0:17:44.640,0:17:50.181 hear the, hear the disc spinning. Oh, let's[br]see. 0:17:50.200,0:17:54.489 There it is. Boy, that's hard to see up 0:17:54.489,0:17:58.490 here. All right. So here's the application.[br]We'll just 0:17:58.490,0:18:03.410 launch this. 0:18:03.410,0:18:09.719 [laughter] 0:18:11.620,0:18:15.000 So hopefully your network connection is faster[br]than a, 0:18:15.020,0:18:18.150 a floppy disc, but if you have a customer 0:18:18.150,0:18:20.370 living somewhere remote and the only way to[br]get 0:18:20.370,0:18:22.720 something to them is by Pony Express, you[br]can 0:18:22.740,0:18:26.000 just put this floppy disc in a satchel and, 0:18:26.000,0:18:29.071 and send the pony on its way. 0:18:29.071,0:18:31.769 The really fun thing is opening network inspector[br]on 0:18:31.769,0:18:35.030 this and seeing how Chrome measures this.[br]Is it 0:18:35.040,0:18:37.410 latency, or is the file really taking that[br]long 0:18:37.420,0:18:38.170 to load? 0:18:38.170,0:18:41.311 So, here you go. You just saw a web 0:18:41.320,0:18:46.460 application booted from a floppy disc. I can[br]go 0:18:46.460,0:18:53.460 to my pollev page and submit a vote. So, 0:18:54.620,0:18:58.270 we joke about coming up with a floppy.js library, 0:18:58.270,0:19:00.550 because if you can see the inspector down[br]there, 0:19:00.550,0:19:02.860 I don't know if it shows, but the retina 0:19:02.880,0:19:04.990 assets aren't loaded. Those were too big to[br]fit 0:19:04.990,0:19:07.561 on this floppy disc, so we came up with 0:19:07.561,0:19:11.099 some fun ideas to span our JavaScript across[br]floppy 0:19:11.100,0:19:14.370 discs. But we had better things to do like 0:19:14.370,0:19:16.790 fix bugs in production. 0:19:16.790,0:19:21.171 So, great. You can put this on floppy discs. 0:19:21.200,0:19:22.809 But I think more importantly there is, you[br]can 0:19:22.809,0:19:25.770 put them inside of phone gap or Cordova apps 0:19:25.770,0:19:27.451 or we have some customers that they want to 0:19:27.460,0:19:30.789 bundle our voting application with one of[br]their mobile 0:19:30.800,0:19:33.081 applications. So we can say, here is our html 0:19:33.081,0:19:35.899 assets, you can put them within your application,[br]and 0:19:35.900,0:19:38.020 then whenever there's three-hundred people[br]sitting in a conference 0:19:38.020,0:19:44.030 room, it won't overload the wifi. 0:19:44.030,0:19:47.420 So, caching aside, there's, there's another[br]component to this. 0:19:47.420,0:19:51.170 Flex, Flex started getting old. It started[br]getting outdated. 0:19:51.180,0:19:53.040 The writing was on the wall that this stuff 0:19:53.040,0:19:55.760 was going to die. So, you know, we set 0:19:55.760,0:19:57.471 out to write a utilization app, it was very 0:19:57.471,0:19:59.700 natural for us to think, oh, you know what, 0:19:59.700,0:20:01.820 let's use middleman. We want this thing to[br]work 0:20:01.820,0:20:05.190 on tablets, iPhones, and everywhere, so naturally[br]we're going 0:20:05.190,0:20:06.550 to use - oh, what do we call it 0:20:06.550,0:20:08.529 today? HTML5. Let's use that. 0:20:08.560,0:20:11.890 Let's use that HTML5 thing to talk to our 0:20:11.890,0:20:15.441 JSON API. And that worked great. We got this 0:20:15.441,0:20:19.139 application out there. It's actually what[br]you saw today, 0:20:19.140,0:20:21.500 it's that HTML5 application. We have all the[br]benefits 0:20:21.500,0:20:24.840 of caching and the CDN and whatnot. But, but 0:20:24.840,0:20:27.790 something came up. Whenever we were looking[br]at these 0:20:27.790,0:20:30.931 visualizations day in and day out, we just[br]said, 0:20:30.940,0:20:33.369 jeez, these feel really slow, because we were[br]using 0:20:33.369,0:20:35.230 short polling. We were hitting our server[br]once every 0:20:35.230,0:20:38.030 couple of seconds to get the new data from 0:20:38.060,0:20:41.520 our server to, to update on the graph. 0:20:41.520,0:20:42.880 So we decided we wanted to do better than 0:20:42.880,0:20:46.390 that. We rolled out a Stream API. We actually 0:20:46.390,0:20:48.831 wrote our own server at the time, because[br]socket 0:20:48.840,0:20:51.440 io wasn't quite what we wanted. I, I actually 0:20:51.440,0:20:54.950 gave a talk in 2012 about this, about streaming 0:20:54.950,0:20:58.060 resources. So we threw up that streaming API[br]server, 0:20:58.060,0:20:59.560 but there were some problems with it. 0:20:59.560,0:21:02.509 Back in 2012, when I gave that talk, we 0:21:02.520,0:21:06.191 were using AMQP on the backend of this thing. 0:21:06.191,0:21:08.159 And there were just a lot of stability issues 0:21:08.160,0:21:10.211 with that. It wasn't quite working with the,[br]with 0:21:10.220,0:21:13.190 the grain of the web and how resources work 0:21:13.190,0:21:15.789 and, and how caching and all that stuff works. 0:21:15.789,0:21:19.171 So, we had these stability issues that we[br]were 0:21:19.180,0:21:22.119 trying to deal with, and what was really nice 0:21:22.120,0:21:25.000 about having these client-side applications,[br]is we were able 0:21:25.000,0:21:27.431 to spit up our stream server on its own 0:21:27.440,0:21:30.779 host, its own completely different host, and[br]isolate it. 0:21:30.780,0:21:32.081 Our team had a lot of learning to do 0:21:32.081,0:21:35.149 to understand how to, not only build these[br]real 0:21:35.149,0:21:37.590 time web applications, how to operate them.[br]How to 0:21:37.590,0:21:38.830 scale them. 0:21:38.830,0:21:41.360 So whenever we rolled this thing out, we'd[br]have 0:21:41.360,0:21:45.181 crashes, and our client-side application was[br]able to seamlessly, 0:21:45.181,0:21:49.829 basically fail over to HTTP short polling.[br]So over 0:21:49.860,0:21:52.260 time, our team got much better at just kind 0:21:52.260,0:21:58.560 of managing all these pieces. And we had client-side 0:21:58.560,0:22:02.100 SOA going on there. So, you can also, with 0:22:02.100,0:22:04.170 CORS, if there's several APIs that you have[br]out 0:22:04.170,0:22:08.170 there, you can consume those from your JavaScript[br]and 0:22:08.170,0:22:11.210 kind of munch all that stuff together client[br]side 0:22:11.210,0:22:13.561 and just do whatever it is that you please 0:22:13.561,0:22:15.119 with that data. 0:22:15.140,0:22:18.590 So, we had so much success with all these 0:22:18.590,0:22:22.571 middleman, these single-page middleman applications,[br]that we started to 0:22:22.580,0:22:25.029 build all of our other applications in these.[br]So 0:22:25.029,0:22:28.490 our approach towards native integrations has[br]been, basically, let's 0:22:28.490,0:22:31.390 build a special web browser that has these[br]certain 0:22:31.420,0:22:34.480 hooks into JavaScript so that our web developers[br]can, 0:22:34.480,0:22:39.091 can be more productive and interact more with[br]basically 0:22:39.091,0:22:40.879 the native application. 0:22:40.880,0:22:43.290 So we can control a lot of different things 0:22:43.300,0:22:47.290 with these integrations from JavaScript. So[br]we start having 0:22:47.290,0:22:50.880 all these backbone applications pop up. Now,[br]if you've 0:22:50.880,0:22:54.260 dealt with several applications, you may be[br]thinking, jeez, 0:22:54.260,0:22:57.081 you know, you're probably repeating yourself[br]with a lot 0:22:57.081,0:22:58.739 of different things. So how do you get a 0:22:58.740,0:23:02.850 handle on this stuff in this world of sprockets 0:23:02.850,0:23:04.980 and middleman? 0:23:04.980,0:23:06.910 So what we did is we took all of 0:23:06.920,0:23:09.711 kind of the common components of this, the[br]session 0:23:09.720,0:23:13.269 components, the models and backbone. We pulled[br]all these 0:23:13.269,0:23:17.561 into this one asset gem that then everything[br]consumes 0:23:17.561,0:23:21.180 from there. So to make those gems, it's just 0:23:21.180,0:23:24.889 like making any other gem. You just say bundler 0:23:24.889,0:23:26.870 gem and then whatever the name is of your 0:23:26.870,0:23:30.070 gem. Here we have pollitassets. And the kind[br]of 0:23:30.080,0:23:32.510 different thing about this gem is that, you[br]check 0:23:32.520,0:23:34.250 is sprockets is there. And if it is, then 0:23:34.250,0:23:37.150 you start appending all these paths toward[br]the assets 0:23:37.150,0:23:38.210 where your asset gem lives. 0:23:38.220,0:23:42.821 So, for example, in our lib/assets JavaScripts[br]gem, we 0:23:42.840,0:23:46.070 have a user backbone model. We have a poll 0:23:46.070,0:23:50.690 backbone model. The stylesheets. We actually[br]use font icons 0:23:50.700,0:23:53.289 everywhere, so that we can fit all this stuff 0:23:53.289,0:23:55.500 on a floppy drive. 0:23:55.500,0:23:59.040 So, we can have all these assets located here, 0:23:59.040,0:24:01.970 which whenever all the other applications[br]consume that, they 0:24:01.970,0:24:04.220 can have a consistent look and feel that uses 0:24:04.220,0:24:06.311 kind of the visual language that we want to 0:24:06.320,0:24:09.349 use throughout all of our applications and[br]all the 0:24:09.349,0:24:11.010 different platforms. 0:24:11.010,0:24:13.480 And of course you have your vendor JavaScript[br]assets. 0:24:13.500,0:24:15.990 So if you have four different projects out[br]there, 0:24:15.990,0:24:18.681 you're probably using four different versions[br]of jQuery. This 0:24:18.681,0:24:20.519 lets us use one version of jQuery and one 0:24:20.520,0:24:23.830 version of backbone. 0:24:23.830,0:24:26.700 The way that we manage these in our development 0:24:26.700,0:24:30.140 environment is just through bundler. So you[br]can imagine 0:24:30.140,0:24:32.580 if you have one version of jQuery, well what 0:24:32.580,0:24:35.000 happens whenever you bump from the one dot[br]x 0:24:35.020,0:24:36.750 to two dot x? You're probably gonna break[br]a 0:24:36.750,0:24:39.500 lot of stuff. 0:24:39.520,0:24:42.150 But we actually don't have that problem, because[br]like 0:24:42.150,0:24:44.691 with RubyGems, you don't really care if there's[br]an 0:24:44.700,0:24:47.359 upgrade happening. What you care about is[br]that you're 0:24:47.360,0:24:50.560 getting the version that you asked for in[br]your 0:24:50.560,0:24:55.600 gem bundle. So we're able to control that[br]by 0:24:55.600,0:24:59.670 pushing our pollev assets up to a basic Git 0:24:59.670,0:25:02.730 repository, and we reference that from this[br]gemfile. You 0:25:02.730,0:25:04.870 don't actually see the, the git reference[br]in there, 0:25:04.880,0:25:07.201 but you can see that, in this case, we're 0:25:07.201,0:25:09.320 saying, hey, I want to use the new feature 0:25:09.320,0:25:13.669 branch of pollev assets. The assets path thing[br]above 0:25:13.669,0:25:17.051 that is a nice little hack so that if 0:25:17.060,0:25:22.109 you're making changes to the pollev assets[br]project, you 0:25:22.109,0:25:23.790 can pull those locally so that you don't have 0:25:23.790,0:25:26.020 to run bundle update every time. 0:25:26.040,0:25:28.360 And what's cool about middleman is, if you're[br]developing 0:25:28.360,0:25:31.530 these pollev assets locally, whenever you[br]reload middleman, it 0:25:31.530,0:25:35.171 actually picks up the changes from the, the[br]assets 0:25:35.180,0:25:37.529 gem. You don't have to reboot the server or 0:25:37.540,0:25:40.211 do anything crazy like that. 0:25:40.211,0:25:44.249 So, the way that we can build new features 0:25:44.249,0:25:46.580 now, let's say that, let's say the worst case 0:25:46.580,0:25:48.380 scenario, I have to build a new API to 0:25:48.400,0:25:52.020 support a new feature. I can branch my Rails 0:25:52.020,0:25:54.260 app project, and I can say, hey, branch this 0:25:54.260,0:25:57.850 off. It's called new feature. I'm gonna add[br]some 0:25:57.850,0:25:59.510 kind of new visualization to it that needs[br]a 0:25:59.510,0:26:01.880 new API. So I can build that API out 0:26:01.900,0:26:04.240 on my server. I can develop that locally.[br]And 0:26:04.240,0:26:07.510 I can point my middleman project at my local 0:26:07.510,0:26:08.540 server. 0:26:08.540,0:26:09.831 And I can branch it in here and I 0:26:09.840,0:26:12.559 can branch pollev assets, and basically have[br]three different 0:26:12.560,0:26:16.071 branches or, sorry, one branch and three different[br]repos, 0:26:16.071,0:26:18.560 all working on the same feature. And then[br]whenever 0:26:18.560,0:26:22.989 I go to deploy, obviously deploy the API server 0:26:22.989,0:26:25.780 functionality first, and then it would go[br]on to 0:26:25.800,0:26:29.000 roll out these middleman single page websites. 0:26:29.000,0:26:34.060 So, does it work? I think so. It's, it's 0:26:34.060,0:26:37.029 worked really well for us. We have to deal 0:26:37.029,0:26:40.990 with some weird kind of bandwidth constrained[br]environments, where 0:26:41.000,0:26:46.181 you can't trust conference wifi connections.[br]And it also, 0:26:46.181,0:26:48.080 I realized that it worked really well for[br]us 0:26:48.080,0:26:51.889 when, about two months ago, Microsoft wanted[br]to launch 0:26:51.889,0:26:58.600 their PowerPoint 2013 store inside of the[br]Microsoft Office 0:26:58.600,0:27:00.470 Applications. They actually have an app store[br]inside of 0:27:00.480,0:27:02.720 there. And we were able to pull a bunch 0:27:02.720,0:27:06.240 of assets from our mobile application into[br]our sprockets 0:27:06.240,0:27:09.550 asset gem and reuse all of that stuff, most 0:27:09.550,0:27:12.650 of it, in the PowerPoint 2013 app. And then 0:27:12.660,0:27:15.880 we were able to quickly make some customizations[br]to 0:27:15.880,0:27:17.610 that whole user experience to make it fit[br]in 0:27:17.610,0:27:20.330 with Office 2013 a little bit better. 0:27:20.340,0:27:22.920 And, of course, whenever you're running a[br]single-page JavaScript 0:27:22.920,0:27:26.730 application inside of this little web iframe,[br]essentially in 0:27:26.730,0:27:30.960 Office, it feels very close. It feels very[br]native. 0:27:30.960,0:27:32.469 So that, that worked pretty well for us. But 0:27:32.469,0:27:35.920 I think, even better than that, than reusing[br]functionality 0:27:35.920,0:27:38.990 is, inevitably, whenever you work on some[br]of these 0:27:38.990,0:27:41.000 projects, you make some kind of improvement.[br]Something just 0:27:41.020,0:27:44.230 feels better about maybe handling a login[br]or some 0:27:44.230,0:27:46.240 kind of status code or something. 0:27:46.240,0:27:48.571 So these improvements that we make in these[br]individual 0:27:48.580,0:27:50.830 projects, we're able to pull them back into[br]the 0:27:50.830,0:27:53.549 sprockets assets gem and then push them back[br]out 0:27:53.560,0:27:55.441 to all of our other projects. So all these 0:27:55.441,0:27:58.019 other projects you see up here benefit from[br]the 0:27:58.020,0:28:02.660 PowerPoint 2013 app, and that just keep, kind[br]of 0:28:02.660,0:28:04.360 reinforces itself. Reinforcing itself. 0:28:04.360,0:28:07.590 So, in a sense, the sprockets assets gem turns 0:28:07.590,0:28:11.150 into this little, perfect little framework[br]for your organization 0:28:11.150,0:28:14.421 that's extracted in the right way, where it's[br]being 0:28:14.421,0:28:17.279 extracted from stuff that's actually being[br]used and being 0:28:17.300,0:28:21.760 proven as successful by customers. 0:28:21.760,0:28:26.441 So, that's a pretty good overview of one of 0:28:26.441,0:28:29.849 the more complex middleman deployments I would[br]say is 0:28:29.849,0:28:33.090 out there, and just managing kind of multiple[br]projects. 0:28:33.100,0:28:36.310 One of the downsides and also plus sides of 0:28:36.310,0:28:40.870 middleman is that there's no out-of-the-box[br]JavaScript MVC app 0:28:40.870,0:28:44.790 solution in there. So in the case of backbone, 0:28:44.790,0:28:46.890 it's up to you to organize all the assets 0:28:46.900,0:28:49.710 in some way that, that makes sense. And different 0:28:49.720,0:28:52.520 JavaScript frameworks have, some are more[br]organized than others. 0:28:52.520,0:28:56.220 So that's both a blessing and a curse. 0:28:56.220,0:28:58.670 It worked out for us because there really[br]wasn't 0:28:58.680,0:28:59.840 a framework. We kind of came up with our 0:28:59.840,0:29:01.480 own and we didn't have to deal with, with 0:29:01.480,0:29:04.711 somebody else's bad framework. 0:29:04.711,0:29:08.909 So, that was the overview of the highly dynamic 0:29:08.909,0:29:11.191 website, which has all these static 0:29:11.200,0:29:13.959 applications stashed everywhere. 0:29:13.960,0:29:17.990 What about static websites? The other side[br]of the 0:29:17.990,0:29:21.280 kind of token where Rails fills the middle[br]ground? 0:29:21.280,0:29:25.700 So, we're developing a lot of content for,[br]for 0:29:25.720,0:29:29.610 our website. There's an explosion of use cases[br]and 0:29:29.610,0:29:32.561 all sorts of stuff that we have to implement. 0:29:32.561,0:29:34.500 So one thing that we'll probably do on this 0:29:34.500,0:29:39.360 front is extract out a content directory from[br]Rails 0:29:39.360,0:29:42.321 app. How many of you have a, in your 0:29:42.321,0:29:44.200 Rails app, it starts out. You have kind of 0:29:44.200,0:29:46.330 the home page, and then it turns into this 0:29:46.330,0:29:48.649 directory called content, and then you have[br]all these 0:29:48.649,0:29:50.990 content pages. Maybe you end up with twenty[br]or 0:29:51.000,0:29:53.000 thirty of them one day and, before you notice 0:29:53.000,0:29:55.670 this big junk drawer of content, and you have 0:29:55.670,0:29:56.870 to look in your routes file and kind of 0:29:56.870,0:29:58.480 make sense of all this stuff. 0:29:58.480,0:30:02.870 So, in middleman, you don't, the directory[br]structure is 0:30:02.880,0:30:05.460 the routing structure. So that stuff checks[br]out a 0:30:05.460,0:30:07.520 lot nicer. And it's just much easier to handle 0:30:07.540,0:30:11.060 this content. And there's also much better[br]support in 0:30:11.060,0:30:14.340 there for different things like image compression.[br]You can 0:30:14.340,0:30:18.441 png crush everything. So if you have designers[br]building 0:30:18.441,0:30:21.419 image assets and they don't understand the[br]technicalities of 0:30:21.420,0:30:24.660 making pngs much smaller, middleman can take[br]care of 0:30:24.660,0:30:26.400 that in its asset pipeline. 0:30:26.400,0:30:30.970 And, of course, on a static website like that, 0:30:30.970,0:30:34.420 you still have some dynamic components. You[br]can't just 0:30:34.420,0:30:37.451 throw a static website out there and just[br]tell 0:30:37.460,0:30:40.979 everybody, like, oh, no, forget about login[br]state. There's 0:30:40.980,0:30:42.880 some common things that people want to see,[br]so 0:30:42.880,0:30:45.211 you can take care of that with JavaScript,[br]and 0:30:45.220,0:30:46.729 you can run all that stuff client-side. 0:30:46.729,0:30:49.100 So you can have some really lightweight JS[br]that 0:30:49.100,0:30:50.600 checks with the server. Maybe it checks for[br]the 0:30:50.600,0:30:53.760 presence of a cookie to see if, if the 0:30:53.760,0:30:56.110 user's logged in or not. And then, of course, 0:30:56.120,0:30:57.790 if you have a contact us form or anything 0:30:57.790,0:31:02.020 like that, you would test these integration[br]points with 0:31:02.020,0:31:04.300 Rails so that whenever somebody types in stuff[br]into 0:31:04.300,0:31:06.170 a form and submits it, it hits your Rails 0:31:06.180,0:31:07.810 app and hopefully it doesn't blow up. 0:31:07.810,0:31:10.600 And, of course, you have other JavaScript[br]applications, like 0:31:10.600,0:31:13.490 Google Analytics, Optimize the Stripe. 0:31:13.500,0:31:14.910 All these little JavaScript-y 0:31:14.910,0:31:18.780 tools that you can throw in there. And, you 0:31:18.800,0:31:21.470 know, it makes it a little more dynamic. 0:31:21.470,0:31:23.160 So the nice thing about a static website is 0:31:23.160,0:31:26.691 that you can't get taken down that easily,[br]especially 0:31:26.700,0:31:28.269 if you have this stuff up in an S3 0:31:28.269,0:31:31.490 bucket or stashed in CDNs. I was at a 0:31:31.490,0:31:33.200 middleman meet up about a year ago, and the 0:31:33.220,0:31:35.880 folks from nest dot com were there. And they 0:31:35.880,0:31:38.360 said they were using some CNS or some, some 0:31:38.360,0:31:40.870 dynamic backend, and they kept being mentioned[br]in the 0:31:40.870,0:31:43.970 press. And their website kept getting really[br]slow. 0:31:43.980,0:31:45.780 So they looked at a few things and I 0:31:45.780,0:31:48.310 think one option involved just throwing hardware[br]at the 0:31:48.310,0:31:51.340 problem. And they decided that wasn't sane.[br]Let's just 0:31:51.340,0:31:54.040 build a static website with middleman and[br]push this 0:31:54.040,0:31:56.480 stuff out there on a really simple server.[br]And 0:31:56.480,0:31:58.640 they no longer had any of these problems where 0:31:58.640,0:32:00.340 their site would get taken down from a, an 0:32:00.340,0:32:04.270 influx of, of traffic. 0:32:04.270,0:32:06.510 So there's a lot of things to think about 0:32:06.520,0:32:09.830 whenever you're building these middleman applications. 0:32:09.840,0:32:10.480 I could probably 0:32:10.480,0:32:12.480 give another two or three talks just on these 0:32:12.480,0:32:15.650 items alone. If you want, ask me questions[br]about 0:32:15.650,0:32:19.170 this stuff later. But I don't have time to 0:32:19.170,0:32:20.440 cover that now. 0:32:20.440,0:32:22.950 And, of course, I encourage you to get out 0:32:22.950,0:32:25.680 there. Build your next website with middleman,[br]even if 0:32:25.700,0:32:28.160 it's a personal website or a blog or something. 0:32:28.160,0:32:31.840 Try it out. If you're working on single web 0:32:31.840,0:32:34.660 page applications, you could take your handcrafted[br]stuff and 0:32:34.660,0:32:36.691 throw it into middleman and start using that.[br]Start 0:32:36.700,0:32:38.759 using the asset pipeline. 0:32:38.760,0:32:41.400 A lot of these ideas that I've talked about 0:32:41.400,0:32:43.571 today, and some of the things I didn't talk 0:32:43.571,0:32:45.849 about, our company polleverything is 0:32:45.860,0:32:47.191 actually abstracting out this 0:32:47.191,0:32:50.529 framework and we're going to be releasing[br]these bits 0:32:50.540,0:32:53.770 into gitfannypack, or fannypack is gonna be[br]the name 0:32:53.770,0:32:56.540 of this, this kind of framework that uses[br]middleman 0:32:56.540,0:32:59.240 and deals with stuff like testing, binding[br]to different 0:32:59.240,0:33:01.941 environments and all that stuff. 0:33:01.941,0:33:04.449 And, of course, if you want to work on 0:33:04.460,0:33:06.470 this stuff every day and get paid for it, 0:33:06.470,0:33:12.150 you can join at team at polleverywhere. So,[br]that's 0:33:12.160,0:33:15.900 my talk. I'm Brad Gessler. I'll be posting[br]slides, 0:33:15.900,0:33:19.390 links, and, and code, up on Twitter whenever[br]I'm 0:33:19.390,0:33:22.280 not working on these slides. Thanks.