 So, this talk is about this framework called Escher.tl and the .tl part means that it's a Julia package. So, this is a convention called Julia package issue for easy discoverability on Google. So, what Escher is, it's a framework for writing web apps entirely in Julia. And this talk, in this talk I'm going to like basically motivate why we need such a thing, why do we need to write everything in one language, why does it have to be this way and how does it has certain kinds of people like UI. And I'm also going to basically get into the construction of such a package, construction of Escher. So, to start off motivating why we need this thing, I'm going to talk a little bit about functional programming. So, it's surprising how many people that actually practice functional programming do not like kind of cannot define functional programming, right? So, people think it's like higher order functions as values, you know, and like various type systems and people say that if you do not have a practically type Hindi-Milner type type system, you don't have a functional language. But at the most basic level, functional programming is just programming with stateless functions, right? You program with functions which give you the same output for the same input no matter where they are executed or how they are executed, right? So, that's the basic fundamental building block of functional programming. But this has a problem. So, if you just have functions which take some value and give back the same value for the same input, how are you going to change the world? How are you going to do some modifications that are required for actual effects to happen from your program? So, one such side effect is UI design because to show anything on a screen, you'll be using some kind of side effect. And the most dominant way of writing UI today is using the web, right? So, the web has this API called DOM, document object model, which is this convention where you use this object called document, which is a huge mutable data structure. And the way you write programs is to manipulate this thing. You go and mutate certain parts of the DOM so that you can see the changes reflect in your UI. This is inherently a stateful abstraction. And it doesn't go well with functional programming because it easily breaks down. So, there's this new idea called virtual DOM popularized by Facebook's React framework. So, what virtual DOM does is, I mean, libraries using virtual DOM do is that they represent the DOM as an immutable data structure. And then, basically, whenever there needs to be a change to the DOM, they just generate a new value which represents the DOM. And then you diff the two representations and figure out what exactly changed. And then you go modify only those parts in the actual DOM. So, this makes for an efficient pipeline. So, you have functions which keep generating GUIs for every update in the app. And then, virtual DOM libraries handle efficiently packages. So, firstly, virtual DOM enables this kind of functional expression of UI where you take some data and then give back a value which represents the UI. So, this has all the benefits that come with functional programming. So, you don't have to think about what state some other guy has created in your app is going to affect your code or how it's going to affect or how whatever you're doing, some mutation to the DOM is going to affect someone else's code and stuff like that. That is one thing. And the other thing is you are only thinking about, at any program point, you're only thinking about the arguments to that point. So, it actually fits in your head. You can think about your large applications as smaller parts which are composed nicely. And then, the DOM reconciliation, which is a trick when you're different, updates the DOM that gives you efficiency for things, right? And it also, like, sidesteps a lot of resource lease problems which are common to easily, which you can get into easily when you're writing stuff, right? So, it also gets along well with the paradigm functional ARK programming. We'll see about that later. So, this is, virtual DOM is substrate for functional programming in tools, right? In web tools, at least. So, there is this package called patchwork.l, which uses this package for functional collections.l. So, what functional collections provide is immutable data structures, like closure orders. So, there are immutable maps, immutable vectors, which patchwork uses to represent DOM strings. And patchwork also uses this library called virtual DOM, which is a JavaScript library, to basically take Julia virtual DOM values, serialize them to, I mean, you can send a Julia virtual DOM value, serialize that to the browser. And the browser will use this library to actually draw the DOM, right? So, also it handles the dispatching itself. So, how does it look? So, this is very simple Julia code. I'm just, this is a constructor called, for a type called lm. I'm just creating an lm, which is a div. And I'm putting Hello World in it, and adding some styles to it. So, these are actually DOM properties. That's how they manifest in the browser. So, I can say, I want to increase the padding over here. So, I have this repel where I, I mean, repel where I write some code, and hit control enter, and the thing updates from the right. So, I can, like, it's basically, you're creating the DOM in Julia, and then Azure can throw it on the browser. So, that's the simple model, the simplest model. And then, so it also extends to SVG. Not very surprising. So, you can already start making these small abstractions for building things, right? So, I made a function called mkcircles. So, this is a function definition in Julia. These are the list of arguments, and this is the expression that gets evaluated. So, this function basically returns a circle with these parameters. So, I'm using that to create an SVG element with a bunch of circles, which give me that picture on the right side. So, I can edit this and it all works. So, one more thing we can get from virtual DOM. This is, like, very important inside. It's that we need not actually just represent these simple DOM elements, right? We can have our own elements which have custom behavior, which have custom JavaScript in base to do something. So, for example, this is a latex element that I'm using. I can change this here. So, this is a latex element I'm using. I'm creating a custom element called cartex, which is loaded over here. It's just a bunch of sql, which creates this thing called a custom element. It's a new spec part of the web component specification. So, here I have an attribute in that element called source, which is, like, the latex version of what needs to be drawn, and then it's going to go render this thing. So, but if you inspect this and see, this is like a bunch of spans with custom styling. So, we didn't actually generate this stuff in Julia. This was actually generated as a single tag, which got rendered into this in the browser through the web component. So, similarly, I have this code mirror component, which will just give me a code editor. So, that's what I'm using right here on the left side. Okay, so this is a very simple subject, right? The LM type. It works by generating DOM, but can we do better? Like, can we abstract other things that a UI program has used? Yeah. Substrate is like the most basic building block for building a UI library. Yeah, yeah. So, yeah, there is some column work code, I guess. But it's, as you'll see later, they're all reusable parts, so you can just combine them in Julia itself and all. This slide show is also made with pictures, so, like, all in a set. So, we need some, can we create other layers of abstractions on top of virtual DOM for making the life of a UI programmer very simple? Okay. So, the users of Julia are not usually UI programmers. They're like scientists and people doing data science. And things like that. Who use Julia for the speed and expressiveness when it comes to mathematical kind of computing. I think it's also very expressive when it comes to general purpose computing. So, we want them to not spend time learning HTML, CSS, and JavaScript. Can we do better? Like, it seems like there should be a nice, very compact abstraction to build everything on top of. So, what Azure does is it provides these bunch of abstractions over this virtual DOM so that it can be used. So, the abstraction one is converting plain Julia values to UI, right? UI being virtual DOM. So, there's this function called convert in Julia, which has a turn-off method. It has a method for converting each kind of conversion you want to define in the language. Like, if you want to define a conversion from a floating point to an integer, there's a convert method. I can just show you this thing in the example. This is the Julia prompt. I can say convert and it'll tell me it's a generic function with 529 methods in whatever Julia I'm using. So, I can also see what are the methods of convert. So, as you can see, it has these methods, for example. So, this one, for example, is a method to convert a big end to an integer. So, you can actually... Yeah, so there it is. That's the definition of the convert method. So, you can dig into whatever you want in Julia. So, that's the convert method. So, what we can do is... So, Escher deals with this type called tile. It knows how to convert a tile to an LN. So, what we can do is, we can define convert methods to convert any type to a tile. I mean, you can think of this as an LN. So, that would be some kind of function to generate the UI for my tile. So, this is straightforward. Like, this is just a string. And what happens is the string gets put in a... It just... The convert function for a string will just return an LN with a span. And the string goes inside the span. So, to inspect this, you will see that it's a span with some hello world text inside. So, you can also write markdown. So, there's this package called... I mean, there's this module called markdown. So, I can say make this bold. All that works. And I can have multi-line strings with more markdowns. Also, I can put some Julia code inside. Code gets in line. I can put some latex if you want to. So, that's like custom syntax for latex. Okay, this works when I... So, I'll just remove this latex for now. It works in the next thing I'm going to do. So, this is kind of ugly though, right? You say markdown.parts and then pass it a markdown string and it creates a markdown string. So, if you look at the type of this, it's actually something called md. And Escher basically... Escher basically has some convert method for md to convert it to type. That's how this is working. So, this is kind of ugly to write this. So, Julia has this thing called string macros. So, you can have a... You can simply make a markdown string which is going to do the same thing. Right? Now, I think... So, the latex got in line over that. So, that's latex. I could have written, like, other phrases over there. So, another thing is this thing called... I mean, another thing is vector graphics. So, Julia has this library called compose.tl written by Daniel Jones which is a very nice vector graphics library. So, it has backends to SVD, PNG, and PDF, and PGS format. So, all I had to do was write a backend for the patchwork. So, what it does is it just generates SVD under the hood. I mean, the equivalent virtual DOM for the SVD. So, this is the Sierpinski's triangle thing. So, since we are in a general-purpose programming language which is also functionless, we can do all these... We can use the power of string machine and then use recursion and do this thing. So, what this is actually doing is Sierpinski's triangle is a recursive construction where in each... So, a Sierpinski's triangle of n steps is a triangle where the three sub-triangles are a Sierpinski's triangle of n minus 1 step. So, that's exactly what it is describing over here. So, the context... The three different contexts you see is telling where to draw the next Sierpinski's triangle. And the T over here is just Sierpinski's n minus 1. And when n is 0, you just draw a simple triangle. So, if I pass 0 to this thing, it's going to just from here the triangle. 1 will be less. So, if you have any questions... So, this is plotting. How do you do this plotting? Oh, yeah. I wanted to show one more thing about the marathon. You can actually interpolate any other UI that you make. Let's just make a text for now. But it could be any other Sierpinski's UI with interactivity embedded. It doesn't matter. So, I'm just making this thing called... Variable called X, which is a latex version of A plus B. And then I can actually just put that inside the marathon string. And it gets interpolated inside. So, I have this full notebook. I mean, full... So, it's like a literate programming summary of this paper called Functional Geometry by Peter Henderson. So, it reconstructs this... This woodcut by M.C. Escher called Square Limit. So, it's again a recursive construction where you have this fun primitive called a fish and you have a bunch of operators on it. So, a picture is just a denotation of what needs to be drawn and then you have these operators on the picture which are very simple. You can sort it in 90 degrees, flip it, flip it, above and beside will juxtapose to this. I'm going to go... You can... So, this is the code that generates this picture. So, you can do things like this with Escher. I'll just show you the code for making this. I'll just show you the notebook once and then switch to the code. So, this is the final thing where we're using all those functions we've built so far to make this final image from a single picture. So, if I go to the code over here... So, you see that it's a giant Markov string with all these other stuff interpolated in between. So, this is an Escher UI which came and got plugged inside. This is the right place in the Markov string. So, as you can see, the whole UI is just a 309 Markov string. I think that's really useful for writing reports and doing things when you are in the flow and you don't have to order with JavaScript and stuff. So, there's one more thing I skipped which is this thing called SimPy. It's a symbolic manipulation package written in Python but we can call it from earlier. So, there's a thin wrapper around this stuff called SimPy which I'm using here and I'm creating a variable called x. It's just an expression which represents x. I can say x squared and then that returns an expression which is x squared. Now, I have a convert method to convert SimPy expression into Escher type. So, that's what is happening there. And then there is SimPy has these symbolic differentiation functions as this function which takes an expression and then the variable to derive it using and then the five over there is the fifth derivative. So, it's computing the fifth derivative of sin x squared second derivative. So, you can play with this and this works. Any sort of expression that you work then you can make this like y and so on. Yeah. So, I'll just skip to the plot thing again. So, there is a package called Gadfly which uses compose to plot things. So, there is this idea called grammar of graphics and there is a nice implementation in R called ggplotting and Gadfly is another implementation of grammar of graphics. It's basically a principle set of primitives to make any kind of plot that you want. So, this is a simple plot where I'm plotting the sin and cos function from 0 to 25 and this is the output I'm getting. So, Gadfly also returns some basically mutable values. So, it's easy to convert them to again fruy. So, I didn't have to do any extra work to do this. Like I wrote a backend for compose so I started working with Gadfly because Gadfly uses... So, there's another cooler plot. So, that's the contours plot. It's basically drawing the heat map. So, another set of abstractions is Layouts. Layouts with CSS. We went and thought about what can we do about it? Can it be any better? So, what we ended up doing, what I ended up doing was borrow some ideas from latex and then use that and some of the abstractions are given by Flexbox Layout which is a new feature that's to... I mean, it's not very blue. Oh, there is a square here. We can't see it. It's very blue. Anyway, I can change the color. Okay. So, what I'm doing here is I'm creating a container of 10 e.m. into 10 e.m. size, another container of 5 e.m. into 5 e.m. size and I'm generating some bunch of colors that I want to use later on. So, and these bunch of colors are generated by this package called colors. I think Julia's color package is the most extensive color package where it's like some of color... color mixing people really love it. So, they contributed a lot and it's like really good. So, there's this primitive called B-bomb. What it does is it... Oh, by the way, this notation, I hope everyone understands. It's like... So, this is equivalent to... over here, I mean, specifically. So, that's the entire... intact exterior. Like, for fill color, I leave out the second argument. It's going to return a lambda which takes the second argument so I can have this nice chaining of where I take something and put it into another thing that changes this time. So, by the way, all these things are returning immutable values. So, you can go back to any previous form of it and then modify it and to create new, right? So, since I'm in a language as powerful as Julia, I can use some, let's say, list comprehension and just sort of create... Okay, I'll just keep that and come back to this. So, you can do this list comprehension. I'll... I have a version in the next slide. So, if you wanted to give... If you wanted to give some spacing between two... In CSS, you would have to figure out which thing to pad or give a margin to and which thing to not give a margin to. If you... Yeah, all that kind of bureaucracy. But Leitech has this thing called V-skip and S-skip, which is like empty spaces in the vertical and horizontal direction, right? So, I can do that here. Similarly, it works if you just change all the V's to H. It'll just make it horizontal. So, it's... Hbox is something that puts all of its arguments in the horizontal direction. So, I can have a bunch of V's and they all go... So, sometimes you also want to expand to fill the remaining space. They can use this thing called flex. If you use flex without any arguments like over here, it's going to put an empty space to fill the... I mean, yeah, it goes right inside the element. But it's a consistent abstraction, right? You're calling functions with your UI and they're returning back. It depends on what they're exporting. Yeah, it's part of color. You can do that. But all packages can decide what they want to export. So, that's what you get in this name. So, there's a statement called export. Anyway, let's just deal with a list of box. One box, two box. I think this is good enough for now. I think it's some bug with my evaluator. I'm just going to call that list X. I can say Vbox X. And that should work. So, I wanted to intersperse some space between all these boxes, right? Again, in CSS, you have both decisions to do than, let's say, like you have to decide where to put the margin. And then you have to go to the last element and remove the margin. You don't want that empty space there. So, since you're writing in a functional way, you can do this thing called intersperse, which has nothing to do with that, at all. So, I want one EM space, let's say. So, what I'm doing here is intersperse Vbox one EM between each element in it. Oh, yeah. Okay, that should never happen. Oh, yeah, not. It's just showing the... So, I can increase that and decrease that and stuff. Put it in edge box. It should work, but it might get compressed. And then there are ways to leverage flexbox, everything to be centered. And then there's the default behavior. Same thing goes for... You can also base around... These are all there in it. So, that's text layout, text time layout, or whatever time layout you want to call it. But it's not similar to... It's slightly not similar to what you're supposed to do. So, how do you give padding and place things inside? That's another thing that you need to do when you're making layouts. So, there's a pad function that will apply arbitrary amounts of padding to any extra UI. Okay, so that's giving this box a premium padding. So, I can use X now inside another... Yeah, that's the padding function. And then you can insert each set a box inside another box by doing this. So, this was my X. What I'm doing here is I'm creating a container of 10-year into 10-year which is filled with the orange color. And then I'm putting the X in the middle of the box. So, if I removed all this padding, it should go... So, it's actually also offsetting... Oh, you can't see the... That's actually... So, what I'm doing here is offsetting... So, I'm placing X... This is the third argument. I'm placing X inside the second argument, the container, and I'm placing it at this offset. And I can start an offset from any point, any corner, right? I could say top left. Both have the same size offset from the top right corner to go minus 3D and 3D and all that stuff. So, you can choose any corner as a reference and then move your thing that you're operating. This is kind of hard to do. This is a code... Like, look at when I'm writing the effect. So, it's a code by Brett Richter to write essays and that's the most about UI programming. So, it's about CSS, right? CSS is so complex that it's never been implemented correctly. Yet. Yet successive versions, but by even more complexity. At the same time, it is so underpowered that many elementary graphic designs are impossible or probably because of you. Right? And most CSS lore is dedicated to treating the tangles of previous acts needed to circumvent incompatibility or approximate the tangles. But I think we can do better by like just abstracting it, abstracting the whole of this need at all. Right? And I think Asher tries to do some of that. One cause of CSS less is the stirring of and flexible abstraction for thousands of pages. And it's also because the language tries to be a tool and a platform. But we can use it as a platform and build a set of principles library functions on top of it. Cool. So, there is this thing called higher-order layout. So, just like box and new box won't cut it most of the time. And it's like like tabs. So, here I have two tabs which have better graphics as the labels. And I can create these two pages and then I have this function called wire which takes two elements and then this is the name for the wire and then it connects this attribute between them. So, notice that this is actually returning a new set of tabs and pages. So, now I can use these new tabs and pages in my layout and they'll still be connected. But this is entirely functional. You're not mutating anything. You're not setting anything. So, another abstraction is the typography. Nothing crazy about this. It's just like a type scale. So, I have this thing called title which goes from one to four and it increases the level exponentially. And then this thing called heading which is actually not so good. Yeah, anyway. So, here is an example of how you can create UIS in a misunderstanding, for example. They're just like any other Julia value. So, you can do anything you want to do with any other value in Julia type. So, this is a list comprehension which is generating four titles and four headings and then concatenating them. Wikite is actually a Julia function which concatenates to vector vertically. And then I put them in a V-box and you get a vertical layout of all the agents. So, so far we saw that we can use this kind of abstraction to write UIS as if they were functions to take, a pure function to take data to UIS, data lines to UIS. What we actually want to do is when the data updates, we want to update the UIS. So, it's possible to create an abstraction where your F remains a pure function and you represent changing data as some data type as you will see. That is essentially like what reactive programming tries to do. So, for interaction we turn to reactive programming. So, there's this practice called reactive.tl which is inspired by this programming language called M. I think some of you might have heard of it. He spoke about it recently and so, it has this thing called signals, library called signals which is basically a data type for representing time-varying boundaries. So, what we want to essentially do is take some time-varying data the subscript T represents like varying over time and then pass it through a function to get a time-varying output. So, we'll look at what a signal is like a crash course reactive programming. So, a signal is basically two things. It has a value at any given time. This is like the axioms that a signal always holds. It has a value at any given time. And secondly, the value held by a signal can change that time path. Very simple rule. And how you create an input signal is using this constructor called input. You give it a initial value because a signal always needs to have a value. And to update the value it contains, you say this push brand function to say 42 onto the screen signal. So, that updates the signal. We can see some some of push in the wrapper. Let's call this push. Push actually does that and returns nothing, but when you look at x with 42 now. So, there is this other operator called consume which can consume let's say I want to add one to each update to x. It is going to return the input signal y which is now always one more than x. So, if I push to x now x by 4, y should be 5. So, you can build this kind of graph of dependencies. So, there are other operators. So, one of them is consume. It takes a function and a signal and returns a signal which is like a map over here. So, another thing is hold l. Let's create a counting example. Hold l what it does is it takes an accumulated value and a new value and then returns one plus accumulated value. That's a lambda in Julia. It takes a bunch of arguments. And I start off with this hold l with a value 0 and then unfolding over x. So, if I look at the ending it's 0 right now. It's basically going to count any updates I made to x from now on right. So, I have five updates. So, hold l allows you to keep some space and then keep updating something. That's the second thing over there of on-signals and then there is filter which will take a function and then a signal and whenever the function holds like it's a Boolean function it's going to keep the value in the signal. And there's merge which can merge multiple signals together and drop repeat which will drop any repeat. And then keep one, take a switch signal and another signal and like switches off the second signal when the switch signal is on Similarly, there's drop when there's FPS. FPS is actually special case here. It can take any signal as imposed. It takes a floating point value and returns the signal which updates that many number of times a second. If you say FPS 30 it's going to return a signal which is going to try to update 30 times a second. But the thing is FPS is like a maximum estimate right. Your system may not be able to handle that many updates every second. But in that case FPS is automatically going to throttle and get you the maximum possible FPS below that FPS. So here's how you implement interactivity. So you create an input signal and then I'll just show you what the slider thing does. So by the way whatever I'm executing here the first thing I execute will be shown on the right side. So I'm just showing the slider now. The slider goes from one to six. That's the range object in here. The column is the range object. So slider takes a range object to create the slider. And then how you can get updates from a slider is using this thing called what it does is it takes a widget actually a widget is a more general thing that I'll get in the next slide and then signal and then it annotates that widget to denote that this widget talks to the signal on the server right. Whenever I update I need to go tell the server that I want to update the steps so I have that and then I can put it in a vbox now the slider is connected to the input and then I'm consuming the input and creating the application. So if I execute this I think something went wrong. There is a case in the evaluator if there is a compiled evaluator it's going to create interactivity. So I'll come back here. So that's how it works. So it's pretty clear by looking at the code that over here I'm using the step signal slider is talking to the step. Here's an example of how you can do an animation. I'm using a FPS Venn here and which state is actually the toggle button over here and I'm creating a signal that updates at 60 FPS when the switch state is right. And finally my UI is just like put the switch there and then consume the slow ball with a fixed trigger. Consume and slow ball function with a fixed trigger. So you would think there will be some kind of tower state with handles. I think that two layer code is generating those and six on top of two and handles on the other. But that could break this nice property of generating virtual DOM. So you can create custom HTML elements which do these nice little things to make a visual. So you call these things behavior. A behavior is something that goes and attaches to another UI and returns a new UI again and it adds some special property to it which results in a signal. For example here is a clickable behavior. I am taking any some arbitrary tile over here arbitrary sry which is this thing called click me which has that font size and some font page. And then I'm applying the clickable behavior to it. So now I get a button which has this behavior. Now I can subscribe with a slide of it. So what I'm doing here is subscribing the click signal which actually updates to the mouse button I click and it starts off with a left button or to maintain that property that all signals need to have a value at any time. So when I click on this it's going to go tell the click signal that I got a click. And then below that I have this folder which is basically counting the thing that I told you. So it's counting the number of clicks on it. So this is kind of composable. So to inspect the element over here what it's actually doing is putting a span over here and then there's a clickable behavior which goes inside the span and then actually eventually it will click on a span. And it's also configurable. You can tell what buttons you want to listen to. And it's also going to add a signal transport. This is what the subscribe function does. It returns the same thing with a signal transport which has some metadata which raises events to send back values to the server. So that's how the clicks go back but we're still generating just plain which makes sure that our system is declarative. So what's in the DOM over here is the clickable behavior which adds events to the event listener and it's configurable and then has a signal transport which has some metadata to talk to the server. And then it also has the stop which will stop events from bubbling. There are other behaviors like fast phase which is a generic thing to get any property on any X event. And then key press behavior which I'm using in the reference to OTS for control and stuff. And then finally there's this thing called interpreter which addresses the concerns that exist between getting the message from the browser and converting it into a Julia value. So over there as you saw the clicks were becoming an actual Julia type saying which also. So all that is hand by interpreter. I think this is too much talking for now. So I'm just going to show some video for a while and then I'll start this is my speaker and he guesses how many lines this is. There's actually supposed to be icons in those. Any guesses how many lines 5 1 5 1 That's a little too often to pick up. It's actually like 7 to 9 89 with a lot of right space. So it's a simple app so the way you write these apps is you make your own model to describe the themes the entire app. So in this case the board describes the entire app. So I'm just going to go through these themes. So this is an immutable type in Julia that's how you create it. So that's the the type is bold and it has a parameter called loss which is a boolean value to a call. You can have parameters which are actually values in Julia. Two types. And then there's a matrix which has the list of uncovered types and how many elements are around them. And then there is there is a matrix which contains like a boolean it's a boolean matrix of mine basically. And then so I have this function all important which is going to progress my board from one state to another given the move. It's taking the board and then a move So in the first case the board is actually dead because the parameter here is full. It means that you have already lost the game. So if you have any moves then you just return the board back. In the next case it's more complicated. You have the board in the move and then what you do is you create a new board where you count the mines around the thing that you place on and then and then return that. That's the main logic of the program. So now what you need is to convert this board type to a UI type. You do that by defining a function. I have this function called show board which takes the board and then creates another UI which is not the board. And it's again built with smaller parts which are things like just things like this block over here. This block will look like yeah add an event and subscribe any updates to that block to the move signal and then at the end I'm just like saying consume show board with the board. The board signal updates automatically when I do things in the UI. So let's go back to while that loads okay so interpreter that's again using same logic taking I think I'm going to do it at the time. So interpreter so you can attach like different kind of interpretations to this on the screen. For example I'm attaching a constant interpreter to this button which has less and then minus point to this thing and then writing that to the delta signal. This is again an alias for for the subscribe operator. And then hold l is going to consume the delta and then keep adding it to get a counter. And thanks to and for all the yeah yeah is very nice about thanks to the people in the community Daniel Jones was in that life back alone was a constant collection and simply I didn't go but yeah it's usable just yeah it's a json so my question is more like so the json from the browser goes all the way to the Julia server and that gets converted to Julia type then you have the functional code which actually processes it as a normal function returns the value and then that gets converted to json and comes back to the browser for rendering. So since there is absolutely no client processing I mean there is like I mean can I what I'm asking is can I write completely client type javascript yeah you can you have to put that in I have one more question yeah I saw that I mean this is pretty impressive so we are replacing that we've got some abstracts just with hundreds of others applying for css have you gone through a css3 I mean yeah let's talk that's what I'm using okay so if anybody would like to go for css3 or Julia right what do you very prefer this you can use all the point of abstract in the DOM basically css3 ultimately is the property in the DOM style. fill color style. background color style. this is just like a DOM property you can you can basically write functions which will implement those css3 cover those css3 you don't really need to use the functions defined inside a set just use the lm-type and then keep adding them this is something like you're easy to use concept tools when you you reach out to the you reach out to the solutions pretty quickly then css3 you can do that write a template you just create a template I can give you a talk why