Supabase & Sveltekit - Build Twitter in 75 minutes

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone so in this video we are going to make something a little like twitter but it's going to be called quitter because i'm going to quit before we finish it but that's okay you're going to learn a lot you're going to learn about storage databases and how to authenticate with this magic link right here so let me show you what it looks like um after i tell you that we're going to use felt kit supabase and daisy ui which is built on tail and css okay so we're going to use magic link just because it's the simplest so you can click magic link um and then it'll send a link to whatever email you put in there so it should send it here in just a moment let me refresh make sure it's there there it is okay and then i can click right here log in and it'll bring me here to the page so i can make a post and i can make comments on posts it's not fully like um real time updated but i could say cool and it will post a comment but you have to refresh to get it but that's okay you know uh we can figure stuff out maybe maybe we'll do a better job when we make it the second time but for example you can also do something like this and i figure what image that is but this is something and i can post it and it'll appear here again there's a little bug that we might be able to fix where the image isn't showing up right away but uh that's there and we got likes okay cool so you can also sign out and this is made with felt cubed right there you can click on it okay so let's actually make this thing i'm going to exit out of that excited that and first what we need to do is we're going to start out with sveltkit so here's some code but we're going to exit out of that and in the terminal what you need to do is go to some directory wherever you want it to be for example here i have it in my sveltkit directory and we're going to do npm init svelt at next and we're going to call this quitter so hopefully i didn't already name something like that but now you can say yes you're going to do skeleton project and we'll just say let's say no to these okay so we can change directory into quitter and we can code dot so open that folder in um in vs code i actually wanted to hide this from you i finally have a second monitor so i can hide it from you over here on my other one just in case i get lost okay but this is our new project that we just set up with us spell kit so what we want to do is add first of all tailwind css which is with npm install or sorry npx cell add at latest tailwind css so it might be a bit different depending on when you're watching this video but just look up spell ad um but hopefully this should work so we do that and then we're gonna npm install daisy ui which is this thing right here so it basically gives you components that are built on top of tail and css but you can just use these and uh they give you these little classes here but then you can modify them with tail and css classes as well so it's just a nice quick way to do things it also has a bunch of themes which i like so it has all these themes but it's got more as well okay so we installed daisy ui and then we need to npm install just for the project in general i haven't done that yet okay there we go cool so we have set up our sveltkit project i believe and then we just need to set up super bass let me just check my notes now that i have the second monitor i can check the notes okay set up super bass project after one last thing we need to do here is require daisy ui so after you've set up tailwind you just need to npm install this ui and then add it here to plugins like that okay i think that's all we need for this felt kit and our tailwind daisy ui stuff now let's go to supa base and we're going to start your project you might need to sign in i've already got my thing here going so i'm going to do a new project just be practice i'll call it quitter did already have something called quitter i don't think so so twitter put in a password you'll remember um put it closer to me create new project okay so we'll have that wow and having the second monitor is nice because i can just copy and you can't even see you can just copy paste stuff into here so first of all oops no i don't want that we're going to have lib and then inside there we'll have our superbase client like that and i can just paste that in bam nice so import create client from at two base slash superbase.js which we need to install still so copy npm install that okay and then we need to fill in superbase url and public key so if we come back here we got our public key right here copy okay and then our url right here so it's okay if people see this because um this is going to be sent on the client so people could like check the source code and this will be there um the reason it's okay is because the user needs to actually sign up in some way so we can track who the user is and based on who they've signed up as so so basically they need to sign up before they can do anything in our site um and then based on who they sign up as we can control what they have access to in the database so okay so that is superbase right there um it's still setting it up that's fine because we have what we need in our client here in swell kit okay so a few random things that we need to do before we keep going is come to thistle try off yeah come to the auth right here and go to settings and what i like to do is just at least for practicing we don't want them to uh they don't need to confirm their email they can just use whatever email and then they'll be logged into that um i don't want this here how do i get rid of that oh well okay i turned that off it was a little slow seemed like it was lagging a little bit but that's okay okay so i did that um and then the other random thing is you can choose a theme so if you want to change the theme of your site you can come to static or not come to uh source app.html and right here do data dash theme so this is for daisy ui you can choose a theme we'll do cupcake and like i said uh here you can choose one from here for yours okay and then i think we can finally oh no we can't finally um we can npm run dev sure let's do that npn run dev open oh whoops it opened it in my other browser okay welcome kit like that so tailwind resets all the styles so it just looks like that okay but so here in app cupcake that's good um let me get back to my notes here so another thing i want to add real quick before we get started is an error component this will just be for error handling in the future so supabase returns errors and those errors have a message that you can show the user i believe um and then we want to modify our layout component just to add a container around the slot here like that okay so now that we've done that we can set up our login page [Music] first of all we're going to create a services file so whenever we interact with supabase we can use this file here there's some weird spacing in here sorry about that but um so we've got to get user so superbase.user that'll just return the user to you for sign in it's just await superbase.off.signin and if you pass in just the email it'll be the magic link like we have it set up so we only need sign in because they don't need to sign up they just need to say send magic link they get it to their email and then we know who they are we know what email they're using so um and for sign in you can have an error you could also get um a user and a session but since this is a magic link it's just gonna we don't care about user recession because those don't start until uh they actually clicked the magic link that's what creates the user in session so we're just checking for an error and here we're checking for an error when they sign out so that's all that can happen okay so we gotta sign in we gotta sign out now let's create our login page login.svelp and just for some boilerplate here we are going to so um we got the error here we've got our sign in we've got this get user function and we've got to go to in a browser so these things here are just used to redirect the user to the main page if there is a user anywhere on the browser um rather than like pre-rendering or um i guess server-side rendering okay so that's just to read that that just redirects to me uh redirect if already uh logged in okay so what do we need to do let's come to daisy ui and find a form input that has a button with it so form input with a button so you can choose either of these i think connected looks a little nicer so it's the first one here so we're going to bring that in here and let's turn this into a form rather than a div just so it's a bit more semantic html and here placeholder search so we can say um email so uh sign in i feel like login is maybe more colloquial login to quitter and let's make this bigger with tail and css class text for xl okay so this label is four that's why it's yellows because i don't have a four for email so the type of this input is email id equals email okay and then our button here will submit our form so get magic link so on submit prevent defaults we're going to do the sign up so let's create another function so what i'm going to do is have a promise a like sign in promise while the magic link is being sent and then it'll resolve with either a error or with some data so let sign in promise equal we'll just say promise dot resolve i think that's what is okay and then we'll have a function so handle sign in so right here when they submit handle sign in we will call we'll say um sign in promise equals sign in and we want to pass in the email so right here we gotta pass in an email like that so let's bind let email equal i'm just going to use this one as the default but for you it would be blank just so i don't have to type it every time and i'm going to bind that value equals email to this input so they're going to type something in we can make this required also like that um sign in promise okay so let's see what we have first of all okay here we are um get magic link so that's all working um click sign in okay so sign in promise right so we want to await this promise so you basically when you when you're working with these types of await promises async stuff you kind of want to think about what do you want to see in every state of this so there's an idle state before anything's happened like that like this and then there's the loading state while it's running and then after it's done did it succeed or fail so while it's loading that one's pretty usually pretty simple so sending magic link to this email um okay so that's what it's gonna say while it's loading now dot then so i've set it up like this so it's guaranteed so super base guarantees rather than like throwing an error for a promise it'll just pass the error to you right here so it's guaranteed to um uh like not throw an error it's not going to error out on you so you're just going to get this error it's guaranteed to resolve that's what i'm trying to say rather than reject the promise so to resolve the promise you get this error and now i want to send back basically this will make sense in the future but basically if there's data so data will be true and arrow be false or vice versa so you can check is data is there data or is there an error so just to make that clearer let's actually do that so this will then return back a data and error i'm just calling this data because that's sort of in most cases there will be data for the sign in there's no data really but this just tells us that it was successful and then we don't have to worry about catching anything because it's guaranteed to resolve just with the data and error so [Music] if there's an error we want to show this form again so if error then let's use that error thing actually we don't need to do affair we can just do error and pass in the error so if there's an error it'll show it show us the message and then otherwise if there's data that means it was successful so if data then i'm going to say um maybe we'll do something like this um text green 600 success so give them a success message successfully sent magic link to there okay and otherwise we want to show this so if it was successful we just need to say good job like we don't want them to send another link basically um so when i resolve right here there's i'm just resolving with nothing like this will be empty and this will be empty so this won't show and this won't show it'll just show this here okay if there's an error it'll show this and there won't be there won't be a data so it'll show this as well um so that's maybe a bit confusing initially but um hopefully it gets clear we're going to do something like this a few times okay anyway so i can come here get magic link some error let me see okay we just need to forgot to pass in email there okay get magic link sending magic link to spelt mastery successfully saying great so now i can come here and i just want to show you too let's say i refresh it and i did it again i'll get an error because i can only send one every 60 seconds okay so here it is login cool so now i'm at the main page so it redirects me to um whatever i have here in my settings okay so cool that is basically all there is to the login page now what we want to do is a create post page so here once we're actually logged in yeah we want to have a create a post page so let me make a new component create post dot svelt okay and we want to have a create post function let me go get that real quick so in our services okay yeah so here in services we're going to add this guy right here create post so what this is doing is from posts so we'll quick we'll uh create that in super bass in a second insert content and user so before we add the image we're just going to do content and so user type something and they submit that so here in supabase we're going to create a new table call it posts and we want row level security so people can't just do whatever they want in the database so add a column user so we're going to link that to the users so this is like the built-in auth users and we want to look at their email so we're basically just going to use the email as the username and identify the person with their email so email and then we're going to have some content which will be text and you want to check these here you don't want it to be nullable so a post needs to have a user and some content and we'll come back here and add images later so save that and then okay so now we have a post table that's great let's go to the oh which one is it another one yeah off go to policies and then new policy okay so kind of like twitter we're gonna make the read access available to everyone so you can just click this here use this template select true so it doesn't matter under any condition anyone can select anything um i think you don't have to be logged in okay and then another policy insert access for authenticated so you do need to log in if you actually want to create a post so i think that makes sense so use this template insert off that role equals authenticated that sounds good now here it gets a bit trickier with update so we're not going to implement any update functionality uh but you know theoretically someone could take our public key and our um basically our superbase config here and like make their make their own app and you know start updating and deleting and stuff even if we don't allow it through the ui someone could just like manually with super base code um try to update or delete stuff so we want to say enable update access for users based on their email well actually we don't even need a template maybe let's just say nobody can update anything and nobody can delete anything so no updates i mean maybe we'll allow delete but no updates so if you want to update uh allow operation false okay so i think the difference between using and with check is like um you know i'm updating something so i think one of them is a condition probably using that gets checked before i do the update like with the current row and then with oops with check is checking for the the the new content that i'm updating it with i believe i'm not sure but that's why there's two because there's something before you've updated it and then there's something after you're updating it we're just going to say false false so no updates okay that's okay and then new policy okay and it will delete access for users based on the user id i think that makes sense so you can delete it if it's your own post so a post though remember so here's the email one off that email equal to email here we're going to use this but we need to modify it a bit so auth.uid uh and i'm not an expert at this so um you know hopefully this is right but um you try it out and test it before you do anything crazy in production or anything but i think this should work to only allow users to delete their own posts so off dot email equals user so this is the posts remember it's public.posts and we created a user column which referred to which is a foreign key to the user user's email the users okay so if the use the person that is trying to update this post email equals the user uh which is an email then allow them to delete well it really should be all probably they could update if they wanted to but i don't know which one would take precedence okay anyway save policy um and there we have for our posts okay so now let's actually create the code so create post we have added this service here create post let me um okay let's get the actual daisy ui component that we want to use so we want a forum text area i think we just want the normal one that's here let's take that and we want a button and i think that can just be oh let me change theme to cupcake because that's what we're using yeah i think we can just use one of these ones here let's see okay so below the text area have a button and that will submit this form so on submit prevent default equals handle create post okay then here in scripts we want to import create post from lib slash services this label wants something so what would you like to quit and this feels a bit unnecessary i mean maybe i should just not have a placeholder and put this here then it's like two labels i don't know but let's make this one maybe a little bit bigger to text one excel four equals post and we're going to bind the value post content okay and let's import that into our index here so script import create post from lib slash create post okay let's see if it's showing up on our page okay there it is here the button can you can say quit that show with and do we want like a a header or something right here welcome to twitter and let me put this in a span uh i mean hmm actually preferably we have like um maybe i say header and then rather i was gonna put in span so i could put a button in the h1 but i think this is probably better i mean do you put an h1n header not positive but then we can have our logout button here [Music] button okay it's just doing that because it's doing like hot module reloading i think and okay yeah it's a very thorough video i usually try to go faster but just gonna go as quick as i go so header flex justify between and let's make this one bigger text to excel oh yeah open the twitter logout what would you like to quit okay cool um and that's that's fine we just need to actually add the post so handle create post so function handle create post okay and now we're going to do that thing again where we have a promise so create post promise equals promise.resolve like this [Music] and we're gonna put await create post promise and actually we're going to do this a bit different basically well let's make this required also sorry i'm kind of putting these in random places but uh the the elements but that's okay okay so required um basically we just wanna we want to block we want to disable the button when we're waiting so we can we can keep showing the form and text box text area i think that's fine but we just want this button here to be different so while we're awaiting we're going to show a disabled button disabled like that and then okay and then there's going to as a response be some data or there might be an error just like before we're guaranteed to get something back it's going to resolve it's not going to throw an error it's going to resolve and then in here we can check okay did this create a post with some data so the data will be the new post and or is there an error so if there's an error we can just show maybe let's see what do we want to show like right below it let's put that error component that we made before so import error from lib slash air.felt so if there's an error it'll show right there otherwise we can also show like a just like before um class text green 500 or was it 600 successfully created post maybe i should yeah maybe i should have made a component that handles this data thing too just like error but anyway okay so if there's an error if there's data just reminder what error looks like so if there's an arrow show it but otherwise it won't show up okay so create post promise await so while it's pending we show this disabled button here and just in case someone like undisables it you'd say type i mean i guess they could get around this too but it won't submit the form if it was for some reason not disabled um doesn't really matter but okay so we await this great promise so when we create posts we want to say create post promise equals um create post so again we should okay we got our post content so user is going to be so we have that you get user function you just return supabasa.user just so that i don't have to import superface everywhere and then use that i can just import it from where i'm importing these other functions so back to here create post so user is getuser and then the content is post content so content and user okay so from post insert content and the user those are the two columns we made and then it'll return back to us the data and or the error well or they are not both okay so let's see if that works i get that error a lot and if it does work then we'll see a new row in our post table so now we have nothing okay this twit is uh grid okay um that doesn't make much sense okay so insert so here's what the error looks like violates foreign key constraint post user f key okay so the issue is that i passed in the user but i need to pass in get user dot email now yeah okay i think that's fine i think this will work okay cool successfully create post and there it is i think this will work so the question is like what if i said like i hijacked as a bad guy at aol.com he's the actual user of this and i tried doing that bad guy okay so i can't do that because uh this is the same error i got before okay yeah i guess because i need as i'm using spelt mess i'm using spelt mastery email right now so the only value that could possibly go here is my own email otherwise i get an error okay so that seems like the row level security thing is working for that at least okay cool so now we have the posts it got created let's make sure that last one wasn't created yeah okay so now we want to actually create the post down here so how do we do that we can well first of all we need a post so post.felt like that let me look at my notes again so that is going to consist of these services here create like and create comment so when we're looking at a post we can add a like and we can add a comment and it's fairly similar so similar structure so it's just like this like const data error away superbase dot from the name of the table and then insert the data that we want to insert okay so we're going to create a like table with a post and a user so come to superbase and a new table likes it seems like they need to be lower case um i'm not positive but i was getting some errors when it wasn't so we also want road level security at column so basically a like we're just gonna let people add likes not take their own likes away so you can add you can give someone a bunch of likes if you want but they're just sort of anonymous likes that is being given to a post so we're going to link this to users and again let's use their email and that cannot be null so user and post so we're going to so this post refers to our post that we made and we can use its id and we don't want that knowable so it might be if this is your first time doing this it might be kind of confusing what's going on like i can name this anything and that will be what i use to insert right here but i've linked it so superbase knows that whatever i pass in here is the user's email and whatever i pass in here i called it post it knows that it refers to a post id um so just it takes some time to get used to that if you're new to this otherwise it might be super easy for you if you've done this a lot okay so i've done something bad it looks like let me see a user post maybe i was just talking too long and then it didn't like that relation likes already exists oh okay okay so i don't know what that was a bit strange hopefully you don't get that error it's possible it's like oh wait there's no columns here okay let's just add the columns manually so this is another way you can add a table so i just add the table with nothing there but now i can add a user primary key no add foreign key relation yes so it is again the user's email that we're going to pass in okay and not nullable well this may be nicer anyway you can see everything it's not it's not all in crammed in column user relation likes already is this oh it does it now okay okay yeah they're there okay yeah that first error we got i'm not sure what that was about uh maybe it's because i did i don't know i didn't go through the flow exactly right but uh it's here now so it should be fine for you so those are likes and let's do a comments as well so let's see if anything happens add column so they'll be the content of the comment which is just text okay it's got to be have something in it and then there's the user that did the comment same as before users email and normally i probably wouldn't use the user's email i'd use like an id maybe but i'm just using email because i'm using the email as like the identifier for the user but in reality i would probably let the user like pick a username and use that but this is just a simple example okay so user and then post that this comment is for so like yeah for example here post we're using the id that makes sense okay save let's see if we get it if we get that error nope okay that's what should happen um okay cool so now we have likes and posts and we have these functions here to create a like and to create a comment so let's go to post which is so on a post that's where you can create a comment and a like okay so what does a post look like let's go to daisy ui and go to card and let's see which one do we want to do um what looks good you can choose whatever you like but i think i'll choose this one here this looks simple enough i mean that's kind of cool yeah maybe i'll do that one got a nice got my color okay so i mean in reality maybe i choose this one but just for fun i like this color so let's do it okay and let's change this to something more semantic like article figure image so what does a post have so what are the props for this export let's get an id um actually what does it have let's see it's got an id a user that posted it which would be the email of the user it'll have some comment content and it has some likes default will be zero have some comments default will be none and then we might get to this but public url it has an image that's another option or maybe i should just call it image but i'll leave that we'll come back to that uh maybe okay sue this is what we need and here we're going to say if public url then we'll show the image okay but we're gonna get back to that uh this later and it would be nice to somehow know what to put as the alt you can make the user um like annotate the image when they upload it but uh for now it's just gonna be the source like that okay so we got card body accent color so what we're going to do is say user which is their email says and this will be the content right here okay and then this button well let's see let's see let's put this um let's put some posts on the page so we can actually see what it looks like so here in index what we want to do is import post from post.felt and somehow we're gonna need to get those posts and render them here so a post will be an object with all those things in it these things here okay so how do we get our posts we need to add a service for that and this service is going to be a bit more complicated because we need to not only go fetch all the posts we need to fetch all the likes and all the comments for those posts so i don't know if i should just copy and paste it in or um well let's see let's start with the first part so let's just go one at a time so it's going to be export async function get posts okay this first part here is um so from posts get get all the columns so before we were inserting but now we're selecting so it's kind of like sql get get all the columns and then we're going to order them by created at um so ascending false yeah basically get the most recent ones and limit five so you get more if you want but right now let's do limit five okay if there's an error here so normally i would just return them that's fine like that but the thing is there's another step which is getting all the comments and likes so but if there's an error from this first step then we want to return that error with so that would be empty and there would be an error um okay but let's say yeah so it has comments and likes so it's gonna look like this so it's a bit confusing but let's try it out um so this is going to get let's take this up for now can i no um this is for the image let me just take that up real quick we'll come back to that okay so promise that all data.map so for each post so data is all the posts um for each for each post go and fetch i got to promise at all okay so fetch these uh fetch the likes and fetch the comments so this promise dot all refers to all of the posts and then here this promise.all refers to likes plus comments and the reason we do promise that all is because you know you could do a wait get likes and then await comments but it's a bit slower because the comments you're fetching the comments is waiting for you to fetch the likes but you can just do it at the same time so promise that all lets you do it at the same time so i'm doing it for all the posts at the same time and we're getting likes and comments at the same time so and then this one will resolve oh this one here will resolve into here and this one here will resolve into here okay and then if we had the image it would go there into there okay so here likes we have from likes select id it doesn't really matter what we select we're just trying to get the count so it could be star maybe i don't know it's fastest but just get count i just said estimated because i assume it's faster than exact um and you don't really need an exact account for the likes it's not that big of a deal and then head true this means we don't actually care about fetching the um we don't care about fetching the row we just want to know how many likes that's all we don't need to actually go and get every object every like object we just want to know how many okay and get it where the post um the post column equals post.id so for this post which is right here and same for comments so select all this time we do care about the actual content and everything uh equals post post id okay so that will give us um the uh count which we will call likes and the data which we will call comments and then from that and we might want to get an error too so like um likes error but uh that's getting kind of tricky i don't think we can go into that right now so yeah you might want to do like a try catch and then you would get error likes error and then down here after doing the map you would throw an error from and try to catch it but yeah that's that's kind of complicated so let's not worry about that right now but yeah normally there would be some error handle but we are just mapping so each post we want to keep everything that was in post originally but we want to add on to it likes and comments and then eventually the public url with that that's all for now okay but that is only for mapping the data so now we have the map data which we added likes and comments to and now we can actually return it so data and error so when would there be an error i guess yeah i guess we would populate error if there's some kind of error that we get from here we could make it be the error and then make data null or something i don't know but we're going to assume that that works okay okay so that is getting posts that's was a bit complicated but here we go just stick with me so to actually get them we're going to use something from svelte kit um context equals module actually i have a snippet for this so let me just use that okay so this is going to run before the page actually loads or i mean it's going to run before the page loads so what you can do here is fetch data and then use export let posts for example and we can um so we don't need like a loading spinner or anything it's just when the page is loaded it'll already have this data that we're going to fetch here in the load so here would be import get posts from lib slash services so posts well maybe data error equals awaits get posts and then we can return post is data but let's say there's an error we want to say yeah there is error so post error so if error well i guess we can do like we did before with the error component let's just pass that error in there so if there's an error it'll show otherwise it won't and that's fine uh and if there's an error there won't be any posts so we can just say so there's no post it could just be empty and we can use an else here so else it'll show this block if it's empty so no posts okay let's see if that is working cool so that was that post we made a while ago yeah this uh it doesn't look it's kind of bright should have done the other this one here um but whatever just gotta stick to what i've committed to okay so here we're gonna have at the bottom we want to leave a comment or we want to leave a like so let's go back to post card actions will say flex or maybe it's already flex but justify between so this will be likes i guess we can do that like so likes equals zero then we want to say like or no if it's one we want to say like otherwise likes so zero likes you can click that and then we'll create a like every time it gets clicked so that's that but then we also want a place to leave a comment so that's going to be similar to what we had before for the magic link form input let's like this one i'm going to do with space because when you're leaving a comment there's not much space and oh wait it's working fine there huh so that means anyway we're going to use this one but you can try this one too connected okay so this will be for leaving a comment and again let's make that a form so leave comments let's see if that looks right uh with space we don't need it to say that maybe say your thoughts okay i mean it looks a bit weird maybe but that's fine just needs to work so uh also let's give this article a bit of a margin top okay cool yeah so right below or where should we do it it gets a bit tricky well let's start out a bit simpler so we need to import the let's import these here create comment create like get user and then we're going to have okay we have our likes equal zero so here on click [Music] let's say add like let's add a function function add like so it's just going to automatically update on the client let's say likes plus equals one and then create like and it needs to know the user which is actually user's email so this again this is a bit confusing but this user is the posts user this user here is the actual uh person who's using the app right now their email so user and then post is going to be id you can maybe think of a better way to name these things so it's less confusing but um that's how that will work so let me see i think that is fine for adding a like let's see so i like it wait like like like like refresh it oh eight likes uh maybe it's because i refreshed it too quickly oh here we go yeah it's because we never set up the likes authentication so policies so likes um yeah we can just real quick nobody can update or delete a like i think that's fine so just real quick we're gonna do enable read access to everyone and you can only create one if you're logged in okay cool and then for comments um anyone can read them and then you if you want to make one you have to be logged in okay and then here so if you want to update it it needs to be i mean you can make no updates also but it probably makes sense so off email equals email so let's see a comment will have a user that left the comment and you might want to give it like auth.user yeah if auth.email equals user or [Music] auth.email equals i don't know how to do that though you have to get the post the post user so if someone leaves a mean comment on someone the person that left the post could delete it also uh but this is for update so they shouldn't be able to update uh okay so you can update your own and then new policy delete so if off that email equals user okay there we go so now if we come back should be able to like them um yeah and now it's still there hi cool okay then i refresh six likes this one has more likes that's i mean this is such a good post so this one needs more likes okay so we have posts we can do likes now and it saves now let's leave a comment so for the comments yeah sorry i'll just need to like maybe copy paste some stuff here so comments we're gonna put where did i put them before uh we'll put it underneath the part actions and then to create one um let's see yeah just because running out of time here so yeah okay so i'm going to paste this in it's the same as we had before so just leave comment um so there's a create comment promise then data error if there's data they created a comment and you say thank you otherwise else if error there's this error here and then um otherwise we just show them the form for filling out the error or for filling out the comment so here this should say comment uh we don't need a placeholder okay so let's have a let comment content equal that um this is kind of bothering me let me just because we created that error component so let's throw it in there import error from lib slash here okay great and then we'll have a create comment let create comment promise okay and then function add comment which will be uh so create comment promise equals create comment and for that we have so it's similar to this here we got a user and they have a post like that and then we also just have the content which is common content okay and after we've created the comment we can say dot then data error we want to actually add this comment onto the screen so data dot comments and then we want to make sure we pass on the data in the error so that this can get it still i think that'll work let's see okay i was doing it like this before add comment okay let's see if that works hi cool bad wait why can't i see anything huh that's weird it's probably because the color of this is white okay i really messed up by choosing that card let me just real quick get this card instead text center i wonder if there's a quick if there's just one pg accent maybe we don't want accent text yeah maybe i can just remove these and it'll be fine okay hello there okay just disappeared if i refresh it's there okay well that's got to be good enough for now so you can try to figure out why there's that error but um i think it's fine for now another thing is do you notice it kind of does this weird thing uh that's because we have server side rendering on so it renders it on the server but then like when the javascript kicks in it gets added for real and it triggers those animations so i think for now it's fine to just turn off ssr so the page won't actually load until it's ready it's just like uh let me restart okay so it still does that it's just it doesn't there's no like initial state before that i wonder why there's space here not here but whatever that's fine okay so we've got likes working you can add stuff bad it disappears i do want to know why it's disappearing thank you so if data data error is there no [Music] huh comment i don't know okay well let's move on uh okay what do we still have to do so we can okay we want to log out that's for sure so i think we had already added the log out yes sign out so let's go index button so on click equals uh handle sign out so let's add that here function uh function handle sign out so let's import sign out from live services okay so we can say await sign out and then go to the login page which is like the home page now do i have have i imported go to no okay let me import both of these and then we'll probably want to do something like this as well on the login page so or on the index page import both of those so go to login okay uh and then oh i need some water or something okay um and then let's do that yeah let's redirect if they're not there so we need sign out we also need to get user now so if there's not a user then go to login if not already logged in okay okay so there's that um i guess we i promised images as well let me see if logout's working if i refresh okay i just misspelled something service says here we are log out okay cool okay magic link where is it okay login there we go okay cool um so let's add the image stuff so that's going to be with storage storage we're going to create a new bucket called images and we'll make it public so anything you post here will be public um and obviously you would need to be checking you know if you just let this go loose who knows what people will be uploading image wise so uh if you're creating something public in prod you're going to need to check like what are people posting okay but anyway so we have images uh we're going to have us policies so i think it is under uh storage.objects so the actual images we want to create a pilot um enable read access to everyone that sounds good so all of these are public and then another policy uh insert access for authenticated users only that sounds good so try that okay and now what we want to do is add a oh wait let me refresh this okay we want to add an upload file thing there so let me just copy paste this component here which is upload image so on change get file it's just a normal input let's add that to our create post so import upload image that okay upload image and let's put that right above the text area bind file so now they can have post content and they can have a file say is null so now when we create a post we want a user content and um image is this image file is this file here so upload image yeah unchange it says so if there's a file then get e.target.files at zero that's what you need to do and that'll put the file right there which we have bound to uh this here okay so we put that in image files so now in our services under create post we want to check for if there is an image file okay so this gets a bit complicated too and i'm sorry but i'll just need to probably copy paste this in let me one second it's a big one okay if image file we want to do okay so if there's an image file then in our storage so a weight superbase storage dot from images that's what we called our bucket upload so i'm going to put it into a bucket that is called whatever the user's email is plus slash so it um like another folder date.now which is just a number a timestamp so this uh should be guaranteed to be unique because the user is only uploading one image at a time so it'll be their email plus the time they uploaded it and this image file so upload this is like the key the name if you've used s3 that's like just the string the location of this file and then you can upload an image file you can also upload like buffer or i don't know by arrays and stuff but we can just do image file this i'm actually not sure what it is but it was in the example in the docs so i kept it there uh okay so it returns to us data and error but because i have data and error here i'm just going to pull data off and call it image data and image error so if there's an image error return that but then we can go ahead and create the post with the image data dot key so this will return to us basically an object with just a key on it and that will be the image and let's create that on our table post we need to actually create that column so right here we say image is image data dot key so name image add foreign key so it'll be our objects and it'll be based on the name so it's a bit confusing but this seems to work so based on the name which is the key so and this is the key or the name okay so it's the name or key of the object allow nullable sure it can be knowable because they don't have to have an image if they don't want to no unique constraint matching given keys for reference table objects uh-oh um okay let's see let's see if it did get added it did get added okay so maybe those are just kind of warnings uh-huh i don't know exactly but um now we have an image column so let's see if that actually works um yeah okay so choose file uh this one here image wow okay it says successfully created okay so right now there's no image because i need to actually fetch the image so just like in get post we fetched the um the likes and the comments we also need to so if post dot image that would be just the um here let me refresh you can see hopefully yeah so images slash the saltmastery gmail.com the timestamp that's all that's getting stored in this table so we actually have to go and get the the url that we can use for the image source uh let me show you so if there's a post that image so for these there's nothing but this one has something we are going to take that post that image we're going to say superbass.storage.from images get public url um otherwise if there's nothing we can just resolve with no data so get public url now this is a bit weird but i basically have to split it on the slash i'm just trying to remove images here because i already have they already know it's from images so i don't need to include that part in here um so maybe i could like split it and use the first part here and then the second parts um like here but basically this will just say sveltemastery gmail.comtitanstamp so that will get the public url and that will get plopped into here and we'll so now our posts will have a public url like that so post yeah this public url and if it's there it'll show it here so hopefully that works let's see oh and there it is cool so now we have this card that looks like that okay well that's at least everything is mostly working you can like it um comments are a bit weird but they still technically work i guess um another thing you might want to do is yeah when i make a post you want to see it immediately so i tried doing that with comments you have to have this dot then but that's not working for some reason oh i think it's because data needs to be spread like this i think data returns a list of it's like list and then it's like an object so i think i just need to spread it like that let me see if that works because you would have to do the same thing for ah darn no comment is not defined oops i misspelled that too okay let's see okay now it's showing up cool okay now things are working i guess it was just erroring out and i didn't notice okay and you might want to reset comment contents i guess you could do that in here like that okay so yeah you do something similar for adding the if you want this to automatically show up but for now you have to refresh it actually see it okay but images seem to be working uh you can log out you can like okay i think everything's working so that's pretty much everything i guess as that last added bonus we are going to add that cool little um 3d thing so it's felt cube svelte cubed this is super alpha um not production ready i believe but i mean maybe it is i don't know you can try it uh but it was just released so it's still a work in progress um but you can basically make cool things so there's just a little bonus at the end i'm just gonna copy paste it in uh let me see if i can find it so uh here so we're gonna add something called cubed that's here so we need to npm install three and spelt cubes you can install three spelt cubed okay so basically i wrapped it in a button you don't have to but so it doesn't take up the whole page i give it some like width and height okay so basically you need a canvas with a background and then you need the mesh which is the actual thing and then you need a camera to actually see it and i use this weird thing called porous not geometry um and then also here i've got a c dot on frame spin so spin equals zero so basically the rotation of this thing will go up by 0.01 constantly i think yes yeah scion frame is just saying like every frame do this so let's see if that is working i guess i need to actually import that import cube from flip slash cube.spell so i get that error a lot but usually you can just refresh and it's fine okay cool now it's spinning and you can yeah it does that okie dokie well i think that is everything um i know i sort of rushed through things but um i gotta go so that's all uh hopefully i can edit it a bit and make it look a little better but please like and subscribe and please try out superbase and that is all for this very long video goodbye
Info
Channel: Svelte Mastery
Views: 3,437
Rating: undefined out of 5
Keywords: svelte, javascript, web, development, frontend, front end, tutorial, learn, coding, programming, design, framework, css, html, css3, html5, es6, sveltejs, svelte.js, js, .js, svelte3, svelte 3
Id: mPQyckogDYc
Channel Id: undefined
Length: 75min 40sec (4540 seconds)
Published: Sun Nov 28 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.