 So hello and welcome, is the sound okay? It sounds a bit over-saturated. So hello and welcome to my talk. So topic is use flask. Might sound familiar to people who use React hooks, but the topic of my talk is use flask or how to use a React frontend for your flask app. A bit about me, like you already said, my name is Adrian, or online user handle at Seafmaster. I can find him in various places, and I'm the lead developer of the Indicor project at CERN, a 17-year-old project now, which actually was used to host Europe Highest in 2006. And we still have the timetable from the conference back then. You know, also I'm one of the maintainers of the pallets project, which is flask, werktzeug, chincher, and some more tools. So I'm mostly hanging out there on CERN Discord channel, helping billions of user tracker, sometimes even writing code for it, but not as often as I would like to. But yeah, trust is flask, great project. And I'm a Python enthusiast since almost 10 years now. I started with a small hobby project. My first thought back then was actually, ah, this language has an indentation for a block. That seems to be weird. And then I started loving it. And I'm proud to say that, well, around a year ago, I finally moved on from Czech fabric to werkt, and honestly, I don't want to look back. So a bit about the status quo instead in case of technologies used mostly in the flask ecosystem. This information is mostly based on what I'm seeing people ask about on IRC. So I'm sure there are some bigger projects out there that, of course, do also many more customized things. But this is about what probably most people do because those are the typical people asking questions as well. So I'm going to talk a bit about the main four pieces and many applications used. So it's WTForum, some Czech-Raria, A-Tricks, and well, JavaScript, which is kind of covered in Czech-Raria. But yeah, you always have people who are seeing JavaScript and Czech-Raria both different languages. And we're starting with WTForums. Well, it's quite nice to use, actually. It's easy for a simple case. So if you have a small application where you just want to put a form, have some validation, maybe generate the HTML for it, it's great. It's declarative. You don't have to do much. It does a job for you. So yeah, great library. You should use it if you do a small application that's mostly static. The problem is, let's say you have something more complex. Maybe some custom widget. I mean, for example, if you're organizing a conference, you might have a widget where you select speakers, provide information about them, maybe what kind of roles there are if they're a speaker or just an author. Well, now you are dealing with probably a list of dictionaries or some other formats that can hold all this data. So you're submitting the data and great. Now there's a validation error. Maybe because the user entered something he shouldn't have entered, and it wasn't called on the client side. Well, anyway, what are you going to do now? Ideally, you don't want to lose the data, but just show an error and re-render the form. So you do a round trip with a value because it comes from the clients and WTForms converts to a format most suitable for Python, and then has to convert back to a value suitable for the HTML form field. Now if validation failed, you might not have data. You can probably convert back to the format client-side code expects. So what are you going to do? Show the previous data you had in the database when editing. Show nothing. I think both are not great cases because I mean, if you don't notice it and say it again, you might lose data. Of course, you can say garbage in, garbage out, but in that case, you really need good client-side validation, which you might not always have, even so you should. The next one, Che Guevry. Let me ask you a question first. Do you in here still use Che Guevry nowadays or want to use Che Guevry nowadays? Okay, not too many. So I mean, some years ago, Che Guevry was really great. I mean, you didn't have to deal with, let's say, IE6 particularities, which I'm sure everybody got to laugh, but nowadays, I mean, there are not that many reasons for it. I mean, for something small, you can still easily use it, but the DOM provides the same functionality as well. And the risk of using Che Guevry is, if it's bigger, you easily get spaghetti code because you have selectors and IDs and classes all over your code. Sometimes you might be using the same CSS class, both for styling and functionality. Good luck when you remove the styling and then suddenly your scripts break. And in a bigger application, it can easily happen that it's barely maintainable at some point because maybe you are including all JavaScript in the bundle. Then you have different pages, which happen to have the same selector. Oops, suddenly the code runs on something it shouldn't run on. Yeah, not great. Another problem with Che Guevry, of course, is there are lots of extensions. Some are very old, so you might get some subtle side effects and bugs, so maybe not so amazing sometimes. Then A checks. The idea of A checks, of course, great, but the XMLHP request API is absolutely horrible. I'm sure most people here agree with it. I mean, you have to instantiate the object. You have to, yeah, you have to put a callback. You have to remember that ready state three or four means that it actually succeeded. There's no constant for it. And yeah, callback hell, of course. Then nowadays, luckily, you have set, which is supported by all major relevant browsers, which isn't bad. Can still be improved a bit like, you can't quickly build a query string from a dictionary, but it works fine. And there's stuff like Axios instead. But then back to the server side, what are you gonna respond to the A checks request? Are you sending back large chunks of HTML? Because that might be easier, just render your Chinsher template on the server and send it back. And then one line to update, dollarwhatever.html responds data if you check your query or setting inner HTML. Problem is nowadays, you might want an API. I mean, every bigger web app should have an API nowadays. Because at least as a tech savvy person, myself, I like having an API so I can do my own things. Especially if tech companies nowadays like to make your ISL are not so great sometimes for technical people. So it would be nice to be able to do my own stuff. Okay, let's assume, okay, we want to do an API. Are you gonna duplicate your code for the API? Because you don't want to return HTML in API. It's the same time. You can't just return the data, you pass to your render template call for the API because that's probably an object with way too many data and not everything you want to actually send to a client. And it might not be JSON serializable at all. Of course you can use something like Marshmallow, which is nice, you should probably use it anyway. But again, if you need HTML at some point, you probably still have some duplicate code for API and non-API calls. Then JavaScript in general. Well, what do you usually see here? A script tag, sometimes even inline JavaScript or just source URL for static pointing to some file. So it's rarely transpiled between formats where sometimes people minify it, which is at least something, especially for libraries. And generally, the code I've seen lately looks like something written to support old browsers. I mean, zombies can be fun. I mean, who doesn't like shooting zombies in the game? But, well, this particular browser, I don't think anybody likes dealing with it. So yeah, please don't support zombie browsers if you don't get lots of money for it. And let me ask you the thing, if you still support those browsers or if your JavaScript still contains a last statement, why are you still writing the kind of JavaScript you could have written 10 years ago? I mean, things improved a lot. So yeah, maybe you can do things in a nicer way nowadays. So how to improve all this? So first of all, you can use a tool to build your asset bundle and assets, in this case, can be everything static, basically, for the client. So of course, JavaScript, but also includes CSS, fonts, images, since I think it can all be handled by a tool like Webpack. There are no tools as well, but in this case, we'll focus on Webpack because I think it's the best-known one. Also, of course, use more than JavaScript. Like I said, probably don't need to support zombie browsers. So you can use also nice new features, ECMAScript 6 and ECMAScript 2017 and newer standards, because like Cisteris and JavaScript is actually fun. And if you do need to support some older browsers, there are tools like Babel that can transpile to all JavaScript, which is not fun to write, but I mean, your tool writes it for you and you don't have to ever touch thanks to source map, even not even by debugging. And of course, you can make the font and reactive using something like React Chairs. So maybe you've tried Webpack out and was like, oh, God, considering Webpack, that's quite hard because you have to write a JavaScript file and I don't think the typical Webpack config is less than, let's say, 30 lines of JavaScript. Of course, you can use it without the config but then you don't have many of the nice features. Then it's basically glorified minifier. But let me tell you, considering Webpack is too hard, no, I don't think it is. Unless you want to do weird things with Webpack and trust me, we did those things or been there, done that. It's not fun to debug this and something doesn't work properly. But no matter if it's a bigger complex code or something small, it is boilerplate code in the end. So for a single or two bigger projects, not too bad, but maybe you do many small web apps, basically a client version of a microservice. Yes, and you don't want to repeat this code all the time. And if you want to update something, you have to do it everywhere, so yeah, not amazing. So question is, can we do something like from Webpack import config? I mean, we're right in Python, we like to import stuff. Well, answer is almost. There's a tool called Create React App and to quote the documentation, Create React App is an officially supported way to create single page React applications. It offers a modern build setup with no configuration. Sounds pretty great, I would say. So what exactly does Create React App do? So first of all, it contains the whole build config inside its own package. So it doesn't clutter your project root directory or any of your files on the version control. It does auto rebuilding and hot reloading of the frontend, which is great during development, especially if you have it up on the second screen. So you save your file and it immediately updates. And it even comes with its own death server which takes care of it. But I think that's enough just talking about the fact. Let's maybe dive into the actual code. So we start with a simple Flask application. I think whoever already used Flask in here probably knows this type of application. It doesn't do much, defines the Flask app. In this case, we're only registering two APIs. One simple one that gives you the current time. Another one that returns the greeting either for a given name or for an unknown person. Of course, it's about things that could be easily done on the client side, but I mean, I needed an example. So here it is. I mean, writing useless code is fun. I think if GitHub actually has a useless code challenge going on right now, so yeah. Okay, now we want the client-side frontend. What are we gonna do? We're gonna call Create React App. And luckily, Node comes with this tool called NPX. Basically, what it does is it downloads the package to specify it to a temporary location, executes it. That's great because you don't need to install it manually somewhere first. And if you don't have NPX, it's time to update your Node version because older versions didn't have it yet. And many of the nice things nowadays don't work well with old Node versions anyway. So you run NPX, Create React App in a folder client, so it creates the app for you, installs a bunch of packages, which usually does not take a few couple of minutes, assuming you have a decent connection and computer. And it even tells you what you can do afterwards, like to start the frontend. We're not gonna do that right now because there's another step I have to think about. Because Flask is a very nice routing system, so you've seen it, app root, you define a rule with some placeholders even, and then you can use URL for all to build the URLs. The problem is how do you do that in JavaScript? I mean, if it's fully static and you only have a few snippets, what you could do is like putting in a data attribute, which works well, okay, for a static URL. If it's dynamic, it won't work because then you probably start doing stuff like string concatenation, template rules, whatever, to put your power on there, which again, pretty much fully manual. And for example, if you change the endpoint name in your code or another endpoint name, the URL, are you gonna remember to update it everywhere in your JavaScript? I mean, you might have tests for both frontend and backend, and yeah, I guess you update those tests, but the test will still pass, except that now you have different URLs on the two sides. So unless you have tests covering both, the application itself might not work anymore. So yeah, half-coded URLs are pretty ugly, and even more so, it's a dynamic. I mean, you're building a URL dynamically, are you gonna remember to do URL encoding of the power in it? If it's coming from the user, you might have to. So let's install some more packages because we're using code as great. I mean, first one, a normal Python package providing some functionality to Flask, and two note packages, and NPM is actually nice enough to update our package chase instead of what's created by Create React app. So no need to update a requirements text for that one. You only want to put the first one in your requirements text or setup PY. Once we have those packages, we have to hook some up with, as build script, hook some up with Flask. Unfortunately, we still need a tiny bit of boilerplate code here. And this goes to a file called bubblepluginmacrosrc.js. So what is bubblepluginmacros? This is basically a plug-in for the build system that's included by default, which lets you define macros in the code-transpillation step. More on that later. In this case, only thing worth mentioning is that the config now specifies that Flask URLs plug-in has an argument URL map, which is output from calling Flask URL map to JSON, which is a package I installed in the previous step. And what it does is basically writing the whole URL map from the Flask app into a JSON format, containing all the details needed to build a URL. Next step we have to do, which is partially because of the bug in Create React app, which, so we have to tell it to proxy requests for the API to our actually Flask application. Since, like I said, we have two dev servers, the one from Flask and the one for the frontend. It's a bit annoying that you have to write code for it. I mean, you could use a one-line command in package JSON, but currently this doesn't work in Firefox because it doesn't sense the right header or something like that. So we have to use the boilerplate code. The advantage is we can use an environment variable to override the URL of the Flask dev server in that case. Alternative to this is proxying would be using course. So we simply run it on different parts and just access through that. Or we could put engines in front of it, but I mean it's development, especially for a smaller app, you want to keep it simple, no need to have engines there. So to summarize what we did so far, first of all, of course, we have the Flask apps that's providing API and only an API. We have the necessary boilerplate for the React frontend, most of which was generated by Create React app, so not much to commit except those two files. And we exposed URL building functionality to our JavaScript code, which they're gonna use soon. And the Create React dev server is now forwarding API requests to Flask. So let's actually start using some React. First of all, Create React app creates this app.js with a small demo page. And in this case, we only add a custom component. So thanks to modern JavaScript, we can actually use import statements that are similar to Python actually. So we import something called demo from file demo and instantiate it. Thanks to JSX, it's basically JavaScript where we can have XML-like snippets. And the other case tag is basically React component, we don't have arguments for it, so we just put it there. Then what do we put in this component? First of all, of course, you have to create the demo.js file, have some imports we will need later, but this is React specific. So if you start writing React, you'll quickly see that, for example, you need to import React to use JSX. So what we do related to Flask, first of all, we include the Flask URLs macro, which looks like a normal import, but trust me, it's not. And then in the next line, five and six, we're actually using something called tag template literals and referencing the two endpoints we defined in the Flask app there. So now we have two things that are somehow related to those URLs. It's actually, both are actually callable to actually build the URL. But first of all, let's add some actual UI since right now our component is still empty. So like I promised in Substruct, we will be using React hooks. So what are we doing here? So first of all, we are defining a hook with a variable as state hook that's providing a field containing, well, something labeled time, and the setter function to actually update the state field. So this is basically when calling set time, it will render the component and time will then contain this value. What we then do is call the use effect, another hook provided by React. Basically by providing the empty dependency list in line eight, we tell React the system runs once and only once after the component has been mounted. So what we're doing here, we simply use set and with a generated URL to send the request and send process to JSON. And then at the end, we're building another URL just for testing. This time was an argument. So we could send a request to this one as well. Well, right now we don't to keep it short. Anyway, as soon as we got the time response back, we are gonna render a message which time it is and what the URL for the greeting would be. So I can actually show you how this would look like. And if I reload this page, it will have the current time from the server and the greeting URL built with argument, I put so. So now you might wonder how the hell does all of this work? Well, are you gonna accept this answer? Probably not. So let's go a bit into the card. So this first line when we're importing something ending in dot macro just tells the bubble macro plugin to actually run some coded build time. But just importing it doesn't actually do something yet. But as soon as we start using the macro, in this case, as a tag template, literal. This basically calls and sends a function provided by the macro at build time and providing a reference to the argument you passed and its AST node. So this actually triggers the URL we're writing. What this thing is replaced with, I'll show you in a moment. Anyway, if you call this function provided by it, it behaves basically like calling URL for with the name equals snake keyword argument. If you're curious now, this is the code that the macro actually generates. It looks as ugly as you would expect from generated code, but luckily you never have to see this until unless you actually look in the generated code files. And it would be even uglier if there had been space to actually put all the building rules to generate the URL. But again, that's flask internal, so no need to actually look at them manually unless you write a plugin to build URLs. So let me show, as I already showed you, now an important part that you can actually contribute to this project. It's on GitHub and under the MIT license, or in the Indica organization called JS Last URLs. Yes, I'm not great at making up fun any names, so it's basically describing what it does. How could you contribute? Well, you could really use some documentation. Right now we only have two small example apps. And yeah, I don't like writing documentation, but maybe somebody likes doing it, so you're welcome. And some guy on ISC actually told me using the bubble macros it would be possible to define TypeScript steps. So if you used it in TypeScript, you could get the proper typing. I'm not using TypeScript myself, but maybe somebody's interested in using TypeScript, so another thing to contribute. Or of course you can just start using it, and maybe hopefully not find some bugs in it. Why should you contribute? Well, you can brag about having contributed to a certain project. So to stay in the topic, there are some other nice stuff to show you. First of all, this thing also comes with a bubble plug in the doesn't use macros for the URL building. Instead, it would give you a way to import the URLs like this. I mean, it has the same features as a macro version, but you need to actually have access to the webpack and bubble config, which you cannot do manually, easily with create, react, up, create, react, up, unless you actually check the config, which makes it a bit more messy. And honestly, this is a version I wrote because initially I didn't know about the macro plug-in, so no idea if you'll actually keep maintaining this one or switch our own project to the macro version as well at some point. I mean, one less package to maintain. Then if you do a real application, you need some validation on the server side. Please don't use WT forms to validate your API requests. There's web arcs. It uses marshmallow internally. It's really great. Also very quick responding to bug reports and contributions. So a great project to use, I think, for form handling and validation on the client side. There's something called react-final form. It's also very efficient, very lightweight. Nowadays, even uses react hooks. Using it for my main project as work, and it works great. And since this example was pretty short on my GitHub account, I actually have a bit more in-depth example. And this also includes some details on how you would actually generate a production bundle and showing some different ways about how you can do things. And this demo looks like this. So yeah, if you update, you see it gets the current time from the server. Or you can go here and you can put emojis. So it shows me the URL it will generate. And if I call the API, I'm getting back a response, including a very pretty emoji. And yeah, that's pretty much it. So let's go back to the slides. So if you're now interested in the project or want to get in touch, you can find me on GitHub and Twitter. And of course, an IRC on Freenote and the Poco channel, those in the Indicator project channel. Since I'm in this library, I was talking about this kind of related. So we are reusing the IRC channel. Or of course, you can talk to me right here. And I even have some pretty hexagonal stickers to give away. So if you have any questions now, feel free to ask. I think we have something. Thank you, Adrian. We have a few minutes for questions. So if you want, you can go to the microphone. Hi. I'm using Flask with Connection. Is it possible to generate those URL mapping with Connection also? I don't know Connection, except that I heard about it in a talk two days ago first. But basically, what the library does, the Flask URL package really exports the function. You can pass the URL map to it. So you don't have to use the Babel magic. So as long as you can add dumps the URL map to JSON and somehow provide it to the URL builder function from the Flask URL package, you can use it. The Babel thing is just syntactic sugar. So you can use it more easily without having to manually deal with exposing the URL building rules. OK, thanks. Hi. Thanks for the excellent talk. I just wanted to ask, there's always the option to do things clearly server-side or client-side. For as far as the user authentication is concerned, assuming a very simple, say, LDAP-based authentication, do you recommend using then Flask login with login required on the API endpoints and then passing something, I don't know, a custom error JSON to the client or putting everything client-side? So if it's LDAP, so you have username and password, I guess. I mean, it has to be on the server-side because I don't think you can do LDAP log in client-side. In any case, which is very ugly, you probably don't want to expose any of the credentials to connect to LDAP on the client-side. So yeah, I would do server-side and then return. Probably would have to use a session token for it. I mean, which is super amazing to have a state for the back end with the API. But yeah, it should work fine. And if you use something SSO-based, you could do it all client-side. Personally, I like having a server-side because then you can just send some tokens there. You don't have to deal with the data from SSO. But I think it's a pro and cons for both options. Thank you. Short question, maybe not. Okay. Thank you, Adam.