Automatic Image Creation From a Figma Template
Can your database automatically enrich entries using third-party data and create custom images from a Figma template? Rowy can! Shams Mosowi will teach us how it works.
Links & Resources
- https://www.rowy.io/
- https://github.com/rowyio/rowy
- https://dictionaryapi.dev/
- https://unsplash.com/documentation#search-photos
- https://www.npmjs.com/package/convert-svg-to-png
- https://codepen.io/jlengstorf/pen/mdqZJyO
- https://codepen.io/jlengstorf/live/wvPLBjg
- https://www.learnwithjason.dev/find-your-next-open-source-contribution
- https://www.learnwithjason.dev/let-s-learn-firebase
Full Transcript
Click to toggle the visibility of the transcript
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
JASON: Hello, everyone, and welcome to other episode of Learn With Jason. Today on the show, we have Shams Mosowi. Shams, how are you doing?
SHAMS: Good. Hi.
JASON: Good. I'm super happy to have you on the show. I am really excited about what we're gonna be covering today. I think it's gonna be really interesting to see. I always love to see kind of automation and how we can move things between the different worlds that we live in as front end developers, but before we dive into what we're gonna be doing today, let's talk a little bit about you. So for folx who aren't familiar with your work, do you want to give us a bit of a background on yourself?
SHAMS: Sure. I'm shams. Co‑founder and CTO of rowy. It's not that big of a deal since we're only four people. [ Laughter ] Yeah, so it's, like, it's an open source start‑up that we're building a, like, a local platform for developers to get into, like, backend development easily without all the boring work of having to manage the DevOps and trying to wait for everything to deploy and all that.
JASON: Yeah. So I guess this is always maybe like a foundational question here, but when we start talking about backend, I think sometimes it can get a little muddy, especially for somebody like myself who spends most of their time on the front end. So you just said do backend without all the DevOps. Where do you start to draw the line? Like what's happening in rowy that ‑‑ I guess what's not happening in rowy? What are things that I'm gonna have to do in backend if I'm not using something like rowy that are ‑‑ when you said DevOps, what does that mean?
SHAMS: So, like, I'll give you a background on myself. So I've been mostly working in small teams, so I have to do, like, sometimes even sole developer. So, like, a common problem about, like, backend is, like, giving access to the operational team members. So, like, having that problem of, like, updating the app data and all of that. That's part of, like, the backend, right?
JASON: Yeah.
SHAMS: Cloud functions. Trying to write cloud functions to trigger as part of the backend that, like, you want to build ‑‑ the goal is to build your app so your users can benefit from it and engage with your users, but, like, at one point spent more time working on internal tooling so that I get everything working. So it's like that kind of ‑‑ that's the kind of backend that rowy helps you with so you can focus more on building your front end.
JASON: Gotcha.
SHAMS: And you want to spend less time as possible on, like, the grunt work of, like, oh, I want to update my data here. Or I want to send out an email to my user when this happens. Or, oh, I want to check, like, this value for my database and store it in my database when this happens, et cetera.
JASON: Gotcha.
SHAMS: Some of the things that you can't do on the front end is, like, oh, using APIs and stuff that have, like, secrets. So you need a backend for that. You don't want to, like, run a whole, like, Node server and all that just so that you can have a secure environment. Because you can't just run everything on the client side.
JASON: Yeah. Yeah, yeah. Okay. So that makes sense. So what you're talking about here, if I can repeat this back to make sure I understand it, is you're saying that, you know, a lot of what I'm dealing with on the backend is going to be managing the access of data. And that data, if I was gonna build it myself, I would need to set up a server. I would need to set up the deployment processes. I would need to have all of my migration tools and all the things that are required to keep that data up and running and secure and, you know, dependable, all those things that you need when you're running a mission‑critical application. And so with rowy, you're taking all of that, you called it boilerplate, I think.
SHAMS: Yeah.
JASON: All those things that kind of have to be done but aren't really unique to your app. It's just the stuff that lets you build you're app. You're taking all of that and putting it into the foundation of rowy so I as a developer then am only going in and defining the data that I want and, like, the logic to get that data. Not necessarily how to store it. How to keep it up. How to scale it. How to do any of those other, more, like, operational things.
SHAMS: Exactly. So it's, like, yeah, and also about the coding part we're gonna see is that we break down the coding to just the small element of each data point, rather than, like, having to host, like, hundreds of cloud functions. Like you start with a project and, like, in the serverless world, you start adding cloud functions that trigger and end up having a big code base of cloud functions. It becomes very hard to maintain and keep, like, keep everything running. So with rowy, we broke it down into, like, having small, like, pieces of code nuggets in your table so that you don't have to, like, you just ‑‑ there's always, like, you're only looking at a thing that is important to you at that time.
JASON: Yeah, code nuggets. I like that.
SHAMS: Thank you.
JASON: It's also getting close to dinner time for me, so now I'm snacky. [ Laughter ]
SHAMS: Sorry.
JASON: Okay. So you said something interesting in there. And I have a little bit of, you know, I know where we're trying to go here, so I'm gonna ask you a bit of a leading question, but when we're talking about rowy, rowy is not just I have, like, a piece of data, like somebody's name and I'm gonna put this into this, like, into a rowy table and it sits there and it's just a name, right? Now I can do that, but there's more to it than that. Because you're talking about these code nuggets, these kind of, like, in place serverless functions.
SHAMS: Yeah.
JASON: What does rowy enable on top of just straight‑up data storage?
SHAMS: So that's back, like, actually, like, rowy doesn't ‑‑ we don't host any of your data. So we ‑‑ because there's already, like, a lot of cloud providers like Amazon, Google Cloud, and others, we don't ‑‑ and we're just a small team of four. We don't want to, like, have to build infrastructure and maintain it. So what rowy is is a layer, like, an interface layer on top of your existing data. Currently, we support Firebase, Firestore and GCB platform because they have, like, very diverse different tools that we can use in our apps. So it makes it ‑‑ it brings that power of having, like, Google Cloud platform scale and Google features like AI and all those features very easily accessible to your app.
JASON: Got it.
SHAMS: In those, like, cloud functions that we manage for you. So we manage the ‑‑ your infrastructure. Like your Google Cloud infrastructure for you. And you can go in and, like, locate your own Google Cloud and we don't, like, we don't have ‑‑ we don't look into, like, we don't have access to your data or anything. It's just the interface. And everything is mainly between you and Google.
JASON: Oh, okay. Okay. So I bring a cloud database like Firebase and I put rowy on top of that, and it's gonna pull in my data.
SHAMS: Yeah.
JASON: And then it's not just one‑to‑one, though, right? It's not just here is my Firebase data displayed in rowy. It let's me do more than that. So what are some of the things we can do with rowy once we have data from Firebase or Firestore into a rowy instance?
SHAMS: So once we have the data, then we start, like, we can set up cloud functions inside of rowy. So it will manage that for you and deploy it. So you just ‑‑ instead of having to deal with, like, trying to say whenever this document is being updated or this document is being ‑‑ it's just like, oh, whenever this field changes, I want to calculate this new field. Rather ‑‑ so it's a lot ‑‑ that's what I mean by the nuggets part.
JASON: So when I ‑‑ when I write, like, so what you're saying is when I go into rowy, I can define something like, all right, I'm gonna give you somebody's Twitter handle, right? Now when I put this Twitter handle into Firebase, rowy's gonna see that that field changed and it can fire something off. So I could have one field that has a code nugget that says whenever the user name field changes, go and get their Twitter Avatar and put that here.
SHAMS: Exactly.
JASON: And I can have the other one that says, like, go get the ‑‑ do a search on Twitter and find the top 10 people in the last few days that they've interacted with to make friend recommendations or something like that.
SHAMS: Yeah, yeah.
JASON: Like all ‑‑
SHAMS: Yeah, and if you have, like, the right APIs, then you can also ‑‑ you can DM that person.
JASON: Oh, cool.
SHAMS: With, like, if ‑‑ either on a press of a button or, like, based on an event as well.
JASON: Yeah. So basically you're taking about, like, some pretty complex data enrichment, is that maybe the right ‑‑ the right word here?
SHAMS: Yeah.
JASON: So data enrichment or, like, derived data or even just straight‑up automation based on the data coming in. So for me, this is always kind of the dream. I want to track as little data as possible in my own databases. And what I, you know, I don't want a bunch of user data. I don't want to have to keep ‑‑ it always makes me nervous when I'm holding on to somebody's, like, email address or their home address or something. I don't want any of that, right? But it is kind of interesting to think about the idea that, like, as I'm building out my app, there are ways that I could let somebody put in some of their own information, and then I can enrich that data with stuff that's available via an API that they would authorize or via, you know, open information like you can go get somebody's GitHub Avatar just by knowing their GitHub user name or something like that. Now we can start building these much more rich experiences without having to ask for a lot of buy‑in from the users to, like, authorize GitHub, authorize Twitter, authorize your Google account. Let me have access to all of your accounts so that I can do this stuff. We can start to take advantage of the data that's already there and the things that we have access to already to build out more valuable experiences.
SHAMS: Yeah.
JASON: And it's not just user stuff, too, right? Like I could do this with really anything that I can get access to on the internet. I can ‑‑
SHAMS: Yeah ‑‑
JASON: ‑‑ start to modify.
SHAMS: Yeah, basically, like, mainly anything that you want to do on the ‑‑ like you don't want to do on your client side and have your app have that feature. Then you should, like, be doing it on your backend. But you don't want to set up a whole backend just for that. You want to just do it quickly and get back to the thing that you really want to do, which is build your product, which mostly is, like, the ‑‑ for the users is the main thing is the front end, that's the thing that they interact with.
JASON: Yeah. Okay. So ‑‑ and that's actually a really good point because, you know, one of the things that I talk about a lot is, like, finding tools that let you just focus on building the valuable thing.
SHAMS: Yeah.
JASON: And so this is very in line with my own heart, what I care about. And so as I'm building out a front end and I want to get a little bit of thing, you know, typically, what I'm looking at is, oh, I'm gonna go reach for a Netlify function. Because that's the world I know. And I know what you mean, though, as you start to build out really complex stuff where it's not just, like, a couple transformations. Now it's like, okay, I need to do a transformation. I need this transformation to depend on that transformation. And, like, now I'm doing, like, a lot of logic. I don't really want to do that in a series of Netlify ‑‑ serverless functions. And I also don't want to set up a Node server to have that logic. Because it always makes me sad when I have to set up a Node server. But I am able to use something like rowy to have, like, my table and my fields and each of those fields has the logic defined right ‑‑ it's right inside rowy, like, I'm looking at my logic in place?
SHAMS: Yeah, yeah.
JASON: That's really cool. Because that's also something interesting where as I'm thinking about my data, we're co‑locating data alongside logic.
SHAMS: Yeah.
JASON: Which I imagine somebody's gonna be like, but, wait, you need separation to concerns. But I kind of like it in this case because it's saying, you know, show me what I'm doing to the data, don't make me open up three different editors to figure out what's going on with mine ‑‑
SHAMS: Exactly. You still have separations of concerns but it's on the actual piece, rather than like you said, write your code from your data. You just separate your code and data into separate blocks so that when you're thinking about it, we'll get to see a lot of the benefits of that as well. When you're thinking about wanting ‑‑ you're not switching contexts and you're not having to, like, switch a lot of tabs and try to do something here and look over here. And then it's just ‑‑ it is a lot better.
JASON: Yeah. So I know that, you know, you mentioned that you're a small team. There's just four of you right now. As you are starting to build this out and see it grow, what are some of the use cases where you've really seen rowy shine?
SHAMS: So it's ‑‑ I think a lot of it is to do with how fast you can get things up and running in production. So it's just there's a lot of, like, oh, we need to ‑‑ like a team needed a product out by Christmas. And they were able to do it in a month. Rather than having to, like, they would have missed the deadline if they had to do in, like, their traditional development style of, like, having to do everything themselves. And just, like, writing everything in VS Code and all that. It makes things a lot faster.
JASON: Mm‑hmm.
SHAMS: And, yeah, you'll get to see it. Just everything is a lot more connected. It's, like, how the, like, the Mac M1 is so much faster than the Intel structures because you have everything on the same chip. It's, like, a similar concept.
JASON: Oh, yeah. That's a good analogy.
SHAMS: Yeah. So, yeah, that's why. Your development experience is gonna be a lot faster because everything is in the same place.
JASON: Gotcha. Okay. Well, I think this is probably a good point then to say let's go dive into this, right? So let's actually take a look at it. I'll switch us over to the other view here. Here we are. Okay. So first and foremost, before we get started with the code, let me just do a quick shout‑out. We are live with shams and that is being live captioned on learnwithjason.dev by Jordan at White Coat Captioning. Thank you very much for being here, Jordan. That's made possible through our sponsor, Netlify, Backlight, and Nx all kicking in to make this show more accessible and just making more things possible on Learn With Jason. We are looking at rowy.io. I know John dropped the link. I'll drop it again for posterity. We're talking to shams. Make sure you go and give Shams a follow on Twitter.
SHAMS: I don't tweet that much. Sorry. You can follow rowy instead if you want.
JASON: Follow rowy instead. Okay. So I ‑‑ that's about all I know about getting started. So I'm looking at the rowy site and you sent me access to a Firebase setup before.
SHAMS: Yeah.
JASON: So this is all I know. So what's the first thing that I want to do if I've got a ‑‑ actually, let's talk a little bit about what I'm looking at here. This is a special kind of Firebase plan? Anything special about it?
SHAMS: No, so this is the ‑‑ basically we use cloud run in the background. So this is, like, an upgraded placement. So this is just a blank canvas Firebase project. I just set it up so we'll have the billing enabled.
JASON: Oh, gotcha.
SHAMS: But in general, the free tier is very high. So it's very reasonable. And then if you sign up, you get $300 free credit.
JASON: Okay.
SHAMS: And you mostly need ‑‑ you don't need it if you're just doing it as a hobby.
JASON: So most of what we're doing today is gonna be available on the free tier. And we'll just call out the part that's on a paid plan, right?
SHAMS: Yeah, yeah.
JASON: Okay. Great. Cool. Well, then I'm ready to roll here. So if I ‑‑ do I go over to rowy?
SHAMS: So we can ‑‑ yeah, we can ‑‑ if you want, we can get started with the get started or we can look at the live demo if you want to see some examples.
JASON: Let's just dive right in and then we can poke at the live demo at the end to show people how it's working.
SHAMS: Yeah, sure. So first, we ask you to log in. Basically that helps us to hand‑held you ‑‑
JASON: I guess I should set up some stuff. If I leave this unchecked, is that gonna be okay?
SHAMS: No. Yeah, so basically that will look at the ‑‑ try to make sure that you have everything set up. So we need that. You can revoke it afterwards.
JASON: Got it.
SHAMS: Because we don't need it to keep going. We just need it to make sure that everything is good.
JASON: Got it.
SHAMS: Okay. Look at the different projects that you need and you have already on your Firebase or you can create a new one if you don't have one from the link.
JASON: Yes. And I just ‑‑ I added this LWJ rowy, so I'm gonna continue.
SHAMS: Yeah. So now just I've already created a project. Initialize rowy. And then it will ask you ‑‑ so here you have ‑‑ it uses Firestore and Firestore rules to protect your data. On the left side, you have your existing rules. And on the right side is what we're changing to it. So you can modify and make it ‑‑ resolve if you have any issues with the ones we're adding. And then you can just set the rules on the bottom‑left. So these are Firestore rules.
JASON: Got it.
SHAMS: And they basically allow you to have client access to your data without having to need a backend.
JASON: And so we won't dive into this today, but what we do have is we've got a good episode with David East where we talk about Firebase. So if you want to go dig into more of that, go and do that. What's up, Don? I just saw Don Brown just raided with some friends. So, welcome, everybody. We're learning about rowy today. So that's gonna be ‑‑ that's what we're doing now. We just got a Firebase instance. And we are giving rowy permission. So I'm gonna set these rules.
SHAMS: Yeah.
JASON: Okay.
SHAMS: And then ‑‑ so this is the Firestore rules. We do the same thing with Storage. So Storage is another service and that's for images and files that are not data. Same thing. And here, we're just setting, oh, if you have roles, then you can add it, and that's it.
JASON: Great.
SHAMS: And your project's set up. And now you have your own rowy, LWJ rowy app.
JASON: Oh, cool. Okay. I understand what's happening.
SHAMS: Yeah. So now that's created. We have, like, you can basically have access to all the CMS features like editing data and creating tables. So let's create a table.
JASON: Okay.
SHAMS: And then let's, like, call it posts. We have primary collection and group collection which is in the, like, Firestore SQL, you have, like, subcollections and collection groups allow you to group all the subcollections into one. So let's say you have, like, users and then inside users you have orders, but you want to have a table for all the orders, you would have a group ‑‑
JASON: Oh, okay.
SHAMS: Or table. Group collection for that.
JASON: Gotcha. Okay.
SHAMS: Yeah.
JASON: So ‑‑
SHAMS: Yeah, we'll set the display as well. I think you need to set the ‑‑
JASON: Oh, got it.
SHAMS: That's mainly so you can name ‑‑ yeah. You can name it. And then most everything else is ‑‑ you don't need the section, everything else is optional. We have access control. So here you can set who can access it. And then this would suggest what Firestore. It's flexible to have any role that you want depending on your, like, how sophisticated, how many people you have in the team and what the access of each one. And you have access to, like, change the rules for each individual toggle user. For now, the default is it allows the admin globally.
JASON: Got it.
SHAMS: So, yeah. You can just create it. And these are auditing. So it will track the changes that you make to your data. So that's like, oh, who made this change?
JASON: Okay.
SHAMS: And when that happened. Yeah.
JASON: And then do we want over these auto columns?
SHAMS: You can initialize created by.
JASON: Okay. Cool. Yeah, let's do it. So, create.
SHAMS: Yeah. So that's your table. And let's add ‑‑ we can add columns here. So do we want to talk about the ‑‑ what we're doing today in terms of the project?
JASON: Yeah. Okay. So an idea that you pitched that I thought was great is that using rowy, we can dig into a Figma template and combine that Figma template with data from rowy to automatically generate SEO images, which I thought was brilliant. Because, you know, I've done ‑‑ this is making images dynamically is something that I've tried a handful of different ways. I really, like, Cloudinary is a great tool for this. I've seen solutions where you use something like Puppeteer to load a page and screenshot it and save the screenshot. So this is a whole new approach that I haven't seen. I've never seen, like, the data layer being the generator for these images. So I'm really excited to see how this works. But so what I think that's gonna mean for us is in this post table, I'm gonna want a title field and a, like, an image field and then some kind of magic in rowy that's gonna make that image field automatically create itself.
SHAMS: Yeah. So I'll ‑‑ so we have basically ‑‑ I want to show, like, how to use, like, Fetch and interact with, like, other APIs. So what I want to do is we'll have a word column and then from the word we'll get the definition from a dictionary API. And then we'll get an image from Unsplash API. And then ‑‑
JASON: Oh.
SHAMS: ‑‑ we'll generate that in a separate column. So we'll just do a short text for now.
JASON: Okay. We got a short text. First one's gonna be title.
SHAMS: We can call it noun or word. So since it's gonna be the definition and the ‑‑
JASON: I understand. Okay.
SHAMS: Yep. And then ‑‑ so, basically now what we want to do is create an API call to get the definition right. So for that, we use, like, a derivative column. So if you add a column, and then if you search for ‑‑ in the cloud functions section. So we have, like, all these different cloud functions sections. So we have a derivative. So that basically is a derived value.
JASON: Okay.
SHAMS: You can call it, like, dictionary API. So break it down into steps first, and then we can ‑‑ we can combine it, but this is I think this will be clearer.
JASON: Yeah, I think this is.
SHAMS: If we have a dictionary API call and then we'll have another column for the definition. Because the response from the dictionary API will be, like, a lot more data than what we want to use.
JASON: Okay.
SHAMS: So we'll just have that. Yeah. And then now you get prompted to set up the thing that we talked about that requires the billing. So if you were just to manage your, like, your data and all that, it's all free, and then ‑‑ but if you need that cloud run because it's, like, part of the enterprise API. So you need billing enabled ‑‑
JASON: Gotcha.
SHAMS: But, yeah, this ‑‑ it's a lot of ‑‑ it's a huge free tier. So it's ‑‑ it shouldn't. So now we just ‑‑ we'll go through the ‑‑ you can select a regen. I think the io one is the greenest.
JASON: This one? Okay. I'm always a fan of that.
SHAMS: And then so basically we can leave that. That will set up, like, in the background that will do, like, the cloud setup environments. So you can minimize that.
JASON: Okay.
SHAMS: And then we can go to Figma.
JASON: Go to Figma. All right.
SHAMS: And then we'll just start a new design.
JASON: Okay.
SHAMS: And then let's do, like, we'll add a frame. We'll make a social media ‑‑
JASON: Okay. Do you know the dimensions off the top of your head or should I Google those?
SHAMS: I was thinking we'll use one of the template frames. The Instagram post was, like ‑‑
JASON: Oh, I didn't realize that was an option.
SHAMS: Yeah. So I think you just choose ‑‑
JASON: Oh, social media.
SHAMS: Social media.
JASON: Instagram post. Okay. So let me delete this one.
SHAMS: And then we'll just have, like, the text on top with, like, the noun. We'll make that big.
JASON: Okay. So let's use, roboto's fine and then we'll make it, like, 100.
SHAMS: And then we'll ‑‑ let's do, like, a definition. We can make that smaller. And then we'll need to ‑‑ we'll need some space for the image as well. So for the image, we'll just do a rectangle for now.
JASON: Okay. Let's go with regular. We'll say this is the definition. We're gonna put an image in. So let's ‑‑ whoops. Put this down here. And this down here. And rectangle up here.
SHAMS: Yep.
JASON: Cool.
SHAMS: And then, yeah, so that's ‑‑ that's all we're going to do in Figma. And then we can export the post to SVG. So what we're gonna do is we want to generate an SVG that we can modify in code.
JASON: Oh, should I ‑‑
SHAMS: That's fine. Yeah, so you just need to change it to SVG. And then there's, like, the menu next to the SVG. The three dots. I think you need to cancel the outlined text because by default it makes it into outline. We want to make it into text. So that's all. And then we can export that.
JASON: Okay. I didn't realize that those buttons existed. This might change my whole experience with Figma and exporting.
SHAMS: Yeah.
JASON: Okay. So now we have an SVG here. Can see it down here.
SHAMS: Can we open it in Code Sandbox?.
JASON: I'm gonna open it in Codepen because that's the one I know really well. Let me open it up here and then we can just ‑‑
SHAMS: I think you can paste.
JASON: Will it work if I just drop it in. Oh, that's beautiful. Okay. So here's our ‑‑ got it.
SHAMS: Okay. So one thing that we need to change is the image, right? So we need to change the image into instead of a rectangle, we want to make it into an image. So that's in the ‑‑ yeah. So we'll call that an image. And then we'll do a, like, I think you need ‑‑
JASON: Oh, wait, did I screw this up? I did. I did the wrong one. Here's the one that I want. So this is an image and you said href.
SHAMS: Yeah. Do you have an example URL that we can do this with?
JASON: Can definitely head over to Unsplash and get one. Let's get ‑‑ here we go. Copy image link. And we're probably ‑‑ that mostly works. We'll probably have to ‑‑ let's see. If I set this width to match. Then we can do that in code as well. I think it'll crop for us.
SHAMS: Nice. I didn't know that.
JASON: Apparently not, but okay.
SHAMS: Okay. Yeah, that's ‑‑ and then we'll ‑‑ one thing that we need to do is if we go to the definition section of the SVG, basically this would be ‑‑ I think you just ‑‑ if you make the ‑‑ it's a little bit down.
JASON: Here's the definition. Got it.
SHAMS: Yeah, so the text box. That one ‑‑ the problem with that is that it will only do ‑‑ it doesn't do multi‑line. So it wouldn't wrap. So we need to introduce, like, a foreign object. So, foreign objects in SVG allows you to use HTML.
JASON: Like that?
SHAMS: So we'll get rid of ‑‑ yeah, but we'll need to get rid of the whole text and replace the whole text block.
JASON: Okay.
SHAMS: Instead of ‑‑ so ‑‑
JASON: Do I want to keep these attributes?
SHAMS: Not really. We just need the position.
JASON: The position? Okay. So the position was X and Y. So I'll put that here. And then let's get rid of these.
SHAMS: Yeah.
JASON: I broke it. I broke it.
SHAMS: I think that's the ‑‑ can we put the definition in a diff? I'm not sure, though.
JASON: Okay. So I have done something. And I don't know what that something is. So I've got my foreign object, and my foreign object has no ‑‑
SHAMS: Does that need ‑‑ oh, it needs a width and height. Yeah.
JASON: Ah, okay. So let's give it a width of, hmm, the X is 74. So what's 1080 minus 74? Minus 74, right? And 32. So a width of 932. And then height. We'll give it a height of, like, 100 to start.
SHAMS: Yeah. Okay.
JASON: There we go. We got closer.
SHAMS: We need to style the diff. I think, yeah. Does that work? Yeah, that works.
JASON: It does work.
SHAMS: Perfect. Okay. All right. Yeah. So now that that's ready, we can check back in. If we have ‑‑ if we have the cloud ‑‑ yep. That's done. We can close that. It will redirect you. You can close that off. And then we'll go back to ‑‑ we'll go back to rowy.
JASON: Got it.
SHAMS: So here, you have the first thing is, like, you have a default value option. So sometimes when you are creating a new row, you don't want to start with, like, an empty field. You want to initialize it with either something by default. Either, like, is it being, like, false or true or, like, a special string? Or you can even do a dynamic value where, like, you're generating it from something else. But for now, we'll leave that as un‑defined because we're only concerned with, like, getting the ‑‑ setting up the listener to the noun. And then we'll select noun. So whenever noun changes, it will do that. And then we'll do a JSON type. So if you search for ‑‑ yeah, there it is.
JASON: Okay.
SHAMS: And then ‑‑ so here we have in the derivative script, we have the, like, the blocks of this one. I think it will clear out eventually. But, yeah, you can ‑‑ you can make that larger. And then we can ‑‑ so this is the code. So this is an example. Basically it's just, like, you can add two rows and it will return it, and then the return value will be stored in the field. So we'll use the free dictionary API. What is it called? It's called dictionaryapi.dev.
JASON: There we go. Okay.
SHAMS: So with that one, you just ‑‑ it's very simple. We just need the ‑‑ we just need to do a fetch and then replace the word with something else.
JASON: Got it. Okay. Is Fetch build in here? Can I just ‑‑
SHAMS: Yep.
JASON: Okay. So we'll get the response. Not have to spell that. I'm gonna call it res. And then we will do await, fetch, and we're gonna make this a template string so that we can get our word here.
SHAMS: Yeah.
JASON: And that's just a get, I think.
SHAMS: Yeah, you don't need to. Yeah. And then, yeah, so you'll get the result out the JSON.
JASON: If I can spell it. Here we go. This is really tiny. Let me make it bigger. So there's our JSON. That's gonna be await. There's JSON. And then we have it. So I can ‑‑
SHAMS: So we return that.
JASON: Return that. Okay.
SHAMS: So for the word, we have ‑‑ we have in the function at the top on the first line, we have all these different things. So we have row which gives you access to all the fields. And we have ref which gives you the reference to the row for, like, other, like, trying to get the parent and all that.
JASON: Okay.
SHAMS: And then you have, like, other database and storage which gives you global access to ‑‑
JASON: And we got auto complete. So I can just hit dot and off I go. So, now if I'm understanding correctly, once I save this, we're gonna get ‑‑
SHAMS: So, yeah. So if you update now, and it will save changes, you can deploy.
JASON: Okay.
SHAMS: Yeah. And then this will build ‑‑ this will build a cloud function in the background. But we don't need to wait for that. I added a special feature just for this show that will have, like, a new feature. It will just ‑‑ you can evaluate straight away.
JASON: Oh, nice.
SHAMS: That don't use external dependencies, we can evaluate straight away. So you can add a new row.
JASON: Okay.
SHAMS: And then see, like, it already said it made it. And then, yeah, exactly. I knew that you'd write that. [ Laughter ] So, yeah. Now that you can right click on the dictionary and you can evaluate. And then you got a response. So if you open it in the side panel, you get all that response from the API. So you have, like, the meanings, and then if you scroll down, you have, like, the definitions. So that's ‑‑
JASON: Great.
SHAMS: Yeah. So that's done. Another thing we could do is, like, let's add another derivative column.
JASON: Okay. Let me close this up.
SHAMS: Yeah.
JASON: And we're gonna call ‑‑
SHAMS: Now we'll do definition.
JASON: Okay. So we're gonna get a definition. And that's gonna be a derivative.
SHAMS: Yep.
JASON: That search to get the field name is nice.
SHAMS: Yeah.
JASON: All right. So this one is going to be Dictionary API.
SHAMS: Exactly.
JASON: And the output field type is gonna be text.
SHAMS: Long text. And then you can see here it's, like, oh, there's something wrong here. It's because it's expecting a string back and you haven't returned that string.
JASON: Got it.
SHAMS: So you get the benefits of TypeScript with JavaScript. You can still write JavaScript but you get all these ‑‑
JASON: Mm‑hmm. We can get the value out by doing row, Dictionary API, because that came back as an array. And then inside of one of these, I can get the definition. I guess I've ‑‑
SHAMS: Yeah, yeah. That's fine. So if you type value in, does it complete for you?
JASON: Uh, let's see. How did that work? Let me ‑‑ so we got ‑‑
SHAMS: So if you did ‑‑
JASON: ‑‑ our first thing. Then we get meaning.
SHAMS: Yeah.
JASON: Should I try a different way to get the ‑‑
SHAMS: If you just try row limit. Let's try directly from the row and then type definition. And then 0. And then ‑‑ okay. Yeah, you can just do that. It didn't complete for some reason. And then we'll get the first element. And then we'll get definitions. I think it's definitions.
JASON: Okay.
SHAMS: So after meanings, it's definitions. And then, like, the first definition we want ‑‑
JASON: Oh, okay. So, meaning, 0. Definitions, 0. Definition.
SHAMS: Yeah. And then we'll return that. Yeah.
JASON: Save. Let's close that.
SHAMS: And then we can update.
JASON: Update.
SHAMS: You can later on ‑‑
JASON: I guess I probably should have waited. Oh, look, I just evaluated and it did the thing. And so now we have ‑‑ oh, wait, I'm over in the wrong thing. I want to go into ‑‑
SHAMS: Yeah, so if you just ‑‑ if you just ‑‑ let's say ‑‑ you want to open the definition, you just open it and scroll down. Like up in the side panel. And underneath, you get ‑‑
JASON: Ah, got it.
SHAMS: All your columns are here in, like, an easier to read format.
JASON: Nice.
SHAMS: And manage. So, yeah, you have some data that you can do in the table. Sometimes like long text, it's hard to ‑‑ like in a table. So you have this kind of UI so you can manage it.
JASON: Yeah.
SHAMS: Yeah. And then let's close that. We can have that later. If you just close the build log.
JASON: Okay. So we got a noun. We got a definition.
SHAMS: You can try adding a new row.
JASON: Okay.
SHAMS: Oh, sorry. Yeah, we'll add another column now. And then we'll do the Unsplash API.
JASON: Okay. So Unsplash API. And this is also gonna be derivative.
SHAMS: Yeah.
JASON: Okay.
SHAMS: And then we'll listen to the noun again.
JASON: Okay. And this one's gonna be ‑‑
SHAMS: We can do a JSON. If we wanted to, we can either do the JSON or the image straight away.
JASON: Let's go straight to the image.
SHAMS: Okay. And then same thing with the ‑‑ with the image. With the Unsplash API. But first, Unsplash API has a secret ‑‑ if you go back to the ‑‑
JASON: Let me drop a quick link. I realize I also didn't link to this Dictionary API, so let me drop that in here for folx. Back here I go.
SHAMS: If you minimize the code part, block, you see you have the ‑‑ so that links you to the manager on JCP so that we're not, like, storing your secrets and managing it. So it's all managed within your own GCP platform.
JASON: Nice.
SHAMS: So I've already added some keys. So we don't have to have them. But basically, it's very easy to add. You just create key button, and then add the value and then the key that you want.
JASON: Yeah, so, like, if I click this, it would give me. Boom, boom, boom.
SHAMS: The name and the value. That's it. That creates it for you.
JASON: Okay. So we've got Unsplash here. So to access that, I then need to ‑‑ is it in auth or somewhere else?
SHAMS: Let's get it out. So we'll do const_unsplashSecret. It's in rowy. Rowy is, like, a utility package to help you do those ‑‑ that interface. So we'll do secrets and then get. And then you can type the secret name. So, like, it will error out unless you have the right key. So that kind of thing, you, like ‑‑
JASON: Oh, nice.
SHAMS: If you're doing in VS Code where you just ‑‑ it doesn't know what your cloud infrastructure is like. And so here you just make ‑‑ you don't have to double check, like, oh, am I using the right key, et cetera? And that's an asynchronous. So we'll have to await. And then, yeah. And then we'll do the ‑‑ we need to do the API call now.
JASON: All right. So we probably want to grab ‑‑ are we trying to get an image that has a tag or what do you have in mind?
SHAMS: We'll just do a query.
JASON: Okay.
SHAMS: So, yeah.
JASON: Like search photos or?
SHAMS: I think so.
JASON: Okay.
SHAMS: Yeah. So, search photos, and then I think it has a client ID parameter. Yeah.
JASON: Okay. So there's ‑‑ there's our basic setup. So we'll get a response. And that's gonna be await fetch. And we want ‑‑ it was row.noun.
SHAMS: Noun, yeah. And then we'll need to pass in a client ID, I think. Or is that ‑‑ yeah. I don't know. Is that not required?
JASON: Let's check. There's probably an auth thing up here. Authorization. Authorization header.
SHAMS: So you can do ‑‑ yeah, you can put auth in. So just post it in.
JASON: Okay. So we'll take this over to here. And we've already got a query going. So we'll do an and, client ID, and then we're gonna pass in unsplashSecret. And then down here, JSON and that's gonna be await res.json. We're not gonna return this. We're gonna go straight to the photo.
SHAMS: Yeah, we're gonna go straight to the photo. We'll get the URL for the first image. So should be JSON. And the first item in the array. And then it should be URLs. And then it's ‑‑ we can use, like, I think it has a small.
JASON: Okay.
SHAMS: And then so that's the ‑‑ that's the URL.
JASON: And if we go back to look at the photos, we can see we get results. Oh, wait, I'm gonna get a ‑‑ I need to get a results object back first.
SHAMS: Okay, yeah. Yeah.
JASON: So we'll have to go into results, 0. And then URLs and then there is a small. Okay. So let's go.
SHAMS: You can do regular or small. Yeah, that's fine.
JASON: Json.results[0], URL small.
SHAMS: Then we need to upload that file to storage. So we could use the URL directly, but we want to upload it to storage to make sure, like, our data stays consistent and we're not doing too many calls. So we want to use the Storage API. We have rowy utility for it.
JASON: Oh, nice.
SHAMS: So, rowy.storage. And then upload. And then we have ‑‑ no, so we have a data option and a URL option. So this one it's a lot easier than using the storage directly. So you have, like, access to storage and you can do a lot more, but, like, these things are very common, and we just want to be, like, not having to repeat ourself all the time. So we want to return ‑‑ let's just declare it so that we can see what it's returning.
JASON: Okay.
SHAMS: Just call the image. And then if we have ‑‑ should return. So that's a rowy. And then we can just return. So the image column expects an array of images. So we'll just pass in an array. Yeah. And that's it.
JASON: Okay.
SHAMS: So now we have ‑‑ now we can see that it's going to work. And then we can update. And then we'll do later. Deploy. And then we can right click and evaluate. Whoops.
JASON: I think I broke it. Okay. So ‑‑
SHAMS: We can console log the URL to see if ‑‑ actually ‑‑ oh, I know what's wrong. We need to profile name. Let's go to the settings.
JASON: Settings.
SHAMS: So the ‑‑
JASON: Here?
SHAMS: No, sorry, let's go back to the column settings.
JASON: Column settings.
SHAMS: Yeah. Scroll down. Second to last one.
JASON: Column settings.
SHAMS: And then the issue is that if you don't pass in this, like, option parameters in the URL, so after URL, we pass in an option and then we'll call a fileName. So it will give you the different options that you have and we'll do row.noun and then ‑‑ it's usually a JPEG so we'll do a JPEG. That should work. And then if we save that, update, and then we we can right click.
JASON: Hey, there it is.
SHAMS: And then you can, like ‑‑
JASON: Come over here?
SHAMS: Yeah, you don't have to open that. So if you go to ‑‑ if you minimize that. And we have, like, on top of that, there's, like, the table icon. If you go up a little bit. And there's, like, so you can manage the row height. Like based on your table.
JASON: Oh, nice.
SHAMS: And then we have, like, other things, like, exporting and importing here.
JASON: Mm‑hmm.
SHAMS: Yeah. So these are all so that you can ‑‑ depending on your data needs, you can set it up like that.
JASON: And for what we're doing here, this is pretty handy, right?
SHAMS: Yeah, yeah, exactly.
JASON: Okay.
SHAMS: So now we'll get to ‑‑ we'll get to the fun part.
JASON: Well, and, I mean, like, let's also take a second to call out that the only data I have entered here is Corgi. Everything else is derived based on that. So we put one piece of data into this database, and everything else auto populates based on what we put in here. So if I'm understanding correctly, I can come back in here and I can say, let's get a burger, right? And then I can evaluate.
SHAMS: Yeah.
JASON: Evaluate. Evaluate.
SHAMS: Yeah. And then basically ‑‑ this, yeah. This is, like ‑‑ it will be automatic once we build the function.
JASON: Uh‑huh.
SHAMS: So once deployed. Let's do one thing, actually. I noticed we have to ‑‑ we want to make the noun column required so it doesn't create a row without it. So go to column settings. And we'll make this column required. So you have, like, other things here, but we just want to make it required so you don't add empty rows to your database.
JASON: Got it.
SHAMS: Yeah. And we just update. And now, like, if you want to try to add a new column, it won't add it until you have something typed in. And then if you, like, refresh that page, it will not store it, I think. Yeah.
JASON: Got it. Yeah, so it will kind of force me to create some content in here.
SHAMS: Because you're dealing with, like, production data and you don't want empty things. Yeah.
JASON: So good.
SHAMS: Yeah. Yeah. And then, yeah. So now we want to get to the ‑‑ basically, these are all happening. Eventually, we'll have them happening, like, based on the noun event. Once we build the final function. But for now, let's add the ‑‑ let's add the ‑‑
JASON: The card, right?
SHAMS: The next function ‑‑ the card generator. So we'll do another derivative here and call it, like, the card or ‑‑ yeah. And then we'll do another derivative field.
JASON: Okay.
SHAMS: And so the way this is gonna work is it uses Puppeteer.
JASON: Okay.
SHAMS: Inside this function. So we'll do ‑‑ yeah, so we'll use the noun. We need the noun and we need the definition, and then we need the Unsplash URL, right?
JASON: Okay. And what's really cool about this is ‑‑ so the way that this is defined is if I ‑‑ if any of these fields doesn't exist, it's not gonna try to run this, right?
SHAMS: Yeah. It will ‑‑ actually, I'm gonna add that soon. But it will ‑‑ the way this works now, it will evaluate whenever one of these changes. I will ‑‑ I do want to add that option to make listener fields required.
JASON: Gotcha.
SHAMS: But for now, it will evaluate every time. So we'll do that output type as image.
JASON: Gotcha. Output type is image.
SHAMS: Yeah, so it's a file. And then what do we want to do now? Let's have a look at the ‑‑ before we go there ‑‑
JASON: Okay.
SHAMS: Let's have a look at the cloud function. The cloud ‑‑ yeah, that cloud button. And so basically, I just want to show here is that we have the ‑‑ so we have this, the posts, and these are all your cloud functions that are on your project, and all the rowy ones are gonna be with name starts with R. So if we click on them, if you can click on that one. So that's the one rowy generated for you. And then you have all these, like, those powerful features of Google Cloud without having to deal with them yourself. You can look at the source code and all of that here. So that, like, we ‑‑ like if you scroll down ‑‑ if you scroll down a little bit, there should be a ‑‑ where is it? It's in source. There should be a ‑‑ so the function config ts. So this is the ‑‑ we complied that into here. You can scroll down and see all the different ‑‑
JASON: Oh, okay.
SHAMS: Yeah. So this is the latest build. We haven't added. So after this, we'll see all the code as well here. So just all of what, like, I just want ‑‑ all rowy does is it compiles that for you into one cloud function for that event. So, like, for that, like, table. And that way you don't have to try to do, like, all the checking of the different listener fields and all those things. Like, yeah, making ‑‑ making sure that only evaluate if this is required. And all that.
JASON: Mm‑hmm.
SHAMS: We want to manage that for you. And you just do your API fetching and we'll worry about the rest.
JASON: That's. This is great. And what I, you know, I also like that what's output is not necessarily, like, this is human readable, you know? We can use this code if we were to for whatever reason want to stop using rowy. It doesn't mean that we can't continue to function on this Firebase instance.
SHAMS: Yeah.
JASON: So you're adding a really nice abstraction and not, like, a forever commitment to you must use rowy forever and ever.
SHAMS: Exactly. Exactly.
JASON: Which is ‑‑ that's nice.
SHAMS: Yeah, so we wanted to make sure that people feel comfortable into getting it. It's just it is on your own GCP. You're not, like, putting it on like some start‑up's cloud. If they have to sunset because they haven't figured out what they need to do, you're like, what am I gonna do? Now I need to migrate. You don't need to migrate. It's all open source. If you need any of this, it's on GitHub so you can host your own ‑‑ so if you go to GitHub. Yeah. You can host it yourself.
JASON: Oh, this is the whole thing? That's also very cool.
SHAMS: Yeah.
JASON: Okay. All right. So now we've got ‑‑ so we've got our noun that we entered. We've got our definition that was derived using the Dictionary API. And we've got the image that was derived using the noun and the Unsplash API, which we can now access if I pop this open, we'll be able to go to, like, noun is gonna be row.noun. The definition will be row.definition. And then the image is gonna be a little bit different because that sounded like it was a rowy file. So if I get my image, it's gonna be row.unsplash.
SHAMS: And then the first one. So this is an array. So it's an array. So do the first ‑‑
JASON: Oh, sorry, the first item. Got it.
SHAMS: Yeah. And then the downloadURL.
JASON: Got it.
SHAMS: So now we want to get the SVG template. So we can declare a template and put the SVG string.
JASON: Okay. So let's go back to our Codepen and we're gonna get this value here. And put this in. I just want to go one more here. No, I don't.
SHAMS: You can right click. Oh, yeah, that's fine.
JASON: Will it format? Oh, it will format for me? Beauty.
SHAMS: Yeah, I think because it's a string, it won't format. Yeah. It won't format SVG.
JASON: That's okay because this is close enough. Here we go. So we've got this here. And so now that I've got my noun, my definition, and my image, I can just drop these in, right?
SHAMS: Um, yeah.
JASON: Okay. Let's do it. I'm gonna go in here. I got my noun. So, noun. Over here, I've got my definition. So, definition. And then here, I've got my download image. I'm gonna set my image. And now this should be a fully generated image and we just have to put it somewhere, right?
SHAMS: So this is an SVG, right?
JASON: Yeah.
SHAMS: And what we want to do is convert it to a PNG.
JASON: Got it.
SHAMS: And because it's using a foreign object, we need to use Puppeteer because I think it's, like, one of the few options that can handle. Because you need to open the SVG in a browser to support foreign objects.
JASON: Okay.
SHAMS: So let's ‑‑ we need to use, like, a ‑‑ there's an NPM package that converts SVG to PNG that uses Puppeteers. If you search for it, convert SVG to PNG. Yeah. The first one.
JASON: This one?
SHAMS: Yeah. I think that one, yeah. So that one, we'll look at how they use it. Do they have a ‑‑ do they have the API example? Yeah, that's the one. We'll just copy that one.
JASON: Okay. So we'll start with our ‑‑
SHAMS: Yeah. Oh, no, put it inside the function.
JASON: Inside the function?
SHAMS: That way it's more optimal.
JASON: Gotcha.
SHAMS: So that you only load it when you need it. And then ‑‑
JASON: Okay.
SHAMS: We just need to do image. Yeah, that's it.
JASON: All right. So I'm gonna get my image. And we're gonna put in the svgTemplate. Is that it?
SHAMS: Yeah, that should be it. That should be it. And then after that, we want to upload ‑‑ now that's, like ‑‑ so we'll do rowy.storage and then upload. And it's a data, so it's not ‑‑ because that's not a URL. So you have to ‑‑
JASON: Oh, right, I'm doing the thing. Okay. And then is it the same thing where I have to give it a file name?
SHAMS: Yeah, you can give it a file name. Same thing.
JASON: Okay. So let's go with noun, card.png.
SHAMS: Yeah.
JASON: Okay.
SHAMS: Yeah, I think ‑‑ and then we'll, yeah, return that as a file and then we'll upload that. Yeah. And that's an array as well.
JASON: And that's ‑‑ we're good?
SHAMS: Yep.
JASON: All right.
SHAMS: And then, yeah, we can update that. And then we'll need to build this time ‑‑ because, yeah ‑‑ so we'll need to deploy.
JASON: Okay.
SHAMS: Because this uses, like, the NPM package. So we can't just ‑‑
JASON: And it's smart enough to just pull that NPM package for us?
SHAMS: Exactly. So you don't have to worry about that.
JASON: That's slick. Okay. But it doesn't like something that I've done. Which is what?
SHAMS: If you scroll ‑‑ can we expand that panel? We can expand the panel.
JASON: Let's see.
SHAMS: There's something wrong. I think there might be ‑‑
JASON: Invalid complied function.
SHAMS: Yeah, there might be an issue ‑‑
JASON: Is it gonna highlight or anything?
SHAMS: Um, you can copy it into VS Code. And then we can see what's wrong.
JASON: Okay.
SHAMS: Not all of ‑‑ actually, scroll down.
JASON: Start here, right?
SHAMS: Yeah, yeah. Yeah, up to there.
JASON: Command failed. Okay. So let's go into ‑‑
SHAMS: I think there is something wrong with the definition.
JASON: ‑‑ VS Code. Create a new thing. We'll call this TypeScript. Drop this in here. And then let's make it bigger.
SHAMS: Hopefully that can help us find it.
JASON: To look for the error.
SHAMS: So it is way ‑‑ did we declare it? Okay, maybe there's ‑‑ okay, that shouldn't be there. That, like, line 29. So ‑‑
JASON: Converse SVG to PNG. Did I do ‑‑ maybe I screwed something up. Let's close this up. Go back here.
SHAMS: Was that the arrow one?
JASON: It was in here.
SHAMS: Is that because of the first line?
JASON: Const async.
SHAMS: Starting on line 2 rather than line 1.
JASON: Oh, maybe.
SHAMS: If that was where the ‑‑ yeah. If that generates successfully then... yeah, if you scroll down ‑‑
JASON: Not yelling this time.
SHAMS: Yeah. Yep. That's it. So now it's gonna deploy the cloud function. And then it should be good. Do we have more time? How are we doing on time?
JASON: We have about 15 minutes left.
SHAMS: Okay. I have a suggestion. Do we want to make it so that the chat can enter words in and then it will generate ‑‑
JASON: Chat, can you be trusted? Are you gonna behave if we let you put in plain text? That feels like we might have regrets, but we can try.
SHAMS: We can do it. Yeah, so I just wanted to show, like, other features that we have on rowy. So we can close that. We'll let it build in the background.
JASON: Okay.
SHAMS: Yeah. So there's the webhooks icon. So let's just go through. So you see here we have, like, the webhooks, which is, like, it receives other services' webhooks. So if we add a new webhook ‑‑
JASON: Okay.
SHAMS: And then we'll just do basic.
JASON: Okay.
SHAMS: And then here we have, like, the endpoint that we'll be calling and then we can ‑‑ we can go skip the ‑‑ we can skip the verification step. And then we have the condition if we want to, like, there's a request coming in, we can condition ‑‑ we can skip that. Sometimes we want to parse and sometimes we don't. We can add, like, additional validation. And all this does is it takes in a request and then it will add it to your data. To your database. So from any, like, it provides an API for you to put data in. So it could be coming from any third‑party webhook.
JASON: Okay.
SHAMS: But for now, I just want to build, like, a web form that you can put in a word in and then we can do an API. If you want to put that in locally or if you want to do a code sandbox. You can do it in Codepen.
JASON: Yeah, let's do it in Codepen because I don't think I have quite enough time to configure something.
SHAMS: Yeah, exactly. I'll deal with that later. Does Codepen have React? I don't know how to ‑‑
JASON: It can have React, but we shouldn't really need it in this particular case. We should be able to just do a form.
SHAMS: Yeah.
JASON: The action is gonna be our webhook, is that right?
SHAMS: Yeah.
JASON: Okay. So we've got a webhook, and then the meth today is gonna be post. And then that is gonna have a label. And the label is gonna have a name. No. Label is gonna have a for of noun. And we'll drop this in. And then we're gonna have an input with an ID of noun. And a name of noun. Type of text. Okay. And then we're gonna put a button, type submit, and we'll say add noun. Don't make me regret this, chat. Okay. So then that gives us the ability to add a noun. And what should happen is if we put in ‑‑
SHAMS: I think we need to ‑‑ we need to save that configuration.
JASON: Oh, I need to save it before? Got it.
SHAMS: Is that gonna go into the body? The noun is gonna be in the body?
JASON: Right. So this is gonna ‑‑
SHAMS: So spread the body into the ‑‑ into a document. So this will create a new document. And then so ‑‑
JASON: I was just gonna do it as body post data, which means that what'll happen is it's gonna post as noun = thing, so I need parse.
SHAMS: We don't ‑‑ yeah. This part here can't ‑‑ we don't have the ‑‑ because it's not a build function, we don't have external dependencies yet.
JASON: Okay. Then let's see.
SHAMS: Do you know how to ‑‑
JASON: I mean, we can just break it up, right? Like we can do noun. We'll do noun = body.split on = and that's gonna be a very, very poorly handled validation for this form, but that's okay because we're going for speed.
SHAMS: We need to enable it. Can we enable that. So once chat is being naughty, we can disable it.
JASON: Yes, which I suspect will be immediately. [ Laughter ] But so that's now added. And is it webhooks successfully published. Okay. Let's give it a test. We're gonna try mouse. And what happens in the console? I'm not sure. Let's go look back here.
SHAMS: Do we have the logs? So you have ‑‑ can you look at the, like, the rowy logs? So if you go there, and then you have webhooks. So this is the build logs. And then this should be ‑‑ oh, select ‑‑
JASON: Body.split is not a function or its return value is ‑‑ oh, it did submit as JSON. You must be parsing it for me then. Which is great.
SHAMS: Yeah, yeah.
JASON: That makes my life easier. Let's go back into the webhooks and fix this. And down here. Okay. Then I just need to get noun out of body.
SHAMS: So the default, it defaults to JSON.
JASON: Got it. Okay.
SHAMS: And then now you can try again.
JASON: Try again. Add. It's okay. And... there it is. A picture of a mouse. All right. Okay, chat, I am going to give you access to this and I swear to God, don't make me regret it.
SHAMS: But see ‑‑ let's see if the ‑‑ did the image generate?
JASON: Is it did. Yeah, it's a dark.
SHAMS: No, that's the ‑‑
JASON: Oh, the card didn't generate.
SHAMS: The card didn't generate, yeah.
JASON: It looks like none of them did.
SHAMS: If you try to ‑‑ no, so they won't ‑‑ it will only happen whenever, like, any of those are changed.
JASON: Okay.
SHAMS: Yeah. Let's see. Can we try again, if you change the mouse word to something else?
JASON: Uh, let's ‑‑ there's our chair. But it doesn't like this.
SHAMS: Can we have a look at the code again? Did we forget to await something?
JASON: Let's see. We await, await. If I go look at these ‑‑
SHAMS: Okay. So it has to be from buffer. So the SVG, the convert needs to be inside a buffer.from. So inside the convert. So it doesn't take a string. It takes a buffer.
JASON: Oh, I gotcha.
SHAMS: And then it will do from and then ‑‑ yeah.
JASON: If I can pass the encoding or anything?
SHAMS: No, that's ‑‑
JASON: Okay. All right. So let's update that. Get it deployed.
SHAMS: Yeah.
JASON: And ‑‑
SHAMS: And then, yeah, so we can make that live afterwards. We can ‑‑
JASON: Okay. So this is here. I'm gonna send this to the chat. Let's see how long it is before I have to turn the whole chat off.
SHAMS: Yeah. So this will ‑‑ okay.
JASON: Here we go. Here we go. So we just got to wait for ‑‑ good. I'm, like, poised over the close tab for when somebody ‑‑ [ Laughter ] Sweden is a proper noun, so we don't get a definition for that. That's okay. Sorry, pal. So it can, like, handle it better and stuff.
SHAMS: So is that built yet?
JASON: Let's see. Here's my logs. Here's the build. Still building. It is ‑‑
SHAMS: It's deploying. Yeah, that should be ‑‑ that should take, like, another minute. Yeah. Do we have more time to do more things or ‑‑
JASON: I think this might be the last thing that we can do. While we're waiting for this to deploy, do you want to ‑‑ for folx who want to go and learn more, are there resources that they should be looking for?
SHAMS: Yeah. So we have ‑‑ so we're ‑‑ we have the docs. We have the GitHub. I saw that you did a show on contributing to open source. So we have a good few first issues that you can look at if you want to contribute. You can join the Discord if you want to try out rowy and need any help. I'm on the Discord. Yeah.
JASON: This episode here if you want to learn how to do open source with bdougie on the show. So if you all want to jump in here, get into the Discord. Let's go back and look. Almost. Are there any ‑‑ oh, here we go. We're done. All right. Okay. Let's try this again.
SHAMS: Yeah. So try again.
JASON: I'm gonna save ‑‑ regret. [ Laughter ] Correct. That is what I'm feeling right now. All right. Let's change this. And does the thing. What about this one? Do I get it? Did we get it?
SHAMS: Hopefully. Did that do anything? Where is it?
JASON: It looks like it's not firing. Is there a log I can see in here somewhere that would show ‑‑
SHAMS: Yes, there is. Oh, yeah, there ‑‑ so, here. So you have the ‑‑ cannot find. So it didn't install it for some reason. Can I see how you did that?
JASON: Yeah. Let's go back over to this one. Column settings. And I did a require. Should it be an import?
SHAMS: No, no, no. Require should be the one. Can we just double quote? I don't know. Instead of the single quote. That shouldn't be the case, but it looks like ‑‑ yeah. So we have to deploy again. Yeah.
JASON: This might be our last try. If this one doesn't work, we'll tweet about it once we get it running.
SHAMS: Yeah, that should be it. So, like, we have the logs there for you. So if there's any issues. It's a lot easier to figure out what the problem is. So if you, like, look at the logs again, we can ‑‑ you can see, like, all the different errors so you don't have to dig around and see, like, oh, what's the problem?
JASON: Mm‑hmm.
SHAMS: Yeah.
JASON: Yeah. I mean, this is ‑‑ and this is also ‑‑ it's just great to see this happen because what we're getting here is, you know, everybody's just submitting this one word, and we're getting, like, okay, a beach. We get a definition and we get this thing. So you can see how quickly, like, chat, I hope your gears are turning here on ways that you can automate things. Actually, you know what we should look at while you're doing this? Don't you have a live demo of ‑‑
SHAMS: Yeah, we do.
JASON: Is it the video enrichment? Let me go grab this while we're waiting for it to deploy.
SHAMS: So we have, like, translations is a cool demo. If you open translations. Yeah. I haven't seen this in a while. But basically if you type in a word, it will ‑‑ it will translate it for you into French. And then it should generate the audio as well.
JASON: Oh, nice. Let's do ‑‑ nice. And I don't think I'm ‑‑ let me pipe my sound through. Where did my sound go? I don't have sound compiled right. Here we go. [ Speaking French ]
SHAMS: Yeah. So basically if we go back ‑‑ [ echo ]
JASON: Ooh, that just went horribly wrong, didn't it, when I routed it through.
SHAMS: Yeah, it works.
JASON: Sorry, friends. [ Laughter ] But yeah, so that's really cool. And then back here is ‑‑ is this the one that'll ‑‑
SHAMS: So this fetches, like, IMDB data as well.
JASON: This one is freaking cool. So let's put in Forrest Gump, and then it's gonna automatically automate.
SHAMS: And from that, it goes in and scrapes IMDB. What page and we can look at, like, the function for it as well. So you have, like, the metadata. Yeah, so there it is.
JASON: Nice. So while that's going, I'm going to try this ‑‑
SHAMS: Make it capital. I think the capital looks nicer.
JASON: Capital Corgi. New Corgi. Do the thing.
SHAMS: Yeah, let's look at the logs. So the first ‑‑ it groups them by sections. So the thing on top is always the latest.
JASON: Oh, gotcha.
SHAMS: And then you can just ‑‑ you can change the day ‑‑ the time duration. So in the top‑right corner. You can just change it to, like, minutes. And that should fetch. Did that finish successfully?
JASON: Still getting a module not found on it, it looks like.
SHAMS: Okay. I'll have a look at that and we can update it and then we can share after the show.
JASON: Cool.
SHAMS: I'm not sure. Yeah.
JASON: But then looking back here, you know, we gave it a second, and now we've got the movie is populated. Description of it. We've got some different metadata. A link. There's a rating, which is pretty cool. Which this looks like something that I can save my own, right?
SHAMS: Yeah, yeah. So this is just interactive field.
JASON: Yeah.
SHAMS: And then you have ‑‑
JASON: We'll have to go read reviews.
SHAMS: So sub tables where you have nested data like reviews. You can add reviews in here.
JASON: Got it.
SHAMS: I think this one has sentiment analysis as well. So if you add a row.
JASON: Oh, sentiment analysis. That's amazing. Okay.
SHAMS: So if you write a comment. Yeah. And then if you look at the code for it, yeah so you have a 90% sentiment. So, yeah, if you look at the code for it, it's very simple. If you go to the settings and then the column settings. And then it's basically just using the Google Cloud Language NPM package. That's all you need to do to get, like, the score of that.
JASON: Yeah.
SHAMS: So you don't have to do any machine learning or anything. And because, like, we're already on GCP here, we don't need to, like, authenticate or initialize, like, client side because it's all on your cloud.
JASON: Gotcha.
SHAMS: It already knows, like, okay, so this is being called on this project and then I'm gonna build, like, this is, like, a ‑‑ there is a free tier on this one. Once you exceed it, you have to pay for it. It's like, oh, who's gonna pay for it? You don't have to manage secrets and everything because it's all in the same project.
JASON: That's very cool. So, chat, I hope your gears are turning. I hope you're thinking of some cool things that you can build here. I know that I've got a handful of ideas. That is all the time we have today. So let's do another shout‑out to Jordan from White Coat Captioning who has been here doing the live captioning all day. That's made possible from our sponsors, Netlify, Nx, and Backlight, all of whom are kicking in to make the show more accessible, and just giving me more gas to play with, right? So make sure you go check out the schedule while you're looking at things on the site. You can head over here. We've got a lot of fun stuff coming up. On Thursday, Cassie Evans is gonna come teach us how to make interactive animations. We're gonna get into some Greensock stuff. Super fun. Mark the schedule on Google Calendar. Make sure while you're going to look for things to do, make sure you get into rowy here. I don't know why that's showing. That's great. Make sure you go and follow them. And I think that is all we've got time for today. So we're gonna go find somebody to raid. Shams, any special words before we wrap this thing up?
SHAMS: No. Just, yeah, go make that 400 follow count for rowy. Thank you so much for having me on. It's been a pleasure. Yeah.
JASON: It was a blast. Thanks y'all for hanging out. Thanks, Shams, for spending some time with us. We will see y'all next time.
SHAMS: Thank you. Bye.
Learn With Jason is made possible by our sponsors: