Building a NextJS Application Part 4 - Supabase

Brian Coords: You are listening to ViewSource, conversations around WordPress and adjacent tech with hosts, Aurooba Ahmed and me, Brian Coords

Intro - What is CRUD
---

Brian Coords: Welcome back Aurooba. I'm super excited to talk all about CRUD with you. Are you feeling cruddy today?

Aurooba Ahmed: So cruddy. Or maybe crew y. I can't decide.

Brian Coords: Yeah. I guess we should give context before we start breaking down the letters and what, how I would maybe spell it. But do you want to give us, do you want me to give us the, what, what is CRUD in development terms? What are we talking about today? Do you wanna break it down?

Aurooba Ahmed: Well, why don't you talk about what crud is and then I can add color?

Brian Coords: Okay. It's definitely one of those concepts that I feel like I learned way later because I was not like, I was like a self taught developer and you know what I mean? Like I didn't get to like the form, I didn't go the formal path. So I feel like it, like one of those things I kind of came across later, but CRUD is like the four most important operations of data.

It's like C for creating data, R for reading data. U for updating data and D for deleting data. And anytime you're building anything for anybody, and you're thinking about content or data, you kind of need to always make sure you hit those like four things. Like, can they create it? Can they read it? Can they update it?

And can they delete it? And if not, why not? And then like permissions and everything after that. But like, those are the four things you're ever going to do with data. And that's what we're doing today with checklists, right?

Aurooba Ahmed: Yes, so the reason I said crewie is because when we first started talking about this episode And how it's really a crud episode. I realized that I did everything except the delete I didn't make I always forget this every single time I remember one of my first programming classes in grade 9 and We had to make this game and in the first part of the game.

There was you know a new game Go to current game or exit and I forgot to create the exit. So everyone would try to go to exit for some reason and they just couldn't exit. I don't know why but the deleting or negative function is the one that I think about very last.

Brian Coords: I think, I think there's two things. I think one is I'm the same way. I always forget like deleting and like, you'll have the client come in and be like, Hey I can't delete the calendar event or whatever, you know, custom thing that I made, you're like, Oh yeah. Especially because in WordPress, like if you're using post types, like it's all there for you.

But I think there should be a, another letter that's E which is like, I mean, it should be crude because I think there should be an E for errors because I think that's the other piece is like. You can do all these things, but like, you have to plan for like the errors. You have to plan for like what happens when it doesn't come back or it doesn't, whatever.

Like, that's just like a fifth thing that happens with your data is that like you try one through four and one of them fails and then like error comes back.

Aurooba Ahmed: Yeah, that's fair. I think also when you're in the business of fetching data from a remote place, maybe there needs to be like an S, so crudes then, because what do you do when it's slow? How are you going to handle that?

Brian Coords: Yeah.

Aurooba Ahmed: You know, like having a loading screen?

Brian Coords: Yeah. I feel like now we're just talking about like States like error state loaders state, we need a state. Yeah.

Aurooba Ahmed: it is cruds and not crude, right? Like, it's like create, read, update, delete, and states. All the different states that your data or your website can be in or your application. Because you have to, you have to account for the not ideal scenario, which is absolutely going to happen to someone, even to you, even in local development environments.

Brian Coords: Yeah. Well, it's like, well, the worst is when it doesn't happen to you, when everything goes smoothly with your local development and you never have an error. So you never really think about what's going to happen when the user does have an error because the, you know, some connection broke somewhere.

Aurooba Ahmed: Yeah, totally. I agree. So yeah, today, what we'll look at is, you know, we've been looking at WP audit for the last little bit. And when we left off last time, we looked at how to create an audit and talked about a lot of different things in Next. js. Pages and components and that kind of thing, but what we never really got to dig into truly is how the data is being fetched from Supabase and how we're editing and saving.

And then you made this really good point about what if I want multiple checklists, you know, I don't want just one checklist. So. Today, we're going to look at, you know, creating multiple checklists, which you cannot delete. And because I forgot, and you know, saving the data. So when you have your checklist, like it should actually be tracking the data for you.

Supabase
---

Brian Coords: mean, so, and everything is going to Supabase. So Supabase is our, our database it's connected to like the user authentication stuff that we talked about a few episodes back, everything's going to be like kind of all connected and Supabase at this point, I'm kind of curious. Are you paying Supabase at all?

Or are you free plan or a self hosted plan? How's that working?

Aurooba Ahmed: So what we're using for this example is the free plan that's on their hosted service. I have played around with self hosted Supabase, but it's just so much easier to set it up on a remote server if you just deal with their hosted one. So I've done it locally because I want to, during this episode and after, I want to put this up somewhere so people can look at the code but then also go to Site, the play, this interactive version of it and play with it.

I have yet to try and see what it takes to set up Supabase on, say, a droplet in digital ocean. So I need to play around with that. That's not something I've done before, but

Brian: Yeah, I was.

Aurooba Ahmed: thing here.

Brian: Yeah. I was wondering because our previous series, we did Laravel and we deployed to like AWS and like, now I've been getting like the bills for AWS and it's not a lot, but it was like, oh yeah, well you have to pay for AWS but that had like the database and the hosting, like I'm using, you know, we used like services all in that and this world of like Next.

Brian Coords: js and React and Netlify, Vercel, Supabase, like all these tools and stuff. It seems like there's like a very healthy free tier and that seems good but also scary because you don't know how sustainable that is but it's but it sounds like we're going to be pretty much free tier for

Aurooba Ahmed: is all going to be free tier. I think it would be, it would take quite a bit of activity and audits and users in order for me to surpass the free tier and, you know, within the world of react and sort of single page JavaScript application type situations. The two main players are, at the moment anyway, are Netlify and Vercel.

And although Netlify doesn't offer its own database store, I recently discovered that Vercel does. So technically, instead of using Supabase, I could have used the PostgreSQL database that Vercel offers and they have like all of it could have been integrated into one if I wanted to use Vercel. So I'm really curious about that too.

So just in creating this, I've gone down like 8 million different paths. I'm like, Oh, look more options. Yay.

Brian Coords: This is why people like PHP. You know what I mean?

Aurooba Ahmed: I

Brian Coords: like the JavaScript world and they're like tools. And I mean, what was, I mean, Supabase really, I think of it as like the better Firebase, but like Firebase was the thing for a long time and like Google bought it. Did they keep it? I don't even remember.

Did they shut it down or it's still

Aurooba Ahmed: No, it's, it's still going, but like the documentation is like getting more and more outdated, I think. And I don't know, I just. I'm traumatized by using Firebase in this one project that we did and I, I just don't want to ever touch it again or think about it again. I just go to Supabase because at least it works and it's reliable and it works in tables, which I just find a lot easier to deal with than document based stores

Brian Coords: Yeah, I, I do not want to be like clicking through a bunch of nested JSON. I just want to look at a table. So good choice.

Aurooba Ahmed: with a bunch of JSON in the table in this case.

Brian Coords: That's true. I think we did have a bit of a conversation about that last time. So I'm excited to see how, how you're talking, how you're editing, adding, fetching data from Supabase.

riverside_aurooba_ahmed_raw-synced-video-cfr_view_source_0063: So let's take a look at the front end and what that looks like, because I made a couple of changes in order to be able to accommodate multiple checklists, and

Frontend Preview
---

riverside_aurooba_ahmed_raw-synced-video-cfr_view_source_0063: then we'll take a look at what that actually looks like in the code.

Aurooba Ahmed: All right, so here we are back at wpaudit. site. And as you can see at the top, instead of saying your audit, it now says your audits, plural, because you can now create more than one audit checklist. So, like I said, you can create an audit, but I forgot how to. I forgot making a delete component, so there's no way to delete it, but you can create a new one.

So I go create an audit. It adds a number 13 in there. And if we go in there, we can save our checklist like, so, and. While we were doing a test version of this recording, we realized that because I'm not using a real time version of Supabase, we're seeing some interesting effects, right?

Brian Coords: Yeah, I guess that's one way to put it. It's, it's, I think the core issue that scares a lot of people from Next. js, React, single page application development, which is like, it's supposed to be saving data in real time. But it never seems to feel like it works as well as you want. And I've even, I was on a project recently where the client was just like, can I have a save button?

They were like, I just, they wanted to know that they could hit a save button. And like, before they walked away, they wanted that confirmation. So it's just such a weird thing. And yeah, we were seeing some issues of stuff. Cause you have to think about like, I changed one thing. I changed another, like, you know, all these things sort of add up and take time.

You know,

Our Bug and Async Data Effects
---

Aurooba Ahmed: Yeah. So the issue, and we can demonstrate it right now, is let's say that I quickly check a bunch of different stuff. Now, if I were to just quickly refresh the page, and of course, now it won't work, because we're recording.

Brian Coords: it's a

Aurooba Ahmed: it doesn't work. It's not. It works now.

Brian Coords: Oh my gosh. It's, I literally was just. Saying this to somebody who, you know, whenever you aren't, whenever you think you're done with something, you record a video for your client and send it to them. Cause that's when you'll find all the bugs. Like the minute you start to record something, nothing ever works.

I mean, like I've never seen this opposite version of like yeah, no, that's not true. That is a thing too, where you say, okay, let me reproduce this bug to show you, and then you can't reproduce it. That is a normal thing.

Aurooba Ahmed: Yeah. But what we want to reproduce here is that if, if for any reason there's a internet connection issue, your computer is being slow, there's something weird happening and you're making a lot of changes really quickly, the way this is currently set up using just one update at a time. you could at some point refresh your page and find that not all the updates that you made are saved.

And right now, in this example, we don't have any UI that shows you whether a saving process is happening or not either. So it's really like you're saving experiences a little bit in the black box. You know what I mean?

Brian Coords: Yeah, because you like, you kind of almost like if you checked it and instead of going to a check mark, it was like a little spinner and then it only showed checked when it came back from the database that it was actually checked or like you check it, but like you don't actually show the check mark until that's like.

Source of truth from the database. That's honestly, that's just like a constant kind of struggle with that sort of single page app, you know, thing. So it's just, it's not unusual that you come across this.

Aurooba Ahmed: yeah, but you know, ideally, the idea is that you can click and things are going to save and then if I were to hit refresh, like I am right now, and you can see nothing change, it looks good. If I go back to your audits is audit number 12, I go back to audit 12, it's going to show me the state that I was in, which is what is happening here.

Now, in the database, we covered this in our last episode. This entire checklist is saved as a JSON, a single JSON object, and we had a conversation which in the episode we had to edit to keep the length of the episode a little bit shorter, even though it's such a good conversation, I was thinking that maybe we should release it as like a blooper or like a bonus episode because that part of the conversation was really cool as well.

Yeah,

Brian Coords: example of like trying to get on the same page of an idea of like an abstract idea. It was like. You know, say it, say it back to me. Nope. Keep refining it. Like, like, I'm not explaining this the right way. You're not getting it right. Like we're just, that was a, that was a good conversation, but yeah, if, if these were all separate fields or separate rows in a database table, it would be a lot easier because you could be updating this road and this row and this row and this row, or right now you're updating one big blob.

And if you do it too fast, update here and update there don't really line up.

Aurooba Ahmed: Yeah. So, to give everyone an idea, this is the kind of object we're updating, where there's an ID, there's a checked, and what we're doing is we're checking the ID of the item, and then we're changing the Boolean checked false true based on the user's behavior. But it all lives inside one field, so if you make a bunch of updates all at the same time, and you're doing this one at a time, you might end up sending Conflicting updates that may not have fully resolved by the time you like leave the page or refresh the page or something like that, right?

Brian Coords: And another thing I would think about too, I wasn't asking about this. Cause when you're doing that kind of like real time back and forth, like that is data that's traveling and like, there is like an, you know, tiny bit of a cost to every time you, every time you move traffic across the network, there's a little bit of an energy cost to it.

And you have this huge Jason that has. 90 percent of that is never going to change, right? It's this, these texts and all that stuff, and you're sending this whole thing back and forth so often. I wonder if it would make it more sense to break some of that down somehow.

Aurooba Ahmed: Yeah, I think that

Architecting Databases and Structure
---

Aurooba Ahmed: it's an interesting architecture problem, right? If we're looking at a list where we never want someone to be able to update the different list items, then I think creating a column for each or something like that, or even a table for each, you know, or something where each user has their own or something like a pivot table or something that is even more intense might make a lot of sense.

The thing that I think about is how if I want someone to be able to customize and remove and add items, be able to make their own new items, et cetera, how, what is the best way to set that up for multiple users who might want to create all kinds of things? And I don't know if I have an answer to that right away, right now, you know, I think there's like, right off the top of my head, I can think of like, at least five ways to do it.

But. We, I would have to play the scenario out and really spec it out to see if that is the way I would want to go, because they all have different pros and cons.

Brian Coords: there's always tradeoffs. Like my default thinking is like each checklist item is a row in a table and there's a column for the name of the row, a column for the description of the row and a column for the checked and a column for the audit ID that it belongs to. And then you're. Editing each row at a time.

But then that means every time someone starts an audit, you have to go in and add 20 new rows to that database table. Every audit gets another 20 rows, another 20 rows. So it's kind of like, and then that, that table's gonna get you, like, that's the WordPress post post meta problem, where like that second table gets really big.

It's, you know, I don't know. It's a really hard one.

Aurooba Ahmed: yeah, and I think I think that's one of the reasons why something like Firebase was created You know a lot of times you really just want a really nice Maybe semi nested, but maybe not key value store actually Ross Wintle he I was talking about this a bunch on Mastodon the other day because he's been looking for something like that and now he's just like, maybe I'll have to create my own.

He, he is excellent at making lots of small little things and it just got me thinking about, you know, I get it, you know, and sometimes that's really all you want. And if you had a document store, that was just a key value store or something like that. Something similar, not quite that simple, maybe this would be a good scenario, a good fit for it.

But yeah, you know, it's a, it's an interesting situation that you only encounter when you're trying to create these kind of applications yourself. And let's be honest, I've never needed to create an application entirely like this that I might want to. I mean, I have done this before, but. I guess in this situation, I haven't thought through exactly what I might want to do.

I'm still thinking about feature sets and so nothing feels set in stone. But just based on what we see even now, you know, I'm like thinking maybe an JSON object is not the right way, or if JSON object is the right way, then the saving mechanism, the way it actually interacts with the data, needs to be different.

Brian Coords: Yeah. And, and I think some sort of like data layer data store, that's going to be a little bit more prescriptive on triaging all of that sort of stuff is probably important. And as you're talking, I was just thinking how, like, you know, say you just wanted to do the, the initial version of this, where you didn't have multiple audits, because obviously that's what made this a lot more complicated too, is like the fact that it's also needs to be like.

Exponentially growing with all these audits. But I think if you didn't, I was just thinking about so many people now where they just like spin up a thing with AI and they're like, Hey, I code this, Hey, I code that or whatever. And it's probably really great for really small proof of concept ideas and things like that.

But the minute you start thinking like, Oh no, I'm going to turn this into. Extra features, extra, whatever, premium or whatever, you know, all these other sorts of things you want to add on it. It's like, no, you really have to actually understand the fundamentals of architecting, like a good app, a good database all that sort of stuff.

Before, you know, I mean, obviously you can pivot it along the way, but like you really do need to kind of know that stuff.

Aurooba Ahmed: Yeah, definitely. The fundamentals of database databases and architecture and that's, this is something that I have read quite a lot about, but it's one thing to read about. And it's another thing to make it happen. And it's been a while, you know, I think when we are in the WordPress world, especially in the WordPress world, a lot of that Baseline architecture is, those are decisions that have already been made for us.

So we often don't need to spend a lot of time thinking about it. And I think I'm in a space where I haven't had to think about it for so long that it feels a lot fresher and something newer that I don't feel as practiced at figuring out right now, you know?

Brian Coords: Yeah. And the thing about WordPress is like, nobody's saying that it has the best structure for databases and storage, but when you do use like core WordPress stuff and you're just like, Oh, I didn't even have to write a rest API end point. Cause it made it for me. And I don't even have to, like, everything is just done for you.

And you can just like jump straight to the, like the building. It is pretty nice. And you don't really. Have to care as much about the performance stuff. And of course then there's like object cache and all these other things that kind of help you along, but yeah, it's definitely very interesting. I'm kind of curious now what it does look like when you save data.

And

Aurooba Ahmed: right. 1 thing I want to say before we get into the code of this is this is something that actually want to create a real working version of and I have created it. It's not out yet because I want to refine it a little bit. But in that version of this application, the way I did it is it is still an JSON object.

However, you make updates and it holds those updates in a single state in a context, which is something that is part of React. And then it only updates the database about every five seconds with whatever the current at that time updated version of that object is. So, and there is UI to show you that, oh, your data is currently not saved.

And then you can hit one to do a save. Now. And it'll tell you when things are saved, just like you would see in something like, say, Notion or Google Drive, in Google Docs, you know, there's always a little bit of information there showing you if your information is saved or not. So

Brian Coords: then in that version, do you get to name your audit and like put what website it goes to? Like is there a field for like URL and name and all this stuff? I mean, cause you.

Aurooba Ahmed: And there's also the ability to add custom meta, like you have even more fields than the ones that I give. So it's a lot more There's a lot more going on and it's a lot more complex than the version we're looking at right now because all of that, you know, it adds so much complexity to the code.

It is simple. I try to keep it simple, but it's still a lot more complex because there's so much stuff happening in there. And that was going to just make everything overwhelming at this version of the application.

Brian Coords: I get what you're saying. You're like, I had to dumb down the code so that I could show it to Brian and his brain wouldn't explode. So I made a separate version that Brian's brain can understand. And all the real hard work is actually in a separate repo. I don't get to look at, I got it. Okay. Yeah. Makes sense.

Checks out. No, no complaints here.

Aurooba Ahmed: The other thing though, the caveat there is that in, you know, making a simplified version of this, there were things that I forgot to think about because I was just thinking about one particular thing that I'm trying to demonstrate. So, you know, this whole thing of just, I chose to remove the context and didn't add context to this.

I should have, you know, I should have, but that's okay. We

Brian Coords: hard because you want to just teach the thing and you don't want to do, like, when you're trying to make code to teach from, you just want to teach the thing and it's really hard to not get down the slippery slope of like, well, I should do it this way. And this is, you know, cause we were just supposed to talk about CRUD.

Aurooba Ahmed: exactly. So, okay.

File structure and dynamic routes
---

Aurooba Ahmed: The few quick changes that we made to our file directory structure is one. Now there's an audit dashboard because we have multiple checklists, so we can't just go directly to an audit list. We have to go somewhere that shows you the different audits that you choose from. And because I made this sort of page based, I decided to make an audit dashboard page.

And then there's an audit folder that goes in and it calls an audit ID. So the URL of this is actually audit slash 12 because the ID of this audit is 12 and that's what's happened over here. When in Next. js, you can create nodes that are dynamics or dynamic routes and they're based on the ID and it's a way to pass a parameter to that page so it can do something with it.

So that's the first thing. The other thing, Is we actually changed our template for the audit itself to add those IDs to those objects because the way it works is whenever you check list, update an item in the checklist, how do you know which one to update in the JSON object and the easiest is to give it an identifier.

And so it's very simple. It just has an ID number.

Brian Coords: Okay. For the route, could you do sub routes? Like after the, after the ID number, like, could you like keep routing different, like views of, of a single object after that?

Aurooba Ahmed: Absolutely. I think that I've never tried to do more than three, but I think technically you could just keep going, but I don't know that you would want to, you know?

Brian Coords: Yeah. But like audit slash 12 slash preview or audit slash 12 slash, like, you know, share or whatever, you know, whatever other pages you're going to want to have.

Aurooba Ahmed: Definitely. Yeah, you can definitely do that. I've done the preview one before in a different application. The share one is also a really good concept. That would make sense a lot too.

Client and Server Components for Supabase
---

In order to send data to Supabase, we have to create a client now, because we're, we have server components and client components.

Aurooba Ahmed: We need a server verse version of the Supabase client and the and the. Browser version of the client as well to pass information or get information from Supabase. And for that, what I did was in the utilities folder, I have a Supabase folder and then I have a client file and have a server file. So the client file exports a browser client.

And the server file exports a server client, which, as you can see, has a lot more going on in it than the browser version.

Brian Coords: And this is separate from the one you built for user authentication. Like this one is just for Supabase, the database side of it.

Aurooba Ahmed: user authentication doesn't, you don't create a, I mean, you can, you do create a client for it, but there's a lot more going on in it. You have to set some cookies, you have to check a bunch of other things, you're actually passing these tokens. This is for. Anything, but the user table, essentially, in order to be able to interact with the tables.

Yeah. So, for example, if we look at our audit page, our audit ID 1 here, you can see that we actually use. This is not this is a server component. So we actually you pull out the create client from the server itself. And then from there, we have to pass it our user authentication cookie store to be able to get the authenticated and correct information from the audit table for that user.

Brian Coords: Okay. And then that's just like a little query builder.

Aurooba Ahmed: That's right. So Supabase, this is something I really likes, you know, it's such a really nice and readable query set up in Supabase like from, so you're grabbing it from the audits table and we want to select data. So we're not updating and we want to select data where the user column is equal to the user ID and ID is equal to whatever the audits ID is.

And I want you to order it based on a descending order essentially.

Brian Coords: okay. So the EQ is like a where, but it's like where equals basically.

Aurooba Ahmed: yeah. The column equals, essentially. And then it returns data and error. And the data will have the data, or if there's an error, then you can check the error and then do something with it.

Brian Coords: Okay. And it's, so yeah, and it's different than like, I guess I've been in the world of like, Doing that sort of thing, but then like you having like a use effect or something where you're kind of like waiting for data or something like that. But in this case, you're using asynchronous functions to kind of pull data.

Aurooba Ahmed: Yeah. I do my best to not use useEffect functions when I can. They are great, but they are what's called a side effect, something that happens after a render and when you can avoid them, you should, and there was a time when I use them a lot, but the better I've become at react, the easier I've found it to not use it and the better my code is, the less memory leaks there are, and it's been really interesting to get into that more deeply and learn a lot more about it.

Yeah, so this is how we grab data, but then in order to update 8 data, what we're actually doing is we're updating in the audit item component and let me close this out a little bit. So we can see this. And this is our audit item. But unlike last time, we now have the audit ID. Because we want to check what item this is part of and then only update that one and the item ID itself.

And we, this is a client component because I wanted to have state, right? And we check if something is checked or not. And then when you click on an input to check it, there is this handle check. Which is also an asynchronous function, which basically talks to Supabase and here you can see. Hey, in wait, that's information right here.

So grab from the audits table. And we're going to update this column with the updated audit object where the ID is equal to the added ID.

Brian Coords: So wait, if you go back up though, you, at the beginning of this function, Oh, do you like, do you like that new VS code? Like stacking thing? I where it stacks like the, the function at the top of your,

Aurooba Ahmed: Oh, yes, I liked it a lot. Yeah.

Brian Coords: it's like I do. And then I get into a really long file and it's like half of my screen.

And then I'm like, what is going on here? But

Aurooba Ahmed: Yeah, I turned it on just recently after seeing it on someone else's video and so far it's been convenient when I'm working with like, really long, weird functions that I'm trying to clean up into

Brian Coords: yes.

Aurooba Ahmed: functions and it's been really handy for that.

Brian Coords: I don't like it in the sidebar though, when you're browsing through files, it started doing it there, and then it's like, I, very confusing. But here, I, I like it.

When to visually show data
---

Brian Coords: Anyway, oh, if you, if you go back up to the top of the handle check, you are immediately, Setting the state based on when they toggle it. So like the minute they toggle it, the first thing you do is update the state.

So the check does the check Mark, does it, but would you, why not wait until you find out from Supabase and then at like, then check it.

Aurooba Ahmed: Yeah, that's definitely one way to go. This is because this code was partially copied from the version where, you know, updates don't happen right away. And so I just check the state and update the state right away. But I think even in this case, you know, you want to provide that feedback. The fact that it, I don't know if I like the idea of, I think it's more reliable for sure to update the state when it's also updated in Supabase.

And that is definitely one way to go. But I think that's not very user friendly. Because something like checking an item should not take that long. You know, intuitively, we think that's weird. And so

Brian Coords: Yeah.

Aurooba Ahmed: Any framework or any, any architecture that requires you to have some sort of waiting period for something so simple as that.

I think that's a problem in how we've architected our application and we should be avoiding that. One of the, my biggest problems with a lot of JavaScript. applications is that things that we think are normal and intuitive are somehow not treated as if they're normal and we should be aiming for them and instead it's like oh actually this is a whole problem and we've created this weird thing when in a lot of situations for example regular websites can do this and so why can't your stupid javascript app do this like what the hell you know

Brian Coords: Yeah. It's, I mean, I get what you're saying. Like when a user checks a checkbox, it should be checked right away. Cause that's the experience that they expect. That's definitely like when you're rendering a page in PHP and then they're going to go to the bottom of the form and click submit. It's like, that makes sense.

And then when you're, it is that vague thing of like when you're in an app, like I did something, the screen is telling me I did it, but I don't ever know for sure that I did. And there's the trade offs because if you did. Not show a check mark very immediately. It would just feel broken. It would feel like a bad experience.

So you kind of have to like, it's, but it's just, you are showing like fake data, that's like, I don't know. It's like a, just a weird trade off. You know, it's hard to

Aurooba Ahmed: I think most people do understand the difference between your current state and what might be saved in a, saved in a database. Like, I could create a state right here called isSaving, you know, and then here I could say set isSaving to true. And we could add a little thing here that, you know, like a state, like isSaving

Right? And if it's not saving, then, and this is super janky because I would just make this in one, but as I am writing this you know, if it's not saving, then show me not saving. What am I doing here? What am I trying to do here? Hold on, hold

Brian Coords: I don't think you need a, not a saving, just like if it's saving, you do it. And then when you update the, when the, when you're finished saving, you just turn saving back off.

Aurooba Ahmed: Exactly. So if there's no errors, then I would set that to false. So now, if I were to click this, it's saying saving, and then you can see it went away. Having a UI like that, that, that could, that's, that's good practice, you know? So in that situation, then you are giving the user enough feedback to help them understand that just because I clicked this doesn't mean it's saved yet.

So even this, like a very basic little saving there, that's nice, you know? Obviously I'd want to style it and it shouldn't show up in that the item, but.

Brian Coords: I mean, I think it goes back to what we were saying at the beginning with like, there's crud operations and then there's like the States and it's not like you, maybe, maybe this wouldn't be the best approach showing a loading every time. Maybe it would, maybe there'd be one loading in the corner for the whole app or something.

But like the point is that like there are States to deal with what happens when it doesn't say what happens in this, like all those sorts of things. Like if you get an error, do you uncheck the box again? All those sorts of things. You know, there's all those. Experiences that you just want to make sure that you think about.

Aurooba Ahmed: Yeah. And

Planning vs Building First
---

Aurooba Ahmed: I think that sometimes they're really hard to think about unless you really sit down and plan your application. I cannot emphasize how important it is to plan your application out. I have too many times in my career jumped way too fast into execution and then have, you know, just a rookie problems, just constant rookie problems and planning saves you from so much of that.

Brian Coords: And sometimes you're like, I just want to get my hands dirty and like make a little bit just to make sure I am going somewhere with this or something. It's a, yeah. I mean, you really shouldn't like design an architect in the browser, in the editor, but sometimes you just. You, you know, sometimes you still do.

Aurooba Ahmed: Yeah, sometimes you just still do. You're right. And in smaller things and smaller projects, there's very little risk, or at least the risk feels a lot more manageable. In a larger situation, I don't know if that would be a good idea, you know?

Brian Coords: If you're doing something where somebody is paying you to do it, that's definitely not the place to go. If you're trying to experiment, learn new technology, maybe a little side project you've had on your mind or something, then that's maybe the, the time that it's okay to do that. If a client is paying you, then like you should be like, or a boss is paying you, like you should, you should be very strategic from the beginning.

Aurooba Ahmed: I also think that planning isn't something that you just, it's like, not one and done, you know, you plan something and then you start doing something and then you learn something new, a new variable is introduced and then you have to adjust your plan and in the, even in the best situations, that's going to consistently happen.

So you have to expect it and make room for it. You know. Yeah.

Queries in Components
---

Brian Coords: your base, I mean, not really, but it's like you're writing like. Like SQL style queries with Supabase, like right in the component, you know, you get to write these kinds of like very strict things, but like, do you like that you, like, it's definitely faster and easier to go straight into like this little bit of a, like a, just a query just to do exactly what I want, but like, do you feel like there should be some layer in between, between like the components and like interacting directly with the database?

Does that make sense?

Aurooba Ahmed: Yeah, no, definitely. I think that, you know, we talked about before how you can create actions and you have a page and they're kind of separated, but. If in a real world version of this application, you don't want your components to actually be directly dealing with the data. You want your components to be isolated that just take in different kinds of information and then maybe pass information somewhere else for a different layer to deal with them doing it in here.

If in a real world version, the handle check would just be saving a state and maybe passing information to a function that it was provided with. And then some things would be happening somewhere else, you know, they wouldn't be happening right here. But for the sake of illustrating how data can be, you know, adjusted and handled, I put it right in the component.

But this is not storybook ready, you know, this is not component testing ready, because you can't have data in something like storybook, which is a great way to do UI testing. Because That's for UI, it's not for data, and this would totally error out and just mess up everything if you had it like this for a real world situation.

Brian Coords: And so in a real world situation, your audit item component would have as one of its props, a function for like on change or on save or something like that.

Aurooba Ahmed: exactly. Update data or handle check. That would be a function that I would be receiving and that would be doing something. Or if I'm using context, I might not be receiving a function here but pulling it out of the global application context within the component itself, perhaps.

Brian Coords: Okay.

Aurooba Ahmed: Again, once there's a few different ways that you can do it when you are not using a form and an action that updates the page.

So that something can happen and then you see the update again in, like, a traditional php or multi page application.

Brian Coords: Yeah. Man, there's so much to think about. So, so you're, so you're basically good in terms of like, reading, writing data, we can't, where there's maybe some extra meta fields that we'd want to add, we can't delete. There's a few things like that. But in terms of like, yeah, we can't name anything. Obviously, there's

Aurooba Ahmed: bones are there, you know, like, so you can create things now. It's just a matter of refining it and. really deciding on a proper data architecture. Honestly, if we want to do an episode on that, I think that would be really interesting. Just looking at what data design architecture design looks at and how to think about it when you, even when you're making a comparatively pretty small application like this or like the one that we made for Laravel, like the suggest episode one, you know, and the different ways that

Brian Coords: I mean, I think I have how I would do it. But I'm curious how you would do it. And what? I don't know. Yeah, there's so many like ways to do it like, you know, yeah, we should do it because I have now I have thoughts about like abstracting like the types of the items themselves like SEO and all that stuff as like one thing and the actual check.

In your particular audit as a separate thing so that those cards are like, could actually be like templatized and like spread around. Like there's so many different ways you could kind of go about it. And like, I think there's going to be a layer where you could share an audit and like attach multiple users to the, to an audit and stuff like,

Aurooba Ahmed: And what happens if you want to edit it together at the same time? And now we're talking about collaborative editing, which is like phase three of WordPress and

Brian Coords: Yeah. And,

Aurooba Ahmed: many things, you know, so many things.

Brian Coords: and like, I, you know, and I would even want to know,

Planning for Database Migrations
---

Brian Coords: like, what happens when you want to make a database change? Like, like Laravel has a good. Like protocol for that. So yeah, maybe that's what we should talk about next. Cause I'm curious how you would handle these sorts of situations.

Aurooba Ahmed: Yeah, I mean, the short answer is you can do migrations in Postgres. Like you could in a SQL database. So a Supabase has like a JS version, a client, a library within it for you to be able to do that. But a migration is a migration, regardless of what kind of database or framework you have on top of it, how you might want to do the migration.

Now, yes, Laravel has like one migrate function, Supabase has one too. That's not all that you have to consider, especially if you're doing like a radically different. Database structure, and I have seen applications where they've done that. And that's quite the undertaking.

Brian Coords: You mean like migrating when you actually have like a ton of like, like my, not just migrate small migrations, like add a column, add a column, that sort of stuff you're talking like change the entire structure. Yeah.

Aurooba Ahmed: Yeah, yeah. Like Jack Ellis, who's one of the co founders of Fathom early on, I think, not early on, but maybe once they got some real traction and they had a lot of users, they did this massive, like, rewrite of the way their database works and they changed services. It was like a whole thing. And I remember thinking, wow, you know, this is really intense, like going from one, you know, Architecture to something else that might work for the fact that he needs to create an application that scales for millions and millions of data views and users.

And just like having to consider all of that. It was, it was mind blowing. You know, I am not his caliber of developer and

Brian Coords: Yeah,

Aurooba Ahmed: Wow. Yeah.

Brian Coords: struggling when I have to move somebody from like easy digital downloads to WooCommerce and like migrate all their customers and all there's like, just even like those sort of like basic pathways that have been tried already, you know, can already be hard enough.

Aurooba Ahmed: always some weird thing with a weird plugin that's causing another problem that you have to consider inside WordPress, you know, and I think when you don't have full control of database design, that makes it even more frustrating, but I think that when you have full control of the database design, it's almost scarier.

Next Episode Preview
---

Brian Coords: So I think there's just really one final step in our next JS journey. Obviously there's a lot of things happening under the hood and different changes and stuff like that. But like, there's just one last thing you have to do when you build an application and that's deploy it. And I'm actually very curious, I don't even know, did you pick Netlify Vercel?

Like what, what is the, what are we going to look at?

Aurooba Ahmed: So I have traditionally always used Netlify, but I think I want to put this on Vercel and see what happens. So I will deploy this to Vercel and then we can talk about it and maybe compare it to a little bit, to the experience we've had with Netlify a little bit too.

Brian Coords: I think that's a great idea because I think Vercel has sort of kicked a lot of other like host deployment companies a little bit. And I think they've, they've like turned a lot of heads. So I'm very curious to

Aurooba Ahmed: Me too. Yeah, and they have things like the V0 and now they have all these services like the Vercel like database that I was talking about, like all these things that I didn't even know they were doing. And now they're trying to be everything, all the different things of a composable framework. And it's a, it's a little bit wild.

Brian Coords: all right, so then let's dig into that next time.

Aurooba Ahmed: All right. I'll see you then. I'll report back.

Visit viewSource.Fm for the show notes and if you're enjoying the show, we would love a review on iTunes or a comment on YouTube.

Creators and Guests

Aurooba Ahmed
Host
Aurooba Ahmed
(she/her) Developer building bespoke #WordPress solutions, tools, and blocks. My name is pronounced "oo-ROO-ba" — Default to kindness, folks.
Brian Coords
Host
Brian Coords
WordPress developer and writer blah blah
Building a NextJS Application Part 4 - Supabase
Broadcast by