Building a Linktree Clone! (Next.js, React, Tailwind CSS)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
we're gonna build a link tree clone using nextgs tailwind and versel Edge config but really you could use any database or any data store here the focus is going to be on trying to replicate what linktree provides really quickly in a nexgs application so let's dive into it so we have our create next app scaffolded here just a basic nexgos application and I ran next Dev to start up our server on the right here and the app that we're trying to build I just went to linktree and picked a random link tree so we've got Selena Gomez here it's it's a pretty simple app but it can show some some cool things that we can do so we have a photo we have a name and then we have a list of links some social media accounts really you could represent this entire thing as a Json object like this doesn't need to get that complex but you don't want to have to necessarily redeploy every single time you update content so you want to have some dynamism to it so maybe what we could do first is just to try to almost replicate the quote-unquote schema that we're working with here through Json we have a name that's going to be some string we have uh what is that an image which the image could be is a good question on like where we want to host the image but let's say we're gonna do hmm do we want to do one local in our application or do we want to do one remote let's do um we'll do a Twitter images for this or really any Avatar here then we've got links and this is going to be an array of stuff and there's I guess we want to keep it really simple there's a title URL let's see how much how much will it scaffold for me come on give me some give me some more here uh sure I mean at the at its core that's probably as simple as it gets although I would argue that this is kind of separate from socials um and Twitter GitHub yeah we could continue on that path but let's go with that so then let's make these links a little bit different let's do um my personal site let's do oh I don't know we'll do the Purcell website sure okay so I mean that's like roughly a a very basic Json schema of what this thing could be the the the very simple database a good old-fashioned Json file link image URL what's this question on whether the link should be an image or not yeah I think this will be uh um let's do copy image we could just do Twitter images here oh my gosh no uh yeah we can do it like that that should work okay let's how responsive is this thing let's go back to our app and let's start building some UI oh he meant the image displayed on each link yeah that's a good question we might want to have some kind like this is uh an optional field in our schema um there's not really that but I want I wonder if that's a actually a valid I guess I could just for the sake of making this work I could do that potentially so you optionally have that image yeah something like that could work okay so create next app scaffolds out with the Pages directory um do we want to do Pages directory we want to do app directory I'm open to either and we're going to want to set up Tailwind so let's go ahead and do that I'll just get rid of my Dev server and we're going to install some dependencies here so I'm using pmpm you can use whatever you want so we're going to do PM I these dependencies and then we're going to emit Tailwinds which is going to set up the files we can copy in this Tailwind stuff here and then we need a global style sheet let's do I'm just going to delete the CSS module we can do I'm just gonna I'm gonna ditch all the Styles we're going to start from complete scratch and yeah do I want to do Pages dry cherry or app directory let's do uh we'll start with pages and we could refactor to app directory later happy new year thanks for hanging out and joining um okay so that should be everything we need to set up Tailwind um we're importing our Global styles uh that's fine okay let's let's cut everything let's just cut it all um and we don't even need to do anything with fonts right now and we'll use image later so we'll just leave that here so we've got our home page and let's make sure tailwind's working as we expect I guess I could just copy this entire thing okay that should be fine I think so let me restart the dev server how many times I've set up Tailwind this year I've set it up a few times definitely a few times okay it works I could just start with the example if I wanted to like the actual tail one example that's pre-set up sometimes it's fun just to like manually do it to make sure I know what I'm doing so yeah it looks like it looks like this is set up correctly as I would expect let's let's start building out this UI so we're going to start with we're going to start with some div and this is going to be Flex item Center justify Center actually um we'll just do item Center and we're going to have an image in here we can use that next image now oh well whatever that's fine could you use the new app directory I certainly can actually I think what will be fun is I'll build this out with Pages just for the sake of it and then I'll move it over to the app directory and we can show a little bit of both um we've got a source image we're going to have probably like feel like maybe like 48 that's a decent guess of what that's going to be and why is this complaining oh it's complaining because I think I'll tag uh let's pull in our our fake data here too so we've got import where it's going to call it data from data.json I think that's what it was so we have we'll do the alt as data dot name data dot Avatar with Heights cool nice okay now we need to say hey we want to be able to optimize images from this location this could be one of the places where it could get a little tricky because if we're going to allow arbitrary images from arbitrary places that makes it kind of hard to have an allow list of where you want to optimize images from so let's just roll with keeping the Twitter image for now and then maybe we'll refactor that out later but yeah we can do it like this or we could switch to remote patterns if we wanted to as well so this is saying hey you can optimize these images from Twitter if you want okay I'll restart the dev server cool so that's that's too small let's do um let's do 120 and let's throw class name on here of rounded uh is it full yep round it full we got a perfect we're gonna do margin wait not not full margin uh margin um X Auto so it should be centered but I think this is probably going to have to be with full the parent might need to be width full as well too what's a package manager I'm using pmpm right now um yes so what do we got here the uh [Music] Flex item Center margin X Auto uh um is that not getting width full what am I doing here with full yes larger than x Auto hmm it's the little things what are we what are we doing here did I sometimes I feel like I always get item Center and justify Center flipped like it's so hard in my head to make sense of them they're too similarly named okay so this is our wrapper let's do margin top uh eight or something 16 Maybe it's actually a little bit smaller here so maybe we'll do 80. Let's do an H1 uh font semi bold this is going to be Avatar dot nay or sorry not name data.avatar thanks for the shout out for the people who caught my justify Center um yes data.avatar that's a oh there's a good question here about um turbo as well too let's see if whoops that's not what I wanted let's see if we could use um turbo repo as well so I'm on the latest I'm using we don't even need re-electric mode in here anymore I don't think um it's it's that way by default in the app directory um if I go to package.json I do next Dev Dash Turbo I don't need any of that there's this like this has been like a like almost like uh once you see it I can't unsee it like the fact that you you don't need name or version or description or author like any of this stuff when you're not actually publishing the package I kind of wish it would just default to private true because like I'm not publishing this package it's just I'm only using it for scripts and dependencies okay so next Dev Turbo um let's see if it's working cool that works so turbo pack here is just for the shared cash benefits if it's not a monorepo uh yeah slight slight clarification not using turbo repo using turbo pack through next.js13 so nexgos 13 allows you to essentially replace webpack with turbo pack which should give you faster uh hot module reloading or faster updates when you hit save so it's kind of nice um we probably want to do another I can probably close this does it matter we probably want to do another div inside here um that looks like a more bold font let's do uh Flex direction or is it well it's not Direction is it Flex call was it yeah uh now I think it needs to be item Center that's where my brain was was off okay let's do bold instead here we'll do margin top of four uh text 2XL no Excel sure Flex call yep okay how we looking uh it needs to be a little bigger but the spacing looks directionally okay so maybe uh you know what why guess when I can just check amazing 96 and what's this this is a 20 point size 20 point size cool 96 text XL that's pretty damn close let's roll with that okay now we have we have a name we have an avatar we want to iterate over our list of links so let's make a new function link um card I guess this is going to take a next link well wait no no no no not going to take a next link because these are not internal links so good old-fashioned a tag is when you want to link to anything next link is when you want to have those fast client-side uh Snappy page transitions between pages in your application since this is a link tree and all these things are just going externally we actually don't want to do that we just want to use good old-fashioned a tag trying to see how much I I was just really curious to see what styles co-pilot gets me by default like what what does it think a link tree looks like I guess we're gonna find out um and I also don't remember what do we have title URL and image uh I guess I mean href is a much better name for this title URL title wait title href image um yeah href title image okay that looks fine let's do can you maybe move my webcam a bit oh duh [Laughter] that's funny yeah that would probably help wouldn't it uh considering it's directly on my what I'm trying to show uh let me let me do that or I think what I could do well now let's move it cool that should hopefully be better okay so we have Link Card we want to iterate over these we're going to do data dot links dot map that takes in a link and we want to have our Link Card component the key is the href yep probably not going to have the same link two different things and then spread the actual link object over the Link Card now it looks like it's messed up the syntax here somewhere probably missing yep just missing that and I think Link Card is going to need to be defined up above here that looks okay uh um what is it here I think it's typescript being like bruh what are you doing because image is optional href string title string yeah yeah there we go that's that's the default styling they give me come on what are we what are we working with here my personal I can't even spell my Perron soul my parental site okay um that looks fine let's refactor this thing so that it looks a little bit better let's start with um we'll make this margin y so that there's more margin in between here actually we Pro looks like we need more than that so let's do margin bottom 40 or something is that right yeah uh uh oh wait sorry I'm looking at the wrong thing um I want it here margin bottom eight yeah okay so these these cards we're going to do rounded small no shadow was there I mean I I guess everyone can have different styles like I think everyone can customize their own link trees to look a bit a little bit differently but we'll just go with like kind of a basic traditional style here which maybe it um maybe it does this get a little bit bigger when you hover over it so sure um let's do hover scale 110 transition all okay padding I yeah that's fine with full um probably need a border we'll do uh we'll do gray 300 and we would probably want to have a little bit of margin between them maybe something like that [Music] um yeah the question is this entire container probably needs um a little bit of X padding maybe eight oh I think round and small is that not a thing is it just grounded medium that looks okay yeah that's all right I feel like the font size is too big um and the text needs to be centered as well too so let's go back into here um font Bowl was it bold no it wasn't even bold it's it's actually maybe semi-bold that looks yeah now we're talking that's not bad oh scales actually maybe a bit much I think 105 was also an option nice nice um um let's do check Center we'll actually do it up or I mean I guess I don't really need to have all this extra elements in here like it's probably unnecessary well I guess if there's going to be an image in here optionally then yeah we probably do want to have an extra element because the image is always going to be aligned left but then this this other div if you think of this whole thing as a box has it's text centered in the middle so maybe let's do let's say that this image could be um we'll do we'll just copy in this image here and we'll do this is probably going to be maybe like 40 at most for the sake of it I'll use the same image and we're going to do it like this the padding is showing here we probably want to have the padding somewhere else like that this image actually did have just a little bit of padding I guess hopefully I don't know if I'm talking too fast so tell me if I need to slow down as I just flying through stuff um let's do rounded small that yeah that looks okay looks all right maybe a little more it's fine okay so we've got an image this is going to be title and this is image and this element what does this say source is not attainable it's not assignable to type string or static import source is not assignable to type string okay that doesn't make any sense definitely is string uh um the expected type oh I think it's because it's undefined that makes sense because what we really want to do here is say that nice um and then we want this to be with full text Center is this whole thing with full oh that's interesting that's interesting I didn't think about that so the the width Center the width Center of this is different than the width Center of this so it's like oh that's gonna get that's going to get interesting on uh mobile too because I wouldn't want to put a placeholder like 40 pixel block here because then when you get small enough that's actually not going to work well so we might want to do like hmm you could do like a calc like minus 40 pixels um or I guess you might change the layout entirely on mobile I'm not sure let's find out what happens here do all of Selena's ones have images oh they all have images interesting okay I wonder if it's do you think it's automatically pulling these images from the open graph image like let me like rare Beauty here right okay let's go to open graph and let's take this and let's drop it in here and what are we working with what do we got here yeah no never mind this is different so it's not you know magically pulling that in there even though it's similar it looks like they must be manually choosing what image they want to go in there that's that's interesting while I'm at this width I'm also realizing that it needs to have it needs to have okay so the the cards need to have a little bit of a of a background here we can probably put some some color flare on this soon but for now let's just do like background gray like 200 or maybe oh even even 50 is like even 50s kind of a lot I don't know that I like that it looks kind of like um I wonder if I should stop and figure out a fun gradient background let's do that Tailwind gradient backgrounds there's some website I remember seeing that had a bunch of different fun oh yeah this one hyper color some cool Tailwind gradient backgrounds so I want something that is real subtle oh that's kind of nice okay yeah let's see what that looks like um so this is actually going to be on probably the body what is it mad about oh it's saying it's the same thing um I wonder if that site is out of date oh how to refresh I was gonna say I wonder if that site is out of date no that's kind of cool yeah I dig it something different look okay so let's do then text white as our default uh uh we'll do oh did I did I actually put text black on this no I did it text White we'll do I wonder I wonder if I want my cards to be white so they have a little bit more so then this could be like text Gray 200 this could be instead of Border gray what we're going to do is back around White and actually I meant I meant like this like a softer Gray yeah the maybe maybe not yeah there we go that's a little bit better okay I feel like I need to fix this padding thing yet oh here we go have you used this gradient before they come out super clean nice oh so these are like really fancy gradients nice let's hmm it's kind of fun oh wow I don't think this will be in Tailwind but that's fine nice oh that's that's really nice and subtle what do we got here precision keep that there angle sure easing curve this is just fun to mess around with um sure let's let's uh let's do this copy CSS um let's let's take a look at what that looks like instead so rather than doing on my document rather than doing this we're gonna go into oh it's actually it actually uses a background image that's really interesting oh interesting is the problem it's not the problem is it's not full height and 100 isn't working 100 you height it's all right I actually don't know if I need no repeat if I just get the height right yeah that's cool I'll uh yeah I'll roll with that something different uh uh yeah let's let's let's roll with that so I can close this close this um I feel like the only issue here is that if they don't all have images it just kind of looks janky so maybe we want to make the images the default I think or optionally we do Reserve that space so there would always be like you know some some div that is uh with um 10 like that like 10 is 10 right with thought it was yeah with 10 should be 40. um let me double check this yeah it's all right with 10 height 10 [Music] . what we probably want to do here instead of text Center is let's do isn't CSS great right Flex justify Center item Center when in doubt you just Spam flexbox because flexbox fixes everything um and I could do like a calc here but I could also do probably like a margin left this this is so dirty margin left negative 10. would that work um I think that should work oh wait sorry negative 10. oh it won't do 10 as in 10 converted to on the Tailwind scale I have to actually put that or I feel like there's another way if you do this is it like is it this maybe yeah if you put the negative in front it negates large and left hand wow this is looking this is looking great let's add more data for for the heck of it next yes.org and nice okay let's do let's do some socials let's replace C let's replace CSS yeah margin left tent nice a hundred safe view height the other day which ensures they'll use up 100 of the visible height on mobile and not count on the browser UI height is that is that standard in browsers right now or is that because I know it's I know that it's a wild wild world out there to get a hundred to get 100 hype accurately represented across web and mobile for multiple browsers and I think this 100 um safe View Heights or whatever it is I think it was being proposed to be added to CSS maybe it's only on like a chrome experimental version but yeah it's wild I wish it was uh I wish it was easier so I'm glad that they're doing that okay we're looking pretty good uh we probably want to have a Max width as well on these like Max width yeah let's do something like that okay so for social sound the bottom we're gonna do we have Twitter and GitHub right now so let's find some oh here we go can I use nice well that's cool that's interesting um let's do a oh we got we got a Twitter icon in here no um let me steal my Twitter icon from my other site so I'm working on a new version of my portfolio and I already have a Twitter SVG and a GitHub SVG there so let's just I'll go over and I'll try to find that let's see uh icons Okay so let me just material UI material UI icons are the best yeah I am working on a new one simple icons nice uh um it put in a bunch and for the sake of it I'm just gonna drop them all in here so what do we got here Twitter icon just an SVG and how what color it takes current color okay GitHub icon cool So Below oh I don't need this views icon either so I've got Twitter icon Gap icon So Below this I want to do data dot socials yeah data.socials.map and let's do um yeah I guess what we could do is probably just do this inline where it's like oh here we go here we go we'll do so Twitter icon do you think he'll figure out it's nice how it figures out the pattern that you did before so it's like oh this is clearly what he's trying to do okay so if socials includes this do a Twitter icon if it includes GitHub do a GitHub icon these icons need to be bigger for sure uh um yeah how big were they decently sized here maybe rather than like manually that's a good point like maybe rather than manually doing that Let's do let's do simple icons or that's an interesting thought using modularized Imports what a material UI icons what do these do these have have them all as well too oh my gosh they have 2 000 icons it's insane simple icons where oh here we go uh uh Twitter oh yeah they have all of them too is there a I don't know if there is an npm package for it but hmm awesome hat oh yeah I've used font awesome as well too yeah let's do um we'll make these a little bit bigger and we probably want to put a bit more margin around um I guess the way it's set up right now oh is that too big that might be too big uh that's fine so what we could do is put this in here put it in a div and we'll do class name what is it Gap there's like uh or grid try to think of I think it's Gap is the one I'm thinking of when I do like four pixels in between each one Gap one Gap two let's do Gap one yeah those are definitely too big now looking at them uh so let's do 30 and this is like what like 24 or something uh uh that's a bit better the Gap one's still it's like an optical illusion almost that it seems larger than the Twitter one um and then let's go here and let's do margin top four well what did we do we did margin bottom eight from the header to the these cards so blue margin top here and then I don't even need on the icons themselves I had the margin right two I can probably remove that because that's what the gap is doing for me and then let me go back to Gap gap for nice nice now I guess the question now what are we missing do I want like a a footer down at the bottom or anything probably doesn't matter um this is fine this is good enough for now let's do um let's move it to the app directory since that was something that folks were curious about so this is a good example of um kind of incrementally moving things over in this instance there's only one route but it shows a good example of like I have this underscore app file that's kind of my Global layout I'm putting Global styles for the whole app and I have underscore document which is setting up the Lang for the language tag on my HTML setting some body styles right and then I have the index so what if we want to move this over to the app directory which the docs for this are on beta Dot nextgs.org and there's this nice little upgrade guide in here as well too that tries to help you Move Along throughout this journey right so the first thing is you have to enable the feature inside of next config so let's do that and then we need to make a root layout so in our directory we have the pages folder this still exists in xjs 13. you know it doesn't go anywhere I'm on next gs13 right now but we also have the ability to make a new folder app and this is essentially how you opt into this new world so I'm going to go in here I'm going to make layout.tsx and this is the new root layout for the application and it takes in a child some child prop and it's interesting when you compare these two like it's just a much more clean way of magically you know making the layout work it's like oh yeah I have you know I have some HTML I have a body and it takes in some children this component effectively replaces app and document because everything in app runs on the server by default as a server component um I can get more into the server client component difference but so what we can really do is take this style sheet and I don't need anything else from here and we're gonna include that and then in document we had what Lang equals English and then we had the body class name which actually don't think was doing anything which we already have here so yeah we can just get rid of both of those and then this index page slight difference slight differences in how naming Works kind of an interesting thing but pages everything was an index or blog or about and the actual name of that was was what resolved to the URL in the app directory everything has the name page file and this is important because you can Nest routes and you can have some funky folder names if you want and everything inside of there you can put Styles you can put tests you can put images page dot whatever TSX is what actually makes it a route so I move this to here let me just nuke pages and we're going to rename this to page and I think that's that's pretty much it uh let's go back over to here refresh the page oh I might need to restart uh oh yeah because I changed the settings oh is my path wrong let's see app so if I go back up styles Global CSS that seems right maybe possibly unexpected token oh did I put something in here oh I don't know I don't know I don't know what is this oh I know what it is classic Tailwind mistake um and my Tailwind config I need to also include the app directory because these are the styles that it's actually looking for content to look for um all of the Tailwind class names uh it is now converted the only difference I see is the icons are black because there was that text white class on the whole page so what we would want to do is actually go back to here and because the svgs are taking in current color they're going to take whatever text color we pass in here so now we're on the app directory that was pretty easy um what if we wanted to move this data to something remotely that'd be kind of cool Let's uh let's let's do that I'm gonna let me go and we're gonna go to my GitHub and is there a difference in terms of the final page weight between pages and app when you import well first off is there a difference in the page weight between pages and app um app currently has less client-side JavaScript than pages and because it's using server components it actually scales better when you have you know 100 different server components they all run on the server so none of that code has to be sent to the client side that helps keep that bundle small for only the pieces of interactivity that you actually need so let's do um let's do link tree next JS clone it's not really a full clone so I I don't wanna I don't wanna you know overdo it here um what else do we got in here is there anything else let's do this post css5 I'm just quickly looking through and seeing if there's anything that we wanted to remove oh we could do uh we could do a custom font as well too since we're already here uh um I need to do um one other thing that would be good to do before we actually push this up would be adding some meta tags so right now the way to do that is through this head file this is likely going to change but it at least works for right now uh uh again the app directory is in beta so we're still figuring some things out we we want to really find the best possible way to do meta tags and SEO data and we have some ideas on how to make this even better so for now um we'll just do it like this we'll do description um next Js plus tail end CSS and favicon I want the viewport uh I think that should be everything because then I can get rid of I don't need I don't need any of those I just need the favicon page layout meta tags and we're in business okay let's push up an existing repository from the command line and then I'll restart my Dev server okay still still running locally I've got some code in here um that looks fine let's move this out of the repository and into something that I can dynamically Fetch and we're going to use for cell Edge config for this so let's make a new project um we're going to go to my account link tree we'll call it link tree next Js uh the way let me just pull change log let this deploy here the way that edge config works it's pretty cool let's see if I can find uh the changelog for it it is a kind of unique data store it's not a database it's not a key value store it's for Json data it's for configuration data and you can update it very quickly and not have to do a redeployment to actually fetch that data so it's kind of nice it's kind of cool um we're kind of abusing it for the sake of what we're trying to show off here like um oh I didn't I didn't commit my code um I should probably do that um link tree so I deployed create next app but okay we'll we'll push up the actual deployment here um I'll kind of show you what it looks like so you see Edge config here I am going to create a new store um I'll call this link tree and so it just made a token for me and it stored that in a connection string that I can use so let's do that um it's kind of nice it gives me the instructions here on what I need to do to move forward so I need to pull in the environment variable environment variable to be able to actually use this locally oh that's not what I want um so we're going to link this to our remote project and it's in linktree LOL existing project what's the name of my existing project uh just link tree is that right nope link tree next.js okay ah so I want to pull this environment variable down and I want to install this package so I'm going to do pni at Purcell Edge config cool and then inside of my page I can import this git so get some value from the key value store and it essentially looks something like this you're able to await getting something by the key and we could we could say this is um uh data or like link tree or something so let's take this since we're in um well actually let me go into the page here so this is the this is the home page and I'm just going to comment this out for now but what I'm going to do is actually go in here and I'm gonna take this data.json and what we're going to do is we're going to copy this we're going to call this link tree and then we're going to paste all of this we can format that save it cool that looks good okay that looks fine let's go back to our local project what I'm going to do is delete this data Json rip I'm going to go in here and rather than importing data from day to day data.json we are going to fetch it using server components so by default this page runs on the server components and when what that means is I'm able to change this from export default function to export default async function now I can just do async away and fetch data directly in my component without having to use the static props get server-side props or similar so we're going to do a wait get link tree was the key and then this is data and this should hopefully work we're gonna find out somebody yeah when I switched to pmpm I had to make an alias I could not I was so used to yarn even yarn I don't know I I had that aliased as well um this less character is the type PN PN does it work Ed um some kind of esm air because esm causes problems everywhere it's probably an issue with turbo pack which is an alpha it's an alpha everyone please and uh so let's try it without um no it doesn't so maybe it's not a turbo pack issue I think I know what it is um I'm actually not sure why the instructions there said to do VC poll because I need an environment variable so I can run this locally and this is kind of a quirk of it's kind of a quirk of Versa I probably need to get this fixed but I don't want VC Pole I I want vcm poll I want to pull the environment variables into emv.localfile and it's going to pull all the stuff and I have an edge config value um another cool thing about Edge config is you can actually just go to it and see the Json right so okay like this looks like what I'm expecting um so let's oh no let's do this again maybe this time is it gonna work this time there we go now now we're talking okay that was probably the issue it probably wasn't turbo pack I think I threw turbo pack under the bus I'm sorry turbo pack wasn't your fault you're you're great just kidding throw it under the bus done I was wrong not it was a combination of both looks like there's a esm thing still that's gonna have to be resolved you gotta love you gotta love it it's always something right what type of data is the data variable now is it any good question yes it is um this is just an any so I think we would want to probably that was a nice thing about having that Json locally is that you were getting that validation of what it was so now we have to you know we have to do this and this is going to be a link uh it's name Avatar links that looks about right or or use Zod yeah I could use some kind of uh schema validation here I think I think regardless I would have to type it in some way because the the any there is not is not great what's not working with it oh uh it's because I typed it wrong oh my gosh I need to get I should use the folding thing oh why can't I it might be my stream settings but I can't click and collapse this Twitter icon GitHub icon but whatever um I think what we actually want is this and this is data and this is oh yeah they're socials too oh man oh man oh my now I gotta type all these brutal brutal it worked so good when it was local now I have to define a schema maybe I should try maybe I should look at uh doing something else here foreign typescript I wonder uh it's I guess we could do some kind of error handling here like uh there's a um there's a has inside of edge config I wonder what's I wonder what's the best way to do this what's the optimal way because I could do if no data if there's no data and this didn't work well we've got problems it's time to throw an error or show an air screen um maybe we maybe we should do that just for the the sake of demo here um let's do that we could do a error boundary here or I guess it's not even necessarily an error it's like if if this doesn't work we might as well just like redirect or go somewhere else like if we can't get the data but I don't know let's let's see what we're working with here um I guess the question for me is do I want to display an error or how do I want to handle this hmm if there's if there's no data just redirect it to Selena Gomez let's do that so this again this runs on the server so the kind of wild thing about this it kind of breaks my previous react brain when you look at code like this because you do an async await in the component if no data you redirect kind of wild that that's like a thing that works but it does if no data redirect to Selena Gomez uh uh oh and it looks like I'm missing a key somewhere in here no I could add these types here we'll say this is a social and this is It's shouldn't it shouldn't it figure that out shouldn't I not need to manually type that you'd think I don't know uh this thing I guess we could put a key on this it's kind of a this is kind of a weird thing that I'm mapping over this and then doing it like this normally there's like a wrapping element and then that wrapping thing has the key on it but we could do we could do it like this either way okay now it's not yelling at me fixing all that stuff because it's complaining because data has no type oh good point good point I shouldn't even need to do this once like this shouldn't even do this because I should be able to say how I I guess I don't know the answer to this how do I add the type now do I just do it like this and then now that is types of Scar types are smart enough to know that okay if there's no data that means that down here it's yeah it is smart enough to know that nice sub nerds sup Theo we're just we're building a link to a link tree clone and I haven't checked my DMs so I'm sorry I've just been I've been uh coding away on the most basic site ever but it's been fun it's just an excuse to code something today and yeah actual next actual link tree does use next.js which is kind of funny um the we're we're we're talking about typescript so this could be a good place for your expertise I've typed this data that I fetched back and what I was trying to figure out is okay if there's no data we're just going to redirect to Selena Gomez's because why not uh and then it magically figures out that the properties below it are social or links so I think we just have to make this data type allow undefined so it doesn't yell at me like that I guess that works oh yeah the chat knows the chat knows yeah what uh what we're looking at here is we're using Edge config for cell Edge config just for the heck of it to put this link tree data as remote Json essentially so we've got a name an avatar links socials and we get this stuff back here what I want to do is actually so in in the app directory in server components it tries to make data fetches static if possible so if you can essentially take a some Fetch and make it static well yeah let's do that and then you can opt in to make it Dynamic if you want what I want to see right now is if I simulate a prod build um because it this is I think something that stumps people up is if you change your data source and you're running next Dev it's still going to refetch data on every single request oh app page exports a invalid Twitter icon GitHub icon field I probably still had the oh yeah why are these exported uh Twitter icon where's GitHub icon oops don't need that okay I'll do a build and then I'm gonna start the production server locally which I don't know I could just push it up to myself I really wanted to but let's just do this for the sake of demonstrating here so I've got this it's the same data I can refresh as much as I want I should now be able to go and hear change data and if it is dynamic when I update this I should be able to pull it and it looks like it's not so it looks like it's it's optimizing this to be static so I think what I need to do is export Dynamic oh that's not what I wanted uh export const dynamic equals and it should give me that the typescript plugin here is going to give me the options we want to force this to be dynamic like run rerun it every single time and fetch the latest data and let's see what happens it tripped you up because it's hard to see when fetches happen without the Chrome inspector yeah I want like nexjs Dev tools to tell me what to happen here that would make things a lot easier when fetch happens in my terminal it's harder to bug yeah I feel that I do feel that okay so we get the new data but will it fetch it dynamically on every request it will okay that makes sense that makes sense so export cost Dynamic Force Dynamic here this is essentially like hey whatever data fetching you're doing on this page this is SSR like this is the effectively the same thing as run this whole page SSR I don't want to have any granularity now the reason it's designed like this is if it's kind of future forward thinking it's kind of a future forward optimization is because in the future in the not so distant future you might be doing something like this you might be doing write me a promise let's see I promise all with three I know Theo that's promised at all stop just write the code I don't need a hundred comments okay I'll just write it myself uh uh I guess my point was in the future you might be doing something like this and one of these is fetching static data you're you're changing the perception from a All or Nothing my page is static or my page is dynamic like there's almost three spectrums to this there is Frameworks who think about data completely static or completely dynamic they either say you render the entire thing server side rendered and that's the only way to do it or you have other Frameworks who say static is the way that's the only way you should run your application everything else is bad then there's others that are in the middle that say well you can do a little bit of static you can do a little bit of server both both are good both have their trade-offs if you want to do a single page app you can do that too that's fine the way nextgs has worked in the Pages directory is you can do that on a per page route so my home page is maybe static my dashboard a client-side app another page server rendered and that flexibility has been very beneficial what's super super cool about the afteractory and it has not been explained at all so far uh working on it is that it's now at the fetch level it's now at the data fetch level so this one could be dynamic this one I'll actually pull up the docs here so it's a little more obvious um so this one could be dynamic this one could be static and this one this one could be ISR it could revalidate static content every 10 seconds and that's wild you can have different different pieces of components on the page that some are static some are Dynamic some are updating their content and not have to think about your entire Pages like well we got to render this whole thing from the server it's kind of wild it is absolutely very wild and that's kind of like one of the next things we're going to be talking about a bit more at the app directory it's just to be honest it's like we haven't got there yet part of the reason for that is that you have to have caching infrastructure that understands how to do that right you know traditional infrastructure thinks about things very black or white like should I cache this page on my Edge should I not cache this page on my Edge um it's it's a newer way of doing things to be able to have it cached that dynamically uh so yeah that's a long wave a long way of me of me saying this should now be dynamic so yeah yeah yeah we could probably also do runtime equals Edge and let me just make sure this is still working it is still working we're going to just push it just push the code uh and I'm curious to see how that works oh my OMG this is very powerful I missed it yeah it's it's pretty cool I feel like we just we honestly just haven't talked about it very much uh slowly very slowly getting around to that I could probably there's I feel like there's so much of the after app directory yet that has been yet to be realized um just because on one hand we're still you know fixing bugs making things work listening to community feedback but also there's so many other features to be built yet uh you know Advanced features or new things on top now that we have this new base you can kind of almost think about app directories like a framework in a framework it's like next JS you know Super Galaxy brain version but you can still use it within your existing setup and you can incrementally adopt it which I think is pretty cool I think it's pretty powerful um yeah let's go uh let's go check our deployment here linktree LOL just push it just push it uh nice we have a link tree clone clone it's it's pretty simple but it's an xjs site with Tailwind fetches Dynamic data renders some links renders some social profiles if anything it was just fun to watch me struggle with tailwind and next yes so I I made it it took a while but we got this we got this side out uh thanks for hanging out see ya
Info
Channel: Lee Robinson
Views: 42,124
Rating: undefined out of 5
Keywords:
Id: eFzNekhVhmM
Channel Id: undefined
Length: 80min 10sec (4810 seconds)
Published: Sun Jan 08 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.