 Okay. So for today, again, for today for the recording, today's meetup I'll be talking about yet another year is a site project that I've built. It's a tiny New Year's resolution app that basically lets you write your new year resolution. As in nothing, nothing like surprising, no, no like super novel features. It was like a very tiny, tiny site project that I've made. Okay. So what I'll be going through in this talk is actually like the study is definitely like going through what is this project that I've made that I've built so that we all have context about what I'm going to talk about today. Like, even if I'm going to go through some, some technical stuff, at least you have an idea about what I'm talking about and where in the part of the app that I'm talking about. So definitely the study is just an intro day after that I'll be talking about a tech stack which probably will be helpful for people who want to build your own own own project. And then there are lots and lots of tools out there. So which one to choose, then maybe what I'm going to go through today will be some sort of like reference for you to choose. Of course, you are still free to choose whatever you want, but at least there's some sort of reference that you know have been used to build something that you have seen before. Okay. Then the last part is where the meat of the, the talk will be about it will be some challenges that I found really interesting some decisions that I had to make, which for while building this, this app. Okay. So the first one is definitely like what is yet another year. So, yeah, another year is just a simple web application. So what application means like it's a, it's a, it's a app. In the sense, you can, it's not just a plain website, you can log in, log out, you can save data in your account and do things with it. So it's like a web buy it lives on the browser. So, so therefore it's like a web application. So, so this web application yet another year is just a new year. I see it's a new year's resolution app. So it lets you write new year's resolution. It lets you track your progress for the year. And then it, and then it also lets you track resolutions over your over the years. Right. I guess I'm not sure about you guys, but sometimes I write them at the end of the year. And then all the start of the year. And then I write it on a piece of paper or some, some notes in my computer. And I just forget where it is that then this, then then it's gone. I can't really look back. So, so, so this app also lets you just write, write, write it in years and then you can just track across the years. What, what have you been aspiring to do? And one more thing is to be able to have a link that lets you share your new year's resolution with whoever you want to share it with. And, and then that, that link will come in handy if you have your blog or something. You can just put it there. And, and people who come to your blog or your website can link it up to, to, to see your resolutions. So, I've launched this app in the middle of this year. About and, and July on, on this website called product hunt. Yeah, so it's, I'll say that I launched it pretty recently. Okay, maybe six months not so recent. Yeah. So, so, okay, before I go to there, I just want to show you guys what it looks like. So it looks like this. So this is like the, the landing page or. Yeah, the landing page or some called the brochure. So this is like, okay, what's the app is about. And then you can go to the web app. And then. Okay. And then you are prompted with a login screen. They can log in. And here I use Google authentication. And basically this is like almost everything. So you have like some progress bar. So if you don't know now it's 18 November and we have 43 days left to the year. If you, which is actually not a lot of time. So if you have a lot of things you have not done finishing this year. Yeah, just keep in mind that you have about 40 days left. So, so then you can go forward by years and see what you have done behind in the past years. And then the last part is that you can. Oh, of course you can, you can like write, write new, new resolution here. They can delete it. So it's like a to do list button with a context of New Year's resolution. And you can share the link. So if you see a link like that, you get linked to a page that you kind of edit anything. So it's a good way to just share your New Year's resolution. Yeah, that's about it for for the app. So it's a pretty simple one. So, so the next one is like, what's the motivation that I built this thing. So I have been a software engineer for about five years. So I've learned many, many things at work, or just on meetups or on my own side projects, other side projects that I've tried to build. And then I just wanted to put it all together to actually get something to launch something. So a lot of projects like kind of stock halfway blue steam or just the idea wasn't like really good enough to want to continue. So, so I decided that I want to build something really small to increase the chances of it actually like reach a point where it can launch. And whether or not I continue development then it doesn't really matter as long as that is launched is sort of like feature complete to for V1. Yeah, so so this is like why I started building this app to, yeah, so to consolidate my learnings and to actually launch something. So the tech stack that I used to build yet another year is actually very, very simple. The tech has been around for a really long time. I mean people, a lot of people have built with this that after that they have moved off and but a lot of people are still continuing to use this tech to build. So it's supposed simple I highly recommend it for anybody who is like starting out building something and want to be fast in to push it out and get feedback from from people. So this for my stack. I use hero cool to host the app and the and the database so and then so that will be on rails which is the server of my app and then postgres the data storage layer. And then I have what pack to compile all the assets, especially because here I also have a single page app which is built in Elm. It's a front end frame. It's a language. It's a front end like language to build front end stuff. So, so what packs here helps me compile my my single page app helps me manage my images, style sheets, etc, etc. And then for authentication I use I just use Google authentication for for my app and then and then the way the the back end and front end communicate is just a simple rescue API. So this is the stack that I used to build yet another year. So next I'll be going through some of the interesting challenges here again I my focus is on the interesting. Not not so much like oh very very difficult problems but more like more like decisions that many people at least I find that many people just thinking for granted always has to be like this has to be like that. But actually I found when I was building I was trying to find simpler ways to do do some things and then and then and then I found that these decisions that I made were pretty interesting and it's something that anybody who starts out will probably face also. Okay. So the first, first interesting challenge that I found is actually authentication. So, because my app isn't like just Ruby on Rails app, usually if you have just Ruby on Rails, you will just use that session authentication the rails default session authentication. And then for people have single page at people start to talk about json web tokens and having like refresh token access tokens, etc, etc. And, and then, and then here I was thinking oh okay I need to do authentication. So how do I make sure that the front end knows all the front end and back end knows who this user is, it must be able to persist must be able to be secure, etc, etc. Then I thought okay, must I use json web tokens, which is like JWT because JWT has they use some, it has this like thing that can prevent people from changing the payload and all and it's sort of like guarantee that to a good extent it guarantees that this user is who he is. Then, then I realized actually the default Rails cookie store works perfectly fine. Because like cookie store, like the rails cookie store is encrypted, the values in there is encrypted is considered generally safe. Of course it's still open to people from hijacking your cookies but then there's like a separate topic altogether. And then on every API request from the front end to the back end from the single page app to your server, it will always send the HTTP cookie, it was always send the cookie in the HTTP header anyway. So my server side will still be able to know who this user is just from the cookie. And the last part is like, it's close to zero setup because the rails cookies store comes like baked into Ruby on Rails. Of course, you still can do JWT, there are a lot of device, they have like a JWT version. I think that there are many, many frameworks that is like a drop in replacement into rails for the authentication system. So a lot of them also have JWT. So of course those, if you just drop it in is probably also about the same amount of work except your front end code needs to handle the JWT stuff. But here I just opted to use the default cookie store and it's really like until now it's like perfect and it's really zero setup time. So in the end I decided okay, I'm just going to use this for the authentication. So this is like the first challenge that I, first decision that I found interesting that I had to make. So the next one is actually implementing authentication. This is not, I think like authentication, like it also falls under the bucket of authentication, but here is like a login system using a third party provider. So in this case, for another year I use Google authentication, right, Google OAuth. So in the usual OAuth setting, the user will, you have a form on your website. User clicks, you will do a post request to the server. The server will return a redirect to the unique URL of the authentication provider. And so you get redirected to Google and then Google, after you log in there, Google redirects the user back to your app. So I was thinking like okay, I have a single page app. Single page app doesn't really deal with redirects so much, at least not that I can imagine how they do it. Then I was thinking more and more and I really, then I thought about it and I thought, oh, maybe I'm in a single page app still renders HTML, right? So if I drop in a form in there, it should still work, right? So I don't need to make an API call to the server and get the link back and then use the single page app to redirect the user somewhere else. Instead, I just do the usual form submission from my single page app to the server and then the server will return a trio to which is a redirect status code. And then everything is that works the same. So okay, I'm going to try that. So the form submission all works so that's super cool. But after that, I realized that there's another problem is that to do a form submission in Rails, there's this security feature called CSRF. So it's like cross-site request for Jerry in short is CSRF. So there's a requirement is that in the form, it needs to have a hidden field, an authenticity token hidden field that has a value that match the CSRF token so that the server knows that this request is valid. And then the first problem I had was, okay, when the single page app generates the markup, it doesn't know the CSRF token. So then how can it generate a form with the correct authenticity token and be able to do the post request successfully. So I went to research online. Many people have told me, okay, you just use JavaScript. I've read many people wrote like you just use JavaScript when take the CSRF token from the page header. And then you just inject it to the form. So yeah, that generally works. But the problem that I realized as a spa, the single page app is that by the time you get the token, it might not be valid anymore. Because the security feature keeps refreshing the token to make sure that every single point that you are making a request is from you. So here I have a problem that the token might be outdated so that this way doesn't really work. So the next, another way that I found was that people say that when you load the spa, you can inject or you can just pass this token to the single page app on boot. So like for example, we react, you usually have a HTML tag and then react just attached onto it and then generate the entire react out. So or any other single page app also works about the same. So it's also the same problem. The CSRF token is only at the start. And then when the app goes through a few requests, the token might not be valid anymore. So there's really no guarantee by the time the user does the post request, it will still be valid. So the last one that I found, which I was pretty surprised that I found that it worked, is that if you have your markup and you have this input tag hidden name, authenticity token, this tag inside your form, if you do a full page reload, Rails UJS will automatically inject the value to this element. So all I needed to do is to make sure that the page that has the form does a full page reload. So for me, it was like the obvious solution because I only need to have a full page reload for the authentication page because that's the only page that has that form for me to do this OAuth flow. So I just, in my front end, my single page app, I just add this HTML element and then I just ensure that every time the user picks a link that goes or gets redirected into this page, it's always a full page reload. And then the form submission will work. So it's that, okay, that's great. Also everything works and it's super simple. So it's like low overhead because there's only one page that requires this thing. So yeah, so that is how I implemented OAuth in yet another year. So the next one is assets management. And in this case, assets, I'm talking about like images or icons or like fonts, et cetera. So here, if you are familiar with Rails, Rails has this Rails asset pipeline. Ever since the introduction or introduction of Webpacker a few years ago, some people move their like managing assets into Webpack. Some people leave it with still with Rails assets pipeline, but only have the JavaScript part, the single page app part that is packed by Webpack. So for me, when I started out, I used the Rails asset pipeline to manage like the images. So in development environment, when I build the app, everything is fine. When I render the app, the images all renders properly. And then when I push to production, then I realized that all the assets broke. The images couldn't render, it couldn't be found, et cetera. So which then I realized that, okay, for the assets pipeline in development environment, it does not require the digest at the back of the name of the asset. And then by in production, it requires because for caching purposes. So then, okay, now I know the problem there. I tried to like find the correct file path for the image, which then made me realize that there's no easy way to get it for Rails asset pipeline. For traditional Rails app, they all use the URI helper to help them generate the file path. But because I'm building a single page app and I'm not using Ruby to build it, so I don't have my single page app does not have access to the URI helper. So makes it a bit difficult to get the URL automatically generated in my single page app. So and then when I try to get the URL with the digest, it's a bit hard or so because only production has the digest. So I need to run it in production or something. So after that, they decided, okay, it's too painful. I decided to move everything to webpack, which is a bit contentious for many people. So I know people have a lot of issues with webpack, but I actually had close to zero issues with webpack. Everything works perfectly. The development production environment with webpack all requires the digest. So Dev and Pro environment is exactly the same. No surprises. If it works in Dev, it works in production. And then Webpack always give me the full URL with the digest, which I can just code it into my single page app. So everything works perfectly. So then I decided to use Webpack to manage my assets. So and the last one that I found interesting that I do think, I think it made me think a bit more about me. Okay. So identity is interesting because these days in the past, we always see like username and password login. That's it. That's only every website uses the same way of logging in. But these days, actually for quite a few years now, we've seen OAuth providers. We've seen Google authentication. We've seen Facebook. Facebook also can do OAuth. GitHub also can do OAuth. Many, many, many different services allows you to do OAuth with them. And then there are newer ones like password list login. These days a lot of full number logins, et cetera. So I was thinking like, how can I make sure that my authentication system scales for any future type of authentication method in the future? So then here instead of only have a user table, I have a identities table also. So each identity corresponds to a unique authentication method. So maybe if I have five authentication methods, because this is like a table, right? So even if next time I can scale to 100 authentication methods, it should all scale properly. So I should be able to handle as many authentication methods as I want to. So all these identities from different authentication methods will be able to map to a single user. So in the future, if a user is worried that he forget, if the user comes to the website, the website has five different ways of logging in and the user is worried that they forget which one did they use in the first time, they can link all the authentication ways to a single user. And then it always maps back to the same user. So this model sort of allows for this. And the last one is like each authentication method. Now that I have a unique identities record, each different authentication method, maybe in the future you require some special keys or something, right? So I will be able to save all this information for different authentication method. So what I found that I think that this model is pretty scalable and as far as I can think of, I think that it should scale well. If in the future I want to introduce other types of login methods. So actually that's all that I have today. So open to any questions about the talk. I think I can start off, right? I understand why you chose Elm over other frameworks. Because I just thought that I wanted to try something new. So of course like in the midst of this thing, I also wanted to learn something new. So then I decided to try Elm. It's not just learning a new framework because it's like functional programming. So I was a bit curious over the years about what functional programming is. So I decided to give you a shot. Yep, any other questions? Do you implement the OAuth without any gem? Do you use any gem for the OAuth? No, actually I wrote my own. I've been one that is a bit dangerous if you implement your own. But I tried to use the only of gem and then they had some issues with this basic flow. Actually I'm surprised that it doesn't work so well. So in the end I wrote my own. So I dug through the docs and the Google's docs and then I implemented everything that they recommended. So in the end I wrote my own OAuth flow. I wouldn't say it's actually not very difficult if you understand why it's happening. So I would say still do it with caution but it's worth a shot. Okay, any other questions? If not, I think... Sorry, I'm a bit laggy. Can I ask about... You said you launched your product, right? Is it possible to kind of share what was your experience like in terms of launching a product? Do you get any traction feedback from users? Anything like that? Okay. The experience is pretty interesting but I would say that I didn't get any traction. So I felt like, okay, I have no experience at all launching a product. Then I don't know... Okay, what should I go next? How to deal with marketing and all. So it was like a really very interesting experience and it's like a learning experience for me. So what I did actually is quite straightforward. You go to product hunt, you upload whatever you have to upload, you fill out this form, you set a launch date and after I've gone through it, things start to make a bit more sense what I can imagine other people are doing before the launch date that you submit all everything up already, right? Then before the launch date, people will be advertising, telling their friends, telling everybody and just getting traction, getting people to look at it and then during the launch date, actually I don't know what can people still do then maybe just reply all the questions and all. So mine was quite bad, I think because the day I launched, I didn't do any of the before pre-launch things. So the day I launched, I just shared with some of my friends and then immediately it was pointed out that the login wasn't working. So the launch date is today, yesterday I was like, okay, I need to fix this thing. Then I realized that I broke something. I said I didn't know I broke something then tomorrow it launched and then it wasn't working. So the launch date was pretty scary because I didn't have any experience. So then the day I had to, after I launched then people tell me that it wasn't working. Then I had to go faster, go and fix it. Yeah, so I didn't get much traction to be honest like just friends trying it or that's it. And it wasn't, but it was a very good experience. So whether or not your app takes off or not, I feel that it's always good to just try once. Then in the future you just get better and launching products. You might know how to do the marketing better. You might know how to do that after that, etc. So definitely do something small and give you a shot. Okay, thank you. Okay. How do you do all the CI test? Do you use Aspect? Oh, I wrote my test in, I use Minitest, but I would imagine like Minitest, Aspect is about the same. For me, I have like tests all written but I actually didn't do CI CD because it's like super tiny. I just from my console, I just push it up to Heroku and just deploy. For me, it's a really small app so I don't really see and I'm the only person working on it. So I didn't really see a point in setting up all the CI CD workflows. To me, it doesn't really matter. And of course, I still write my tests and making sure my app, I can continuously work on my app with confidence, with the tests in place but I didn't use the, I didn't have a CI CD pipeline. Okay. I think that we are, actually we are over time already. So maybe I'll stop the top here and then I can close up the Minitest. Okay. So let me stop the sharing.