Location-Based Next.js Middleware With New Relic Synthetics
If your app needs to behave differently based on user location, Next.js Middleware gives you control. And New Relic Synthetics make testing easy. Observability Week Day 3 features Daniel Kim!
Links & Resources
- https://twitter.com/learnwdaniel
- https://newrelic.com/
- https://nextjs.org/docs/api-reference/next/server
- https://www.bloomberg.com/news/articles/2021-07-07/best-pizza-city-in-america-is-portland-oregon-say-modernist-experts
- https://snack.tips/portland
- https://docs.newrelic.com/docs/synthetics/synthetic-monitoring/getting-started/get-started-synthetic-monitoring/
- https://twitter.com/learnwdaniel
Full Transcript
Click to toggle the visibility of the transcript
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
JASON: Hello, everyone. Welcome to another episode of "Learn with Jason." Today on the show we have Daniel Kim. Daniel, how are you?
DANIEL: I am doing fabulous. How are you?
JASON: I am doing great. A little bit of technical difficulties. I'm excited to talk about the subject at hand today, but first, before we dive into what it is, let's talk a little bit about you. Do you want to give us a bit of a background on who you are and what you do?
DANIEL: My name is Daniel. I work as a developer advocate at New Relic. I actually came from an Next.js startup before I joined New Relic. I feel like I'm going back home with the stream. I don't focus on browser or synthetics or anything like that. I focus on our Kubernetes experience and how we support a cloud made for developers, but today I get to jam out on frontend. I love doing fun, weird projects. That's my specialty. I'm so excited to do a food based project with you, Jason, because I love food. That's why I live and work, is for food. I'm very excited.
JASON: Very much agreed. People are like, why do you travel? I only go to cities where the food is good.
DANIEL: Yeah, I want to try every kind of barbecue, every kind of dumpling. That's why I like to travel. Yeah, for sure.
JASON: I have publicly stated that I would happily become a dumptarian if I could.
DANIEL: Yesterday, I hosted a meetup in San Francisco called devs and dumps where we ordered 1,000 dumplings.
JASON: What?
DANIEL: It was like 80% gone in a couple of hours. It was amazing the rate at which dumplings were consumed at that meetup. I was like we ordered way too much food, because we had trays and trays and trays of dumplings. Most of it was gone by the end of the night.
JASON: I had a dream where I was surrounded by trays and trays of dumplings. I feel like you may have put to go one of my fantasies actually.
(Laughter)
DANIEL: Yeah, it was a fantasy of mine for sure because it's always been a dream of mine to be surrounded, all 360 degrees, with dumplings and every different type of dumpling.
JASON: I'm looking for a studio G bleed of leaning of towers of dumplings all around me. We could talk about this all day, but we should probably talk about something else.
DANIEL: Sorry. I get real passionate about food. It's a major driver for me.
JASON: Speaking of which, let's talk a little bit about what we're going to do today. Okay. Stick with us, chat, because it is going to take us a second to get to why this is about food.
We're going to be working today with Next.js. More specifically, we want to start playing with the ways Next.js can handle location based stuff. There's a lot of cool stuff in this middleware where you can determine where somebody is requesting the site from and make alterations to what the site does. You can also redirect them to different versions of the page, but what's really interesting about it is it poses some challenge that I never had to think about before, such as when I have said that everybody in, I don't know, Denver, Colorado, needs to see a different version of a site, how do I verify that it's working, right? Because I'm in Portland. If I'm attempting to troll my friends, I can like set the location to Portland and then see that it works, but I don't have time to go to Denver and load the sightly site and make sure it works. If I was targeting multiple locations, what do I do to solve that? It sounds like you have a potential solution for us today.
DANIEL: For the first time, enterprise software has a solution for us regular developers.
(Laughter)
DANIEL: That should be a sound bite.
JASON: Chris, you know what to do. Chris is the editor for the show.
DANIEL: Synthetic monitoring as a concept has been around for quite a while actually. It's a way mostly back end developers test their operation systems are working efficiently. Now synthetic monitoring can be used for frontend websites. It can automatically send a robot or script to your website from any location you can dream of or you can spin up a location of your own. You can theoretically set one up from Antarctica, if you wanted.
JASON: Okay.
DANIEL: You can have a script test your website or system as if it was a real life person or a machine from a particular location. You could actually have a script from Denver, Colorado, try out the workflow from your entire website, like clicking around and validating that some things work and is displaying what you want it to display. You don't have to physically travel to Denver, Colorado, to test if your website works.
JASON: That's great because the horse at that airport freaks me out.
DANIEL: Oh, yeah. That airport has a lot of conspiracy theories around it.
JASON: Chat, if you've never gone down the rabbit hole of DIA conspiracy theories, you should definitely do it because it's weird. It's dark. It's amazing. There's a demon horse.
(Laughter)
DANIEL: Yeah, I've only been there once. I try not to connect to Denver anymore.
(Laughter)
JASON: I imagine that was the exact opposite impact they were trying to have when they built that airport.
If I'm building an app and that app relies on location, if I want to test that app from any location to validate what I'm building works, a synthetic is going to allow me to have a robot actually hit the site and then it gives me what do I get when I do that? Do I get the response headers? Do I get a screenshot? What's my goody bag look like after I've run a synthetic?
DANIEL: You get a bunch of goody bags. You get a screenshot. You get the entire graph of how things load. This is actually really important for more complex websites that might be loading different resources based on your location and CDN. If they use a CDN that's region based like a developer from Japan goes to your website from a different CDN, you can see the different performance issues that may come from multiple people at multiple locations accessing your website.
JASON: Yeah. I'm just kind of thinking how useful that waterfall would be to see it from different places because one of the big challenges when you're building a site is, especially as it gets more complex let's say you've got your frontend on the CDN and that's globally hosted and you're happy. Then you reach for a service like AWS lambda, without thinking about it, you only locate those lambdas in U.S. east 2. When you load the site from Australia, you start 20 to feel that lag of the speed of light from the east coast of Australia to the U.S. We forgot to add locations for where our back services run. You can start to find these bottlenecks that you wouldn't notice if you're building for your own speed because I'm here in Portland. If I put something on west coast U.S., I'm not going to notice. It's going to be really snappy. I'm going to be super impressed with myself, but somebody loading that from Asia is going to be like, why is this website so slow? My CDN node is Hong Kong. Why the heck is this so dang slow? The synthetics give a really good indication of, oh, wait, I have a huge lag between this request and the response from my API.
DANIEL: That's for sure. And the best part is when these issues happen, you want to get in front of it as soon as possible. With a platform like New Relic, you can basically get alerted when certain things are not what you want them to be. If you get a Slack notification or an email about this is not going well so you can go fix it, more of your customers and user notice. That's the power of setting this up for your large enterprise production website. You want to make sure that things are working as much as possible to keep your uptime up.
JASON: Yeah.
DANIEL: At the New Relic, internally we use inset synthetics to drive our internal emergency room. We have a synthetic testing our login flow to make sure every one of our users throughout the world is able to access our website. If that synthetic fails for any of our locations, the team gets paid to be like, yo, this login doesn't work for your users.
JASON: You just said something that made me connect a dot. I had thought when you said we could use synthetics, that it was a page load, but you just said you test the login flow. I can run like a full integration suite from anywhere in the world using synthetics?
DANIEL: Yeah.
JASON: Oh.
DANIEL: I don't know. Angie is the queen of Seleniums. You can run browser tests with synthetics. You can test those really complex workflows directly from Dallas, Texas, or Portland or Tokyo.
JASON: That feels especially important as you start getting into things like, for example, GDPR compliance. You want to run different things in different places. The worst experience is when you start getting notices about legal policies that don't apply to you. You just dismiss it because you don't care. Instead, we want people to actually see relevant things that affect them. If you don't have a way to test that, it can lead to the engineers just saying, well, I don't know, better safe than sorry, just show it to everybody. I think that's not really what we're after, right?
Also, being able to use an integration test to show the flow of, oh, yes, our payment parity scripting actually works. When you load from a country with a lower income, you reduce the price of your product to match the income level so it is affordable. Purchasing power parity is what it's called. I love that stuff, but it's really hard to test, so a lot of us use somebody else's script and ship and hope for the best. Being able to actually put together an integration flow and hit the site from somewhere you know has a price change and make sure the price actually changed and when you go through the checkout, you see it works, all that stuff is really important and really hard to set up if you don't have something like synthetics.
Okay. Let's take this full circle here. How is this about food?
DANIEL: Oh, yeah. I think there's lots of famous bites that you can have with your friends. One of the most divisive things you can do is starting an argument about the purity or the ultimate way to cook anything. I know there's a famous feud on this channel about burgers. What is the actual best way to cook burgers?
JASON: Yes. Yes. There is a checkered past. Sarah Drasner, who is one of my favorite people in the world and also one of the best devs I've ever met, has the unbelievably incorrect opinion that the best way to make a burger is to sous vide the burger patty. I don't know how anybody could look at a Smashburger and go, I'm going to put this burger in the bath and this will be better.
DANIEL: Food fights. We want to keep everybody happy. When Sarah visits the website from her location, we want to keep her keep the friendship alive.
JASON: Yes.
(Laughter)
DANIEL: We want to make sure the website says the best way to cook burgers is sous vide burgers, but we also want to keep Jason happy. Because he's from Portland, we want it to say Smashburger. That's the theme of today's stream. How do we keep friendships together by keeping everyone happy by making them feel their favorite cooking style is X?
JASON: The underlying message of today's show is we're going to teach you how to make websites that sucks up to them and makes them think they're correct.
DANIEL: Exactly. That's marketing.
(Laughter)
DANIEL: That should be another sound bite too. That's marketing.
(Laughter)
JASON: Okay. I think at this point maybe the best thing to do is to switch over and see how all this works, so why don't we head over into our pair programming view? I'm going to get this off screen. We're going to make where did my window go? Here it is.
First and foremost, this episode, like every episode, is being live captioned. You have a closed caption button there on your Twitch player so you can turn that on. Tess is here from White Coat Captioning, taking down all these words. Thank you so much for being here, Tess. That is made possible through the support of our sponsors: Netlify, Nx, Pluralsight, and New Relic, who is putting on this whole collection of O11y Week streams. I don't know why I forgot the word for stream.
We're talking today to Daniel. If you want to go and follow Daniel, you can do so on the Twitters. I'll drop this link in here.
DANIEL: I might have slightly gotten inspired by Jason from my Twitter handle.
JASON: Learn with Daniel. I love it. All right. We're talking about New Relic today. We are going to get into the New Relic here's a link to the home page if you want to check that out. We'll get into the synthetics and the docs and stuff as we go. I think that's the extent of my knowledge on what we're doing today.
Daniel, what should we do first?
DANIEL: Yeah. So, I already started a base repo for us to work from. It's under GitHub.com/ let me drop the link instead of me trying to stumble through a large URL.
JASON: All right. I've got that here.
DANIEL: Let's just clone that repo.
JASON: I'm going to clone down the starter.
DANIEL: Uh huh.
JASON: Okay. Let me grab this.
DANIEL: Feel free to follow along, folks at home.
JASON: This should be a good time. We're using the GitHub CLI here. Then I'm going to check out starter. Come on. Get branch. Hit fetch all. Now we can get starter. Please stop helping. That is not a helpful thing to happen when I tell you to do this thing. How do I get the starter branch if I'm what is the thing I'm doing wrong here?
DANIEL: I use GitHub. I'm an embarrassment.
JASON: There's a way to do this. Maybe I need to do a get checkout origin.
DANIEL: You can also do dash B.
JASON: But I'm in the wrong branch is the problem. I'm not in the correct folder. Oh, my God. My goodness, y'all. We're off to a great start.
DANIEL: I'll say Git is the hardest part.
JASON: That's true. It's all downhill from here, everybody.
Okay. We're going to open up this project. I'll start by installing dependencies. Thank you.
DANIEL: Is that a monkey emoji?
(Laughter)
JASON: Let's start this thing up and see what we've got. I'm going to run npm run dev. And we've got site is at local host 3,000. I'll copy this, come over here, and here is our site. This is the burger brawl. We've got smash burgers versus sous vide burgers. I think this is the best website that's ever been made.
DANIEL: I don't know because it's basically saying we've got to figure out who the winner is though. It's not complete. This is a start to a great website.
JASON: It is the seed of a perfect website.
(Laughter)
DANIEL: Nice. Yeah, let's just start by making a page talking about the actual correct answer, which is smash burgers. I think we should just start by making a new page.
JASON: Okay. We'll say answer.txs. I'll copy and paste some things so we don't have to remember it all.
Let's see. How does this all work? We've got the contenders' component here. We'll say "the best burger
DANIEL: Smashburger.
JASON: Okay. And if we just drop this out, that should give us a pretty let's go take a look at what I've done. Cool. I'm pretty happy with that. That seems okay. What am I missing?
DANIEL: That was so fast. Yes, that looks beautiful.
JASON: I think this is the magic of component based frontends. Oh, good. I can just read what this is. That's what I want. Yes, perfect. I am done.
DANIEL: We've also got to add an answer for the wrong answer because I'm also on Team Jason. I love Smashburger. We can call the other page. I don't know what we should call it.
JASON: The wrong.
DANIEL: Nice.
JASON: Then we'll go in here and swap this one out, and we'll say then we can switch over to wrong.
DANIEL: You do you, I guess.
(Laughter)
DANIEL: Sorry. This like cracks me up. I can't believe I'm coding this live on a stream on like a work stream. This is really fun.
JASON: Yeah. Sometimes I do just take a moment to think about what I do for a living. You've just got to chuckle.
DANIEL: Yeah, it's really funny. I think that took all of three minutes. We've now got to put in some middleware logic.
JASON: Okay.
DANIEL: A middleware logic to redirect the request as it comes in to the correct page.
JASON: Okay.
DANIEL: So, I think let's just start with VS code and going and creating a new file in the root directory called middleware.ts. I think this is a really good time to bring up the next documentation, which I think is fabulous. I'm going to drop that in the chat.
JASON: Oh, you you went straight to the server. Is it this one?
DANIEL: Yeah, that one.
JASON: Okay.
DANIEL: We're going to be using next/server to basically help us with middleware. We can actually get metadata about the requests coming in and use the next dash server to redirect all the traffic coming in to the right page.
JASON: Uh huh.
DANIEL: We're going to be importing the type next request from next server as well as next response.
JASON: Daniel, I'm going to interrupt you real quick because momen88 the assayed, we want other options different than burgers if this is about food, and I think that is brilliant. Chat, here's your challenge. Let us know in the chat what the best food feuds are. New York versus Chicago style pizza. Include where they're from because if we have more time, we can add more locations and answers and options for things. If you load this site from New York or Chicago, we can show pizza instead of burgers, for example. Drop those into the chat. If we've got time, we'll come back and do some.
All right. Sorry, Daniel. I interrupted you. Go ahead.
DANIEL: I just want to drop this in the link to people everything you can do with next server. In the server, we're going to import from next/server as well as import next response from next/server.
JASON: As not a type, right?
DANIEL: That is not a type.
JASON: Okay. We're going to get import
DANIEL: I love how next just abstracts this out for you so you don't have to do anything. That is just beautiful. And then we want to export a function called middleware. And then the input would be the request. We have to do req, and then we do the little colon and then next request.
JASON: Okay. Is that the only argument?
DANIEL: Yeah, because that's we're basically looking at the request coming into the website and figuring out where to direct it after that.
JASON: Got it. Got it.
DANIEL: Let's make an if statement. To make it easier, what country do you think would prefer sous vide burgers over smash burgers?
JASON: Let's say France because they invented the wait, did France invent Sous vide? You know what? I'm sticking to my guns. You heard it here first.
DANIEL: I'm afraid of pissing off people, but I also like living on the edge. I like it.
(Laughter)
DANIEL: Let's see. If direct dot geo dot country equals FR
JASON: It's a country code, right, capital FR?
DANIEL: Yeah, exactly. Then req dot next URL dot path name equals wrong. Else we can do req next URL path name equals what was the URL name? I forgot.
JASON: Answer.
DANIEL: Answer, yes.
JASON: And now
DANIEL: Oh, sorry. Go ahead.
JASON: How does this work? If I remember correctly how next middleware works, because we put this in the root, it is going to run on every request, right?
DANIEL: Uh huh.
JASON: If I'm reading this code correctly, somebody from France would never be able to get to the home page. They would automatically see the sous vide. Somebody from anywhere else would automatically see smash burgers the way this code is written right now. Is that correct?
DANIEL: Yes.
JASON: Okay. Do we want to test that first?
DANIEL: We can't test that right now because we have to return something in this function.
JASON: Got it. Okay.
DANIEL: Let's do return next response dot rewrite and then parentheses req that next URL. Right now, what it should do is redirect directly to the sous vide, the wrong page or the answer page, depending on where you're from. Hopefully it does that. That would be great.
JASON: Let's see. It didn't like oh, that's fine. That's because we didn't set a key prop. Middleware is running. Did something fail? Unexpected token. Oh, interesting.
DANIEL: Oh, I forgot.
JASON: We're redirecting everything. This is catching the JavaScript files and all the assets as well, so we're returning okay, okay.
DANIEL: I forgot to do something. We forgot to export the URL variable. If we don't export that variable, it'll ruin everything. We have to limit what we redirect. What we want to do is we want to export the constant called config.
JASON: From the middleware?
DANIEL: Yeah. And then we want to do matcher colon and then quote marks and the slash. We basically want to redirect every request to the main page to answer or wrong. Hopefully that worked.
JASON: There we go. There we go.
DANIEL: Life coding gets my blood pumping.
JASON: All right.
DANIEL: But we want it to be a little bit more dramatic because we want people to go to the home page and click a button to find out the right answer. Let's now put that. In the main page, let's add a button that says "find out the right answer" or "find out the answer." I don't know what the right phrasing would be, but having a button for that would be cool.
JASON: We have a component for that, which is cool. We can go here.
DANIEL: I don't know how that happened.
JASON: It's almost like we planned this. Let's go to the big link here. We want the H ref. What do we do here? Where do we link to?
DANIEL: Yeah. The best part is you can make any URL because basically we can have the middleware redirect the URL you create here to some other thing. But for the sake of this, we can just make it let's just have the default be "go to answer."
JASON: Okay.
DANIEL: And then in the middleware, we can say, if it is from France
JASON: From Frawns?
DANIEL: Sorry.
(Laughter)
JASON: Okay. Now we have a button, but we can't see it just yet, so we need to do I just change this to answer and now it will work?
DANIEL: Yeah.
JASON: Yeah, yeah. Okay. Look at that. Okay. Moment of truth.
DANIEL: Please work. Yes!
JASON: Just whacked my ceiling. Okay. I think we did the thing because I don't know how to test this because I'm not in France.
DANIEL: Honestly, I would love to get a work trip expense to do to France to test this website. Hey, boss. I need to go to France to test this website. I would love to be a software engineer where synthetics exist. That would be so nice.
JASON: We just got such a better button text from the chat.
DANIEL: Discover the truth.
JASON: Discover the truth. I love it. I love it.
DANIEL: Now, let's just test the button as if we were in France. Are you down?
JASON: Yes. I'm down. Let's do it.
DANIEL: You can go to New Relic. The best part is there's no coding required for this. You can have coding. I prefer not to code if I don't have to. All we have to do is go into oh, maybe not upgrade yet. This is called marketing, folks. There's an X on the top.
JASON: Oh, there it is.
DANIEL: You have to go to synthetics. It's in the very bottom of the little robot. Perfect.
JASON: I like this little robot. Just zoom in on that robot for a minute. It's a good robot. All right.
DANIEL: Then create your first monitor. There's that big white button. And then today we're going to be doing something really basic, but you can go as complex as you want. Like I said before, you can create very long selenium tests to test your very complex environment. Today, we have a button that we have to click to show a page. We're not dealing with rocket science here.
JASON: True.
DANIEL: So, we're going to do a user step execution, the zero code monitor building on the bottom right.
JASON: Okay.
DANIEL: And we have to create a name. What should be the name?
JASON: The food feud. Here's actually a question. Am I setting up one named synthetic for each task or am I creating a group of synthetics and I can add checks underneath this?
DANIEL: It depends on how you want to set it up. You can be very lazy. France could fail. If we assert the answer should always be sous vide burgers, you could go that way. If you have a large environment, I suggest you have a different synthetic for every single scenario you expect. You should have a separate synthetic for France. You can always validate for users of France it will always show the best burger is sous vide burgers and then other places would have Smashburger.
JASON: We can do the FR so I know that we're checking France.
DANIEL: Exactly.
JASON: Okay.
DANIEL: If you could change the period to one minute, that would be great.
JASON: Just so that we get more of these. Do I need to care about any of these?
DANIEL: No.
JASON: Okay. Select locations, that feels like a good button.
DANIEL: Yeah.
JASON: France.
DANIEL: And we do have France.
JASON: Dope. Okay. Estimated monthly checks. This is going to yell at me because it is going to go over my limit.
DANIEL: But it's fine. We're going to disable it after the stream. We're just going to set it at one minute because
JASON: I don't know if it's going to let me.
DANIEL: Oh, shoot. Maybe we have to go back and then change the period to be five minutes. Hopefully. Or 15 minutes.
JASON: Let's see if it will let me. It has to be 500. Check schedule this month. 500. That's, what, 30 days where we need 500 divided by 30 days. Wait, is that what am I doing? That math is absolute nonsense. We get 16 checks a day. That means we can't even do is there a way to say only run this for a little bit?
DANIEL: No. I should probably add that as a feature request. Let's set it at six hours and see if that works.
JASON: Yeah, it will give us six hours.
DANIEL: It should hopefully run once.
JASON: It should hopefully. We need to navigate to do I need to deploy this?
DANIEL: Oh, yeah. That would be helpful. New Relic can't sneak up in your browser and monitor your local host sadly.
JASON: You'll have to walk me through this part because you're going to have me deploy somewhere I don't deploy.
DANIEL: I use Vercel CLI. Yeah, hit Vercel off or login.
JASON: Okay. I think I have an account. CLI login failed. No Vercel account. Okay. We're going to do that real quick. What is that? Wait, I do have an account.
DANIEL: That's really weird then.
JASON: How do I okay. My username. What am I hooked to? Can I hook up to login connections, GitHub.
DANIEL: Ah.
JASON: Now I'm hooked up to GitHub. Okay, great. I'm going to close this, go back here, try this one more time. Nope. It's happening. GitHub. Should be logged in. CLI login success. Okay.
I'm in.
DANIEL: Yes.
JASON: And now what?
DANIEL: All we have to do is hit Vercel. That's the command to deploy stuff.
JASON: I haven't forked this repo or anything.
DANIEL: I think you just have to click yes. You just clicked no.
JASON: No. Okay. Here we go. Do I want to modify these settings? I'm assuming no. And this I assume is my yeah, okay.
DANIEL: It's currently building. It will take like a couple seconds, I think, to deploy.
JASON: Okay. We can kind of watch this happen. It's doing stuff.
DANIEL: It's kind of scary to see it deploy. Hopefully everything worked. Okay. We have
JASON: That worked. Now if I click this button, it shows me that one, which is not surprising. That's what it should have done. We can come back here, put this one in, right?
DANIEL: Yep.
JASON: And then I need to click element.
DANIEL: Uh huh.
JASON: By ID CSS or X path. We need to get back in here and check what's this button called? I should probably add should we add I feel like this is going to change every time.
DANIEL: Something you can do that works for me is have the text of the button and just put it in. Discover the truth.
JASON: Okay. I can just put in
DANIEL: Yeah.
JASON: Text?
DANIEL: Yeah. I tried that yesterday and it worked. Don't have the quotation marks. Just discover the truth, straight up. And then we can always validate it by clicking validate. We can always validate each step of the building.
JASON: Okay. And so, what we could also do, if this text doesn't work, is add like a data attribute to the button which doesn't affect the behavior. It doesn't have to be tied to the CSS. It can be like this is a testing hook. That is a pretty common path that I've seen. We can do this without adding an ID, which is not necessarily what we want to do.
DANIEL: For sure.
JASON: Okay.
DANIEL: Hopefully this works.
JASON: Hopefully this works. And then the other piece that we need to do is we need to check we're asserting something, right?
DANIEL: Yeah. We have to assert that the title is I guess you can't test it while it is validating. Oh, shoot. Wow, that is taking a long time. Yeah, that's the code that powers it.
JASON: This is cool. Just kind of like does the whole thing.
DANIEL: Yeah, because we don't want people oh, it worked. Okay, cool.
JASON: It worked. And look, it showed us the right thing.
DANIEL: Yep.
JASON: Okay. That's great.
DANIEL: Now let's just assert.
JASON: We want to assert text.
DANIEL: Uh huh.
JASON: And we want to let's see. That's an H1, right? The header?
DANIEL: Yep.
JASON: We're going to get the H1 and insert that the text contains sous vide.
DANIEL: Can we just double check that the header is H1? Oh, perfect.
JASON: Yeah, that's what we're doing here, is sous vide. I want to make sure I've got my I don't know if case matters, but let's make sure it works. Okay. That should do it, right? This should validate true?
DANIEL: Yes, that should for France. Let's click save.
JASON: Saving.
DANIEL: I'm looking down because it is kind of small on my screen. I kind of look funky on the camera.
JASON: All good. All good. So, does it show when one is running so that we can make sure that it is doing the thing?
DANIEL: I don't think it shows when it's running. I think it should run for the first time when you create it.
JASON: Okay.
DANIEL: I think we might have to wait for a little bit. Let me see if chat knows because I think there's some New Relic people in here. You can trigger to check manually.
JASON: Can I do that monitor results. Resources, failures. Where is my check? See full map. Go back here maybe.
DANIEL: I think you might have to oh, shoot.
JASON: And so, while we're doing that, I'm going to look back through momen is saying from the Middle East, some Egyptian food. I know in between Nigeria and is it Ghana, where there's a big feud over jollof rice. Is there an equivalent of that in the Middle East? Egyptians will go over to how good they are at making that thing. Oh, yeah, we make the best whatever it is.
What else? I think we could do the pizza thing. That would be kind of fun.
DANIEL: Like Chicago versus New York.
JASON: Uh huh. That one I know we can do pretty fast because I'm almost positive we can find Chicago pizza. Yep. Look at that casserole.
(Laughter)
DANIEL: Oh, my God.
JASON: Let's see. This is going to work. We'll get this, open a new tab, and then let's do New York. That looks like a New York slice. We'll do that. Is that a New York slice? It's good enough. Somebody from New York is going to fight me. Open that one in a new tab.
DANIEL: Which team are you on though?
JASON: My controversial opinion well, actually it's not even controversial. It's just backed by data is that Portland is the best pizza city in the world. The comments are heating up right now, but there's a whole article on this. Watch, watch. Portland best pizza look, here it is. Look at this article. The best pizza city in America is Portland, Oregon.
DANIEL: The Portland pizza I've had is fabulous. It's a good in between between New York and Chicago. The city doesn't make its entire personality based on pizza.
JASON: That's true. It just makes good pizza.
DANIEL: Exactly.
JASON: And the thing I like about Portland is people from all over have moved to Portland and made excellent pizza here. A couple of people from Detroit moved to Portland and made good Detroit style. We've got whatever lovely 50/50s is with edible flowers. We've got the Ken Forkish and Apizza Scholls. Really good variety of pizza, which is why Portland is the best pizza city.
DANIEL: I'm headed to Portland today. Do you have any recommendations?
JASON: Are you legitimately headed to Portland today?
DANIEL: Right after this stream, I have a flight at 1:00.
JASON: I will send you a list. I have a whole look, I built this website. It's called snack.tips. It's just a bunch of food in Portland.
DANIEL: I love that you bought this domain.
JASON: Of course, I bought this domain. I would be a fool not to buy this domain.
DANIEL: It's called domain driven development, I think.
JASON: That is absolutely true.
(Laughter)
JASON: All right. Let me go back in here and let's take a look.
DANIEL: I think I got some tips from New Relic. Do you see run check there on top? No, no. Go down there. Let's check if that worked.
JASON: Here it does show zero failures, one checks.
DANIEL: It worked. Let's just go to results.
JASON: Oh, results. Here we go.
DANIEL: Then click the little table.
JASON: Success. And look at it. Here we go. Here is our waterfall. We can see 182 kill kilo bytes. We have a script log. That's also cool.
DANIEL: We may have to rerun it. There's some quirks with the platform.
JASON: This is cool. It shows those bits.
DANIEL: Even though we're using synthetics for a fun purpose today, it's really useful when you're trying to build a website that's accessed by people from all over the world so you don't have to manually test everything. You can get alerted when things go wrong. You can go fix the issue before a lot of your customers start complaining on Twitter.
JASON: Anything that can tell you something is happening before your customers do is good. Because the worst way to find out something is wrong is to have somebody email you and be like, hey, your thing is broken. Let's see. We've got another one. Do we need to tell it to grab the screenshot?
DANIEL: No. It should do it automatically. For some reason, it's not grabbing it. Okay. That's really weird. If the check is successful, that means the header was there and people from France are able to see sous vide burgers are the superior burger, which is not true.
(Laughter)
DANIEL: Because we don't boil burgers. I didn't know that boiled burgers were a thing, but apparently that's a thing.
JASON: I don't know. I've never understood the appeal of a meat bath.
DANIEL: The thought of a meat bath is creeping me out, but okay. Now that we have a couple more minutes do you want to start building the pizza or the Egyptian food or whatever chat wants us to build?
JASON: Let's do it.
DANIEL: What food should we focus on?
JASON: I think maybe momen dropped because I didn't hear anything back about the Egyptian food, so let's do pizza because that is one that I understand. I am going to create a new file called "pizza," and I'll just copy my index. This one is going to say "pizza" what's a good P word? Pizza punchout.
DANIEL: Pizza punchout. I like it. It's slightly aggressive.
JASON: It is very aggressive. Chat, maybe give us a better one. I am going to think of let's see. I shouldn't have put myself on the spot to be clever. This is not going to work out. I'm going to fill out these while I think. We've got New York style and Chicago style.
DANIEL: New York style. I think someone in the chat said Naples for Italy.
JASON: Neapolitan, yeah. We can do the country base you mean?
DANIEL: Or we can do city base.
JASON: Can we do city based? Because I think city based would be fun to show.
DANIEL: Yes.
JASON: Slice thin, crispy, delicious.
DANIEL: You're a New York style fan?
JASON: I like all pizza.
DANIEL: Even casseroles?
JASON: Oh, yeah. I'll talk a whole bunch of crap on Chicago style pizza and then I will absolutely eat one.
DANIEL: I was in Detroit last year. I really like Detroit style pizza.
JASON: Detroit style pizza is killer. I have yet to be to Detroit, so I look forward to the day that I get to have the real deal, but I've been to Detroit style pizza places in a few different cities. I love the style. There's a good spot up here if you want to get a good Detroit style pizza. It's called East Gleason Pizza.
DANIEL: You're the expert on pizza. I love it.
JASON: Chicago style pizza, deep dish, loaded with flavor for cheese fans. How about that? Yes, good enough. I think I can just hot link some of these. Let's make it square. Now I've got to remember how image X works. We're going to go to I'll go down here. 500. Height is going to be 500. You want prop to be entropy, I think. Should give us a good one.
DANIEL: What are you doing right now?
JASON: This is ImageX. Unsplash uses it under the hood. You have these options to do different types of crops and stuff. If it is a picture of faces, you can focus on the faces and all that. And so, if you want a specific size of image, you can take the image and apply some different filters. What I did at the end here is I just changed the width and height to 500 so it is the right size and then set crop to entropy because it is the most visually interesting piece of the image. Now I don't have to drop in a giant image and hope for the best. I can just drop this right in here and that's going to work.
And then for the New York style, we can do the same thing. I'm just going to copy/paste this to avoid making everybody watch me do that twice. We'll go into here
DANIEL: I love it.
JASON: And then down at this side. Just grab everything from the width, paste. This one actually, the entropy might screw us because this is going to be pretty visually interesting. Let's see. What we'll do instead is we will use bottom.
DANIEL: Oh, that's good. That looks really yummy actually.
JASON: I love a good pizza by the slice. It's such a deceptively hard thing to make. It feels like people try to make pizza by the slice and then it is a real disappointment. You can't go wrong with pizza, but which style reigns supreme? Then we're going to go in here to our site, which is not running anymore. We'll npm run dev. And I want to go to pizza punchout.
DANIEL: How did you create the image in the logo on top? It looks really nice. Is it like a gif?
JASON: These are little images I create sometimes to keep from doom scrolling on Twitter. I used a gif creator doing two versions, like rotating back and forth.
DANIEL: Oh, wow. That's really smart.
JASON: I could have used svg, but then I was like I'm not spending that much time on this.
DANIEL: Nice.
JASON: Okay. My alt tags are incorrect. Let's see. Style, pepperoni pizza, deep dish pizza with a cheesy slice being lifted out of the pan. Now we've got alt text is actually useful.
DANIEL: Somebody asked what we're building. We're building a website that tells you, depending on where you're visiting the website from, what is the best type of a pizza. Folks from New York will get New York style pizza and Chicago people will get Chicago style pizza.
JASON: Yeah. We're in the midst of adding the pizza version, but we've done so far is this burger version. If you load from anywhere in the world except France, you'll see the Smashburger page. If you load from France, which we picked arbitrarily because sous vide is, I believe, a French word. If you go from France, you'll see the sous vide page. Now we're working on the same thing but for pizza, and we're going to set up by city. We want to look at New York and Chicago as the cities we want to show. We need our answer page, which we can get out of here. I'm going to grab this one and duplicate it. For this, what I'm going to do is actually just do an answer dot NY and answer dot Chi. Then we can head over to the pizza page, grab New York style out of here, go to New York. Watch me alienate all of my New Yorker chat members. They all just logged off like right now. Then we'll do the same thing for Chicago style. Now Chicago has logged off.
What we need to do then is update the middleware, right?
DANIEL: Yep.
JASON: Maybe walk me through how we want to do this because here's how I want this to work, like what I'm envisioning in my head. Everybody who is not in New York and not in Chicago should still see the burger page, but if you're in New York or Chicago, I want to show the pizza page. The home page should shift for New York and Chicago to show the pizza page. And then if you're in New York or Chicago, when you click "discover the truth," I want to show either the New York page or the Chicago page based on which one you're in.
DANIEL: I need you to repeat that so I can write it down.
JASON: If the city is Chicago or New York, show the pizza home page instead.
DANIEL: Uh huh.
JASON: Else show the default home page.
DANIEL: Uh huh.
JASON: Then if city is Chicago, show Chicago answer page. Else if city is New York, show NY answer. Basically, if we get we would need a block that's like if if we do if req dot geo dot city do we just get this? Do you know how this works?
DANIEL: Oh, I have no idea, which makes it really fun. I think we can just log it out. I think we can just use logger. I'm very excited to try it.
JASON: Here's what I want, is to do this check, right?
DANIEL: Uh huh.
JASON: If we're here, then we would set I want my matcher to have like multiple matches. I do one of these, and then we'd need to if this
DANIEL: So, you can do conditionals. You can do you have to add the matcher all the routes you want to change into matcher. Do you see rewrite at the very bottom, like return rewrite? You can actually insert custom logic there. We'll have to now have multiple return statements for everything we want to return. Inside of that if statement, we'll have to add a return statement. We have to copy and paste that in there. And then basically return next response rewrite. Instead of req dot next dot URL, we have to write new and then capital URL, bracket parentheses, then the URL you want to transform, comma, transfer URL.
JASON: Okay.
DANIEL: Does that kind of make sense, what I'm trying to do?
JASON: It makes sense, and then I'm just melting my brain right now because we have to let's see. How are we doing on time? We're doing great on time. We need to check if looking at the home page
DANIEL: How about this? If it's in the U.S., it goes to pizza and for everywhere else it guess to burgers.
JASON: Yeah, we can do that, but we would miss the Chicago/New York check. We need two pieces. We need to check if they're looking at the home page one set of redirects. And then if we're looking at the answer page, we need a second set of redirects. This is actually if looking at the answer page, we would need to check if the geo country is France. Then it would be else if
DANIEL: We actually can't keep line 11 and 13 because we have multiple URLs that we're trying to transform. It's not just one thing. We're trying to change to two things we want to change the base as well as the answer. We actually have to put we need to just return the next response, rewrite with the URL we want to transform it to. Does that make sense?
JASON: Yeah. We need to return next response.
DANIEL: Rewrite.
JASON: Rewrite.
DANIEL: And then
JASON: New response.
DANIEL: No, it's new URL. It's a new URL object. Then you have to open the parentheses. Then it would be the URL you want to redirect. It would be that, comma, and then the request dot URL or req dot URL.
JASON: Oh, I see, so we get like the base path.
DANIEL: Exactly.
JASON: Okay. Got you. Then we'll take this one and do the same thing here for answer. We can get rid of this. We can get rid of this.
DANIEL: Exactly.
JASON: If the geo city is Chicago, we would want to duplicate this a couple of times.
DANIEL: Imagine the state machines of this. Oh, my gosh.
JASON: What have I done? Oh, I did a thing I shouldn't have done. We're going to take this, copy/paste. That's going to be New York and that's going to be our else statement.
DANIEL: This is machine learning, right? A bunch of if else statements.
JASON: Exactly. Nobody knew this was how it was going to go, but I just started an AI company today.
DANIEL: I was looking for air fryers online. Everybody was like AI air fryers or AI rice cookers. What are you trying to do?
JASON: This is me checking that we're trying to go to the answer page.
DANIEL: Oh, no. We don't have to do that because the do you see the new URL? The first part of the statement, the quotation mark, is the URL you're trying to redirect. You don't need to check
JASON: This is the URL we need to redirect?
DANIEL: Yes.
JASON: Because that's not going to match then. If I want to change, when we visit the index page, New York or Chicago, we want to show them pizza.
DANIEL: Oh, sorry. I just had a brain farther. brain fart. Yes. Yeah, yeah, yeah.
JASON: This one, we need to check the path name?
DANIEL: Next URL dot path name.
JASON: Next URL dot path name. That would be this, right?
DANIEL: Yes.
JASON: Okay. And so, then the next piece would be to take this this would be answer. And then we're going to take this whole thing and try again.
DANIEL: Wait. Should we just test this part first before we do that?
JASON: Yeah. We can test anything you want. And then this would be I'm just going to delete this is what the code should be. I don't know if my exact setup here is correct, but this is like the logic that we're after. Why are you mad? Or. Right? This would be pizza and this would be root. This is at least pseudo logic.
DANIEL: It looks correct. I'm excited to try it.
JASON: Okay. Let's give this a shot and see what we can get here. I'm going to attempt to load the home page, and that is doing what I want. Now I'm going to just try, for the sake of okay. Let's log this. Req dot geo. Don't tell me you can't do stuff. Okay, fine, computer. You're right this time. Where's my geo? Does it show up in the browser?
DANIEL: I think so.
JASON: I think I may have missed I may have screwed this up.
DANIEL: Do you want to do just req dot geo dot city? I think it is like a JSON
JASON: Undefined. That's probably because we're local, right?
DANIEL: Yeah. I think we have to deploy it on Vercel. Let's try that.
JASON: Let's see what happens. Oh, let me turn off the Portland part. We'll go to Chicago and then let our synthetics do the work for us. I'm just going to type Vercel. And we're doing it. We're going. It's happening. There we go.
If I come back out here I think that part is working at least. Let's go build our synthetic and try it out.
DANIEL: Yes.
JASON: I do this synthetic monitoring. I don't build it inside. I do a new one, right?
DANIEL: Yeah, you build a new one.
JASON: Okay. This one is going to be we'll do the same thing here. We'll call it food feud pizza. Got to set it to six hours again. 12 hours, one day.
DANIEL: It still won't let you?
JASON: Oh, I know what it is. We haven't set a location yet.
DANIEL: Oh, okay.
JASON: Select the location, and this time we're going to set oh, crap.
DANIEL: Chicago. There's no Chicago.
JASON: There's no Chicago or
DANIEL: We may have to change the code so it is Portland and
JASON: Yeah, let's change the code to Portland and San Francisco.
DANIEL: Uh huh.
JASON: Portland, San Francisco. The same thing for this one.
DANIEL: I really hope this works.
JASON: I really hope this works too. I'm very excited to try it. Let's deploy one more time. Oh, come on.
DANIEL: Vercel.
JASON: Portland and San Francisco. Right? I can do them both?
DANIEL: Yeah. Yep.
JASON: Okay. We're going to define the steps. We're going to navigate to our website. Right? And then we're going to click an element, and that's going to be "discover the truth." And then we're going to assert text. How do I can I do conditional?
DANIEL: Not with this view because this is the no code. You can't do conditional. We can just expect one to succeed and one to fail.
JASON: Okay. We're going to locate the H1.
DANIEL: Uh huh.
JASON: And make sure that it contains what did I say Chicago style. I think Portland will get Chicago style and San Francisco will get New York style. I think that's the way that we replaced that. Should I try validate or save?
DANIEL: We can validate. No, let's just save. Let's just save. I trust us.
JASON: Okay. I trust us too, Daniel. All right. Let's see how this thing is going. We've got waiting on checks to run.
DANIEL: I think you should run
JASON: This is also deployed now. I'm seeing pizza. Okay. Now let's try again. Let's see what happens. Hey!
DANIEL: Oh, shoot. It worked!
JASON: First try.
DANIEL: Wow. That never happens livestream. That is impressive. Wow.
(Laughter)
DANIEL: Wow. I am impressed.
JASON: I can't believe that worked. This is wonderful. If anybody wants to try this to validate, hit this up if you're not in Portland or San Francisco. You should be able to try this and still see the burgers. Give it a shot.
DANIEL: In San Francisco, what should I see?
JASON: If you discover the truth, you should be seeing pizza and New York style.
DANIEL: It does. It does.
JASON: What?
DANIEL: What?
JASON: Look. We're the best programmers on the planet.
DANIEL: Honestly, yeah.
(Laughter)
DANIEL: I want to show my screen. Look.
JASON: Unbelievable. Look at us go, everybody. This is brilliant. I am so happy that that worked on the first try.
DANIEL: That never happens, Jason. Jason, you're like next level.
JASON: (Laughter). Okay. Are you done? We've got a failure. Good, good, good. That's what we wanted. Now we'll go to results. We've got a failure. The Portland check.
DANIEL: Yeah, I got burgers. Yes! Let's go.
JASON: Wait, this one should have worked.
DANIEL: Wait.
JASON: This one's Portland, right?
DANIEL: Yeah.
JASON: Right? We loaded from Portland. That should have
DANIEL: Maybe it ran before it deployed. When did it run?
JASON: Maybe. Let's try it again.
DANIEL: You're trying it from Portland, right? And it showed the right thing.
JASON: One of two locations failing.
DANIEL: Hmm. I got excited before it loaded.
JASON: I know. This is good. We're still one of two locations failing. Does it round robin these where it tries each one?
DANIEL: Yeah. Hopefully it works.
JASON: Okay. Here's our second one.
DANIEL: Oh, it still failed. That's really weird.
JASON: It still failed. Here's what I don't know. We're going to have to look at the Vercel logs, assuming I can figure out how this works. Let's go to Vercel. Then we've got this site here and then logs.
DANIEL: Yeah, view build and function logs, I think. Oh, it's realtime.
JASON: It's realtime. Okay. Let me try it. I've hit it. Anything? Hello?
DANIEL: Can we try revisiting the site instead of reloading it, maybe there's some caching going on.
JASON: Perhaps, perhaps. Okay. Let me close this, open a new window, try again. Show me some logs.
DANIEL: Wait. Did we do console logs where it only shows up in the console?
JASON: I console logged from middleware, which should show up in the logs. I don't know how Vercel does this.
DANIEL: Me neither. I just deploy my portfolio. Shoot. Should we exit out of middleware? Let me try it again. I'm like reloading the website. Oh, wow.
JASON: Okay. It's mostly working. Check logs and synthetics. Do we get logs in synthetics?
DANIEL: Yeah.
JASON: Unexpected token. That's like Vercel's junk.
DANIEL: Yeah.
JASON: Oh, wait a minute. Wait, why would Vercel be why would you put that in my production site? Don't do that.
DANIEL: What is next life feedback?
JASON: Isn't that their commenting overlay thing?
DANIEL: Yeah, I think so.
JASON: So why is that in my production site?
DANIEL: Yeah, that is concerning. What is the URL that we're testing?
JASON: Isn't this my wait, which one is which?
DANIEL: I think the top one is what you're supposed to share out.
JASON: Always up to date view of this branch. Unique view of this deployment, but what I want is my actual URL. Project deployment, domains. Maybe I need this one. Okay. Let's try this one more time. Oh, see. This one didn't work. Okay. Maybe now we get logs. Why does that only work that works in one version and not the other. Do I have to promote something hello? Food feuds. Deployments. This is the one
DANIEL: Eight minutes ago. Yeah. It's not automatic?
JASON: Apparently not. Okay. Let's try this one more time.
DANIEL: My dog is just joining the stream.
JASON: Oh, that's good. Okay. Unfortunately, we ran out of time, and I'm going to blame this one on Vercel not really making sense. Oh, now it's working. We're going to have to check the synthetics later, but that was a Vercel problem and not a New Relic problem. With that, we're going to call that a success.
Daniel, thank you so much for taking time with us today. This was a ton of fun. I had a lot of good laughs on this stream. Chat, I hope you enjoyed this as well. If people want to learn more about this, where should they go next?
DANIEL: If you want to learn more about synthetics, you should check out the docs link I am dropping right now into the chat. And if you want to learn more about Next.js and all the goodies you can do, check out the Next.js documentation, especially the server documentation. I think you can do a lot of cool personalization stuff. Hopefully, maintain your friendships. Don't let food divide friendships. I think that's the lesson I want to impart on everyone before I leave.
(Laughter)
DANIEL: I don't know. All of my friends and I that hang out a lot, we have similar tastes in food. I think food is a big part of my friendships, but don't let it divide you.
JASON: I have definitely noticed I've become better friends with people who eat I'm not saying I won't be friends with a picky eater, but I definitely hang out more with people who aren't. This was super fun. Thank you so much for hanging out today.
I'm going to do one more shout out. We've had Tess from White Coat Captioning all day here. That's made possible through the support of our sponsors. This has been O11y Week. These last three episodes have all been about observe observability. Thank you, New Relic, for making that possible.
Daniel, you're going to come back later this month.
DANIEL: Yes.
JASON: We'll come back and cause more chaos. Thank you all so much for hanging out today. See you next time.
DANIEL: Bye.
Learn With Jason is made possible by our sponsors: