Page compositions in Next.js with Uniform Canvas and the Jamstack
Cable management in Next.js: creating compositions with different headless sources with Uniform Canvas in Next.js.
Transcript
hello everyone we are live oh this is scary man yeah man my eyes are moving oh wait are they falling were you looking not sure what ai is doing to me but it's good fun your eyes and disagreement with your brain exactly um as happens pretty often to be honest all right so let's see if i can find something that's a little less distracting this is yeah it's a bit much wait i'll stick to something like this or that this is the best i still like this one the most i'm analog dude you you you digital and analog it's it's a nice exactly balance it is and the funny thing is i'm in a place where everything is analog in the french countryside and you're in a place where everything is digital in like california so it's it's kind of a strange combination it all fits yeah awesome so how about um what let's talk about what we're going to do today how about you kick that off yeah let's see so a lot of next year's excitement has been happening this week next gs12 is out a bunch of new features on versailles is available so why don't we have some fun with that since yes that's getting some some traction attraction and love and um yes let's see how we can uh take a vanilla next js app and wire it up to a uniform canvas and in terms of why what we want to achieve is turning a static page that you get by default from next starter into a content driven page so we're going to wire it up to two different cmss through uniform and we're going to add personalization on top of that with tracking and we're going to deploy it to versailles with edge functions running edge side personalization mode so we're going to alternate between client-side personalization running locally and edge side personalization and then see if we can empower creation of brand new pages without code changes so that's gonna be our goal today how does that sound it's a pretty intense and also lots of stuff to do and i'm really excited and especially and because it's all this new for sale stuff like they came out with this like two three days ago and we are basically full-on ready to show everything we do with it which hopefully will be best will be impressive let's let's see if the how the demo effect treats us yep but i'm assuming you're going to be going to your life exactly lots of things coming together yeah what could go wrong everything and nothing i love it [Laughter] all right let's get going yeah yeah share your screen and let's kick this off all right sharing the screen boom how does that look that looks great how about you start like this yes exactly cool so here's what we're going to do we're going to start with next js getting started page uh we're going to use uniform and we're going to use contentful and content stack i already have some content in these headless systems i'm gonna be altering between um the um docks our own docks and um some notes i've been taking so just to streamline uh this process of putting things together so yeah exactly all good but everything that you'll be seeing here you'll be able to do yourself uh though the vercell edge functions is just game out so we we have internal support for that so that will be coming out very soon yeah but you're able to do the same with um cloudflare uh workers or netlify edge handlers if you have access to that so this is not uniquely available in versailles but because this is so hot we gotta try that yeah this is like fresh off the press man i'm ready let's do it all right so let's get uh let's get our brand new nexus up going here so i have i'm gonna run this in the console we're gonna use live stream live live to live so for all the people watching while we're doing this feel free to ask any questions if something seems odd or we're making typos which alex never does but who knows um feel free to comment and see what's up here okay so we're gonna go create next app did you just do that yes we just did that so cool we're gonna cd into our live stream demo live and then we're gonna start vs code on that and see if we can get the app up and running so let's check out dependency so we're using hot new next gs12 and check out how fast it is yeah that's what i want to ask like this startup is that webpack 5 or is that rust it's all rust baby 3.1 seconds cold compile yeah that is something like for me what is interesting though is like they didn't go to something with es build but they just made the webpack thing faster i think it kind of makes sense because everything runs there anyways and it runs so well right nothing breaks so yeah good yeah it's awesome [Laughter] so yeah so we're gonna start building stuff here um what do we have here so we have um single page uh this is what we're showing here see if i can do split screen here if that's too small how's that is that okay that looks great let me just make this a little bit bigger maybe yeah exactly yeah because normally that um react app should be responsive so a bit more code yeah all good so this is what we're gonna do we're gonna turn uh this code into code driven by data by content um so first and first we're gonna split this page into two components so we have component number one here and component number two this grid they will live in the separate components this will make our lives much easier right so let's go ahead and do that uh see i'm a terrible typist here i'm gonna call it hero jsx the more often you go live man the the better you start typing yeah we should do it more often so i'm creating new uh react component here where i'm rendering exactly the same markup and because we have two tags here the same level we need to wrap it into fragment and this is our extracted hero component so this means we can just replace this with hero and hopefully maintain the same sort of experience except for the styles so we need to bring our styles into hero so we had to do that there we go so balance of the unifor universe restored then we're gonna take this grid out and do the same thing for the grid i'm gonna create new component called grid gsx component call it grid because why not and we're gonna replace this with the same markup we probably need to drag our styles into the grid as well because it's referencing some of the home styles and grids now we we just replace these hard-coded jsx in here and actually refactor two components so yeah this will help us a lot as we move forward for this so our next step what we want to do is control placement of these components outside of code so what we're going to do create these two components in uniform and we're going to use uniform api output to render out these components based on how they placed on a composition so composition is some it's a structure that describes how to compose your particular page a particular portion of the page so we're gonna model these two guys in uh in uniform so okay so maybe for the people that are watching that don't know us just yet because they came for all the next magic can you maybe give a like a bit of a global overview of what we do at uniform and why this is actually super cool to put into this stream yeah thanks tim yeah so what we do we we're providing the first tool composable digital experience platform it sounds like a lot of buzzwords maybe to some but it sounds magical [Laughter] uh what what this allows us to do is use headless technologies best of breed headless technologies and turn them into a digital experience platform so essentially allowing marketers to compose pages without code and to use personalization a b testing on top of those pages so developers keep using the tech that they love like next gs um we're not controlling how you build components completely up to you so you have the same freedom you've been enjoying in the headless cms context but you business users get the value of being able to visually construct pages whether it's landing pages product detail pages if you're in the commerce land maybe it's screens for mobile um so these entities are channel agnostic that we call compositions compositions built from components um so that's the that's bridging the gap between these two worlds through components right so components will be modeled in uniform as entities created by business users without code and mapped to your react or view components depending on what you use in your code base yeah so generally how i try to explain it is imagine you're a developer right and you're you're building all you have all these headless sources and you connect them up in your front and you make a jam sex site that's lovely everybody likes doing that because you can choose exactly what you want and then you have these content editors and marketers come to you and say hey i have these five products and i have content from this system and content from that system can you just make me a page tomorrow where you connect everything up and then developers are like uh no i am mid-sprint how do you expect me to just do that and so generally you do because you're a developer you like to do a good job and you figure it out but wouldn't it be nice if you built this the correct way once and it just works and then you get away from that feeling of annoyance that you don't that you have to build this thing while you don't have time but there's also annoyance on the other end like content editors are like oh but i can never do what i want and now you can because we make this thing where you can connect all these headless sources together in one place you can drag and drop stuff and then on the front end it's one sdk and you don't even have to know what these sources are and it just kind of works really easily and so that's why we want to show you this as well on top of all the fancy next stuff because it works so well together exactly exactly yeah that's pretty much the technology stack uh we have available we have more integrations we have integration with salesforce cms as well it's just not featured here yet but yeah you pick your integrations we do the heavy lifting of pre-wiring all those integrations for you and providing business user an interface to create these structures that will be powering our pages so you have options at any point and here i can actually select multiple cmss if i wanted to so for this demo i'm gonna pick two um i can also add commerce if i wanted to but maybe that's for another live stream and we're gonna of course use next sure so here we're entering the process of establishing connection between your uniform project that i just created in this guided setup and either you can create new space or you can link to an existing space in contentful so i already have some content in there and that content will drive the heroes so i have three of them already in there so be able to repurpose that content and since we want to show you the power of choice you also have a choice of adding another cms maybe another cms on your existing project this is honestly like if you have never seen this this is pretty insane we are literally connecting now to multiple cmss that in the same interface you can grab content from and then compose with yeah exactly and for content stack uh since we don't want to duplicate content we're actually going to model our grid items in in there and these green grid items up we're going to be powering this list so every tile is modeled as a entry in content stack so you see our documentation with title tags and uh there should be a url in here so thank you hisham for your comment by the way i'm just jumping in in between because it's so cool if people actually interact with us means they're watching yeah well you can learn as you call it as well right of course but if you wanted to say hey dude why don't you just do sitecore we might do it maybe not this stream but who knows yep anyways so i'm gonna uh save these for later this will be api keys we'll be using for our project moving forward and um so at the end of the process we have project already wired up with all these integrations so we have uh three of them canvas is actually one of the integrations the platform so i can add more later if i wanted to but we have two integrations for cms so let's get started with those so first step as you remember we have our components so we need to model these components as a first step so first component is called hero everything is managing component library under canvas uh so we're gonna pick a cool icon of apple watch because why not okay sure and the hero is what is hero rendering heroes rendering some title and some text so that's what we're gonna we're actually gonna start with uh without uh a cms so we're gonna just model them as text fields and this will allow me to show you how to switch from uh cms to cms so these these types these are just basic text primitives storing title and text for hero later on we're actually going to link it to a cms so that that's for later so that's our hero then what else we have we have a grid right yep and is this one of the nice candidates for using slots here because we have items inside the grid right oh yeah okay i'm a little bit ahead i'm sorry then uh we're going to need to have a third component type that would actually be representative of our page but we sort of don't have to do that so if we want to turn component into composition we just can toggle this box and what this means is that i can now create new compositions from this component called hero so you don't have to start with a page if you want to swap out one component of your existing app with a composition driven component you can i'm going to call it home and you can see this is the canvas editor and we have single because it's a single composition a single component composition we only have hero in here so we cannot add other other components we will get back to that in a second but hello world will do here for content and i'm not gonna publish this yet so this is now in draft setting an entity we called home composition it doesn't have a slug you don't have to use a slug and now we can pull that in into our app and see whether we can render this data and the actual hero composition so in order to do that i'm gonna go to our tutorial and i'm gonna switch to the section called fetching data from canvas and i'm going to start importing our sdk yep before we do that we kind of need to install the packages don't we would be nice so npm install canvas canvas react because next gs is using react and cli cli might be optional actually at this point well it could be that you have it globally installed right so yeah so we got three packages yep and now we can start let's restart our server and then we'll start bringing in canvas client into our index route so yeah and so this canvas client basically provides the sdk to query our services right that's what this thing does okay yeah i tend to just narrate to make it myself understand and hopefully then our audience will do the same because i tend to under narrate well you're you're writing code man that's fine that's why we do this together we'll do this together so you can see uh canvas client is instantiated here and we need to pass api key and project id here uh so are we gonna go like living on the edge and copy paste or we make an end file okay nice yeah let's let's yeah right yeah let's do it right envy.uniform api key and this one i think is called uniform project id this will allow us to connect to the client we also have another api host a parameter here and api host will be helpful if we're gonna connect to do a proxy layer which we'll talk about that in a second so we're gonna fall back to uniform.app oh oh uh in here but in case if we override our api host we can actually reroute the request to a tbd location so let's leave it at that and there's two ways to fetch our composition one is get composition by slug but we haven't used this log so we can use git composition by id and pass the id of our composition which can be just retrieved from the url oh yeah so there we go thanks paul for for the night's mask we have to do something right honestly the lo-fi version is actually better like the real-life one but yeah didn't always work nice nice so so what we're getting here is the composition from the response and we're passing that into the props of our home page so that means we need to pick that up from here so we can render it and let's render this outside of sorry inside of the main tag so we're gonna do yeah just have a look at this composition right exactly just let's let's spit it out see what happens see what happens oh boy i just clicked one and i'm in a pool of blood oh while we have a 500 error i'm in the pool of my own blood wait i'm gonna have to change this probably need to restart the server after the nvidia file is added oh yeah most likely that's it minor details in our details um composition not found oh did you publish haha that's that's that's the question isn't it that's your question so what if because i didn't publish we can pass the state here oh yeah we can do a state for draft exactly the draft and there it is so we got our hero here the name of it you might want to zoom in a little bit if you show it like this yeah there you go cool there we go and this is we have our parameters yeah so what we can actually do is render this out in uh slightly different fashion here so one ways to for us to retrieve uh these properties title and text is to use the composition component from our sdk and we're going to use render process to get it out so this is open position and instead of doing it raw we're going to do something like that hey robert did you just come in to say you're not going to be able to watch thanks dude thanks for coming in anyways we have the suits on just for you man do you forget i'll stop here there we go yeah there we go it works hello let's do split screen again it's more fun you just retrieved your composition and inside you get props title and text from that composition basically right so we're gonna get it rendered out here title and text and this is an extra semicolon got somehow trapped in there yeah i saw that as well ah there we go so can you show how this looks in yeah this is what i wanted to know so you're getting your parameters back from your composition now and that's what you're showing that's our yeah parameters in here we also support hot reloaded preview so that can be enabled on top of that but we'll we'll have to do control re refresh the browser refresh that's fine so that's uh that's kind of getting this data raw that's how it looks like using render props but um can do much better than that uh why don't we create the actual reference to the components that we already have right so we don't yeah because you just created grid and hero so we're working on the hero at the moment right all right let's do it so we can do that but uh we we will also need to change things up a little bit here because right now we cannot place any other component in this composition it's a single component composition so this is where we're going to need to create another just full screen here another component type called page and this will be our proper composition so within that page we're going to host multiple components so we need a slot to be created for that slot is a place to host multiple components yeah i can configure my slots here i can do let's say i want to host grid and hero and in future i'll be able to personalize an a b test right and let's just leave it at that i i don't need any other constraints i can put more constraints in place but totally optional so here let's put uh some sort of icon it's always the challenge of selecting your icon but you're doing it pretty well it's like you research the icons muscle memory yeah exactly so why don't we now recreate our composition that will be slightly different composition type you can see i now have page in addition to that so we're gonna turn this into a home uh sorry turn into a page composition type we're gonna call it home and here you can see i have this content slot where i can drop more components here's our hero here's our grid check this out so i can add any number of these if i wanted to in future and you can drag and drop them around right so you have different order and stuff yeah cool exactly so we kind of reconstructed this so the id has changed so i need to update the id um where we're referencing it here oh because you made a new composition because it's a page now yeah so now it's okay full flash page and because of the shape of this composition it has changed so we we do not actually see anything here because we now have slots right so these slots this is what the actual structure of composition looks like you have slots content um and then within you have an array of these components hero and grid so this means that we need to adjust our code in order to render out our components so for that well first we need let's go into our code we're gonna need to change this this is not gonna work for us no because now you have this you have the slot now so you need to find the slot and then show the data exactly so if if my page itself had parameters like title and text they will be rendered so i can bring them back here text of type text so you can actually store maybe you have metadata parameters hello world coming from the page right in this case the the code will uh render out our our components here and our title and text but um just not gonna be able to do anything with the hero and the grid so why don't we change that so we're gonna not use this and we're gonna use another piece of sdk called slot and we're gonna match the name content so now in this case slot will be able to render us hero any number of instances of hero and grid component once it's placed but it doesn't know where to find them well it needs to find the components itself right exactly yeah so we need to give it uh composition also have this function called this param called result renderer and we're going to need to bring that in as a function okay let's consult so in this case this is just rendering component type a name of the component and not the actual component just yet so let me wire it up now there we go we have a hero and this is a grid so we can just use the component type that it's showing yeah exactly cool so we actually we don't need that so we need to return more something along these lines where we actually interrogate component type and if the component type is hero as it is set up in our component library we have this public id this patch right then we're gonna return it the hero component but this means you have to import the hero as well right exactly exactly actually i'm learning react while we do this this is nice hero where's my hero yeah that line two and three there you go uncomment this out we have a hero and then we have a grid and we just restored the original functionality of our but now structure of this page is controlled by uniform so if i go and reorganize stuff let's move grid up refresh oh yeah that works well cool so we're cooking we're cooking okay what else we're not rendering the actual data yet no exactly because we have data for all these items in our cms systems so now we're going to have to do something with these components right so we get those title and text i know they're on the props so we can essentially just replace hard-coded text with uh title and text um so we just destructure them from the props and that's that's our uh title and text here let's see i don't see world anymore though because that's why [Laughter] we just destroyed the world there you go it's oh it's halloween special so so for me there's this just one learning question here on my end when we look at this react stuff so when you import this hero component and you return it in your resolver how is that black magic happen that it's giving it all the props well it's the composition itself that will oh handle that so it's gonna sdk will just give it these props yeah okay it's gonna have a map of all components you have it's gonna know how to resolve it and it's going to push the props into them great yeah that makes it very easy actually so now we can just clean this up a little bit and now we have our basics in place uh we're gonna leave the grid as it is for now um right now we have um here a component let's focus on on that one so the content maybe it's time to wire it up to a cms because it's we sort of we need to yeah i think we're ready for our cms stuff let's do a hero right want to do the hero from cms cool let's do it so the process because the integration is already here all we need to do is create another parameter i'm just going to call it content id and i'm going to link to contentful and in contentful i have this we actually support multiple environments now in multiple spaces so you can pull content from multiple spaces if you have multiple spaces in your contentful setup so here we can constraining the selection of this parameter called content to only pick heroes from our contentful system right yeah and we might as well delete title and text because we don't need those parameters anymore because we'll be pulling from cms so alex what is your opinion here how much um stuff should you store in our system and how much should you store in the cms well anything related to your core content model that belongs in cms right so that's anything that may be related more to presentation logic let's say you can figure how many slides to show in your slider just a silly example that's more connected to the component itself and its configurability rather than to a particular slide you want to show in that slider right so slide is the core content model and then how many slides to show and how frequently maybe that's something you want to model here because that's a bit closer to the component itself so it will also avoid you to pollute your cms model with the specifics of your implementation that could change over time but your content could still be there in a more pure fashion so this means there's a true difference between actual content and presentational content that is a pretty important distinction to make yeah um definitely so here you can see we get a message that hey you have some title and text data but it's not on the model so we can just remove it because we're not going to need it and instead of that i have a content parameter here allowing me to link to my heroes inside of my headless cms how about that so i'm going to do that as a link now content content will be there we'll be able to deep linked into it we're not pulling content we're not owning your content we're just referencing it so if we look into our source instead of title and text we storing a reference to a given entry in your given integration means that we're gonna need to have uh an additional process we call data enhancing that will actually go to your headless cms and fetch these um these entries by id so we don't want to take over ownership of content but we store this composition and what's shown on the page because imagine there's sensitive content there or you have some caching stuff going on or you're changing data we then suddenly have to become in the know of what you're doing which shouldn't be what a platform is doing right it should be opinion-less and completely open exactly exactly so this is this is what would happen if you query a uniform app directly so we're going to query our canvas api enterpoint we're going to give it a slug in this case this is coming from another project this is not this project but helps me demonstrate the the point here yeah and you can see we also have a similar content contentful entry here that's not expanded or enhanced but if we route it through our proxy which i'm running here on localhost 3333 and remove https we will get this entry expanded so we're actually going to get title and text out of contentful and available on the response so depending where you route your api to you're going to get this different behavior and so just for people who are watching this this this this code that proxy you can run that anywhere right you can actually put that on a surface function or you can run it in your own code base on ssr like it's just javascript exactly you can bake it inside of your app you can run it in your preferred environment where you run node or you can run it serverlessly wherever it makes sense in this case because i'm going to need to deploy in a managed cloud environment i need network connectivity oh you might want to do https here right yeah it actually works it opens both yeah this is what we're gonna need to do we're gonna need to rewire our app before we can get the actual data to go through that proxy setting this uniform api host will allow us to switch over api host in here to that proxy and i think you should restart this one yeah exactly because of the environment variables point right let's see what happens i don't expect us to see anything uh because structure of our props changed a bit so let's have a look what the these props look like i'm gonna so i was expecting these coming from props but because we created that uh content a parameter called content everything is uh yeah you're gonna see it inside your content yeah that's the name of the thing so we need to just to look it up from elsewhere and then this will be coming from content instead that's it there we go hero for everyone and this is actually now contentful data this is coming straight up from there fancy and we didn't even have to query contentful that was just done for us nice yeah that was done on the level of enhancer that's running yeah that's in your proxy basically that's running behind the screen yeah exactly so so we're good um we get our hero now let's wire up a content stack as another cms that would be powering our grid now the model for grid and tim you alluded to that though we did not rehearse it but you you oh sorry yeah i went with this i went a bit early you saw where i'm going with it so i want to model this a little bit differently i can model this as a list in headless cms and just reference to an entry that stores a list with grid items or i can model this with slots so in other words i can turn grid into sort of a container component so i'm gonna add a new slot here called items this can be any any other name here and i'm gonna pause here i'm not i don't have the actual component to render an individual file yet we actually need to make a grid item component still did i just take you completely of course with my comments no no that's that's actually what we need to do yeah course corrected me uh i forced corrected you it's because of my outfit yes so now you can see uh we're picking from content stack and we've seen grid items here i'm going to make it a required parameter i'm going to call it content as well as we did before sort of via a convention and now i can now allow my component to be placed here i can do it from my grid container or from grid item i can actually click allow in a slot and pick grid container component and pick a slot where i'm expecting this component to be placed in that's a nice quality of light feature just right there because otherwise you have to click around all the time too many clicks yep okay so we have a grid additional slots so check this out i can add one grid item documentation i can add another grid item examples i can add another grid item learn and let's add a fourth one to deploy so this is referencing these entries and these entries will contain our title text and url which you can actually provide here next yes uh xjs where is the learn start learning learn basic let's put this link in here so we have some link oh yeah exactly cool there we go so now we have the content we're referencing this content now we should be able to render out this grid but now the grid renders our uh completely static stuff oh yeah okay no good so what we're gonna turn this we're gonna extract this individual components into kind of smaller units or atom level components yeah cool and i'm gonna just pull it out from the um yeah you already made these probably it's easier to copy paste i'm just gonna copy paste exactly it's perfect we'll save us some typing time what we have here we we change our grid or to use a slot because we have a slot called items and then for every uh component we're actually going to rendering the grid item here directly so we have a choice of going through the function called render resolver and actually going to register grid item here if we wanted to but if you don't wanna mess with this you can actually manually if you know what kind of component you expect here to be rendered you can just render it out through render props yeah you can choose your own children basically here right exactly exactly okay not much happening just yet not much happening why is that did you publish or no it should work right even if you don't save i didn't save oh not even oh okay no living dangerously yep say and now we have completely layout driven position here i can move things around let's say let's move our deploy first and what this allows us to do is essentially personalize and a b test individual elements here if we wanted to so if you want to allow that capability that's not the benefit of modeling it this way inside instead of grid i can actually allow personalization a b testing by just picking those components yeah and now check out i have personalized this and a b test this so if i do want to personalize tile number three i'm able to do so if i model that as a list inside of my cms it might be easier to compose because i i just i would pick an entry and the level of the grid right and cms will bring me the list the array of grid items but i won't be able to personalize um element individual elements i can personalize the whole batch the whole list but not the whole not not individual grid items so you have those options how you want to model this depending on how much flexibility you actually need so now what where where are we we have completely content driven [Music] layout consisting of two components sourcing content from two different cms's and now i can create new compositions which we're gonna do later that is going to power a brand new page so that's um actually maybe maybe we should do that maybe we should do that just to show you another reason to go there i'm gonna bring another page definition this will be a slug page definition oh yeah sure this is gonna be just a copy paste of index with exactly the same code but it's going to have an extra function here um called get static paths so actually going to query canvas for all compositions that have a slug and they will be powering new pages that want to create outside of our code in other words our compositions could start driving page structures on your site again if you wanted to so i'm going to create another one called about us and drop a hero and select hero for architects give it a slug called about now what i am expecting here is that going to slash about would render our route and our component there it is fancy i love when things work so easily that's good you are well prepared so that's stage one complete we have completely cms driven [Music] app with dynamic components and everything is controlled by business users without us needing to make any code changes well that begs the question can we do more than this can we start personalizing what happens always do more alex you know this exactly let's do that let's personalize something let's personalize our hero so i'm going to click personalize this and i'm going to create a couple of more variance here i'm going to pick one hero for architects another hero will be for developers yeah and then here i'm going to need to tag these particular variants with a different intent before i do that i'm going to call this um a hero personalization container because this will be uh we'll be able to identify events and analytics related to different personalization activities so we're going to make sure we have a human readable name for this you can see we have three variants but there is no way to associate them with any intents so intents allow us to target our content to to give an intent so we have one called developers so let's create one intent for developers this is going to be we have a bunch of different signals that can resolve this intent the easiest one will be added query string d equals one we can control the strength of the signal so every time d equals one is added to a page developers will get a score of a hundred strength which will resolve this particular intent so while you set up the next one let me just quickly go over how we do personalization because we don't actually do rule based stuff we don't really have segments or personas and things like that we look at intents which is basically when you go to a website you have an intent on that website right you want to buy something or you want to read about developers or architects or both and we actually have some sort of scoring based system where signals that you give off like clicking on a link with a query string or having visiting a page will basically signal your intent and we figure out based on your actions what we need to show and what your intent will be and then we do do that with scoring and so the only thing we would have to do is kind of tag these components with whatever intent they are for and then the user will do things and we will figure out what they want and then show them the right stuff and we can do that without talking to an origin server which is really cool because this is basically blazing fast personalization that was the shortest i can explain it i think but here we go yeah and how having those intents here allowing us to associate them with a given variant right so we have two heroes architects and developers so things are set up but our app if you imagine we just added canvas sdk we haven't added uh anything related to our personalization a b testing it's the capability we'll call optimize so that needs to be added on top of that because it's it's optional so if you don't have to personalize you don't have to you can just use canvas directly but we want to so what i'm gonna do here i'm gonna bring a couple of more pieces of my uh little cheat sheet project so here we're gonna add a couple of more we're gonna need to add a container uniform container so we're going to replace the existing implementation of the app js file with the one that has instrumented wrapper around all of our app we're also going to need to add a couple more packages here yeah so this this wrapper around this provides a context for our tracker to figure out all the signals that users are given and so then it becomes much easier to to kind of figure out what content to show for the personalization exactly so just add a couple more packages related to tracking tracker is the one that orchestrates everything that we have in our system and you can see i have navigation component globally added here and this will just allow me to link to navigate between a home and about so just a little facility here on top of that we have a couple of lib items that i need to drag over and this leave items let me bring the whole folder yeah just put the whole folder there's a couple of extra helpers there that we'll get to in a sec i guess so the tracker itself uh is gonna consult this manifest file that we're going to pull with all of our personalizations a b test definitions that will be bundled in your app so there will be no runtime calls to our backend for it that's just configuration data and then it's important to configure where the actual tracking data is stored you have options you can use index db local storage external system and since we track everything in cookies again this is first party cookies this this this will allow us to persist some of the scoring that we're matching and you can see i sneaked into little edge handler this is this is for the last piece oh yes we're going to do some first cell etch stuff exactly uh also we need to bring that manifest into our system so i'm gonna add a new npm script that will allow us to pull it in so i'm gonna call it manufacturer from cli oh something's up there i think this was a previously copy pasted version let's see i broke my package.json file that's great oh extra comma at the end extra comma at the end man there you go yeah um manifest is actually just contains the definition of how intense that we just created in ui so this is something will be bundled in your application again this is not visitor data this is configuration data and we should be able to just do yarn dev and then see if we have our app rendering now with personalization in place so we have here for everyone you can see chrome extension is lighting up meaning that personalization is active and there is some intents available allowing me to simulate what happens if i match developers well get hero for developers let's hack some stuff what if i match developers but i'm on the architecture architect side now we have hero for architects so personalization is working because everything is running here this is all running client-side on hydration time we can also run it server-side if you have server-side rendering setup but in this case this works hydration time and server set rendering time together i guess uh which is fine but we wanna after we deploy this app we actually wanna run it at the cdn itself and execute personalization in there but as a gem sex site right initially yeah so static site that will be exported uh so why don't we go ahead and do that you can see uh all right we have um a couple of uh things we need to change so first we need to change the output mode to edge because we expect it to run at the edge instead of running in a traditional ssr client-side rendering setup and we're gonna need because we're doing versailles we're gonna need to add another piece of the puzzle uh which is called middleware gs this is extra page definition if you watch the nexus conf you'll be able to recognize this so this middleware takes over quest response for our app that will be running on vercell and it will activate our handler and this handler that's tucked away here in the lib folder this is the one that actually going to perform the job of executing personalization on the page so the page will be pre-rendered static but it's going to be modified before it reaches the browser with only the portions of the page you're supposed to see based on your context so that's a that means you can add your own stuff if you wanted to here to maybe do other scenarios that requiring edge edge functions besides that i think we also need a custom document uh here and this custom document essentially uh renders our default state for us and it facilitates sync between next state and what happens on the server side so somebody that is happening um because i'm just learning about next here that is happening only for ssr related stuff right it's like your base page that has all the information for the render yeah okay i think we need to add a little bit do you have to um install the cookie storage stuff perhaps yeah we need to cut and have a couple packages because the edge stuff is separate package we need to pull that in on top of that and see if anything is broken well still starting so let's say so is it running through the edge already but locally now locally exactly so nice let's let's go ahead and i don't like this warning let's oh i think your grid items need a key property because you're looping over them ah that's all right that's all right i learned to ignore this for now oh really i've had well i'm bold for a reason because i've had like huge projects where for some reason the caching was so weird and the things that we did didn't work and it was always adding a key so i i tend to just add them anyways for this it's not no biggie yeah since we approaching the hour mark let's go ahead and make it build exactly and so we're now actually doing um ssg right here this is doing uh production build right so yeah i can start up this server and it's going to run ssr on 3000 if i wanted to oh okay so this is actually a proper ssr okay cool [Music] now on top of that now let's uh let's try to deploy to resell so i already have uh this will probably gonna ask me to create a new project we're gonna see how they go so i can essentially specify the values of my of my environment variables here that i already have so this is my api key don't look don't look be quick be quick oh this is really only api key as well so okay i could just do this while you do this no i'll put it back guys this is only a read-only key so not to worry all right set up new deploy sure pick a team existing project no project name yes now this handy cli should be able to set up our stuff cool i think we need to override anything let's just see this cli is decent man that makes it so easy and as you notice i have dash dash prod so we're actually going live with this command of course we're going live should have tried this differently but it's fine is this going to be on uniform.dev no [Laughter] no it's going to be on on versus domain exactly it's all good uh you can actually stream logs here is uh oh npm uh-huh uh-huh uh-huh one more thing i've been missing uh some of the oh yep special sauce uh private so private special sauce that sounds a little uh halloweeny shall we say [Laughter] it's a special sauce so npmrc will allow me to pick my environment variable for npm token and use that to download private packages uh we need that for the edge edge stuff yeah exactly all right we're building see if anything happens in our cell here oh actually is there an oh there it is but this is your install issue again so it seems to not be able to find our package there interesting is your npm rc host key on your uh path that might be the thing the npm token and if it's not on your path you might just want to type it in there but that's not one you might want to share yeah that's fine so why don't we uh let me figure it out i think but a local install is working however so that's pretty interesting oh do you have to give the npm token to um for sale perhaps probably yeah and you can probably give them an environment variable probably i thought i thought it would pick up from the npm rc but because it's running the build elsewhere probably that's not oh it that could be exactly all right so i'll be back in a second cool you're just adding that stuff to for sale now yeah yeah that makes sense so we still have six lovely visitors and fewer so if you guys have any questions for us um feel free to inject if not also fine we're just here having fun going from scratch to something that is actually very decent in like an hour which is in my opinion quite unheard of um is if you see how much we've done so that's pretty cool so almost there alex are we good almost there nice i wish i had elevator music but i think that's probably not allowed yeah we need some sort of standby music or something yeah i'll just do it like this so just for people tuning in we're actually uh there it is um working on oh let me just remove our elevator music working on adding our npm rc token to for cell so it can actually build so let's see if it works now let's see it looks like it looks like something has compiled yeah that's exciting stuff we just don't know what perhaps an ex-worker it seems to be working serverless functions created in 646 milliseconds not bad using beta middleware all right beware be careful it seems to be working oh i think your build is done at least production so production and what happens so this is we are developers oh it actually works and so this is basically personalization on the edge without javascript right or is this still with hydration uh it should not require javascript let's disable it let's see what happens oh man this is the big moment oh we're still architects okay so that means that it has understood to personalize this little bit without javascript on the edge with the new for sale workers nice so um alex would you mind pinging me that url so i can put it in the chat yeah you can have a look or just go on slack or something or yeah here private chat put it in here we go yeah we are live very very so if you do d equals one that's developers a equals one that's for architect let's see how fast time to first byte is for the document did check this out 16. three milliseconds 63 milliseconds well there's not that much on the page but this is proper fast forward personalization i love it now it's uh now it's two seconds for some reason um let's attribute that to for cell edge handlers better yeah no see now it's loaded fast for the first time well for for me it loads really fast i'm looking at it on my browser here and like these pages of course are static right but they also personalize because i'm seeing architects now let me just reset the scores and then it shows me hero for everyone again it works yeah there's something in my ah i'm simulating slow 3g why not why not so yeah this is sometimes it's going over 100 sometimes it drops to like 60 70 so i think since it's still beta i think there will be more optimizations but yeah well most likely they just don't have it in too many places just yet i'm i'm here in san francisco man i'm hitting a node in my backyard probably yeah yeah you're basically just going to the edge of the street man that is something and we did this in one hour and eight minutes on top of shenanigans with me and my crazy face not bad i think we can do it in under an hour next time yeah i'll do like this oh look at my bald spot it's really weird now okay let me just filters filters let's just not do a filter how about that so um this was great and so we we reached the hour um that was our goal we still have a bunch of people watching would there be anything we could still do alex to um you know give it a bit more fun is there anything else we could do uh what do you think i don't know maybe some can we add some commerce to this uh potentially maybe some big commerce because we have this really nice integration with them and we're partnering with them very soon releasing all that stuff so that could potentially be cool or um we can show how it works in next but that's kind of almost the same as in in next so maybe that's not the the way to go i think nox deserves a separate yeah it could it could deserve its own because you know what's interesting when next three is coming out and when it's more stable it will actually have the native serverless functions with api and all that stuff just like next has and that runs in workers and it can even run in a local browser worker if you wanted to so there's a lot of fun stuff coming with that and for sell and netlify and all these guys will be integrating with that and so next three will be kind of on par now with what next is doing so it's going to be super super interesting for me at least because i'm a next guy and so i'm learning every time i look at react stuff which is great as well and they're getting a little bit closer right so it's yeah it's now just not which one is better but it's more what is your opinion what do you like more basically and so maybe we can do another stream a bit later on where we do this whole thing in the fuel ecosystem that's all good for me so alex what do you feel about doing the big commerce thing and if if not if it takes too long we'll just end it here and do another one soon unless someone in the audience wants to see something let's see if you have any questions if you have any questions and let's see if there's anybody watching on linkedin as well i'm gonna have a look there my internet seems to not want to work um if we don't get any questions we'll just end it here and um for me it's beer time friday night for you it's friday morning so you still have a ways to go today lots of things to do yeah i think next time let's let's target commerce knocks yeah sure that that will be fun and yeah great maybe knox 3 since it's all hotness these days no in future community and um we've also managed to make all our packages now work with next three because it's running with feet and it's doing es build and native node for a lot of things so we're we're working on like how do our esm packages output so it works in all these new modules and stuff and it's it's all starting to come together so i would be really keen to try that out anyways but that's for next time oh alex actually has a question let's put it on the screen when pushing the visitor score to death it blinks from arc to death any chance on fixing that in one minute um [Music] what could that be alex would that be our hydration potentially or maybe because it's on uh serverless functions it blinks because it swaps out content because and when it hydrates it's getting you score so essentially to avoid that you either [Music] use like skeleton loading technique so you essentially swap out component without cumulative layout shift so you essentially you cannot render component at build times if you do static site export you cannot really do that because you don't know which variance of component you need to show at that time so you exclude that and you just render a skeleton instead and then it's client-side hydration will take over if you don't want that edge side so that's another reason to use edge site with edge side there is no blink there's no content swap because that happens before browser gets html on the yeah on the edge side of things that's another option um you're gonna need to have a cdn capable of that so so far we have it working on cloudflare on netlify and vercell and working on akamai as well so that's yeah that giving you yet another option so gen generally alex the best that we would love to see is if you use an edge render to have the initial personalization in and then you hydrate because then slow devices can take some time to parcel the javascript but it's already personalized based on the cookie that they had so that's the nicest combination so we actually have a question from peter thanks for great question alex yeah it is thanks so simple question can you show what is possible inside the edge could we import another script or is it just super low level it is very low level it is essentially dom manipulation at the edge so you you can inject things in there um but it's like our library that transforms um that special script um it's it's not extensible so it is only allowing personalization a b testing to take place uh but you could on top of that you can post process uh that stream that was processed by uniform library and do whatever you want inside of that function yeah it could be maybe we do a more detailed deep dive on that what what else can you do after the fact um within that middle where you have access to essential end result and then you can post process that yourself yeah and nothing stops you from just adding another edge handler function in there if there's another api endpoint you want to use you can do your own thing but it is pretty low level right there's not that many basic imports that you get to use i think serverless functions probably even do more at the moment than these kind of things but that's all good you know it's innovation it's new um super happy to figure that all out and for us we've been doing this for a while now so we've quite optimized it and it's good to see that all these companies are coming out with their edge workers and then we suddenly already have something i don't think we had to change much code to make it work on for sale right alex um yeah it's it's very much same code because i think cloudflare workers are used under the hood with for cell h functions so okay so it's very close then the activation process is different so the dev experience is um definitely uh very much streamlined here with this concept of middleware yeah and is familiar to to developers yes so that question like we plug in here our handler but you can plug in other other handlers here i can imagine so we keep this piece open and if you want to do geo-based redirects or some sort of post-processing other injection stuff you can cool so if we don't have any more questions we're quite long now already even though there's still some very awesome people that are still watching so thank you for watching all the way through if you wanted any information on this let me just grade you a quick banner because we have this you can actually come here and then if you wanted a demo um from our from us like one on one and you have all these questions that you might have in mind right now we are fully happy to totally show you everything and if you have some crazy use cases we will probably be able to personalize around them as we do and so feel free to subscribe to a demo and we will we'll reach out you can also find us on twitter if you want to so there's um let's see if it can display our names oh no it doesn't work here anyways um cheers everyone thank you for watching and hopefully see you soon hi everyone happy halloween cheers unicorns unicorns you
Related videos

A Uniform Canvas use case deep-dive
In this Livestream we are unpacking how Tim created a Cloudinary shoppable video player based on Uniform Canvas data from Contentful and BigCommerce

Jamstack Fridays with T&T | Jamstack and beyond with Alex Shyba
Tony & Tim have invited Alex Shyba to talk about the Jamstack and beyond!

Uniform Product Meetup
Personalization Basics: Intents and signals