 But I'm here to share, not as an expert, but someone who's struggled a lot to understand FB and made some jumps here and there, and I've been doing it for a couple years in Clojure and ClojureScript. That's my studio. We do everything design and develop in Clojure and ClojureScript. And today I'd like to share what a full stack is looking like with the community. But given that we have so many things, obviously 45 or 15 minutes is not going to go into depth, so I would rather focus on the breadth. And if we have any questions, I'm happy to answer at the end. But before that, a show of hands. How many of you consider yourself a functional programmer? Now if you may, please keep your hands like that, because I have three more questions. How many of you are back-end engineers? How many of you are front-end engineers? How many of you are both? How many of you do design as well? Okay, one person. I'll try to raise my hand. So do you realize how hard it is to actually do everything inside your head? It's pretty hard, right? I struggle a lot because often we have ideals of doing one thing in one language or library. But once we move beyond that, we're not battling with ideals, but we're battling with libraries, people, different kinds of things. How we do in JavaScript, CSS, whether it's Clojure, Scala, Haskell, doesn't matter. We're always struggling to kind of have a kind of a unified point of view, right? And it's especially true at Fullstack, because we have templates, UI, events, we have obviously database modeling, and also responsive design. So in this talk, I will touch on HTTP APIs, but that's something we all understand. So I will skip the details of it, but I'll spend mostly on the design and database modeling, which is datomic and Clojure script. Now how many of you recognize this? How about this one? One more. Last, but not least. Again, this is something I'm interested in. Now, this is a language we may not be familiar if you're not in design, but often design is not necessarily CSS. It goes way beyond that. So print designers, people in creative studios have a language that is very abstract. They're very declarative in nature, just the way we think of SQL. So if someone asks this, what do we do? That gentleman out there who does design, I'm going to write a higher order function. And believe it or not, I will have answers for these at the end of this. In fact, there is a higher order function in Clojure script that decomposes selectors and declarations as data structures. Now as I said, I often struggle to be in FB, understand FB, and then I move to other areas and I'm constantly confused. So I always try to remember and remind myself, how do you unify things? And obviously, that requires a lot of focus. It requires that you cut down unnecessary things and look at the bare essentials. What Clojure and Clojure script taught me was that it does ... Now again, I speak as someone who has worked in a lot of prototypes, a few production apps. I think that FB doesn't have to be one way. There's Types, which is Haskell derived, and there's List, which is not traditionally typed. There's an option. So the core of it, as you all know, is Lambda architectures. But if you dig even down, this is my version anyway, because we all speak different languages. This is what I found, that it's actually data, as in data structures, compositions, and abstractions. What does that mean? Let's start with data, life without types. Now this is a famous quote. Rich Hickey has always promoted this, and I think it makes sense, because four years ago I read this, it didn't make sense to me. It's finally making sense. It is always better to have a lot of functions abstracted over a common set of data structures than creating new hierarchies, classes, or types, and then reinventing different composition patterns. And that's just one way of looking at it. Obviously there's no right way. Now, what is that the single most unit in Clojure and Clojure script? This is again a question. I constantly ask myself questions. This is how I learn things. Now I've been coding for 14 years, I think, 12 years professionally, I think 13 years. And the way I learn is basically I just ask a bunch of questions, find out, and then try out a few things, and then get a gig, get better at it. So in Clojure it comes down to one thing. It's called Eden. It's actually a data transfer format. It's just a data structure. It is a language agnostic data transfer format. You can think of it at JSON to begin with, but it actually has symbols, keywords, and literals. And you will see what that means, data tags to extend the notion of what data means without language. So in this example, the other day I was tweeting on LambdaCon saying that I ended up walking up, and if some of you are living in Boulder, there's a place called Iris Poetry Cafe. It was awesome. So I ended up reading a poem out there, and I actually write it in Eden, which is crazy, right? So this is how I write it. This is my title, my book here, et cetera. I'm still working on it, tag. What you see here is actually a set. This is a notation of a set. A reader that reads this, any language which implements this can transform that into a set in its native language. Obviously, there's Clojure, Clojuscript, Python, JavaScript, and a host of other languages that is able to read this. Now, this is just a data transfer format. Yeah, it's an extensible data notation. Actually, now that you asked me, I'm just lying there. But I think there is a subtle notion in Eden. I think it's, I like the name. Now, the next step. Again, as I said, bottom-up thinking is something that I've learned in Clojureland. So you start with the smallest data point, which is a data transfer. We are not speaking of languages, not speaking of data structures, just a notation to hold all the data structures, sets, maps, lists, symbols, keywords, and more on them. So what's the next? Datomic. In Datomic, everything is actually structured in Eden. When I looked at this couple years ago, it was like, just didn't make sense, like most things in life, I think. And this is how it looks like. And we will, again, I'm going to show an entire demo. There are like six demos coming up. Hopefully I'll have some time. DBID. What you see out there, this one, is actually a tag literal. A reader that reads this, the data structure, will have at that time a notion of what this means and can parse that. In this case, what is parsing is, again, a keyword value in a vector, which is positioned with zero and one slots. Again, we're not in language yet, but still there is such simple explanation or declaration of what the intent is in just the notation. Next step. As I said, I was looking at integration, full stack, in Clojure and Clojure script. What does that mean? HTTP. Now, I've been doing web services since starting with soap. I don't know how many of you have done soap, but it is something. In Clojure, it boils down to like three things. The sense is as pure as the slide. I mean, the slide is not as pure, but it's request and response as immutable maps. You have a request that comes in, a response that goes out. A handler is simply a function that takes, it's a unary function that takes a request and returns a response. That's it. And there is a concept of middlewares, which is a higher order function that is simply taking the handler, now remember the handler returns a response. Now what you can do in middleware is you can go into it because you're closing over that handler's response. You can actually inject response attributes into it. Brilliant. This is actually popularized in, I think, Ruby stacks. And this is one of the first libraries that has come out in Clojure in 2010. It is still the de facto way to build web services. So you write middlewares to do cross-cutting concerns. Now I've come from a Java background. We used to do AOP and things like that using 500 lines of code to do one thing. In this case, you write a function and you're done. You write a higher order function and you're done. And you can now move across all your concerns into middlewares and you compose them in this example. This is my application. I'm taking a handler. I'm composing with middlewares and what I have is a pipeline. This is how you do back in APIs, HTTP APIs in ring. There are, of course, routing and other things, but this is the essence. Again, this is just data. Requests are immutable maps, responses are immutable maps. You use higher order functions to compose them. There are no types, not yet. All right, let's push it further. I'll keep pushing this and if I'm not pushing enough, I want someone to shout. What if we can view HTML as data? That what you see here is actually a generates an HTML as a string or a DOM depending on which library you use. If you use a closure library, it will emit a string, an HTML string. If you use a closure script library, there are about six of them, I think. It will limit a DOM. What you just see here is literally data structures built on Eden on the first slide I showed you. Now, I'm trying to pay attention to what I'm speaking and I hope I'm able to clarify as we move forward. Everything is built on that simple concept. It's a data notation. Focus on data, right? Li is a vector, this is a vector, right? This is a vector, this is a map. So what we just did is we express HTML attributes in maps, the elements in vectors. Because vectors are positioned, there are associative data structures. You can, there's slots involved, you can now nest vectors. Done. You can express any arbitrary HTML in just vectors and maps. Let's push it further. Now, this is React. There are four or five libraries now already in Clojus Script. And I think if you're in UI, this is something that is exciting for most of us because it is probably one of the few functional UI composition concepts. Yes? I'm sorry, this one just sort of slipped by and I apologize about that. You said that the elements in the vectors are, sorry, the members of the vectors are elements and what are the maps? Maps are the attributes. Yeah, so HTML is elements and attributes, elements and attributes. So elements are vectors, attributes are maps. So you nest vectors because they're associative. So this is React. Again, let's not go deep into React. The focus of my topic was doing full stack and what's the core essence of that? So we just look at data structures. So virtual DOM is provided by React and this is an om example. As I said, there are other examples. They have the same concept. What I'm doing here is again, as you can see here, I'm expressing HTML here as data. Render state is a pure function. It just renders and I guess that's it. Then there's a shared global state atom, which is managed by a cursor. We will look into that in the demo. Let's push one more step. This is where I'm more excited because we can do this before. CSS is data. I think this will kind of complete my obsession with what is the one unifying theme across. That's a clear fix. If you've done CSS, this is the most frustrating thing for any beginner. How the hell do you clear a container that is wrapping child objects? Sure, it's the great designers who have popularized patterns, but I'd like to put everything in a function, especially a pure function, and potentially having a unary or make sure my arguments are designed such that I compose those functions when I use other concepts. So clear fix is a function that returns this class. Again, if you've seen HTML as data, this is the same concept. Now, as you can see, I've been trying to understand what is the common thing. And I found that, OK, there is this notion of data. Now, how can we do data and design? Now, I'm most interested in the intersection of it, because I think there are some fascinating things that can happen over there. So obviously, it's not easy. As you know, life is always full of surprises. And I keep going back to what I've been learning so far is that you have to be really stupid to make something brilliant. And someone told me this that I just didn't get it. I think it's a UNIX hacker or something. And he happens to be a list hacker, too. So obviously, I'm like 1% of how he thinks. And he said that if you want to make a system really good, you have to stop being intelligent. You have to stop thinking too much. You just do one thing. And you repeat it, and you do one thing, and you repeat it. And it struck me, because I am a writer. I've been writing for eight years now. I have like three short stories published, 25 of them out there. I'm writing now for three years. And this is exactly what I do. I keep doing it. I fail. I keep doing it. So I said, OK, let's do that in Clogescript. So everything is there. So let's try to compose everything, because data structures are actually mutable in Clogescript. They're lazy. So you can load one gig of data if you want. But everything is lazy until you realize it. You can, of course, apply, restrict that by filtering. So we have everything, functions to create sequences, functions to filter sequences, sequence predicates, functions that transform sequences. These are basic things. Of course, there are things that are beyond that. But that will be an advanced topic, which I think demands a workshop on its own. You have the usual suspects. This one out here is interesting. This is a classic example in Clojure Docs. You can repeat. Both of them are lazy sequences, infinite lazy sequences. You're interleaving them, and then now you're taking five. A single. This is a single S expression that I'm able to compose with two infinite sequences. I couldn't do this in other languages. In fact, I didn't understand what infinite sequences were. In Clojure, everything is a sequence. So it goes one step beyond Lisp. That is, it abstracts the three common data structures in a sequence abstraction, which means you can build your own types with that abstraction. That's how you build abstractions in the Clojure line anyway. So there are more things like transducer's P-map composition. And if anyone wants to know how that works, happy to answer outside, this stuff is fascinating. Because now you're composing functions. You're building pipelines that is not possible before. And this stuff is most exciting. But I won't be covering this. I just want to lay out what's out there. As I said, I want to cover breadth first in this. Now, before we get into the demo, this is some of my projects that I do. I'm trying to take an open data format, which is about 15 million books out there. It's an open source API and data set. This is how it looks like. It's quite beautiful, actually, if you know how to parse it. It's just a CSV at the end. But there is values in the CSV, which are JSON. And the time is not good, et cetera, et cetera. And this is how it boils down in Clojure line. This is a very basic example. We're not even dealing with transducers here. I said parse CSV, unary functions, pure functions. I say read CSV. I say parse JSON, which is basically a thread last macro, which is just taking the result of feature and piping into the next result. It's a UNIX pipe concept. And the last, I just open that, and then literally reuse these. So this is kind of my workflow, is when I take a data set, I just look at what are the things that needs to be done. The exception wall, functions for it, pure functions. And then at the end, I use a thread last macro that pipes the results. As you can see here, I hope that anyone who has a basic notion of less parentheses model and how its expressions work, I hope this is readable. Take the result, parse CSV, parse JSON. Timeify is basically conversing to the Jota time. If you know Java, it has a mutable date time concept. Enough of that, so let's go into the demo. So I'll start with, so before that, most, all of the demo is built with two of my Liningan templates. I have the repository, I have the references up. If you want to build one, you just do it right this. Yeah, so it's called Mala. It's a full stack Closure script, Closure template. You just say Liningan new Mala. Liningan is a build tool, and then say, we will create an entire stack for you. So the examples you're seeing is built from this, and I've added two libraries. Again, I have references to that at the end. So as you can see, this is how the structure looks like. You have a simple source, and this is something I put up. This is not the best way to do it. Okay, let's see, that better. Let me do this in Emacs, it's better. So this is how the structure looks like. Can you see that better? Okay. So source has three things. This is how I use, by the way. This is not saying this is how you should do it, but this is how I prefer. API, I have routers, a server, utils, and there's a data for, if you want to connect to the database, which I think most of us want. And there's design, all of the CSS goes here. Includes script, by the way, which return everything as functions that I compose and own as values. CSS are classes values, we will see that in a bit. And UI has components, all the components are here, and the state is there, and again, it's just a way to. So right now, I will show you what, so I'm looking into the API now, I want to show you basics of Datomic, as I said. So I have, I'm connecting, I started a REPL. So let's start a connection. This is how you start a connection. And I'm using a thin wrapper I wrote, called Atomic, which is just simplifying a few things for me. But this is, let's say you start a database like this. API server, okay, API data, switching into the namespace. Typing always is hard outside here, huh? Okay, that's better. Okay, so I connected to a Datomic. So nice thing with Datomic is for local testing, you can create an anonymous in-memory connection. So that's my connection. So I said I read a poem out there, so I wanted to try out something. I actually put this together the last few days. So I said I will take my poem, which looks like this. It has a YAML front matter and a simple plain text. So I said I want to write like this, but I want to transform it in Clojure. I don't want to write everything in Eden first, because I can write transformers. So I wrote a poem and I put it in the resources. So let me try to read that now. Never change things on the fly. Oh well, so we'll do something else. So instead, so I have a bunch of things here. So instead of reading that, instead I will read a blog. Okay, so blog is a poem in my case. This is how I like to see it. So this is basically this guy here. It's the same format, right? I try to express everything in a data format first, inspired by Eden. Have a content format and do transformations. So I transform that into this thing, right? It did read everything, as you can see tags. It's a Eden structure. So I'm doing transformation steps. So now what I do is I want to create schema. So create, so this is again some sugar I added on top of the Atomic API. So I create an author schema, poem schema and tag schema. So if you've seen this, how do you start modeling this? So you have a real life, you always get things like these. So instead of creating tables and things, you have to ask questions like, how do you want to model this in terms of single units? In Datomic, everything is a fact, and a fact is a tuple of five things, entity, attributes, values, transactions. But here, one of the ways you can model this is like I can have an author model, I can have a poem model, I can have the content model, I can have a tags model, right? So that's how we did it. So it's again, this is just data. Schema is a vector of vectors, saying that the first one's, this is a keyword, it says it should have a name, a full name, string, it's a one to one, they make it a full text index, right? Same thing with others. So I created, this is one of the ways to do it. You can do it in any way at an attribute level. The way I did it is create an author schema, poem schema, tag schema. So let's just create schemas, okay? It's apparently it did something, I don't know what it did. So let me just, let me check if it's valid. Okay, it is valid. Just to make sure that I didn't, I'm not cheating. Hey, it's a false. So it does create something. So now that we created it, so let's create, let's create a poem, or in our case, let's create an article, right? So what I'm doing here, so it's idiomatic in closure land to put everything in exclamation at the end if it's changing state. We do change states sometimes, right? So that way you know there are side effects. So I pass the connection. Connection is just a database which we got as a snapshot and that's actually a value. It doesn't change. And it's sitting in my local. It's not even connecting to the server at this point. There is no connection to the server. So what I do here is I created a poem. I got an ID back. Well, what does that mean? So let's see. I'm gonna get these attributes. So I created something, I don't know. Now Datomic operates at a very low level because it wants you to build things on top of it. So I can visualize things. I did get something back. So I did actually get the same attributes back. So we just created in a few steps. We took a text file with some format in it. I had to write a transformation. I created three schemas for my text file, converted into Eden. Then I saved it and now I can, I have an ID for that poem or article in this case, correct? So let's create further. Yeah? So in this case, so let's finally do the tag. So everything in Datomic returns an entity. Everything you do creates a fact. Now that I've tagged something using the database connection on the entity, it created a new entity. So once you start kind of going this route, you will see that everything is the same thing. It's like recursion, right? Everything is a fact. Attribute is a fact. I create a tag. That's a fact. Now what does this look like? I'll show you what that looks like. That's a tag. As you can see, that's actually Eden data structure. Tag name, composition, tag poem. Now this is interesting. This actually created a foreign key reference in the database land to that poem. This code will be up. So again, going into the details would kind of, you know, we'll miss the overview. But in Datomic, it is possible to create attributes and entities and then give reference to it to the parent entities. It's kind of the best of sequel land. So this is all good. I create new tags, composition, essay. So now the next thing is queries. And I'll stop at the queries because that's just the beginning of the whole into the constrained language. In queries in Datomic, what you do is you take the database snapshot. In this case, this is my get tags query because I want to get tags based on a poem title. This is an arbitrary query I want to write. So how do you do it in Datomic? So you pass a map. It is basically, it's where causes based on constraint logic, which simply takes the entity, attribute and value. So in this case, what I'm saying is, let's see, even get tags, connection. So that's the title, right? So it did give me all the three, right? As again, data structures. It's a set of three things. How I did it is a query. This is the Datomics query. You quote it because there are some things that are not available like these variables, but it's basically a find in where that's the pattern. Find tags, and I'll tell you what the tags is at the end. This is the current database. The poem title I just passed. Now this is where things get interesting. If you're familiar with Datalog or Prolog, this is kind of your problem at home. I was fairly new to it, but with the notion of data structures and Eden, this was easier for me to understand as I prefer to understand everything in kind of a unified point of view. So this is just entity attribute value. I said, hey, the poem title is the poem title. Whatever the entity ID is, put that here. Take a look at this one. What I'm saying here is tag poem, and everything has the same entity ID. Like I said, tag poem is actually referring to the poem title. Take that entity ID which was returned by this. This is an implicit join. There is no joints in Datalog or Datomics query logic. I said, give me the poem title. Whatever the entity ID is, that's this entity ID. And now, again, I'm joining here. The same entity ID, give me the tag name, put that in tags, and that's a tags. That's it. So I just got a custom query. Now, I want to stop here with Datomic because we have quite a few things to do. And there's also one more thing. You can get an entire history. This case, I'll push that. But I want to stop there and then switch over to HTTP ring because I want to continue that conversation on what happens when you move data along. So when we looked at API layer, one of the first thing that comes in mind is routes, right? So we have, now we created a poem. It's stored in database. We have a few queries. Now, how do we expose that? Very basic stuff. Here, you just expose it as, it's as simple as this. You put a get route. In my case, I put a get poem and then read the poem from the database. I apologize for that. And then this entire thing is one, as expression, route. If you're familiar with Python and Ruby, it's the same thing. And then I send that as a response. Nowhere here have I told how to return the response. Nowhere here have I told where the authentication scheme is. Nowhere here have I written what the headers should look like. Everything happens in middlewares. Once, and that's here. So this is my final middleware. It's a function. It composes. It takes, wraps a JSON body, wraps a JSON response, wraps Eden parameters. If it's an Eden type, it automatically recognizes, if it's an Eden, it'll put an Eden content type. And there are some API defaults that puts a lot of things like content header. I wrap a course. So as you can see, I'm doing two things at a separate point. I do this one time and I don't have to do it for each request handling. And what that looks like is this. So you can see everything is populated. Sets the cookie content type, right? Same origin. All the things that you perhaps have missed if you started from scratch. This case, see? It sets everything right. Even if I'm getting a page, it puts the right things there. So this is the kind of a brief overview on ring. We can go on further, but the concept was again the same thing is that you're doing two things which is composing requests at one place and doing cross cutting concerns at another place. So that was something that I really liked. I couldn't find this in any other library, any other language library. I think this is the simplest way to do services because I actually don't want to spend more time on services because there's really nothing much going on. I want to spend more time on data in the UI, which is the next part. So I haven't shown you this. So this is where the UI portion is. I hope this will be a little exciting because this was to me completely alien three years ago. So I said UI is, so let's see how it looks like. We're going to go a little fast here in this case. Let's see if we have a really sample UI. I'm doing an autocomplete. It looks boring. It works fine. But as a designer, I don't like this, right? So what I do is I want to change types. First thing I do is I change into a new typeset and I'll tell you what's happening behind the scenes in a bit. So I want to change it to a classic typeset and then I want to make sure, okay, that's better. See things have changed, right? If I did not use these, it looks ugly, at least to me. So even further, I want to change each word style. I want to change the type of head style. I want to change the input search style. And I'm going quickly because we can go on forever on this. I would love to show you each and every implementation. As you can see, I've actually created an entire style sheet for each component individually. And on the fly, when I'm kind of, when I did my backend, my role is now to switch on the front end and not think about the backend because I like to think that way. Now I'm able to declaratively compose my styles, swapping on and off without affecting at least in this page. Of course, if things get complicated, you will have the classic CSS object oriented inheritance trick. But I'm trying to figure out how to do that. But at least in this case, I have my servers running and I'm now swapping styles at component levels. So the next thing is grids. And how many of you are into responsive design here? Good. How hard is it to put a grid together? I'll show you in a bit. It's a single function. And there's something I demoed at Clojure Resta last month. So this was a single function. You don't need Bootstrap. You don't need like these libraries. I mean, if you're a true engineer, I would say that go to design. There can be engineering problems. You can apply the same logic there by learning some design principles first. You can kind of use some of the techniques we've done and apply that. I was able to get to this by, I basically copied someone's blog in SAS and I've wrote a single function. In fact, a small grid system is about six functions. And this is based on a library called mesh. Again, it's up there. So how does that look like? So it looks like this. It's mobile first, adds scales to it. I haven't written any CSS. This is all just Clojure script using garden. So how does that look like? You might think this is a lot of code. This is it. Obviously, that's a library. So I mean, including my library mesh, mesh.grid. And I say, hey, create a grid, wrap widths. In fact, change the gutter size. Things look different. Now, if you realize this, like you might think that you could do this in SAS CSS. Sure, you could do it, but you can't pass functions across to like a DOM mounting, a lifecycle in React and say, hey, at this point, mount this style. You can't do that in pure CSS, unless you're doing trickery. And here I was able to do it. The third quick one I want to get into before I get to the last one is typography, which is something that I'm interested in. This may not be what most of you are interested in, but at the same time, I hope that I will incite you to this, that you can create scales. It's a notion of modular scale. Anyone familiar with it? Yes, so the notion is that when you're creating a type system on the page, especially coming from print design, your H1 to H6 are body copies. There's a nice aesthetic way of arranging them in a rhythmic fashion. Golden ratios, major, minor, third, et cetera. And some of the libraries have come out recently as CSS jQuery, but it's just complicated to me. At least I wasn't able to read it initially. They were good. They were well-written. So I said, how do you write it in closed script? It's a single function. Again, I don't take credit for any of this. I just read blogs, read The Creator of Garden. I saw how he wrote his blog and asked, like, just put shit together, I guess. But to me, it's like, when you're kind of following this path, when everything is a single function and everything is data, I don't know about you, but I don't consider myself an expert in anything. I mean, when I learned Clojure, I thought I don't know programming because that's how I felt. It's like everything kind of boils down to a couple things. And if you can focus entirely on those, it is possible to create interesting concepts, interesting abstractions, right? So in this case, my golden ratio, I can show you ratios. This is how I set my ratio. This may look like not a different language completely. It's not even closed script at this point. I'm saying, homepage, I create a scale, right? In this case, I'm creating a minor third. I can create a golden, yeah, sorry. That's a golden ratio. And since the type is big, I change it to small. So that's a little more, that's a different ratio altogether. In this case, I do minor third, have my base font as 16. So I'm able to see ratios, even different fonts. This is actually a sans. This is a serif, and this is a, this thing. So if you're heavily into type, you're actually doing this stuff at such a declarative way. I mean, what is functional programming if you can't be declarative? At least that's how I think, right? I'm not creating casals here. I'm not building, I'm not imagining things. I'm just trying everything in REPL, and it's right there. That is my workflow. And I think that's, I actually, that's what I learned from the communities. You're not imagining things and how things should look like, things should behave like, because life out there is hard. No one tries to follow your orders and patterns. You just have to imagine data and then see how things move, and then hopefully it'll work together. That's kind of my philosophy anyway. So the last one, as you can see, that we had grids in typography, which I think is 95% of web design anyway. And Clojus Script Garden gives you the kind of abstraction to express them in functions and data. And if you want to, this is a quick one I skipped earlier, is that you can have graphs as well. This is just an OMAP. So this is an OMAP, in this case, is returning the data as you've seen in the back and the API. It's a graph I'm using D3. Now, Clojus Script interoperates with JavaScript pretty well. It's a D3 app using Dimple Library, and all I'm doing is just loading the data, sending it with Core Async, and then switching. How this works is basically a single mon function. This is it, this is the view. So if you're familiar with React, so you have a render state, right? In this case, I'm building the entire thing. It's an HTML, as you can see. I've built individual components, device form, that's a device form, chart figure, that's a chart figure, right? And then I'm passing, there is a big giant state. Everything is held in a single atom state, state called app state. I can view the state. In fact, I can actually view the state here, which we haven't seen, but in Clojus, the app state is viewable in Chrome. So what we're doing here is basically composing individual pieces, and using React's render model, and then based on the data set saved in the big global atom. Now you might think, why global? Well, in OM, it gives you cursors, which I think some of you are probably Haskell developers, so it's actually implemented with that fashion, is that it gives, each component gets a cursor, in this case, you can see the cursor. Chart figure gets a cursor to the giant map, global map. That way, you get a path, a distinct path into your global map, into your tree structure, and you're not sort of allowed to destroy it. It's nice, I think, because now you have global, which is atomic, the mutation is atomic, because atom is a data structure in Clojus script that doesn't allow you to just change the atom arbitrarily, and now with cursors, each individual component get access to their path. It's like, where is my path in atom? Ask a cursor, and it will give you. That's obviously a simplification. So with these two notions, you can actually build components individually, and then those events are actually channels. In this case, I put a simple go loop, which is, for a very simplified answer, it's like, create a channel on mount. Every time there's someone clicks, send an event to that channel, and then the event is basically a closure. In this case, get measurements, as you can see, this is all it is. Get the host, this is all binding, but the actual one is just one line. Get me the URL, in this case, the URL was API device type measurements, right, which you've seen behind, and cursor update, one line. Of course, it takes a lot of time to get there, but at the end, once you have a structure working, which is always hard in an app, it boils down to a few things like this, which I like. For my last demo, which I actually demoed this at the Clojure West, is as a concept where I think I'm exploring now, is that we've seen individual pieces now. We've seen design, grids, typography, we know services, we know things can be done everything live with a live environment. That's all good, but how do you put together? So this is a simple app, it's actually not an app. It's a page with data, oops. So in my case, okay. So I have the state, my entire content is actually an atom. So now I'm taking React one step further and putting content and styles inside. So what is happening is, everything is immutable, everything is atom, take it one step further. This is experimental idea, obviously. So what you see here is a magazine design that I'm putting together. It's got some responsiveness to it, things like that. But I haven't tested fully with the different content types. So if you're trying to design a webpage which is deriving data sources from different things and if you want to single, in a single shot, view it, how would you do that? It's really hard, I think. So I'll show you now with this OMS, this is where OMS really shines. So anything Clojure script based shines is I can swap my logo. You see that? I can swap. Now I can even swap my entire content. Have you seen that? So again, composability happens when you kind of separate individual items, right? In my case, everything is individual. Every component is styled and mounted differently. But it's all shared, their properties are shared in atom. So now I'm able to kind of review and preview and also go back. I wanna pause here for a minute. Styles content data for a webpage, for a web app swapping between them with a single button or a single function, in my case. The undo was actually four or five lines. It's not a big deal. This is it. It's literally four lines of code to undo. So if you move every all of the state into an atom, in Clojure script, and if you manage that, if you have an architecture that can render your page coming from different data sources, obviously there's an architectural need to update these. But once you figure that out, now it is possible to render pages with different properties. To me, this is as close to getting declarative as possible because now you're able to tweak data sets, tweak content pieces, tweak design, build them separately, and now test things to separate. And now this undo kind of goes forever. So that's pretty much it. And there are some slides out there, and then I just wanna end with this code. There's also a higher order function if you wanna see how I did the type setting by passing higher order function, that's for the slides. But I wanna end this saying that, I don't know about you, but a lot of things are hard if you're used to a certain way. I've been a long time Java guy. I've done Python and jQuery a lot. So when I moved to functional programming with JavaScript and then got into Clojure Script and Clojure, people always keep telling you, you shouldn't do this, you shouldn't do this, you shouldn't do this. I don't know about you, but I feel that I think we should decide that for ourselves, right? Because no one should tell you you're stupid or you can't do this, I think. Because I think I'm stupid, so what? Now I try things and I learn. And I think unless you're learning, unless you have an environment that is live, Ripple and Clojure gives you that. Unless you're constantly experimenting, how do you know what is good? So I think Unix has solved this problem. I think I feel proud about what Clojure is doing. I think it promotes a new way of thinking. It asks bigger questions I think that you must experiment a lot, fail a lot and come up with new abstractions and I'm still figuring it out, so thank you.