skip to content

Custom Command Bar Using Autocomplete With Algolia

As part of Jamstack Conf, Jason is building a swag app with experts from around the community. This 5-part series will go through the whole process of building an e-commerce site with Shopify, Algolia, Sentry, Twilio, and Fauna.

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: All right, everybody, we are back. And it's still Kelly Vaughn. No! I fixed it. I fixed you. Why are you doing this to me? I know, I know that I did this right. Let me try to get it force a reload?

BRYAN: There should be something at the bottom.

JASON: No, I broke it all. It's the website and I apparently have something cached that shouldn't be cached. Hello, everyone, this is also not Kelly Vaughn. This is Bryan Robinson. Bryan, thank you for joining us. How are you? How are you? How's it going?

BRYAN: I'm good. I'm slight more fresh than you are after a few hours of live streams but I've been enjoying it, watching along as it happens. I'm doing good.

JASON: I'm feeling great. You know, I'm looking forward to this is a heavy week. We're doing 3 of these today. We've got the regular Learn with Jason show tomorrow, we've got two more Jamstack Conf sessions on Wednesday. So make sure you mark your calendar for that, everybody. We have the regular Learn with Jason on Thursday and because of a reschedule, we have a special Learn with Jason on Friday. We're going to be streaming every single day this week. There is a lot going on. I am probably going to sleep all day Saturday. It's going to be great.

BRYAN: Good job.

JASON: Yes, yeah, so everybody what we're going to do this time is something that I am super excited about. Bryan, do you want to give us an overview of what the project is?

BRYAN: Sure. So obviously, you have some lovely buttons that do some amazing things that you've set up with Rob and Kelly. But buttons are lame. So let's do some power user work. Right? Let's give an input bar that a user can use to discover additional powers on the site. Right? Algolia is about all search. The user can type into, discover commands. We'll set up one to ingest the email to the serverless functions. And then, do an action based on that. In this case, it's going to hit the serverless function. Going to allow a user to slap the email address and slap it over to the serverless function. And that'll send off. And I've got some swag points for later if we get there. But that's the basics.

JASON: All right. Let's do this. Pair programming view.

BRYAN: Not Kelly.

JASON: Sorry, everybody. I'm pushing hot fixes in the 15 minute breaks. It's all good. This is going to be good. So, to date, what we have accomplished is just to show everybody here. We have site running locally, and functionality to create and add items to a cart. We can check out that cart on Shopify. So we've got our cart here, if I go to checkout, takes me over to a Shopify thingy. And then, if I go to my postman, I can claim swag and I'll use my own email here. We can claim that swag. Sends back a coupon code. We're going to call this function using Algolia here, the autocomplete library. And that's because there's currently no way to actually get this coupon code, right? We'll make it a power user feature, which I'm excited about. What should my first step be?

BRYAN: I'm going to ramp us up for time because we're in a crunch. Since we're doing this in React and we're in astro, we need the React render. Astro JS/render React. And the two other things @Algolia/JS. You can use it with Algolia, works amazing with Algolia but really any data source. Anything's going to work here. @Algolia/autocomplete theme classic. We don't have time to style it ourselves.

JASON: Anything else?

BRYAN: That should be all we need I'm pretty sure.

JASON: All right.

BRYAN: Is that already done? Wow. Nice internet connection.

JASON: Yeah. Definitely, let people drill holes in my house to put fiber in here.

BRYAN: I would if I could. Let's dive into the project. And we need to create a component.

JASON: OK.

BRYAN: Components folder, create an autocomplete.JSX. And the cool thing about astros, it's going to let us use any frontend. You're using preact, I'm going to use React. It would work together. Usually, I would do this kind of step by step in the tutorial, but let's purport big statements, going to import React and then destructure in an object a few things. We need create elements, we need fragments, use effect and youth those will all become clear later on, but mainly, create element is going to be the method we're going to use to create the auto complete stuff, fragment's going to be what is used what is built for that. And then, we use (inaudible) for mounting it and all of that good stuff. We also need from React dom which I forgot to have you install. Apologies. We need the render method from React Dom.

BRYAN: Import autocomplete.

JASON: Auto complete.

BRYAN: Perfect.

JASON: It auto completed my auto complete import.

BRYAN: You start to see it everywhere. Auto correct on your phone auto complete pattern. And then, we need those styles we got, too. Import the auto complete theme classic.

JASON: Got it. And then what?

BRYAN: Now make our component. Export a function called auto complete. And pass it its prompts. Inside this, we'll do a few things, first, set up a container ref, so equals use ref.

JASON: Anything in the ref?

BRYAN: Null. I don't know if we need it. And then, we're going to actually initialize or autocomplete. Const search equals and this is going to be the auto complete method we imported. Auto complete parentheses and it's going to take a configuration object. Inside the object, we need to tell it what container to be hooked to. So container: Ref.current. And we have to specify a renderer. Uses Preact but we're going to use React's version of everything. So that's an object that's going to have Preelement, which is the method it's going to use and fragment.

JASON: Create element.

BRYAN: Just pass those two.

JASON: Like that?

BRYAN: Exactly like that. Perfect.

JASON: So we're forcing the, I got it. I got it. OK.

BRYAN: Telling auto complete what renderer to use.

JASON: Got it.

BRYAN: Next up, we're going to use autocomplete's render method. I'm being very explicit about that. So it's render parentheses, we're not going to it's not property. So, yep.

JASON: OK.

BRYAN: It's going to take an object at the beginning that's going to be the children and then, the root after that. Outside. Yeah.

JASON: As a second argument.

BRYAN: Inside the function, things are going to get slightly confusing, React Dom's method here. Naming is the hardest thing in dev as we all know. We have two renders on the page. It's fine. So inside this, we're going inside the next render call inside of this. It's going to accept two arguments, children and root. Children without the object notation.

JASON: Like that?

BRYAN: This is boilerplate. We have a how to use auto complete in the docs. This is copy and pastable from there.

JASON: OK.

BRYAN: We can go ahead and close out of our auto complete initialization. You already kind of have and go outside that method call. I'm going to take us one step here and make sure everything works. We're going to return a function and use search.destroy.

JASON: Use effect or something?

BRYAN: Yep. I got way ahead of myself.

JASON: No worries. Let's do use effect. And is this only on initialization?

BRYAN: Yes, actually, check for props in case we need to pass problems, if props change, we want to keep an eye out for that.

JASON: We're going to move this in here.

BRYAN: Yep.

JASON: The return statement, we need to return cleanup.

BRYAN: And there's a destroy method on that search that we just created. So search.destroy as a function. And that will

JASON: It's honest.

BRYAN: It is. It's very death starrian. But it works.

JASON: OK. All right.

BRYAN: Outside of our use effect, we're going to return back, basically, our new component. Return the div of that container ref. Also, I appreciate chat has been working diligently to make sure that the submarine covers the Kelly Vaughn name. Thank you, chat. I appreciate that.

JASON: Not Kelly Vaughn and honestly, given how this is working, let's just update here, we'll make it a dumpster fire because that's how this is going. Perfect. Let's get this, get this thing rolling here. Where should I put this?

BRYAN: Your index.astro, so we can decide where we want to go. In my playground, I put it above the two images, you can put it wherever you'd like.

JASON: We'll go components and auto complete.JSX. And we're just sticking it wherever it needs to be, is that right?

BRYAN: Exactly. I put it down inside your layouts above your products, basically.

JASON: Right here?

BRYAN: We need to do a couple of things. We can't put auto complete. It's not going to work properly. It's not going to work as a server rendered component, static rendered component. It needs to be climb visible and you need to tell, I think you still need to do this in astro, tell it to use React to do that. Client: Visible equals React.

JASON: Like that?

BRYAN: I think so. I'm pretty sure we need that.

JASON: It doesn't like something we did. You might have mismatching versions of React. And you know what we need to do? We've got to enable that render.

BRYAN: In the config, you're right.

JASON: Astro renderer React. And then I'll have to stop and restart that to get that to work.

BRYAN: There's some configuration that goes into it.

JASON: Cannot find astro renderer React. Did I typo that? Astro.js. That's my fault.

BRYAN: Yeah, there we go.

JASON: Typos, thank you, Jordan.

BRYAN: Good catch.

JASON: Chat is always faster than me at that stuff. We're getting closer, closer, no such file or directory, build React dom.

BRYAN: Did the install work?

JASON: Try it, again. Let's make sure it worked. Here is our React Dom, let's try it, again. Come on, do it. And now, we have auto complete.

BRYAN: It does nothing. We haven't told it to do anything yet. But it has a nice search icon and it's going to fit 100% and all of that good stuff. The first thing we can do to make it a little bit easier to use is inside of index.astro, we can pass a prop to it. We can pass the place holder prop, which is just a configuration item inside of, oh, one more thing to do inside of auto complete jsx, sorry about this. Add that in. I would say try/slap or something like that. But we need to pass in at the end of the search initialization, we need to spread the props into that.

JASON: Spread the props into what?

BRYAN: At the end of the render statement. We've got the render inside use effect inside the search, right there. Then, just, spread prop so all of those props get added in as configuration objects.

JASON: Got it, got it, got it.

BRYAN: We could've put a place holder property on the if I weren't fancy. That's going to let users know what to play with. Gives them an example of the actions they can take.

JASON: I got it.

BRYAN: We don't have data in here. So auto complete assumes data. You need to have data to populate it. Oftentimes, that comes from an Algolia index or a third party API, we're going to do things statically for our actions so we can have functions attached to them. So back into our auto complete.jsx.

JASON: OK.

BRYAN: Add a new property on to the configuration. All the stuff we're going to do is inside of that search, auto complete initialization area. So the next thing we need to do before the prop spreading, we keep the prop spreading last to keep things clean.

JASON: OK.

BRYAN: We need a few additional things. We need a set of sources, we need, where are my notes for this? A few things here. We need that code is a mess. We need sources and templates and other stuff inside of those sources.

JASON: Get sources is that?

BRYAN: Exactly what we need.

JASON: OK.

BRYAN: Inside of that, we're going to have that, that's just a function, get sources method. And then, really what's that's going to do actually, sorry, this is going to be get sources: And takes an error function as it's, there we go.

JASON: OK.

BRYAN: And we can actually, instead of returning in the brackets, we're going to do an array, return immediately out into an array for that. You could do other mutations and things like that as you needed but we don't need to do any of that. So each object in this get sources method is going to be, basically, a federated search for things. An object with a source ID and we're going to call this actions.

JASON: OK.

BRYAN: This will need a few additional things. Two things we need are templates object in a get items method.

JASON: A get items method?

BRYAN: Perfect. So get items is what we're going to do first. We're going to turn back a static array. But we could, in theory go get some API calls, we could do some mutations all of that good stuff. But we're going to return an array and that array is going to have one object inside of it to begin with.

JASON: This is going to return an array as one object inside of it?

BRYAN: Yeah, and we'll give this a few pieces of information. Label's just a property. And this is actually almost anything we add in this object is custom named. Right? None of these things have special meaning, we're going to use them in various ways. It could be name, title. This is just the label. And then, in this case, we're going to have it be slash slap.

JASON: This is the command we want to run?

BRYAN: The command but also the label.

JASON: Gotcha.

BRYAN: I like to have a place holder on this, as well, to give additional information about what they're going to do. So I would have placeholder as a string, and then, put a space in there just so we have things a little bit easier and then I said, your address@email.com.

JASON: OK.

BRYAN: And then, that's actually all we need for this to show up.

JASON: OK. And this is JavaScript.

BRYAN: Yes, definitely JavaScript.

JASON: If I save this

BRYAN: We're going to error out or we're going to get OK. Let's see.

JASON: Do I need to reload?

BRYAN: You shouldn't need to reload.

JASON: It's doing something.

BRYAN: I told you two things we needed, we did one of them. We have our data. We need a display template for it. So inside of our template's object, the one we're going to focus on now is the item method. So inside this is going to have an item.

JASON: Just one item?

BRYAN: Yeah, inside this as a function.

JASON: As a function?

BRYAN: Yep.

JASON: OK.

BRYAN: It's going to take an argument, we need to destructure an object to get the item. There's other things that get passed into the item. But into this, we just need curly braces item.

JASON: Got it.

BRYAN: JSX, string, something like that. Return back paragraph with item.label for now. Items and object, we want item.label.

JASON: OK.

We're building out the whole thing.

Let's make our lives easier and make it open when a user focuses on auto complete. Open on focus inside our auto complete.

JASON: Open on focus.

BRYAN: And do one thing to make our user slides easier so we automatically select the first item in auto complete.

JASON: OK.

BRYAN: Default active item ID. It's a mouthful. And that's equal to curly places zero. We're not filter on this, but if you type slash slap space, your email address, nothing will happen, but it's here. And it's ready to go.

JASON: Mm hmm.

BRYAN: We need to tell auto complete what to do with this information. JA ya yep.

BRYAN: The overall source, so this one big source that we have, the actions source can have an on select method as one of its items.

JASON: OK. Do I put that in as an item?

BRYAN: That will be, no, it's outside of items call. I think that's where it needs to be.

JASON: OK.

BRYAN: You can pass in parameters, I pass in params and that's going to give us a couple of things we can use to do stuff with. Inside this, we're going to destructure params into item and set query. Back to nothing with a user selects. So we can use these two things. So the first thing we're going to do is call item.on select. We're going to make this method in our data.

JASON: OK.

BRYAN: After that, set query to a blank string. And that will remove the query because after you've sent it, we don't want it in there anymore.

JASON: Gotcha.

BRYAN: Now, add that on select on to our data.

JASON: Right. And is that in the

BRYAN: The get items. That will be the third property on this.

JASON: That gets params?

BRYAN: Yep. But basically at this point, we can do whatever we need to. So the item got myself backwards. So a couple of things that we get out of by default in auto complete. The first of which is in our get items call or our get sources call, we can pass in the query and we do need the query that's being sent.

JASON: We need the query being sent. Here? OK.

BRYAN: We can use that to filter things but we're going to get what the user typed in.

JASON: Gotcha.

BRYAN: We're going to pull out and split on that query the label and the thing that came after it. So, inside of our on select, set up a ticket ID or email or something like that. Query.split, currently inside the big object. The label's what we want to split on.

JASON: OK.

BRYAN: Label, plus a space. Is this making sense? We're going to find

JASON: So

BRYAN: Label plus a space.

JASON: The query is this whole thing. Slash slap space email. What we're doing here is going to get the second item.

BRYAN: The second item on this. So the first, you know, the first index of that. Yeah. OK. I have never destructured like that. Never thought about doing an array like that. That's exactly what we need.

JASON: OK.

BRYAN: I put a bracket 1 at the end but I'm old school.

JASON: This is helpful if you put a comma, it skips. It's nice when you're trying to dump something.

BRYAN: That's what we need, the email address to the user. Let's console log it to make sure we get it. We can send that as a fetch over to over to your function.

JASON: Here we go, we're going to console log the email. I'm going to come out here and we're going to slap, no slap. And then you hit enter.

BRYAN: Yep. Go to my console.

JASON: Ta dah!

BRYAN: Send that as a post request, or send it however you need to

JASON: And we can do that here?

BRYAN: Inside this function.

JASON: OK. Chaos. Is suddenly available to me and I'm very excited about it.

BRYAN: Yeah.

JASON: OK. All right. We can, then do a fetch request. Can we make this async? Can I async this?

BRYAN: I don't think we're inside of yeah. Give it a shot. I have never tried that. But absolutely.

JASON: I'm going to async this and we'll get some data. Await the fetch and fetch API, look at the name of this, again claim swag. That's going to be method post and we'll send in our headers of content type, I don't think we actually need this. I feel like I'm making my life hard by having to type out application JSON.

BRYAN: Isn't it safer this way?

JASON: Safety? That's not how we do things on this stream? We're going to stringify the email. So what should happen, then, is we'll get the

BRYAN: You're awaiting. Do you need to be doing it then?

JASON: Otherwise, we would have to do data and await. This should get us back just the data at which point we can console log data. Let's give it a shot.

BRYAN: I don't know if async's going to work.

JASON: It works, y'all. Look at that, we're claiming, we are claiming swag through a commandbar. That's dope. That's really nice that just worked.

BRYAN: Should we go for swag points? Or do we need to do other things? Do we want a message appear?

JASON: I want to do so many things. What can we do? Take me on an adventure, Bryan.

BRYAN: So, why don't we first make sure that we have a function that you can use later to do some notification. That's good user experience. Let's have inside of our component, outside, like, in the component file, you could be a good clean person and move into the utils folder. Let's toss a function here. Show message function. So we can do something with it. You could put in inside the source. But I think we might want to reuse it if we did another action.

JASON: Fair enough. So we can, theoretically, make this work. And so we want

BRYAN: Have a console log. It's dependent on how you want to integrate it with the rest of your astro project. Console log, the message and we can, basically, pass in what you get back from your function, that way if it errors, even, we get the error into the console, as well.

JASON: OK. All right. So down here, instead of this, we run show message.

BRYAN: Yep.

JASON: We will and we get a message and the message comes back with a coupon code and, yeah, there we go. I wonder if, I mean, one way we could do this is, there are a lot of options for what we could do. I think the challenge is that we didn't, like, you know, this was not an app that was built with scalable architecture in mind. It was, let's see if we can solve this problem, right? So this is what I would consider like an MVP of an app. So, there's some things we don't know how they're going to work. Like, could we get other, like other parts of the app to fire off? Maybe. Probably. I don't know. We could see.

BRYAN: Dangerous words.

JASON: Yeah, right. So I'm curious, like, there are a few things that we've done here the one that's getting me a little bit is when I run this, like, it empties, now, is this the sort of thing where, we've got a kind of general commandbar. Is this the sort of thing that we we could style this up to only show when we use the command K shortcut. We could do other things, too. I guess, maybe a better question for you, what do you want to try next? What should we try to adhere?

BRYAN: I've got 3 options I'm semiprepared for. We also go completely AWOL and all of that. Few things we could do. We could make sure as we type, it is actually filtering and we are highlighting what the user's typing. We could integrate and get some other Algolia not Algolia, but Netlify or Jamstack swag appearing in there. We could also add another action that could fire off the work that you were doing with Kelly for the second area down below, right? To have a swag pack.

JASON: I see, so we could have a

BRYAN:/pack command.

JASON: Oh, look, we have an index problem. That's fine. We can live with that for now. But, what would be interesting is, like, could we get it when you use the coupon code, we could throw it into the cart?

BRYAN: Yeah, anything's possible. As soon as we get the response back, we can update that.

JASON: Yeah. What should that on select be inside get sources?

BRYAN: Naming is hard. There are two on selects we're talking about. One is a method provided by the auto complete library and that is the method that fires inside of a source. Right now, one source that has one item we fire that method and you can do anything you want at that point. We need to fire a specific command based on the data we have. In this case, we set a new method on each item specifically that will fire when a user selects an option in auto complete. That will happen if a user navigates to it. A few ways to fire. On select versus on click or something else.

JASON: Got it. Got it got it. OK. So, yeah, basically, we are, we're giving the item an on select and defining that on select here.

BRYAN: And that allows us to have multiple commands that do whatever each command needs to do. It doesn't shoe horn us into one thing to happen when the on select method's called.

JASON: There's a lot of flexibility in this and that's what's exciting. When we get into this on select, that's basically somebody clicking button. So this can do anything you could do in a click handering. Handler.

BRYAN: Yep.

JASON: If you've written click handlers, you could basically reuse them. Click this button to claim your code or use the command thing and we can call the click handler with the email. That's that is really exciting, I think. For me, at least, the part about this that gets really cool and where I feel like there's so much potential is, you know, you can build these really complex interfaces and, for me, I'm a power user, right? I'm a keyboard shortcut guy. I like using keyboard shortcuts. I, you know, love the Alfred is the one I use most of the time and it's got all of these things I can do. I can run snippets and, you know, do standby text to things I do all of the time. And there's all these things that are available through this sort of keyboard shortcut of command bar. Really, really nice.

BRYAN: Can I blow your mind really fast, Jason? Not something for today, but this is all inside a search box, right? It's a command palate and plus search and everything else. But what if your search box was in a rich text field and what if your search box appeared when you said the character act and searching for people you can mention or documents you could mention.

JASON: The way it works on Twitter?

BRYAN: Yeah, we have a piece of documentation that covers creating Twitter's @mention stuff. And talking about auto complete is writing even more around it. So to go further and talk about how notion does it, how all of these big companies are doing it and all it can all be powered by auto complete JS. What happens when you take a search box and make it this inside of a text field? Like, a lot of things can happen. And anything that can happen in JavaScript can happen. It's pretty cool.

JASON: Really cool. It shows, I think the part that is exciting about this is it's an abstraction that's simple enough. Like, OK, simple is maybe a loaded word. There's a lot that goes into configuration, but in terms of presentation, you know, when we look at what we're building here, it's not much like it's, you know, there's some this, we can style that up however we need to. And we're using this theme. But we could dig into this and figure out how to change the theme and make this look however we wanted. Right now, it's like, if I just want to dig in here a little bit and figure out what's going on, we can click on it and here's the auto complete. All right. So these are all the things that are happening here. If I want to add new styles, can do it with 300. Whoops, if I add a unit to it. Here's now, we've got this, right? And we can just go in and kind of make this stuff work.

BRYAN: Yeah.

JASON: And it works the way we want it to work.

BRYAN: You can remap the classes to other class names. If you were using tail wind or something, something that came with a built in input kind of field, you could have all of those map over to whatever, you know, whatever pattern library design you're using.

JASON: Yeah, I see Phil in the chat talking about his imagination is popping and mine, too. Another thing to potentially happen, you can run sound effects on my STROO stream and a while back, we started out this prototype of allowing people to log into a private dashboard and one thing that would be cool, it would be fun to do a SOIND board.

BRYAN: And the great thing can't please everyone all the time. Come on. I love the sound effects. I don't know. I don't know.

JASON: There are so many good opportunities for making your apps better. And you're already pulling this data together. You already made the list of posts that data got pulled from somewhere. If we feed it into this items array. So we drop it into get items, put the data in here. For of each of these, this on select is something we could reference at which point we have made a fully, recan do really powerful stuff here. This is just an action, right? We could do a whole other set of sources. This could be action. So you want to run the commands. I want to, I don't know, if you're a mob, I want to get a list of subscribers. If you are any subscriber, you can get a list of sound effects.

BRYAN: You could make it inactive and then, a user knows, oh, well if I want to interrupt Jason constantly, I can subscribe and I can get these actions. It's all about what's showing what's possible to the end userbeing like, hey, wouldn't you want to use your prime subscription on Learn with Jason.

JASON: It costs you nothing if you're a prime user and I get a dollar and that helps me pay for the live captioning we've got going. It helps me do things like make these rubber ducks. Have you seen my ducks? Yeah, if you know you can buy these I made so many of these and I you can get them now. If you want to go to the store and get yourself a rainbow Corgi, that's a thing you can do. And your subscriptions make that possible.

BRYAN: So, Jason, I don't have this, right? But I did a little prep work and I made an Algolia index of swag with Netlify. Should've used your swag, that would have been more fun. Corgi toys. But we could kind of showcase what that might look like. 17 minutes. Like

JASON: We've got 17 minutes. 17 minutes till victory? I say we do it.

BRYAN: I'm going to need my cheat sheet on this one. We're going to use a couple of new things and we are going to need to install some stuff.

JASON: I'm ready.

BRYAN: Only one more thing and that's going to be Algolia search.

JASON: NPM install Algolia search, like that, right?

BRYAN: Yes. We're going to auto complete works with any API or static data as we've seen. But we have a couple of helper methods for Algolia. It's an Algolia open source library and does extra batching and other stuff at the request. Stuff that goes way over my head. But it's nice. It keeps things fast. Is a big thing for us. So what we're going to do is initialize a search client to actually make calls to an Algolia index and display those calls, display the items in the index alongside our actions. If you missed your opportunity to get a slap bracelet. Maybe you want a Netlify T shirt, right? So you can display that next to it. And even if it says sold out in our command, like, there are these other things in there, as well. We can do kind of the dirty version of this. Import at the top of our component. Import get Algolia results, CamelCase inside the object. And this is going to come from the auto complete library. This should work.

JASON: We'll make it work.

BRYAN: And we need to import Algolia search from Algolia search but not going to do it from the full library. Algoliasearch/lite. The query only part of it. You don't need the entire library, it's got a lot of additional stuff for writing data and all of that. We want the lite, it'll be faster, speed, speed, speed. And then, we need to initialize that search. That search client. So let's make a new variable right under our imports, const search client, equals Algolia search and two arguments and actually, I'm going to send these to really fast. I trust chat. It doesn't need to be an environment variable. These are actually both publicly available and would go into a build process anyway. This is the

JASON: I have to go between two computers. It's OK. I can type very fast.

BRYAN: OK.

BRYAN: Do you need to paste it somewhere else? This next one?

JASON: It's happening. F55A.

BRYAN: This is rough. I see what you have to type.

JASON: 0AD

BRYAN: It's in the repository on your computer.

JASON: You told me that now. OK. So that's like 80% certain that's going to work.

BRYAN: Two things happening there. One is my app ID in Algolia and the other one is the search only API key. It's read only, you can't do anything malicious, you can rack up charges but I work at Algolia, they'll strike them for me.

JASON: That sounds like a dare. Don't do that, chat, don't take that dare.

BRYAN: We have a search client, we need to do something with that. So we're going to add a new source. So in our get sources array, we're going to add a new source. And let's give it a source ID of swag. It doesn't really matter. It's a unique identifier.

JASON: Got it.

BRYAN: And need to do a get items call here. Same as before, yep, just function. And we're going to return the get Algolia results method and pass that configuration object. So first, we're going to pass it the search client that E with just created. And then, we're going to pass it a set of queries.

JASON: Okay.

BRYAN: This is an array. We're going to do an object and only going to pass it one query and pass index name. Inside my Algolia dashboard, I have an index called this. Pass it the query that we get from our get sources so that Algolia knows what the query is. And then, we can pass it any number of parameters, which I don't actually think we need to worry about right now. Let's leave that and see if we get it OK. .

JASON: That's it?

BRYAN: Search client queries and template, let's do two templates on this one.

JASON: OK. So templates.

BRYAN: Let's start with a header to separate things out. We have actions, now, let's set up the header and return an H2 or H3 or something like that. Inside this header parentheses. A header function.

JASON: OK.

BRYAN: And return H2, probably. And let's say more swag or something like that. We'll pass one item with two things. Item, we need all of the item information and then also for Algolia results, we have additional components. And those components will do things like automatically highlight our text. Automatically do things for us. So we need these two things and then, we're going to return.

JASON: What was the second thing?

BRYAN: Components. Naming.

JASON: OK.

BRYAN: Return out. An anchor with H ref. I grabbed 3 items and I made objects for them inside of my index. Let's go ahead and close our anchor. We can put a title if we need to in all of that. And inside this, instead of grabbing the item.title which we could do and it would display, let's make sure as a user types, we highlight this. Let's do a component called components.highlight. So left angle bracket components.highlight. Highlight's capital H. It's going to accept two props. It's a self closing tag, thank you.

JASON: Got it.

BRYAN: It's going to take a hit, a search result coming back, the hit is going to be the item, the entire item object. And then, it takes an attribute, and that attributes's going to be an attribute of the object. In this case, I have a title that is the titled swag. Equals a string of title. And close your anchor on the other side if it's not. Let's see.

JASON: Was I supposed to add a highlight? Or it does highlight?

BRYAN: It's highlighting because you're using components.highlight.

JASON: It's smart. I don't have to build this out.

BRYAN: Exactly. We could build this out. We could've built this out for our actions. I think this is more interesting. Save it and I'm going to cross my fingers and hopefully, we didn't break things. We broke things, let's take a look the a console and see what we got.

JASON: It didn't like templates.item is not a function. Is it supposed to be items?

BRYAN: Items, items.

JASON: Ah. Nope. No. I fixed you.

BRYAN: It's item. It is item. Templates and we have templates. Templates is not an array. It's one big object. I should have caught that earlier. One big object with multiple things inside it.

JASON: Oh. So that's what I screwed up. Like this?

BRYAN: Yes, if everything is lining up. That should be fine.

JASON: Hey, look at it go! Beautiful.

BRYAN: Now we have our actions and 3 additional pieces of swag in case people are disappointed they can't get their slap bracelet. And you can actually

JASON: Click that and goes over.

BRYAN: One thing we're missing and we'll do this fast you can't keyboard navigate and have it work. If you navigate to Netlify and hit enter, nothing will happen. We need to tell it what to use when that happens. Inside of our where did it go? I'm terrible at syntax, I have to have my cheat sheet handy. We need a get URL, get item URL.

JASON: In templates?

BRYAN: Inside source. Use the method get item URL. So right do right after the yeah. And that's going to take as an argument an object we need an item off of. We need the item. And then, return item.URL. And that's going to tell auto complete where to send people when it's selected. So now, yep.

JASON: Ta dah!

BRYAN: They're in the keyboard. Fully accessible at that point. You don't have to worry about that. It's all ready to go.

JASON: And I tabbed through to get to all of the things I needed.

BRYAN: You could although use your arrows. JA ya let me rephrase, I came out here and like tabbed through the site to get to the auto complete.

BRYAN: There it is.

JASON: Can I can use my arrows to get around, drop in, ba bam.

BRYAN: Type in Netlify.

JASON: Mhmm, yep, that's nice.

BRYAN: We don't get that out of the box. We didn't do a filter on our actions.

JASON: We've got 6 minutes, do we have time?

BRYAN: We have to write regx. Are you prepared for that?

JASON: I'm always ready. Let's make it happen.

BRYAN: We're going to get a little hairy.

JASON: Not me.

BRYAN: Me, too. Right? I have this. I have the cheat sheet because I need the cheat sheet for it. In our action's get items, we're returning an array. Right and we're going to set up a filter on that array. At the end of that we're going to grab, not the item, we want to destructure the item to the label. All we need is the label for this. And we're going to need to test it against a pattern.

JASON: I'm so ready for this label.match and we're going to do something like this. BRU.

BRYAN: Go for it.

JASON: We should be able to go query. just the string?

BRYAN: Yeah, should be the string, I think.

JASON: So we're going to do just the query. That's not going to work. We want it to be like this, we'll set it up with the query. Right? We go query and then we pass in the flags of case incentive.

BRYAN: Yeah, should be the only flag we need.

JASON: And that was one, two, three. Huh?

BRYAN: Except for

JASON: No, I broke it.

BRYAN: Yep.

JASON: That filter is not a function. Don't you lie to me.

BRYAN: You're not on the array. The .filter needs to be on

JASON: It is on the array.

BRYAN: We want to be on actions. Inside of our slap, right? Where the slap is. It's in the first get sources. I'm pointing, you can't see I'm pointing. So at the end of this get item's array, that's where you want to filter. You're filtering that array.

JASON: Here we're filtering?

BRYAN: Yes. We lose it from that one. But if you type slash,/slap, let's see if that works.

JASON: That's only filtering this get item but it's not filtering this get items.

BRYAN: But Algolia is filtering the other get items. Algolia's handling all of that based on our index rules. It should be, at least. Was it not?

JASON: Oh, it is. OK. OK. I didn't realize that.

BRYAN: Yep.

JASON: I understand, if I say Netlify, there's Netlify in the description, which I assume is matching. So it's like

BRYAN: Is it, though?

JASON: I wonder where it's coming from the URL and it's matching the URL?

BRYAN: Might be. I haven't configured this index really and you can do a whole bunch in the configuration to make sure stuff like that doesn't happen.

JASON: We can see the command and the swag item. So we've got, we've got our filtering working. We have a pretty basic regular express going there. Dope. This is dope.

BRYAN: I'm not going to say the possibilities are limitless because you're limited by a whole bunch, but there's a lot of weird stuff you could do. And I say weird, I feel like this audience is the one there's some weird stuff you can get into with this. Mm hmm. What I love about this is the happy path here is really happy. Like, let's go look if we go in here and we look for Sarah. This like the happy path here, there is a Netlify plugin for Algolia that if you add this build plugin to your site, it'll automatically, the build plugin is linked down here, you can see here this Netlify plugin. If you add this Netlify plugin, any site that deploys through Netlify will automatically generate an index, you don't have to configure it, you don't have to think about it, don't have to do anything. And then, you add that index the way that we added our index here. You do the search client and the key, the read only key. And then, you just drop that sucker in right here. Right? So we drop that sucker in, we put in the index name, which gets autogenerated and you find that in your app. And then, you just drop it. This is bog standard theme classic Algolia auto complete with that index. I wrote maybe 10, 15 lines of code to get this running. And now, you can search the you can just do I had an alias here. If you search, it's my name, right?

BRYAN: It's highlighted everywhere

JASON: This is such a powerful and fast thing to do and if we want to go deeper, if we want to jump off the deep end, we can't. And with that, we've got 1 minute left. Bryan, what a day. You're not Kelly, you're not Rob, you're Bryan. Oh, my God. It's been a long day.

BRYAN: Yeah.

JASON: Where should people go if they want more?

BRYAN: Twitter.com/Algolia or Algolia.com. And actually, since I think Ben is in chat talking, check out doc search. For those of you who do open source and now technical content, if you're making technical content, you can use doc search. We can get you set up. It does some scraping, some other stuff where it gives you search out of the box. If you're doing technical authoring or docs. And then, yeah, Twitter.com/BRob for me. We're going to be doing more around super user stuff for auto complete with Sarah in the next few weeks. There's even a CSS article that's coming that's going to be really interesting.

JASON: Absolutely. Today is the last one we're doing for today, but it's not the end of this app. So on Wednesday, Nathaniel Kenwell's coming back, he's been on the stream before, and we're going to use the send grid API, which is part of Tulio.

And we're going to set up some error monitoring on our app. But that's not all happening this week. We've got Jennifer Widelo coming tomorrow doing dev flow work optimization. I saw people asking about my VSCode plugins and my CLI setup. That's what we're talking about tomorrow. If you're interested in that stuff, come through, Jennifer is brilliant, she's really funny and she's going to talk about how we can boost our productivity by setting up our environment. Then, we've got Thursday, we're going to do color contrast and accessibility with Todd Libby. You may know Todd Libby from eating lobster rolls. He's also an accessibility enthusiast and expert and on Thursday, one of my favorite people in the whole world Aisha Blake. Make sure you join. And we're going to add observability to Jamstack sites using New Relic. What a week, y'all! Head over here and add to the calendar so you can see when these are happening and you don't miss one. It'll adjust for your time zone. And with that, we're out of time. We're over time. Oh, my goodness. Bryan, thank you so much for helping us. Y'all, thank you so much for hanging out for a 3 hour marathon. Appreciate you. Thank you to White Coat Captioning for sticking through and Diane for running those captions all day. Thank you to the sponsors, as always, who make the captioning, you know, Jamstack Conf made this possible. Oh, God. Inception. We've got the captioning, and we've also, Netlify kicks in Fauna, auth0. And with that, we are done. Bryan, thank you so much. Chat, thank you so much. We'll see you next time.

Closed captioning and more are made possible by our sponsors: