skip to content

Let’s Learn CommandBar!

Adding a ⌘+K shortcut to open a command palette in your app is a great way to give your users more control. CommandBar lets you add powerful search, nav, & custom actions quickly. James Evans will teach us how!

Full Transcript

Click to toggle the visibility of the transcript

Captions provided by White Coat Captioning ( 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. And welcome to another episode of Learn with Jason! Today on the show, we have James Evans. James, how are you doing?

JAMES: I'm good. Thanks for having me.

JASON: I'm happy to have you. This is going to be a fun episode. Do you want to start us off with a bit of a background?

JAMES: Yeah. For sure. Let's see where to start. I'll talk about myself for 30 seconds and then talk about CommandBar which is more interesting. I studied computer science in college which had the primary benefit of helping me meet my two cofounders, Richard and Rene. Never actually worked a day in my life as a software engineer which is how I disclaim any technical problems we encounter today. I actually started -- my first job was in investing.

JASON: Okay.

JAMES: Which is fun in a lot of ways. But quickly led me to realize that I wanted to build stuff as a career. I left the world of investing. Joined a startup. I made the rare web 3 to web 2 transition. I joined a crypto startup and then in 2018 when that went bunk, we started working on our own projects and CommandBar is the latest and definitely the greatest of those.

JASON: Nice, nice. So, let's talk a little bit about CommandBar. So, CommandBar is the name of your company, but CommandBar is also something that I've just started to see show up in the wild a little bit. It's become increasingly popular in Slack and Discord, all over the web to see this command K shortcut. And that opens up a bar and then I just type something into it and I'm able to navigate or move around. And so, I guess what -- like did CommandBar start that, did you sea that starting?

JAMES: We definitely did not. We see ourselves as evangelists of the pattern. Definitely not the creators of the pattern. We -- the brief origin story of CommandBar. Richard, Rene and I were working on a different product, a tech product. If anyone in the audience teaches computer science, it's called Code Post and it's a free tool for helping CS instructors give feedback to students. We were working on that. For the sake of this discussion, think of it as a generic crud software product. And we were working on that. And our super powers as founders was we were really responsive to user feedback. Which meant that any feature that a user wanted, we would put into the product and people really like that. The problem is if you do that repeatedly, you end up with a product that's really hard to use. You use the features, and as a user, it was hard to understand how to set up your account and get value in the way you wanted. We were trying to fix this problem and we all used apps like Yes Code, Super human, that had this pattern. We realized that this could help mitigate, even solve our UX problems. Because instead of someone landing in Code Post, having to figure out all the vocab words we were using to describe our business logic, what page to go to, to do action X, they could just search. Just state events and then it would be the job of the search bar to go to the next steps that would correspond. And so, we built it for that product. And the more we got into it, this is the most amazing -- ever. Why doesn't every piece of software have this? Why is it limited to these few products? And long story short, we decided that -- that's how CommandBar was invented.

JASON: Gotcha. We're having a little bit of connectivity issues here. It sounds like you might be buffering a bit. But we caught 95% of that. And for folks who are watching live, if you want to follow along in the live captions, that will also help in case anything gets garbled and in the way. So, yeah. I mean, I kind of agree. I -- the command palette, this idea of a universal command K shortcut is really exciting to me because I've found that as I've navigated around different apps, this universal ability to just hit command K and then make stuff work, it creates a uniformity across my entire experience. And, you know, you mentioned stuff like, okay. So, Superhuman, that's what I use for email. Slack and Discord are what I use for chat. All of those, I am doing something and hit command K and it works. And if you want to try CommandBar in action. Go to your Netlify dashboard and hit command K, you would have the same experience as in Slack or Discord or superhuman or any of these that have a command palette. CommandBar opens -- this is the part that's cool about CommandBar. What I've used it for is like navigation. I would open it up and say, take me to my sites. But it does more than that, right? What else can you do whether you're using CommandBar?

JAMES: I think like the geeky way to describe it would be it lets you query content just like a regular search bar. But also query over business logic. And that can mean jumping to any page in a product. Random access. Instead of like having to understand the hierarchy of how pages are constructed. Maybe you're looking for a specific setting. This is a use case we see a lot. often times a user is looking for a specific setting. This is a use case in Netlify. You might know where the settings page is, but there might be eight pages of settings and you might not know what's the actual sub page that contains the setting I'm interested in? One of the most-used CommandBars in the world is actually in macOS preferences. The search bar on the top right. No one is figuring out -- hierarchy is so inscrutable. I have been using Macs for 15 years, still haven't figured it out. The random access of pages is a big one. That's a simple use case. And we'll set up the navigation use case. It's really quick. You can take it further and actually let users take actual, you know, create or update actions in a CommandBar as well. And so, we'll walk through a case there, you'll be on a detail page and you might want to edit the underlying content. What's the button or the menu that contains the action that I want to perform on the record? Or you might know it, and this is the other problem with CommandBar. The first set kind of discovery. I'm trying to do something inside of product. I'm not totally sure how. That might be because I'm a new user, or I just don't use the product often. The second category is I know how to use the product a lot, I know how to do what I do. And that's slow. That's the value of CommandBar. It's a lot faster to use with or without the shortcut. And we'll get into the distinction later.

JASON: Okay. Yeah. And the first thing that comes to mind when I imagine implementing one of these is that sounds like a lot of work, right? My initial gut reaction is to have a command palette, does that mean I have to re-implement across the app? I built these settings pages and these inputs. Do I have to re-implement all of that? Here are my forms, and here are the different inputs that I need, is that all getting re-implemented? How does that work when you start plugging into CommandBar?

JAMES: Yeah. I think the easiest way to understand this is, you know, we'll get into this and we'll see the way we set up the -- the demo app that we're gonna walk through. We tried to simulate was an existing app with the existing data sources. How do grow from that to an app that also includes a great command palette.

JASON: Right.

JAMES: It's really -- the way I think about it, I like analogizing CommandBar to Neuralink. Maybe that's my ego speaking. You can think about it. You have to wire up CommandBar to data, sources and actions and we take care of the presentation -- the actual user experience part.

JASON: Oh, interesting. Okay. Okay.

JAMES: We're the search bar that lets you take actions.

JASON: I got you. That makes sense. Let's see. What else should I ask? What have you seen as people are building out their CommandBar experiences? You're, you know, you've offered this basically software as a service. So, anybody who wants to can go to CommandBar, sign up for this and implement a command palette on their site. What would you say are the biggest things people are seeing in terms of benefits? And also, surprises as they -- as they implement this feature on their sites?

JAMES: Yeah. That's a good question. I think the most surprising thing that people realize once they set up a CommandBar -- and frankly, this was somewhat surprising to us as well. I think a lot of people think of a command palette as a power user experience. And it's like -- it's kind of -- it's kind of in the -- I think in some ways we do ourselves a disservice by calling ourselves "CommandBar." Because it sounds like -- and it is -- portmanteau between a search bar and a commandline. That's like very explicitly what it is. But then people think, command, commandline. That must only be relevant for people who use a commandline. So, a technical audience. Or power users. People who are using, you know, a product a lot. Kind of that speed use case we were talking about. What we find over and over again is that it's yes, it is really useful for those people. But the discovery aspect is like creates, you know, as much if not more value for the people who set up CommandBar. Because what they find is the new users increasingly have that muscle memory to open it and type what they're trying to do. Because they don't understand the underlying command. We're working through -- go ahead.

JASON: I was just gonna say, that actually makes me wonder, do I get -- do we get analytics as CommandBar users that say this is what people search for that gelt no results?

JAMES: You totally can.

JASON: What people are trying to do?

JAMES: Yeah, that specific search -- a specific search that our customers have found really useful, we call it Dead End. It's a search that didn't end in a successful command execution.

JASON: That's like passive user research too.

JAMES: Totally. Yeah. And one of the things we encourage everyone to do is once you have been live for 2 weeks, filter all your Dead Ends for your new users. And then you've got like a great list for what people want to do in this your product but aren't able to do.

JASON: That is... had not even considered that. And that's a brilliant way to look at this. Because it just -- it just makes sense. Like if you teach people that if you want to do something in your app, you should open the CommandBar and type in the thing you want to do. Basically, you have a built-in wish list. Like you've either solved their problem or you didn't. If you did solve it, you set out what you wanted to do. If you didn't solve it, you have a checklist of users say they want X, Y, and Z. I mean, I love that. Because obviously we all should be -- should be, chat -- doing targeted user research. We should all be focused on asking our users out what -- what are they using -- what pain are they solving for using our product? What parts of the workflow or experience or development process are they struggling with? And that helps us build a list that's actually built on user needs and not just like on our gut feeling of what would be cool or practical. But what I love about this is that it -- it gives us that like, okay, I'm not asking users directly. They're telling me directly what they wanted to do. And that's a really great way to validate that the products that we're working on inside of our company are things that people actually want. Like if we've got, hey, 10% of users write this query and it dead ends, that's a pretty good indication that would be a valuable thing to build.

JAMES: And it's totally not a substitute for the more targeted user research that you're talking about. The way we see it used is in two ways. One is to help you tee up questions that you may not have asked. Like we had one customer on CommandBar who set it up and then saw tons of people searching for the word "Slack." This isn't a thing in our product, why are they searching for this? They update with the users and did the targeted research and people wanted a Slack integration. It wasn't on the roadmap. It was striking in the data to see that word and the various iterations and the spellings. And the next is to build N. If you think a lot of people are interested in the future, you can just go into the Dead End data and see like how many people were actually searching for it without me prompting them? Because, of course, we don't want to do the research sessions and say, would you use X?

JASON: Yeah.

JAMES: That's a hard yes to ask. But at one point in time they wanted it.

JASON: That's like the number one, like, major problem that researchers run into are people trying to validate products who go, would you pay for a product that did this? And everybody saws yes and nobody opens their wallet, right?

JAMES: Sure! I'll spend that fake feature money.

JASON: Yeah. And that's the thing. You're not looking for whether or not someone feels they're going to pay for it, or if they have pain if they don't have it. I open my wallet because I need something to be true. Every once in a while is because I want to be happy for no run. Most things I buy are a minor pain. Oh, I wish my laundry detergent smelled better. I opened my wallet to solve that pain. Hey, my desk broke, I need a place to work. I'm going to open my wallet to do that. And it's is the same online. I paid for super human because I want that palette in the email. I turned off the creepy tracking, otherwise I love that feature -- or that product. Things like that.

JAMES: Did you command K preview tracking.

JASON: Yeah, command K, disable tracking, the tracking pixel, whatever they do. Yeah, get out of here. I love that thing. And I think the thing that's interesting is that what -- what this does, like you said, is it gives me a list of pawn people are feeling. Like if everybody is searching Slack, it's because they have a pain. I don't want to have to log into this app and look at the notifications. I want the app to tell me when I need to pay attention. Great. Slack notification. But that's bigger than Slack. What else do you use? Do you use Slack? Discord? Do you want like Twitter host for your status page? All these things, it opens up questions. You can talk to users. how are you using this information? What happens when it's in Slack? A whole new avenue someone might be willing to pay for.

JAMES: I forgot who it was, but someone a while ago Tweeted, why doesn't every app have a feedback box that takes up, you know, the whole quarter of the UI. At least for new users and just encourages new users to dump their thoughts as they're using the product. What they're finding, what they're struggling with. And you thought that was really insightful. But when saw that, yeah, as a product person, I would love that data. But it also sounds like a lot of work on behalf of the user. To like -- even if you're just stream of consciousness. It's laborious to take your thoughts. Doing user interview requires work on behalf of the user. To make your thoughts make sense to the product person. And the commandline is like v2 of that concept. But importantly, it gives the user a reason to do that. Because it's really useful -- it makes it easier to use the underlying application and the user research is kind of a byproduct of the fact that it's like useful for users. And I wanted to piggyback on something you said earlier. Which we think about like all the time. It's just that muscle memory of doing command K. Some people don't do command K, by the way. Command P is also --

JASON: Oh, right, right.

JAMES: We thought about calling our company command K. But we didn't want to pigeonhole ourselves to one shortcut.

JASON: Power bar was taken, right?

JAMES: Yeah. Exactly. We originally for programmers in the audience, the name of our company is Foobar Inc. We thought it was hilarious.

JASON: That's got to be the hardest thing in the world to Google.

JAMES: Yeah. We thought we were being really clever and get free SEO juice. was extremely expensive. Someone figured that out before us. This idea of muscle memory across the Internet is so important to our company. There's this amazing blog post written in the year I think it's 2000 called the end of web design. Do you know this one?

JASON: I don't know this one. I need to go find this one.

JAMES: Amazing read. Basically the premise is web design is over. The building blocks we have today are the building blocks we have going forward. Why? Because people spend way more time on not your site than on your site. And so, it behooves you as a designer to use patterns that other people use because those are gonna be familiar to users. You shouldn't invent your own building blocks because that's going to require a ton of work.

JASON: That's such a good point because if you think about what we do when we're in situations like working at a team that has four distinct units. And dozens of teams working inside those units. I did this when I was at IBM. Everything we talked about was with creating predictability and cohesion and this feeling of using the same app and making sure that everything was predictable and universal. And that was all, you know, we're like, let's build a design system. Build a design language. People get grumpy about bootstrap, the Internet looks the same.

JAMES: That's a really useful concept.

JASON: Yeah. It feels exactly the same to use every site built in material UI. Now, I weep a little bit for the like hit to creativity that comes with that. Like I used to love the weird web. And I still do love the weird web. If you go to my website, Jason.AF, it's weird. The UI is not great -- or the UX is not great. It's a little messy. But that's sort of intentional. I'm trying to be playful and weird. I'm not trying to sell anything on the site. If I was having you go there and perform actions other than explore and play, I would have built that site differently.

JAMES: You're the nook and cranny bar that has regulars and people like it for the aesthetic, not the department store optimized for selling stuff.

JASON: Right. And you go to those places for different experiences. When I need to go buy pants, I don't want to have to like know a secret password to get through the front door and then like have to dodge of bunch of people in American gladiators gear and get to the dressing room. I want to go and get done. When I go to a bar, I want to walk in the door and they throw a water balloon at your head and if you get hit, you get bounced. It's fun and it's ridiculous you tell a story about it. It's an adventure.

JAMES: Yeah. What we're trying to do --

JASON: The site is not broken. However, the road domain is. If you hit www.learn with Jason. But I broke Learn with I will fix it today. Anyways, I just interrupted you, James, go ahead.

JAMES: No, one of the thing us like about CommandBar is most of the forms it's a floating modal. And it is very style-able. It doesn't have to work on the aesthetic of the site. You can summon when you need it and gets out of the way.

JASON: You know what this reminds me of, this is a niche reference for folks who watch a lot of TV. It remind me of on The Good Place, Janet. Wherever you are in The Good Place, you say, "Janet," she pops up and disappears and -- it takes me to the place I need to go or does the thing I need to do and lets me back into wherever I was. It's kind of -- it's not a pattern interrupt. It's like a pause. Pause to accomplish something and then go back to what you were doing.

JAMES: Sounds like Clippy. They refer to us as Clippy, but not annoying.

JASON: You should do that as an April Fool's joke.

JAMES: The design. Going back to the design thing. You can kind of view -- the only thing we do as a company is we are trying to make a new building block happen on the Internet. And so, hearing you say like I use command K across multiple sites, super-exciting because the more people have that same experience, we can create way more value because people are coming to a site, new user. Don't know how something works. We want them to be able to expect this experience where they can just pop open the search bar and state their intent. We believe that should be a universal expectation in software. We're trying to get over this hump of we want the building block to be so common that it becomes a requirement. It's hard to start a new building block, once you get past that critical point, it's the expectation. There have a lot of Netlify users who want this. We see this in other apps we use and we want this experience? Netlify as well. That's cool. When someone comes to us and says, my users want this, it makes my day every time.

JASON: Yeah. And I feel -- one of the things love about tools like this. I made the decision to work at Netlify because of the same thing. When people use Netlify, they compare it to what they were doing before, I don't want to do it without these tools. Make my life easier.

JAMES: It's like two day shipping. You didn't need two day shipping, but it's hard go back.

JASON: Yeah, CommandBar's like that as well. Once I get used to the fact that an app has it, I don't really use NAV after that. Because I mean, this is a standard problem for like every app. As it grows, where do you put things in the navigation? Like, okay, I want a theme toggle. Well, we don't have enough room to put the theme toggle up in the header. So, let's move it under user settings? Appearance settings? Something else? Does it go to the footer? Like where do I go to find that theme toggle? Well, in Netlify, it used to be hard to find. Now you command K, right theme and it says toggle theme, I hit enter and now I've toggled my theme. And I don't have to think about it anymore. For example, we just shipped a new color theme in the Netlify app. That I love, by the way. We might look at it later today. But you can go try it right now. You can just command K, toggle theme, command K, toggle theme. It's so nice to be able to do that. Rather than figure out --

JAMES: And just expect, well, I don't really know. Okay. I'll just command K search for it. The other thing we haven't talked about -- and see how this works once we get into building it. And I think we're early in enabling this as a company. But we believe that you shouldn't have to use the words of the underlying product to get something done in a product.


JAMES: The Netlify command is toggle theme. Now people are going to try to search for synonyms in Netlify and find it doesn't work. We're working on it. But we think you should be able to do toggle theme, dark mode, light mode, change color, any way of expressing that action, you shouldn't have to learn the Netlify words to toggle theme in Netlify.

JASON: Gotcha.

JAMES: That's why people love analogizing it to a commandline. That has some merit. I prefer voice assistant as an analogy. It gets to the idea, you have to -- especially with some of the more free form ones like Google assistant. You tell it what it has to do. If it's any good, it will do it or show you some options. That's the state we're driving towards. Hit app, state intent. Use UI for the stuff that deserves UI. When they have to build a hierarchy in the user's mind, use the UI. Not trying to replace GUIs. It should be easy and you can tell the software what to do.

JASON: For sure. I feel like the questions I'm asking now are going to be exactly how we do this. It's probably going to make more sense to switch over into pair programming view.

JAMES: Let's do it.

JASON: Jump over, to pair programming mode. Camera two. Shoutout to our captioning, we have Amanda with us today from White Coat Captioning, taking down these words. Thank you, Amanda. Made possible through the the support of sponsors, Netlify, NX and Backlight, kicking in to make this show more access to believe more people. Go find that on the old home page. Talking to **James **today, on @dazzeloid on Twitter, give him a follow. And talking about CommandBar specifically. And if you want to see this in action, let's just do a quick demo. This is the -- the Netlify site. So, if you want to see like I typed theme. And now I'm in the theme. Ands this the facelift that I'm so happy about. We just got a whole bunch of teams together and worked on making the Netlify app look like the Netlify home page. Which prior to this, it definitely didn't. And now they actually kind of feel like they're part of the same app universe. So, I'm really, really thrilled about this. But I can just command K, theme. Back to dark mode. Beautiful. Look at that go. Yeah, if you want to check it out, check it out at You can try out a CommandBar that is actually implemented. I shared a link to the end of web design article, we talked a little bit about The Good Place. And now I think we're ready to do some CommandBar.

JAMES: Let's do some CommandBar.

JASON: Lets rock and roll. Oh, a little bit of echo. Check, check? We're fine. What's my first step if I want to get involved here?

JAMES: So, if you were not Jason and you wanted to get started with CommandBar, you can just click the -- I think the try it now button.

JASON: Try it now. And I mentioned this in the chat, if you want to make that window bigger, there's a window and you can copy the embed link into the new tab and you can see the full screen and you're not looking at a tiny little window. I'm going to sign up for my account with my Google. There we go. I have done it. I'm just gonna just put in some stuff, one to ten. And why do I need CommandBar?

JAMES: You're in.

JASON: I'm in!

JAMES: This is the sort of normal onboarding flow that we take you through. A lot of people are signing up for CommandBar aren't super-familiar with command palettes. This tries to explain what a command palette is and why it's important in an app to get you started. We created an account for you, Jason, that's pre-loaded with some goodies. I can get you into that account now.

JASON: Yeah, yeah, please do. Okay. And then while I'm doing that. If you want to actually pull up that repo that I shared.

JASON: Yeah. Right here. Here's the repo. I'll drop this in the chat as well.

JAMES: So, yeah. For anyone who is following along, this app is a little demo app -- well, let me back up and say, if you ever want to like understand how CommandBar works, the best way is to go to a site that uses it. Netlify is one, ClickUp is another one. Very different type of app. But gives you a sense for what CommandBar does. If you want to explain what a command palette is to someone, I'm faced with this challenge quite often. As you can imagine. We built a site, That's a sample app that has walk throughs and explains what CommandBar is. If you're an Office fan, you will enjoy some of the content we had way too much fun putting together. What we're gonna do now is walk through -- we essentially simplified this app into this repo that Jason was just sharing. And we're gonna walk through adding a CommandBar to that simplified version of the app. The cool thing about CommandBar, you can't install it without an underlying app. So, you have to actually put it in the context of some piece of software. And so, that's what this repo is.

JASON: Okay. So, we're gonna go into here. I'm gonna GitHub repo, clone. And let's see... I'm also going to move to CommandBar. All right. So, in here, I open this up. We've got a public folder. Click some pretty straightforward stuff in here. And a source folder. And this is a React app. I think I saw on the README, this is built on create React app.

JAMES: Correct. Very, very simple.

JASON: Cool. I'm going run this thing. It's Yarn. So, Yarn. And this will take a second. Almost. There it is. Ope, just kidding. Here we go, here we go, here we go. All right. And then I can yarn start. And... it's an app!

JAMES: Hey! Okay. Cool. So, basically the idea is this is a simple CRM for the purists out there. Very similar to a to do list app. There is some records. Those records have some information on them. You can edit those records. And then just so we can demo the navigation use case, there's a second page. Now, we're going to put CommandBar into this app. But if you hit command K --

JASON: Okay.

JAMES: Voila! We very CommandBar in this app. So, this is what we are driving towards.

JASON: Got it. That's where I am.

JAMES: You can obviously use the navigation commands, right? And then you can also search through those companies.

JASON: Nice, nice.

JAMES: And then there's a new command once you get to -- once you open up a company that lets you actually edit a property of the company.

JASON: Oooo... that's cool. Okay. We can do stuff like say, oh, no, the Crusty Crab -- or monsters Inc., they don't want to work with us anymore. That's really -- okay. That is actually really handy. That's cool. That's really cool.

JAMES: And those are the three big buckets of use cases that we see people put into CommandBar. So, there's basic navigation, we'll walk through that, search, we'll walk through that, context to where actions we'll walk through that. What this demo does not capture is the use case that you were talking about which is that long tail of pages and actions that might not find their way into UI because it's hard to demo an app with a long tail of actions.

JASON: Sure, sure. And that's okay. We're looking to get started, not to solve every problem. I imagine you're gonna have a list of resources at the end if you want to go deeper. So, let's get started but maybe showing me how to delete all of this and then we'll add in this thing from scratch.

JAMES: Yeah, for sure. There's not a lot of code in here. React app, we use Tailwind to make it look good. As a lot of people do. All the code is in the use.CommandBar.ts file.

JASON: If I delete this -- let me not delete it. Let me just empty it here. What -- we only export this? Okay. So, I'm gonna do this. I'm going to --

JAMES: Yeah, keep the hook.

JASON: I'll just leave all this up here because we're gonna end up needing to write it again. That way we can talk through what they are.

JAMES: And I'm gonna have you do one more thing. Let's talk about the first step. Once you head back to


JAMES: Okay. Perfect. Here you are. Go to the docs, which is the button in the bottom left. Or you guessed it, you can always use CommandBar.

JASON: Okay.

JAMES: Okay. So, go ahead installation. Cool. So, basically three steps to installing CommandBar. The first thing you'll do is grab our package which you've already done, Jason.

JASON: We've already gotten that, if I open up that package, we've got CommandBar here. So, then I need this piece.

JAMES: Yes, exactly.

JASON: Is this -- this is like my instance name?

JAMES: Exactly. So, that's a code that corresponds to your organization that's gonna make sure you grab the right config.

JASON: Okay. We have got one of those out of the way. Now you have my init. And then we boot it.

JAMES: Yep. The difference between init and boot, when you're in a CommandBar, you don't add the whole library. Init pulls down the latest version of the library. And then boot is what actually says I want to make CommandBar available to my users. So, once you init, you're not gonna see anything. Once you boot, you will see something. If it works.

JASON: Okay. So, in here I do something like window.CommandBar. Is this gonna work? It's create React app, right? So, it should.

JAMES: Yeah.

JASON: The us ID, do I need one of those right now?

JAMES: You do. This is how you identify the user. You can do 42424242 -- whatever you want.

JASON: All right. Okay. Pop that in here. All right.

JAMES: Cool. And just so people are sort of following how this hook is being use the. If you go to app.js. Or JSX. We're calling --

JASON: Use CommandBar.

JAMES: At the top level. Got it.

JASON: Okay. This is not actually a React hook. This is named like a React hook, but it's not actually functioning as one.

JAMES: Indeed.

JASON: Got it. All right. Cool. So, then I don't need to return anything from this. I can just kind of run this straight up and we'll see what happens if I go to my local host. Actually, before we do this, let me do one of these and reboot this thing. Okay. No CommandBar. I'm gonna hit command K and nothing happens. And if I go up here, nothing happens. So, then I'm going to reboot this thing. And we've got our button back, that's good. I'm gonna hit command K and it open up a thing. And I'm going to type something and we don't have any -- nothing is in here, right if this is un-configured.

JAMES: One day you'll get to a place where you can do and try to introspect your business logic instead of your commands for you. We're not there yet.

JASON: All right.

JAMES: Cool.

JASON: That was pretty painless to at least get it in. What's my next step if I want to actually show something?

JAMES: Let's set up some navigation commands. At this point, we should introduce this other player in the setup story which is the CommandBar editor. We're gonna write some code, but we also have a GUI, and you'll actually do some of the command setup that in GUI. The GUI is a little bit different than the other GUIs that you have probably seen. Open the CommandBar back up. For those following along in the docs, this is step three of setting up CommandBar. And then once you're here, type "Open editor," two words, and hit return.

JASON: Oh. That's neat. Secret. See, this is what I was -- see? This is the secret bar with the water balloons. You just got to know the password to get in.

JAMES: It's the Konami code.

JASON: All right.

JAMES: All right. So, welcome to the editor. The editor is essentially a CMS for commands. The whole purpose of the editor is, well, one, to make it easier to get set up quickly. Two, so anyone on the team can contribute to setting up commands or making changes to commands. You don't have to ship code to ship changes to CommandBar

JASON: Nice. And I see Twilio just raided us. Welcome and everyone who is watching. To catch you up on what's going on, we are working on integrating CommandBar. **James **Evans is here from CommandBar talking about that. So far what we have done is talk why it's exciting. You can watch the replay for that if you're interested. And what we are doing right now is we have literally just started. We imported CommandBar module package. And we have used my CommandBar ID to get into my account here. And now I've written a use CommandBar which gets called in the app like this. And we have the very basics. And we're using the editor which we opened with open editor as the command in the CommandBar. So, we're in our local app, but we're actually using CommandBar now, which is pretty slick. Okay. So, anybody who knows to do this, and who is part of the account, I assume, is going -- well, yeah, because I had to log in. Is going to be able to add commands. And to do that, I just -- I just navigate? Is that...

JAMES: Yeah. So, as you'll see, some commands can be set up without any code. Some will require some code. NAV command, basic NAV commands don't require code.

JASON: I feel like there's gonna be -- what is this? What are you? I don't know what this icon is called. But I found it. So, behavior is same tab.

JAMES: Yeah, let's do same tab for now. We'll upgrade it in a second.

JASON: And was it leads?

JAMES: I think it was leads. Yeah. Yeah, it's slash leads.

JASON: Slash leads, okay. Category navigation. Synonyms, so we could do something like users and people and companies, right?

JAMES: It's return -- not comedy limited, it's return limited.

JASON: Oh, gotcha. Okay. Users, companies, people. All right. And then for an explanation. View all leads. And then as a Mac OS short cut, we could add these, but we don't necessarily need to.

JAMES: As we'll learn later, we think users should be able to attach their own shortcuts to stuff. So, if we have time, we'll make that happen.

JASON: Cool, cool, cool. All right. And then do I just --

JAMES: Yeah, hit that big orange toggle.

JASON: Ayo. All right. Now I'm gonna come back here and I'm going to close this. Apparently --

JAMES: The editor, yeah, there you go.

JASON: Okay. Hey! The right code. We didn't have to write any code. We now have basic NAV. That's nice.

JAMES: Indeed. Let's do one more thing. So, for anyone who is setting up CommandBar inside of a React app, you'll probably want -- you don't want -- you don't want the browser reloading every time the user does navigation. That's why we have nice things like React router, right?

JASON: That's why we have nice things. Got it.

JAMES: So, we're using the same tab functionality. That is often gonna trigger a reload. So, to avoid that problem, we're going to hook CommandBar into whatever client-side route you're using. In our case, we've got React router hooked up.

JASON: Okay.

JAMES: So, go ahead and un-- uncomment. Go back -- in this case, we're gonna do a lot of jumping between the editor and code. The way you set up your windows is perfect. So, go ahead and uncomment the React router. And then what we're gonna do is let's actually set up a useEffect.

JASON: Within here?

JAMES: Yeah. For that you'll want to looks like uncomment line 1.

JASON: Okay. So, we'll do a React useEffect. And is this like on initial load?

JAMES: For now, yeah.

JASON: Okay.

JAMES: Cool. And then let's use that navigate -- use navigate hook -- to grab navigate object. Actually, sorry, you want to do that outside of the hook.

JASON: Okay.

JAMES: Perfect. And then back inside the useEffect, we're going to create a router function. And the router function is just a function that takes a string URL and uses your client side router to client side route.

JASON: Like so?

JAMES: In this case, you'll just want router to use navigate. Yeah. That's it. There you go. So, CommandBar is going to use this function to do client side routing. This is one of those do once, use many setup steps. So, this is like the first thing we have everyone do so they can use the router for all of their navigation commands. So, now you just need to make it available to CommandBar.

JASON: Okay.

JAMES: And the way you do is that is window.CommandBar.add router.

JASON: And I pass in my router.

JAMES: Correct. And the only other thing you want to do is make the useEffect depend on navigate.

JASON: All right. And then here I assume I just check this use router box?

JAMES: Yep. That's right. It's saying you don't have a router to find. But we just did it. If you refresh it will go in.

JASON: Okay. I'll close it up, go to leads, and it does this. Navigate to somewhere else. Let's go to integrations and we'll go to leads. No reload. Great. That did exactly what we wanted it to do.

JAMES: Indeed. This is the setup for all basic navigation commands. So, we could go in and create navigation commands to our heart's content using the router and it all will function this way. That's really the first use case that we wanted to cover today is just setting up those basic navigation actions.

JASON: Right. And so, we can go back here and just to do another one really fast, we've got the integrations. Right? And then we'll -- we'll do like a plug. There we go. And that's gonna be a link. Use router. And that goes to integrations. We won't set up any -- anything for that. So, it's live. And now we can go integrations. Gonna go leads. And we are now fully using our app, right? That's pretty slick. ooo! This is interesting, look. It's fuzzy. Like it let me typo and it still works. Which is really nice.

JAMES: Step one on our journey to make it so that you don't have to use a specific syntax of an app. Going from CommandBar to proper NLP certified search bar.

JASON: That's really nice. And also with my synonyms, I can do like, people. Oh, not quite. Yeah, I typo people and it works. And I can -- what was the difference? Like users. So, this is really nice. With some lightweight, and also if we look at our dead ends, we'll see, people are typing this and mean this. Go to the synonyms. We can catch people.

JAMES: That was exactly right. And that's one of the reasons we built the editor in the first place was to enable that loop. Because as you're using your own app. You will come up with the synonyms. You will forget command K, and you will use a different word. You find it's frustrating when it doesn't take you where you want to go. We will have it pop up in the editor and you can go where you want to go.

JASON: Yeah. This is great. It's going exactly what I want it to do. I have spent under 20 minutes, including a lot of gibber jabber, getting this up and running. This is an existing app. There are a couple things we could say here, this demo was built for this. At the same time, we didn't use any code in the app. We've completely contained the bar in this one initialization file. And the only -- the only integration we have so far with the app outside of it just sitting on top is this like let me use the router so that we get single page app style navigation. And so, this would work with React, we could put in a Vue router. We could use it with Next or Remix or Gatsby or whatever. And it will work because we have to tell it how to navigate with the programmatic API. I think every framework has a programmatic navigation of some sort. Or use Window location. Or write your own complicated, load the next page, grab the body.

JAMES: People tend to do funky things with the router. That's how we design the SDK. Where possible, you can provide a generic function and do whatever you want.

JASON: I love that. Okay. So, I get navigation. That all makes sense to me. What should I add in next?

JAMES: Level two. Okay. For level two, let's make those leads searchable. So, you've got that table of leads, Crusty Crab, GameStop, Stark Industries, what have you. Let's make it so you can jump easily to the leads. This is the Slack use case. People always reference Slack as one of the most used interfaces. This is quick switch like Slack S.

JASON: Yes. That is also, I would say, probably my most-used. Yeah. I want that.

JAMES: Okay. Let's do it. So, preamble. There's two ways to make stuff searchable in CommandBar. One is to take stuff that's loaded on the client side and provide that entire list to CommandBar. That's what we're gonna do in this example. Obviously, there are plenty of lists out there in the world that are not client side loadable.

JASON: Right.

JAMES: If you're following along in the docs, you can connect CommandBar to the server side endpoint. Take the user's query, pass it to whatever endpoint you want to use, home grown or commercial system and provide back results. We're gonna do the client side example today because it's really fast for the user.

JASON: Got it. And so, you could theoretically hook this up with your own instance or Elastic search or something like that, right?

JAMES: Totally. Yeah, I don't remember how the Internet in the CommandBar is configured. But whenever you use a CommandBar like, for example, if you go to click up or shortcut and you see a loading spinner on the right-hand side as you are searching, that spinner is reflecting the fact that we're going and taking our query and hitting the backend.

JASON: Gotcha, gotcha. Okay. That makes sense. That's good. That means -- this is not like a full replacement for everything that you would put into your app. This is a convenience layer on top of all the services you're already using.

JAMES: That's a perfect way to describe it, yeah.

JASON: That makes it really nice. Perfect. Okay. So, level 2. We're gonna do some search. And we're gonna do that client side. How does one do such a thing?

JAMES: Okay. So, for orientation, just head over to the store folder. Just so we can see what we've got in state. Yeah. And then sorry, store.ts. My bad.

JASON: Store.ts, gotcha.

JAMES: Cool. This is our state. And we're going to load companies into -- into CommandBar. And where are we gonna put companies? We have this abstraction in CommandBar called context. Context is basically CommandBar's global store. So, if you want to put -- if you want to make any data available to CommandBar, either to make it searchable or to use it in some other way and to configure a command, you add it to context.

JASON: Gotcha.

JAMES: Add to context. Exactly.

JASON: Context, the window.CommandBar.add Context. All right. Inside here we have a key, an initial value, a -- the initial value is a context loader, I'm assuming that's a function.

JAMES: It can be a function or a value. Yep.

JASON: Okay. So, I'm gonna say leads is my key.


JASON: And then be a literal value. Which could be all of my leads. Which we then need to load.

JAMES: Yes, if you want to put a literal array, ABC, just to illustrate the point. That would work. But we want to go grab -- we've got our leads defined somewhere else. So, we've got to go grab them. And you can use the Voltio infrastructure to do that. And I think we have the imports up top already. Yeah. So, this -- the first two that are -- that are commented out.

JASON: Okay. All right. So, instead of this, we're going to -- and I don't know Voltio, so you're gonna have to guide me here.

JAMES: No worries. So, at the top of the function, let's grab snapshot from the use snapshot hook and pass it to underscore.

JASON: Okay. And it's like a top level like this?

JAMES: Yep. And just put the underscore to the first conditional argument.

JASON: Does it need something? Why is it yelling at me?

JAMES: Yeah, the underscore.

JASON: Oh, I have to pass that in.

JAMES: Yeah.

JASON: Underscore. Got it. Got it, got it, got it.

JAMES: This is giving us access to our goal store. We could pass in snapshot.companies, that's a literal. That would work. Why don't we just go ahead and do that.

JASON: Okay.

JAMES: Cool. You added your first set of data from context. Before we depart from the code, we do want to subscribe to changes in the context array to keep CommandBar context in sync with your state management.

JASON: Got Claripy.

JAMES: To do that, you guessed it, just wrap it in a useEffect.

JASON: I guess, ah, let's not do it that way. Let's do it a better way and have a second useEffect so they don't all re-trigger at the same time. And we will snapshot and then move this one in. Like that?

JAMES: Yes, sir. I think probably just for cleanliness, make it dependent on snapshot .companies.

JASON: Okay. Done and done.

JAMES: Oh! We have loaded data into CommandBar. You're not going to see any commands.

JASON: Not yet.

JAMES: It's not showing up in CommandBar yet. We have to tell CommandBar what to do when one of those pieces of data are selected. Go into the context tab.

JASON: Here we go, context.

JAMES: Hit inspector at the top.

JASON: Hey, look at these. All right. So, that's pretty straightforward.

JAMES: Cool. Now we just need to tell CommandBar what to do when one of these is selected. And that's gonna make it searchable.

JASON: Okay.

JAMES: The way you're gonna do that, you're gonna create a command. Commands take action in CommandBar. Whenever we select a piece of content, you will have an associated command that does something. So, we can actually start from the context page. And then see leads down there. This is a bit of CommandBar terminology. An attribute is something in context that's not searchable. And a record is something in context that is searchable. So, we have put something into context.

JASON: Why would I use one or the other? Why wouldn't I want something to be not searchable?

JAMES: We will see an example. But you can control which users see what commands. A lot of people just pass in their entire user object. But you might put, is admin flagged. That's a piece of metadata.

JASON: What roles.

JAMES: Roles as really common one.

JASON: Gotcha. Okay. That makes sense. Then I could use this -- so, you mentioned that this is like a -- this can also be a function. So, theoretically, I could get the current user's roles and only show them companies that their role is allowed to see as part of that. And that would be using that attribute? Is that correct? Or am I doing something else?

JAMES: Yeah. You could definitely do it that way. And even in the editor, you can like maybe we can just show it. So, if you go to commands again. And let's say you're like, well, I only want to make the leads command available to people who have access to the leads command. Or the leads page. So, you go into the command, you would go to that availability tab at the top there. And then you can create conditions that describe when this command is able to be used. Those can reference data and context.

JASON: Gotcha. Okay. Let me delete. It's always available back to leads. Discard changes. And we're gonna go back to context. And now you said a record is something searchable. And we want this to be searchable. So, I'm gonna click this button.

JAMES: That's correct. Quick find just means I want it to be searchable without selecting a command first. So, let's go ahead and do that.

JASON: Okay. Label field.

JAMES: It's actually labeled. This is referring to the property of the object. That's the primary key.

JASON: Okay. Okay, okay. So, what that lines up to is in this context we have a label. And I'm saying use the label field from the leads -- the leads context object. Got it. Okay. I understand. Oh, and now it has a create command.


JASON: Okay. Create command. Or jump to company.

JAMES: Perfect.

JASON: And we'll -- I don't know, that looks -- that's a company icon, right? And we're gonna link and that will use the router. And that's gonna be home. No. What will it be? Let's try it. Let's go to one of these. And that's gonna be... leads. But then we need leads -- oops. That's not it.

JAMES: Go back to -- we're gonna create a dynamic link. So, as you saw, it's slash leads slash ID.

JASON: Right.

JAMES: We can't hard code the ID. What are we gonna do.

JASON: Look at it go!

JAMES: Exactly. You guessed it. This is another pattern that I'm really supportive of becoming common across the Internet. Double curly braces.

JASON: Okay. Maybe I missed a piece, though. Is it this lead?

JAMES: Correct. This lead refers to the selected lead and then you can just dot into that to grab the ID property.

JASON: Yeah, but I am missing my dot, which makes me wonder if I did something wrong.

JAMES: No, you're good. You can just do this

JASON: Dot ID. We're gonna use router. I lost my icon when I started bouncing around trying to find stuff.

JAMES: And then you just need to add a category. Add it to the search category. We should probably rename the category and add it to the settings for now.

JASON: Okay. Add it to settings. And we'll leave the rest of it together. Turn it on. Okay. Now let me go back to these and we'll just rename this one to -- what would you call this one? Search?

JAMES: Search, yeah.

JASON: Okay. So, then I'm gonna jump out. And we will say, jump to user. I'm gonna crump to Crusty Crab. Okay. That was easier than I expected. I mean, that's great. Like this is -- this is wonderful that is just does... that's awesome. That's super-helpful. All right.

JAMES: A couple goodies. One thing to note that we got sort of for free which you may not get for free if you're following along is if you command K and search for Crusty Crab, you'll see that the icon shows up. That's because we have a property called icon that contains either an SVG string or a URL to an icon. If that to show up, you have to have the icon property in your records.

JASON: Got it, got it. And so just to show what that looks like, I'm gonna go to companies. And you're speaking specifically of this.

JAMES: Yep. Looks like it's a URL. You can also pass an SVG string here. So, if you want to do some funky icon creation on the fly, you can do that too.

JASON: Got it, got it, got it. Very cool. Very, very cool.

JAMES: And then one other goody. We talked about the label key earlier. That's, you know, what shows up in the title of the record, the primary key. There's other data here as well. For example the contact name. Let's go ahead and make contact name searchable as well. If I search for Eugene, it's gonna show Crusty Crab. And you're gonna do that from the editor. So, head back to the context tab.

JASON: This one?

JAMES: Yep. And then scroll down to searchable fields.

JASON: That's cool.

JAMES: And then save.

JASON: All right. Okay. see you CommandBar. This is great. I mean, I love that.

JAMES: The loop, right?

JASON: It's just nice. It's just nice to not have to do extra stuff to make that work. Like -- and what I like about this is it feels very approachable because I -- like we have this data in here. And there's some stuff that is, you know, you have to configure data a certain way like having an icon field. But I have a suspicion that if I wanted to change the name of the field, I could. Is that right?

JAMES: That's like the one field you can't change.

JASON: Okay. We need to create an icon field if we want that to work. But if I want to search new number of fields, this is -- I assume this is not limited except by probably the common sense. But you can put any of the fields in your entries here to be searchable so somebody could basically type whatever and it would work. How would this work for, say, speaking of a CRM. Say you use a tool like Gong that is gonna transcribe your sales calls. And you remember somebody was talking about something and you need to follow-up with that lead. You start typing the phrase that you know they said. Oh, we need X. You're like, type in X. Does it do full text search like that? Or is that when you would start reaching out?

JAMES: It totally could. It's kind of -- people are surprised at how fast client side search could be. So, the registration is always -- if you can, always start with client side search. Throw as many fields as you want into the searchable field section and see how fast it is for your biggest users. Or your users with the most data.

JASON: Try it and see.

JAMES: One thing we do, one technical note. Sorry, say that again.

JASON: You think we've got a little bit of a delay. Don't worry about premature optimization, just try it and see.

JAMES: Exactly. We find that it starts to get slow if you add a ton of fields at around 15,000 records on the client side. Obviously if you have gargantuan records.

JASON: Sure.

JAMES: But most people are surprised it's above a thousand. One technical thing, if you include a really long searchable field, we will turn down the fuzziness for that. Because if you have a really long searchable field and fuzzy match, you're going to match everything.

JASON: Yeah, right. That makes sense.

JAMES: Okay. So, we did search.

JASON: Now we've got navigation. We've got search. We have been doing this for about 30 minutes. And we already got further than I think I expected us to get. Why not make it harder. I want to -- we've got this edit button. Can we add that editing feature where I can change the stage?

JAMES: Let's change the stage.

JASON: All right. I'm ready.

JAMES: So, this is going to showcase a different type of command. So, to date we have been talking about links. Both of the commands that we've create ready link commands. They're different flavors. The first one just takes you to a page, static link. Second one takes you -- the search takes you to a dynamic link depending on what you selected. we're going use a totally different command type for this next selection. A callback command.

JASON: Okay.

JAMES: Like I said, we try to be as generic as possible. It's really useful to use arbitrary JavaScript in the app. That's what a callback is. It's going to run JavaScript provided by you on the command side when the command is executed.

JASON: Okay. I'm assuming since it's arbitrary JavaScript we're gonna write that first before we wire it up.

JAMES: Correct. What we're doing here is similar to what happens when someone sets up CommandBar in the real app. Get in there, set up commands, attach their data and then what is the business logic? This is the Neuralink example. We're placing the probe on the brain of this app right now. We're making this business logic available. Cool. So, we are going to learn a new SDK method called add callback.

JASON: Key. So, this can be arbitrary, I assume. So, I can say like, update lead status. Is that what it was?

JAMES: Yeah, status, perfect. That's the field we're gonna act on.

JASON: And then the callback function itself is gonna be one of these. I'm gonna hide that so we can see what's going on.

JAMES: Cool. Now we just need to, you know, peek into the logic of the app and figure out how we're gonna update the stage of a company. And so, the function that we're gonna use is called edit company details. And that's a function that exists -- it's actually the import is already at the top of that file.

JASON: Oh. Got it. That's in store actions. That makes sense. We store action. We're going to edit company details, which is this one here. And take a look at what it does. This takes a company ID. Takes the field of -- field of company? And the value --

JAMES: It's just saying it's a generic edit function. Which field do you want to edit?

JASON: gotcha. We can technically edit any field, but we're going to edit status. Find into the companies, find the one that matches by ID. And grab -- assuming the company exists -- we get the field. And then we update it to be our new value and add the notification. Okay. That all makes sense. I can follow that. So, let's get this one in here. And then we're going to... I assume. Can I just drop like edit company details directly in here? Or I have to translate a little bit?

JAMES: Pretty much. You can drop edit company details in there. Now the first argument is what company? So, we'll come back to this. For now, I think just put 123.

JASON: Okay. So, we need company ID. We need --

JAMES: Which we don't have yet.

JASON: Right. And the field is gonna be status which is --

JAMES: It's actually called stage ID. Yeah, there you go.

JASON: Stage ID. All right. So, we're gonna update the stage ID. And the third thing was the value. And the new stage ID is gonna be like, we'll just go new stage ID. And...

JAMES: Perfect. So, we've got two slots that we need to figure out how to fill. The first of those slots is company ID. So, this is what company are we acting on? And for this, we're gonna use context again. So, we've got the active lead as a property in our global store. Our global store. We just need to wire that piece of information, provide that information for context just like we provided leads.

JASON: So, we wire it into this context?

JAMES: I would just go ahead and copy that entire useEffect and make a new one. And then for there -- yeah, exactly.

JASON: And is it lead?


JASON: Okay. And that's all happening up in here.

JAMES: It's actually called active company.

JASON: Active company. There it is.

JAMES: Mixing our terminology a little bit.

JASON: Has a missing dependency. And that needs to be active company. Here we go. All right. So, this one then --

JAMES: Okay. Cool.

JASON: Is gonna be just company.

JAMES: This is a good teaching point which is that you've now got two places you could draw from. You could draw from your Voltio store or draw from the CommandBar global store. Those two things are in sync because you wrote that useEffect correctly. We always recommend using CommandBar context. And the way you can guarantee you get -- to avoid raise conditions, to get the most up to date context as of when the user executed the command is to use context. And we actually pass context in as an argument to the callbacks.

JASON: Is it destructured or just the first argument?

JAMES: You can do destructured. It's the second argument. The arguments that are provided to CommandBar, that's what we're gonna use for stage ID. The second argument is just the full context object.

JASON: Got it. Like that.

JAMES: With free pass by reference. If anyone is wondering.

JASON: Okay. So, then I'm gonna go lead ID?

JAMES: I think that is... correct.

JASON: It doesn't like --

JAMES: And type context.

JASON: What's the right context?

JAMES: We have types. They're not here. For this we can commit the cardinal sin of just anyfying it.

JASON: The chat is losing it.

JAMES: Jason's going to immediately jump off the stream and wash his hands.

JASON: I'm the worst TypeScripter on the planet. I don't know. Just change it to .js. We've got unhappy chat.

JAMES: We're half a step away from doing that. Okay. We've got the active lead and this is going to update with the new ID. Now we need to figure out the new stage ID. We don't have it now, but if you remember how the command worked, we were on a lead, and open up the command, and actually select the stage.

JASON: Right, right.

JAMES: We're providing input. We call that an argument. So, a navigation commands that we have created so far are argument-less.

JASON: Right.

JAMES: Actually, if you go back to CommandBar for a second in the app.

JASON: One of these? This one. Here we go.

JAMES: Sorry, go to your CommandBar that we have been building. Close out of the editor. And then instead of searching directly for a company, just open up the CommandBar. And then see jump to user. See that little arrow on the right side of jump to user? That means this command has an argument and it's gonna take some user input. So, if you select jump to user, it's then gonna show you the list of records. Now, we made it. We turned on quick find. That made it so you didn't have to first select the command to search for something. We're going to basically re-create this structure for change stage. But stage it in the gonna be searchable before the action is selected.

JASON: Gotcha. Okay. Great. So, to do that, I need to -- let's see, we have our active lead. And then my argument that comes out here is that gonna be like a -- is it like a whatever I want to call it so I can choose like args.stage ID?

JAMES: Exactly. You can set the key in the editor.

JASON: Okay. We'll set this part up. This theoretically will work. We're not gonna call this until we have the pieces we need.

JAMES: Exactly.

JASON: We have the lead ID. We need to define the command in the CommandBar. Because if I go back here and reload and open it one I don't have an option to update my lead, if I type in Crusty Crab or whatever, still don't have any options here. So, yeah, I guess step one is like how do I call this? Or we need to create this new command that is gonna use this callback. And then step two will be figuring out how to define the arguments.

JAMES: Exactly. Before we do that. let's just add the wrap and useEffect.

JASON: Wrap effect and useEffect.

JAMES: And on mount. Dating myself.

JASON: Okay. Take this. And move this down here. All right. And this is gonna depend on -- does it depend on anything?

JAMES: I don't think so.

JASON: Yeah. Okay. That's fine. So, we'll do that once it mounts, okay?

JAMES: Cool. Okay. So, now let's create the command. So, let's go ahead and add it. We don't really have a category for it. Maybe we can rename help to actions.

JASON: Okay.

JAMES: Cool. Create command.

JASON: Add a new command. We're gonna put it in actions. Here we go. And this is gonna be update stage. And we'll just give it like a -- sure. And, oh! Callback. That makes sense. Callback key. Don't need to copy-paste, it was already populated for me. That was wonderful. What's that?

JAMES: This is just gonna show you how to do --

JASON: What?

JAMES: It's just gonna show you how to do it if you haven't done it already.

JASON: Nice. Add an argument. Argument name is gonna be this one.

JAMES: Nailed it.

JASON: All right. And then an argument type, list of options. And we can pull in context records. Okay. All right. Things are starting to click here. So, do we have -- let me check -- stages. [Laughs] So, now I can pull in my stages the same way that I pulled in my other stuff here. My snapshot.

JAMES: Precisely.

JASON: Wait. Do I already have it then?

JAMES: No, we haven't added stages yesterday. We're going to add it the same way we added companies.

JASON: So, I'm gonna add stages. And we're gonna go snapshot.stages. And then I'm going to --

JAMES: You can just type "Stages" there.

JASON: Wait. What did I just do? Navigated to a weird place. So, I'm gonna... is that gonna break?

JAMES: You're just gonna have to refresh after you create it. Just save and then come back to it. Yeah. Refresh and then --

JASON: Saving. All right. Coming back in. Update my stage, add an argument. Now I'm going put this stage ID goes in here. Hit that button, it's a list of options. That's gonna be stages. There we go. It's autopopulated because I added it in first. They can select a single one. Preselect current context key for the current value. That's gonna be the existing stage ID, I would assume. So, like --

JAMES: We should skip this for now for speed.

JASON: Okay. So, just save it.

JAMES: I think so.

JASON: All right. Let's roll. I'm gonna turn it on.

JAMES: I actually know there's gonna be a problem. But we can run through it.

JASON: Okay. So, a thing a broken because this doesn't seem to be tied to a company.

JAMES: Correct. So, oh, well, it is, actually. We're on the Crusty Crab.

JASON: It is. So, it's gonna work -- we're in contract negotiations. Let me change it. Let me update it to contact it. And it says... I broke it.

JAMES: We're just -- it's just the difference between passing the full stage option into the function versus the actual ID of the stage. So, the only thing you have to do is in your callback, instead of args.stage ID -- args -- excuse me -- args.stage ID.ID.

JASON: Ah-ha! Okay. So, let's go update -- we're gonna say qualified... and now it works. Okay. Perfect. Okay. That's working. I did notice that's a little disconcerting. I thought it was unhooked because I didn't see the like Crusty Crab part. So, can I associate this action?

JAMES: Yeah. Let's do it. Let's maybe change the name of the command to include the active company. So, to do that --

JASON: Oh, is that all we have to do? Okay.

JAMES: You could do like, we see parens often as a pattern to describe the -- yeah. There's no autocomplete there yet, sadly. But it's coming.

JASON: Okay.

JAMES: But you still need to use the double curly braces. It's just not gonna help you out.

JASON: Okay. All right. This is gonna be -- remind me, is it context dot?

JAMES: Context..activatelead.label.

JASON: Okay. Wow. All right. And then what else do we need to do here? We're just about at time. Any last touches before we move on to next steps for people who want to keep going?

JAMES: The command is done. I think a really satisfying conclusion is to attach a keyboard shortcut to so you can imagine you're trying to update 30,000 leads and you need to do quickly.

JASON: Okay. And for me to do that, we're gonna say -- yeah. I'm just gonna save it as L. So, if I'm in here and I type "L," oh, my goodness. And then we go to the next one. Wayne Enterprises. Type L. This is great. I love this. Like this is such a nice -- these are the sorts of things that I want to build, right? And I never do it because they start as a simple idea and they immediately balloon up into a million little edge cases and feature requests and things like that. And that's sort of what I love about this era of Dev tooling is that simple idea that I had that gets too complex for me to build is now because we're building modern building blocks, you know, based on this, and the web design article that you shared, we're building common interfaces, I don't have to build that. There's a company that had that idea and is putting all that have effort. These patterns, CommandBar, I could whip that up in a day. We all think that. Oh, man, there's so many little things I would love to add and it spins off into a whole company. I think that's such a -- this is definitely one of those cases where, you know, I started out convinced that a command palette was a good idea. And throughout the course of this episode, I've just kind of noticed like little touches that I had would have eventually wanted that I didn't know I needed until I just tried it. The L to update the lead status. Come on. Like that's -- it's so nice to be able to do those sorts of things and just have them run.

JAMES: Exactly. I often say this. This is literally all we do. We are doing nothing but doing this interface. I love when people build their own command palettes. We always get ideas for people building from scratch. We think this is an interface, a pattern that deserves like the full attention of a company because there is so much to get right. One last thing before I let you hop off, we should update the -- the styling just to show folks it doesn't have to look like this. So, if you go into the editor again. And click on settings. And then styles. And you can maybe switch to the other theme.

JASON: Did that work?

JAMES: I'm honestly forgetting what it looked like before.

JASON: Let me switch the theme. This is modern.

JAMES: This is one we created for you. Just for you. The Jason theme.

JASON: This is nice and clean. This is wonderful. And these are all customizable, I assume?

JAMES: Totally.

JASON: I mean, this is great. We are unfortunately out of time. So, I am going to -- I just dropped your Twitter into the chat. Everybody go follow **James **for more information. I'm also gonna drop the Are there any other resources you want to shout out as we are wrapping up this episode for folks who want to learn more?

JAMES: CommandBar/docs. That's where we have been following along today. If you want to put a CommandBar in and whether users will use it. This is all we do. We would love to walk you through and come up with use cases.

JASON: This episode like every episode has been live captioned. we have had Amanda here, thank you so much. Made possible through our sponsors, Netlify, NX, Backlight, thank you for kicking to make this more accessible. Look at the schedule. I don't have time to talk about it today, but I'm very, very excited. Go and check this out. We'll be adding this more all the time. Add on Google Calendar button, follow on Twitch. Hit the subscribe but then and ring that bell. James, thank you so much for taking the time today. It's been an absolute pleasure learning how CommandBar works. Chat, go out and build some stuff. Tweet at us what you build. Turns out I'm really into CommandBars. We call this a success. James, thanks for hanging out. Chat, stay tuned. We will find somebody to raid. Thanks so much.

JAMES: Thanks for having me.

Closed captioning and more are made possible by our sponsors: