 All right, so I think we'll make a start as the last few people trickle in. My name is Kevin Yank, and this is Developer Happiness on the Frontend with Elm. So I think we are all of us here to get today together, at least in some part, because the Ruby programming language was written to make programmers happy. And as he touched on in his keynote yesterday, DHH, when he describes the design objectives for the Rails framework, he put optimizing for programmer happiness right there at the top. And in this article, the Rails doctrine, DHH describes what he means by developer happiness, and it gives us a few examples. And the one that stood out to me was these array accessors. We all know about array first and array last. Well, Rails adds array second, third, fourth, and fifth, and for good measure throws in 42. And there is no reason for this feature to exist except to make programmers like us smile when we find it in the documentation. And so that's what I think of when I think of programmer happiness. Now I work at a company called Cultramp down in Melbourne, Australia. We build a big web app that companies like Adobe, Airbnb, and Slack use to measure their company culture to collect feedback and data to drive positive change in their workplaces. And so as you might imagine at Cultramp, we take our company culture very seriously and our development culture too. So we value programming languages that make programmers happy. And for that reason, we made the choice early on to use Ruby, and more recently, we've been adding some elixir to our backend as well because these are languages that make programmers happy. On the front end, we chose React not too long ago. And up until about six months ago, we had three teams all building their UI in React. Now the thing about React is it's a JavaScript framework. And this is probably in the top 10 list of cheap conference slide laughs. But what I'll add to this unoriginal observation is yes, the book on the right is actually getting bigger with new additions to the language in ES 2015 and later. JavaScript is getting better. It's getting some nice programmer happiness features. But the thing about JavaScript is it's part of the web platform. So you can never take anything out of JavaScript. And so the book on the left is getting thicker at the same rate. And so for all its strengths, and I will certainly acknowledge that JavaScript is an amazingly versatile and powerful language, it is not, I think, a language designed for programmer happiness. And so for that reason, when it came time to light up a fourth project team at Culture App, we were open to other possibilities. And the possibility we decided to experiment with was Elm. So in this talk, I'll give you a brief introduction to Elm. And then we'll dive into some things about Elm that I think are great sources of developer happiness. And I'll break these into two big categories, the lovable compiler and Elm's radical simplicity. And we'll drill into each of these a little bit. And I'll wrap it all up by coming back to why we're all here today. We'll talk a little bit about Rails and how it compares to Elm. So let's go for an introduction to Elm. It's my distinct pleasure to provide, I hope, the first real glimpse at Elm for many of you in the room today. And that makes me very happy. Elm calls itself a delightful language for reliable web apps. And I think a lot of hay is made of that word reliable. You'll probably, if you've heard about Elm, you've probably heard of its claim of no errors at runtime. But we're here to talk about developer happiness today. So we're gonna focus a little more on the delightful aspect. Elm is a language that compiles to JavaScript. So when you write an Elm app, you'll write a number of modules in separate files. And you'll feed those files to the Elm compiler. What comes out the other end is a big blob of JavaScript that is ready to run your program in a web browser. And when you write an Elm app, you will be following this architectural pattern called Elm architecture. All Elm apps in practice are structured this way. So you'll start by writing an init function. And that function's job is to generate the initial model for your app. And when I say model, I'm not talking about like an active record model that's like a single entity in your database. This is a complete model of the current state of your front end as it's running in the browser. And then you write a second function called view that takes that model, whatever it is at any given time, and generates the HTML interface for your web app. Now if you're familiar with something like React at all, you might know the way it lets you generate a virtual DOM. So every time your front end is rendered, it calculates the entire user interface. And then the React framework takes responsibility for intelligently and efficiently updating just the changes in the actual browser. Elm does the exact same thing. It has its own virtual DOM implementation so you get all those same benefits. And as part of your interface, you'll declare the events you're interested in. And if the user does something like click a button, the Elm runtime will send your program a message. So you need to write a third function to handle those messages and that'll be your update function. And its job is to take the message that's incoming, your program's existing model, and to put them together in order to generate the new updated model for your program, which the Elm runtime doodly feeds to your view function to generate the updated interface. And your program ticks along through this cycle and that's how Elm programs work. So let me show you what this looks like in code. Over here we're going to start by gluing together all the parts of our program. So I've got a main function here and I'm calling HTML beginner program and I'm saying my model will be provided by my init function. My update function is called update and my view function is called view. So we will start by writing that init function I mentioned. It will generate our initial model, which is just a hash or as we call it in Elm, a record with a field called count and a value of zero. We'll then write our view that takes that model and generates our interface. And so that'll be a div and that div will have no attributes. That's what the first empty array is there. And then the second array is the child nodes of that div. So inside that div I'll have some text, which will be the count from my model. And then I'll have an HTML button that generates on click an increment message and inside the button we'll have the text increment. So I've just made up a name there that increment message. So I need to tell Elm what that is. So I'll say my message type will be this new type that can be only one thing, it'll be increment. And then I write my update function that receives that increment message and my current model and it generates a new model, which is a copy of the existing model, but with the count updated to be count plus one. So there we go. We have a complete Elm program and whenever you click that button, the number will go up by one. And I'm only lying to you a little bit here and that is with the formatting of this code. I've formatted this code so it's easy for Ruby developers to read and JavaScript developers to read. In practice in the wild, Elm code is usually formatted this way. So it's quite a bit taller. Elm likes its vertical white space. But the other thing you'll see going on is these weird commas. So in both of the lists, the commas instead of being at the end of each line, they're at the beginning of the subsequent line. And Elm does this in order to get really clean diffs. You can add new entries to these lists without modifying any of the existing lines. Languages like JavaScript and Ruby do this by supporting trailing commas. Elm prefers to do it this way. I've seen the argument made that if you forget to type a comma, it's a lot more obvious when your code is formatted this way. But I have to admit this was a sticking point for me when I first started playing with Elm. I thought I could kind of get on board with reading code in this format, but there's no way I'm gonna be able to train my crusty old fingers to type code in this format. The good news is you don't have to learn to type code in this format because if you're writing any amount of Elm code, you're probably going to use a tool called Elm Format. It integrates right in with your editor and every time you save your changes, it will snap your code into this community guideline approved format. And there are no configuration options, so there's no Rubocop linter rule wars to go on in your teams. It's really satisfying just to apply the tool and follow the rules and it takes care of the formatting for you. And this actually provides a really satisfying moment of developer happiness. When you're first learning the language, you find yourself typing a lot of code kind of sitting back in your seat thinking, I'm not sure this is quite right. And when you save your changes and the code snaps into place, you get that nice feeling of validation that what you typed at least syntactically does make sense. And that was the first experience of developer happiness that I had with Elm. So that's a brief introduction to Elm and what it looks like. And at this point we'll delve a little deeper into sources of developer happiness that you get with Elm. The first being Elm's lovable compiler. So if you've heard much about Elm, you've probably also heard that it has a reputation for great error messages. And I'm here to tell you today that Elm has the most amazing error messages I have ever seen in my career. Here's an Elm error message, for example. It says, cannot find variable list.nap and it shows my line number. It shows my actual line of code. If it's a red jaggy underline under the part it's objecting to and it even goes on. It says list does not expose nap. Maybe you want one of the following. And its first guess is actually right here. I meant to type list.map. I made a little typo and it's able to fuzzily search the API and guess that what I meant was probably list.map. This is what errors look like at the command line. If you're like me, you probably have a nice editor with an Elm language integration and so this is what error messages look like in Atom, for example. So you get them as popovers when you hover over the red underlined code. They're very nice. Elm errors are also extremely specific. So in this case it's saying the second and third branches of this if produce different types of values. The second branch has the type string but the third is a float. Hint, all the branches of an if need to match so that no matter which one we take we get back the same type of value overall. So the error message is not only telling us what we gave it and what it expected but it's also telling why it had that expectation and even how the language is designed in order to create that expectation. Really, really specific and especially as you're first learning the language this is really helpful stuff. Speaking of beginner friendly errors, here I'm trying to concatenate two strings using the plus operator and that's not how you do it in Elm. Elm has a plus plus operator and you can see the hint at the bottom. To append strings in Elm you need to use the plus plus operator, not plus and there's even a hyperlink to the relevant documentation. And so when you get something wrong as a beginner as often as not the compiler will guess what your intent was and give you a pointer to the right thing to do. So in the program we wrote before did anyone happen to spot the bug? Because the Elm compiler spotted the bug but I'm not gonna read out this error message because this is actually not that great of an error message. It's pointing at this part of my code as the source of the problem when in fact the bug is down here. I'm passing model.count which is a number to the text function which is expecting a string. And the reason Elm is not able to pinpoint the source of that error is because it doesn't have enough information to do so. I've given it conflicting information and the best it can do is point to the part of my program where those conflicting things come smashing together and I try to plug them together into a coherent program. So the issue is that I've written an init function that has a count that's an integer and I've written a view function that expects a count that's a string. And Elm doesn't have enough information to know which one of these is correct. Elm is a strictly typed language which means the compiler decides for you what all of the values in your program, what types they are and if it finds inconsistencies it gives you an error like this one. So what you can do to get a better error message is to give Elm a little more to go on by providing some type information. I'm gonna declare this type alias called model and what I'm saying here is any time I say model what I mean is a record containing a count field that's an integer and the compiler goes right oh gotcha boss and then I can annotate my init function and say init returns a model and it goes cool that checks out. That matches my expectation and now my view function I can say it takes a model as an argument and returns HTML and the compiler goes bop bop sorry that's not quite right and it gives me now a much better error message. It says the argument to function text is causing a mismatch. Function text is expecting the argument to be a string but it's an int and that makes fixing the bug super easy. I can just wrap my model count in a call to two string and we're done. So Elm has great error messages especially when they're powered by static types and you provide the necessary amount of information for the compiler to understand your expectations about the types flowing through your programs. So let's talk a little more about static types because when I showed you this bug you might justifiably have thought what kind of modern language is this that it can't automatically convert an integer to a string for me when it needs to. Well in order to explain why this is the case I'm going to give you a slightly more real world example of a subtle bug that Elm's really strict type system protects us from. This is a search field that we might have on our site and what I've done is I've put a hyperlink under it that you can probably barely read and it's suggesting that I might wanna repeat my most recent search just by clicking that link and if I were to implement this in JavaScript I might have some code like this where I've got my search history in an array and then I'm outputting a string where I use string interpolation to put the first element in that array right in the string. And the problem here is that I may have never done a search on this site and so that array might be empty and what then happens is my user interface displays the word undefined. JavaScript helpfully converts that nothing into a string and displays it for all my users to see and this is an especially devilish kind of bug because JavaScript is operating as designed here there is nothing wrong and so this isn't the kind of thing that'll turn up in your error tracking software. This will just be delivered to your users as business as usual and you'll never find out about this until you happen upon it yourself. And in fact if I give you a peek behind the curtain here a little bit this is CultureAmp's JavaScript error tracking system as of about two weeks ago and if I zoom in I can show you that every single one of these errors has something to do with a null or an undefined value making its way through our system and exploding at the point that we try to use it. When I was taking this screenshot I couldn't resist going in and trying to fix one of these bugs and I couldn't do it. These bugs are really hard to track down because the place where undefined explodes often has almost nothing to do with the place where it actually gets set in your system. So these are really hard bugs and the reason the person we have to blame for these is this man Mr. Tony Hoare who in 1965 invented the null reference. And in a recent conference talk he said I call this my billion dollar mistake. At that time I was designing the first comprehensive type system for references in an object oriented language. Algal W, everyone's favorite, right? My goal was to ensure that all use of references should be absolutely safe with checking performed automatically by the compiler but I couldn't resist the temptation to put in a null reference simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities and system crashes which have probably caused a billion dollars of pain and damage in the last 40 years and as you can see from our error tracker the legacy continues. So let's look at the equivalent ELM program. This is an ELM list at the top and then in the suggested search function I'm doing a bit of string interpolation to take the value that's returned by list.head and plug it into the string. And the thing is this ELM program will not even compile. When I try to compile this the compiler says that it's expecting an appendable and the hint at the bottom says an appendable might be a string for example. It's expecting a string but the left argument is a maybe string. So what is a maybe string? Well this is a maybe, this is a type that's built into ELM and a maybe something is either just something or it's nothing. So a maybe string is either just a string or it's nothing. And if we look at the API docs for list.head you can see that if we call it on a list with things in it it returns just the first thing but if we call it on an empty list it returns nothing. And so by exploding on us the compiler here is forcing us to handle both of these possibilities. List.head isn't guaranteed to return something so I need to handle it if it returns nothing. So in order to do that I can just change this to a case statement. This is like a switch statement in Ruby. And I'm saying that if list.head's history returns just the latest search then use the latest search in my string but if it returns nothing use this alternative string no previous searches. And so the compiler is forcing me to handle both cases. Because we're all Rubyists and we like some elegant code I'll show you a slightly more elegant version of this. We can use pattern matching in Elm to just match on the pattern of the search history and if the search history is a list starting with the latest search and followed by the rest of the list we can use the latest search but if it's an empty list then we return no previous searches. And the thing is that the maybe type that I showed you before isn't any kind of special case even if I'm doing pattern matching here if I remove that second branch the compiler catches it and says this case does not have branches for all possibilities. You need to account for the following values the empty list. Add a branch to cover this pattern. So through and through the language the compiler is watching our backs and forcing us to handle every possibility. And for this reason Elm is able to make that remarkable claim of no errors at runtime. Due to its strong static type system in which nil is not a thing. To wrap this section of the talk up I'm going to give you a sense of what it is like to build new features in an Elm app. So we'll go back to this program that we've been working on and we're gonna add a new feature to it. I'm gonna go to the view function here and I'm gonna add a second button. This button will be called decrement and generate a decrement message and right away I've got a red underline because the compiler doesn't know what I mean when I say decrement because that's a new name that I've made up. So that's easy to fix. I'll just go to my message type and say there's no longer just one possible message. I now have two possible messages that I might receive in this program. And the compiler says okay great but then you need to update your update function. And it says the pattern does not cover all possible inputs. You need to account for the following values main dot decrement switch to a case expression to handle all possible patterns. And so sure enough I've hard coded the word increment in my function definition there so I can replace that with a variable and then I'll do what it said and add a case statement here. And at this point you can see where my cursor is. The next step here would be I'd go down to the next line and re-indent it under that new branch but because I'm using elm format I can just hit command S to save my changes and it will do that indenting for me. So it's also a really nice development tool this elm format. But my code's now underlined in red so just in case I forgot what I was doing elm is saying this case does not have branches for all possibilities you need to add one for main dot decrement. So I'll go ahead and add that second branch and when I save my changes elm format puts in the requisite vertical white space and I'm done. That's how you add a feature to an elm program. And the reason I took you through this was to highlight the fact that all I really came up with on my own was adding that button. I just imagined the feature that I wanted to exist in my interface and I added it to my view function and from that point on the compiler was leading me by the nose step-by-step through my code base telling me what needed to be added for that feature to exist. And this is what adding new features to elm programs feels like and more importantly this is what refactoring in elm feels like. You can just grab a function that's gotten too big for its bridges and rip it out and put it in a new module and from that point the elm compiler will point you to all the broken connections in your program that you need to go and fix. The lovable compiler that you get with elm is like this perfect pair programming partner that is always guiding you to the next step that you need to move forward rather than complaining about the thing that you just changed. It's really nice and that is one of the two big sources of developer happiness for me in elm. The other is elm's radical simplicity. So elm has a batteries included philosophy and as Rails developers we're quite familiar with this. Rails is this big collection of lots of tools that come all bundled together, pre-configured to work nicely together so that we don't need to learn them separately. And that is surprisingly rare in the JavaScript ecosystem. If you've been watching JavaScript lately you may have heard of this term called JavaScript fatigue or read an article like the one in the background here complaining about the dozens if not hundreds of cleverly named frameworks and languages and dev tools that you need to get your head around and understand how they relate to each other and install them separately and configure them to work together and read the docs for each one separately. It can be a nightmare to try and get into JavaScript development for this reason. And if we look at the stats for NPM the node package manager it's no wonder this is the state of affairs. JavaScript is really a victim of its own success here. The orange line is NPM, the blue line is RubyGems. And I don't know if you had this experience too but when I first got into Ruby even in Ruby I was like put off by the sheer number of cleverly named gems that I needed to get to know. What is devise and why am I supposed to care and why is it called that? If you look at the graph here it's telling us that the problem is about four times as big in the JavaScript ecosystem. And in my experience that's no exaggeration. So if I'm looking to build a modern JavaScript application I'm probably putting together some collection of tools like the one on the left here. And Elm seeks to address this issue by providing all of those things or their equivalents anyway built in with a single installer. You install it once and you've got the equivalent of all of these things configured to work together. There's a single website with a single tutorial that you can follow to learn how it all works. And it is night and day different. And so as Rails developers we probably have some sympathy for this batteries included approach and it's one of the reasons I like Elm so much. Especially for bringing juniors onto our teams. It is amazing how quickly juniors become productive on our Elm code base as opposed to our React Redux code base that often can still be bamboozling them weeks into their new job. I find it a big difference. Functional programming the good parts. So this is Evan Zapplicchi, the creator of Elm. I probably should have mentioned him before now. But in the official Elm tutorial on the website on the very first page he says forget what you've heard about functional programming. Fancy words, weird ideas, bad tooling, barf. So this is an opinionated fellow and his opinion is that Elm doesn't need to be any more complicated than it has to be. And that is what he's sought to create. Elm is a functional programming language and if you've dabbled in functional programming at all that can be a daunting set of words. Because functional programming languages are often full of these weirdly named concepts. But Elm tries to be different and I'll try to illustrate how here. This is a feature of all functional programming languages including Elm called partial application. So I've declared a function here called add that adds the two arguments it takes together and returns their sum. And so I can now type add one two and I get the number three back of course. But I can also just type add one and what I get back is a function that's still waiting for another number before it can return a number to me. So this is a partial application of the add function. And this partially applied function is now a value that I can pass around in my system and use somewhere else. So for example I could write a new function called increment and increment is just add one. And it takes a number and returns a number. So now I can say increment five and I get six. And hopefully this serves to explain why functions like add that take multiple arguments express their type definitions like this as like a chain of values that you pass in one at a time leading to a return value. So in functional programming circles this feature has another name and it's currying. And currying is a weird name. It is hard to understand why it's called that. It's hard to form a mental model around this feature when you're learning functional programming. And so in the Elm community they don't use this name. They just call it partial application. The clearest label they could come up with for this feature. But features they don't need, they remove. So features are constantly being removed from Elm with each subsequent release. Here's an example, before the recently released Elm 18 it had this feature where you could put a function in between back ticks and that would let you put the name of the function between its two arguments instead of at the start of the argument list. And this let you create these readable formulations like buy milk and then dip cookie. But the problem with this syntax is that those back ticks are really confusing if you've not seen them before. To beginners, these look like strings. And so what they figured out is that they could change how and then works and instead use another feature of the Elm language that they already have, the pipelining operator. And if anyone here has played with Elm at all, Elixir at all, the Elm pipelining operator is the exact same thing. It's one of my favorite features of both languages. And so using the pipeline operator where you can still say buy milk and then dip cookie and they get to drop the back tick syntax. And as of Elm 18, that syntax simply doesn't exist in the language anymore. So wherever they can, they are removing features to make sure that Elm is just functional programming the good parts. Lastly, Elm programs are made up of just two things, immutable data and pure functions. And this contributes significantly to the simplicity of the language. So let me tell you what I mean by these before I tell you why it's a good thing. Immutable data, if I give you a Ruby app or a Rails app and I said user.update prams, probably most of the people in this room have enough experience with Rails to spot that this is an active record object and calling the update method on it will change that user object in place. And if I still wanted the old version of user, well, I better have made a copy of it before I made this method call because it's gone now. But in the very same controller action, I might also call hash.merge, which is designed a different way. Hash.merge doesn't modify the hash in place, instead it returns a new hash with the updates applied to it. And the reason these two things might exist in my program is because these are two different APIs designed by two different people with two different design sensibilities. And we as Rails developers just over time start to navigate these design differences and understand why different functions work different ways. But this is confusing to beginners and it's not an issue in Elm because in Elm, values are immutable and so I can pass my user to this update function safe in the knowledge that update function, not only will it not change that user, it couldn't if it wanted to because Elm values are immutable, they can't be changed. All you can do is create a new value with some changes applied to it. And so I know for a fact that my update function will return that new updated user. I don't have to learn that, that's just how all Elm functions work because that's all they can do with immutable data. Going back to this Ruby function though, this Ruby method call, if you know your Rails, you also know this update function does something else which is persist changes to your database. And this is what we call a side effect. It's you call a method and besides returning you, its return value, it also has some impact on the rest of your system or the outside world. Elm functions simply can't have side effects because all Elm functions are what are called pure functions. And a pure function means that a function, all it does is calculate its return value for you. And the only information it can access in doing that are the arguments that you pass to it. And if you pass the same arguments, you'll always get the same value back and that function can't do anything else to the outside world. It can't make an Ajax request, it can't persist anything to your database. It can't even tell what time it is because that would be information from the outside world that might change the value it returns on any given day. So all Elm functions are pure functions. They cannot have side effects. That is a restriction of the language. So you might be thinking, hang on, I might wanna make an Ajax request in my Elm program. Can Elm not do that? Well of course it can but in order to do it, we need to expand our view of this Elm architecture that I showed you before. You might have guessed it from the name but HTML Beginner Program gives you this simplified version of Elm architecture and the main restriction it gives you is no access to the outside world. And you can often actually start building your app with Beginner Program and when you're ready to graduate to something that has effects, you can switch your function call to html.program and the compiler will guide you through all of the API changes you need to conform to. But when you do this, you get a more advanced version of the Elm architecture and it looks like this. You still write an init function that creates your initial model but that function can also optionally return a command to the Elm runtime. So that might be a command like say, make an Ajax request and the Elm runtime takes that command and actually does that thing for you. In the meantime, your program's view function will have to render a user interface and if you don't have any data yet in your model, then that will probably be some kind of loading view and then when the Ajax request completes, the Elm runtime will let you know about it by sending you a message. This is just like the messages you get from the user clicking a button in your interface but now this is a message generated by the Elm runtime and so you handle it just like any other message with your update function but that update function can also now return optionally a command. And this is how you, for example, kick off an Ajax request in response to the user clicking a button in your interface. And so that's what the more complete Ajax enabled Elm architecture looks like. So I'll show you what this looks like in code. We're gonna go back to our init function here and this function now needs to return both a model and a command. And if you don't want to do a command, well you can just return command.nun to say I have no command for you but if you do wanna do something like send an Ajax request, well you can call a function like http.send and I'm passing to it gotData which is the name of the message I wanna get back when this request completes and getData which is a function I will write to describe the request I wanna make. I'm using http getString which makes a getRequest expecting a string back from the server. As you can imagine there's things like postJSON and stuff like that and we provide the URL. And so all we have to do now is handle that new gotData message so we need to go to our message type and add gotData to it. And gotData is a wrapper around a result which can either be an http error if the request failed or the string that we have successfully received from the server. And then we need to handle this message in our update function. Let me go back there. So there's the update function. We just add a couple of cases using pattern matching. We say if it's a gotData with okay inside it we handle the successful data. If it's a gotData with an error inside it we handle the error. And there you go. That's how you do Ajax requests in Elm. And importantly both of these functions are pure functions which means you can call them and they will not actually generate an Ajax request. All these functions do is generate a command. They return a command. And what causes an Ajax request to happen is when you return that command to the Elm runtime. But you can safely call these functions anytime you want. For example in your test suite these functions are really easy to test. All you do is call them and see if they give back the command you expect. And because no Ajax request will actually occur these are really quick, these are fast tests and you don't need anything like mocking in your test library. The Elm test library simply doesn't support mocking because it's not needed in a world where all of your programs are made up of immutable data and pure functions. So that's Elm's radical simplicity. And just to wrap up here we'll take a look at Rails and Elm because they have some similarities. Both Rails and Elm have this batteries included philosophy and they both pride themselves on their clean language syntax. But there are some trade-offs as well. Ruby on Rails is a dynamic, object-oriented and very flexible language and that's what you want in your backend language. You want a general purpose programming language that could conceivably do anything. And we've seen some talks at this conference showing just how versatile it is. But on the front end in the hostile environment that is today's modern browser and might be sharing space with ad blockers and who knows what else, you want a simple language and one that gives you as many guarantees as possible. And so Elm has chosen this trade-off and it has designed itself to be static, functional and relentlessly simple. And because of these characteristics Elm can give you those guarantees that let you develop with confidence and provide developer happiness. And finally there's at least one clear win I can call out and that's Elm's amazing error messages. I think every other programming language could learn at least one or two lessons from what Elm provides you when you get your code wrong and I'd love to see Ruby adopt some of those. Now if you're wondering how we bring these two worlds together, how we integrate our Elm front end with our Rails backend, well I will refer you to this talk coming up this afternoon by my colleague, Joe Cranford. She's talking about React on Rails and the journey we took adding a rich front end to an existing Rails app and all the same plumbing and machinery we use to integrate our React front ends with Rails, it's the same stuff we're doing for Elm and so if you're interested in how that works please come along to that talk, I'm sure it'll be great, I'll be here too. And with that I will thank you for your attention and take any questions.