Join Kevin and Nathaniel Okenwa, Developer Evangelist at Twilio, as they utilize Twilio's Voice SDK to build a Directus extension that allows outbound phone calls directly from the browser.
Speaker 0: Hello. Hello. Hello.
Speaker 1: How are you doing?
Speaker 0: It's good to hear you. Great, mate. How are you? Yeah. Yeah.
Yeah. I'm doing alright.
Speaker 1: I'm doing alright.
Speaker 0: It's wild to me that we have been friends in the same kind of job family for so long, and I don't think we've ever run a workshop before.
Speaker 1: I know. I mean, I think it's been a missed opportunity for all the wonderful people that we haven't been able to hang out. Genuinely, it's crazy because we went to university together, for those of you who maybe have never heard. So we we've been known each other for a long time, and our careers have, like, had these moments where they almost look like they're about to cross. And I feel like this might be one of the first professional cross that you've said.
I'm really excited.
Speaker 0: Yeah. So I thought we'd open by just introducing ourselves, introducing what this event is, introducing what we're gonna be doing, how it's gonna work, and then we'll launch straight in and make a mess of it for 2 hours. How's that sound?
Speaker 1: Sounds good. Sounds good. I could start by introducing
Speaker 0: you first.
Speaker 1: Hi, folks. My name is Nathaniel Okenwa. As Kevin would know, I talk a lot and I write code, so my friends call me Chatterbox Coder. That's where you can find me on all the socials. And I work for a company called Twilio, which is kind of what we're gonna be talking about today.
Twilio, for those of you who don't know, it does many things. But here's the TLDR. We are telecommunications APIs that help you build amazing communications into your applications. That sounds like a lot of words, but you've definitely used Twilio at some point. If you've ever received a text message from a company, a phone call from a company, maybe a 2 f a text, lots of emails when it comes to Black Friday, even all sorts of communications, chances are they may have been using Twilio under the hood.
Some of your biggest some of your biggest brands and favorite brands that people use use Twilio under the hood. But we also do so much more. So if you do wanna find out about some of the more advanced use cases, feel free to chat to me because the well of Twilio can be quite bottomless.
Speaker 0: Yeah. Definitely one way to put it. Yeah. If you're here, you might be coming from the Twilio world and not have heard of Directus before. So I will also tell you a bit about Directus.
Directus is a back end, basically, that you can use to build wicked applications. You connect it to a new or existing database, and any number of asset storage, storages, storage. I don't know if it's like the word sheep where it's the same in plural. And you immediately get developer tooling, including APIs, a real time interface, authentication, and a user management system, and this really lovely web application with which to interact with that database, which you can easily hand to people who aren't developers. So you don't need to build APIs.
You don't need to build kind of these admin panels, admin panel back ends. Really cool tool. And today, we get to converge the 2, which I'm really, really excited about. So, the project today, is oh, actually, no. A little bit more preamble.
This event's happening as part of Leap Week 3. This is our week of announcements. On Monday, we did a keynote where we announced directors 11, which is coming out this week as a release candidate where we announce new shows for Directus TV. This platform you're watching this video in right now has, now 35 shows worth of content. You can go and potter around and find some cool awesome content too.
Speaker 1: Like, I must say.
Speaker 0: Thank thank you very much. Thank you very much for that. I'll pay you under the table later. And also, and and a bunch of other things, as well. This is one of the workshops that's happening this week.
So this one right here is this Twilio workshop. After this, like, an hour and a quarter after the end of this event is a 100 apps and a 100 hours live where Bryant and some of our colleagues are gonna build an app in 60 minutes. I don't know what he's gonna build yet. I'm not sure he knows yet, so that would be chaotic as it was last time. Tomorrow, we're doing a workshop with Deepgram, which is a voice AI company.
We'll be building a cool project there and then a community social networking thing on Friday using a platform that doesn't suck. So you can come and have a chat with other people who use or know about or are interested in direct us, in hopefully not too of a not too much of an awkward format. But we're getting ahead of ourselves. We're here for this Twilio workshop. And what we will be building today is a panel extension for Directus Insights.
So Directus Insights is this dashboard builder tool here that we have. And in a dashboard, you have any number of these panels which can interact with the data in your database. But these panels aren't just for reading data. You can actually put components within them that are interactive. So you can add, like, forms and buttons, and you could just run arbitrary codes in them if you want.
And that's what we're gonna be exploiting today.
Speaker 1: So so what I'm hearing, right, because I have not played around with insights. So, insights essentially just give you the ability to create components that are powered by your data. So there are some obviously components that are really well built. And then see, it doesn't actually have to just be reading data because the thing that I'm really excited about is the fact that the stuff we're gonna do is going to read data, but it's gonna interact with it and cause other things to happen as a result. And that's something which I think is very, very powerful, especially when it starts to come to, like, workflows and building maybe internal tooling as well for people.
This could be really, really useful.
Speaker 0: Ding ding ding. So we've not spoken much about director, so you're kind of coming in it pretty fresh as well. So please keep asking questions. But, yes, you said a word you said a pair of words there, which I think is really interesting, which is internal apps. And I actually think that is the kind of hidden power of director's insights.
While all of the panels that ship out the box are very much about, you know, building graphs and charts and reading data and analyzing it, it doesn't it's not just that. And you can also obviously build panel extensions and distribute them through the marketplace. So today, we're gonna build a panel that will have a drop down and show you the users inside of your directors project. With other phone number to those users. And so there'll be a phone number attached to them.
And then you press a button, and we'll use the please forgive me if I get it around the Twilio voice SDK. Yes. That's what it's called. Fantastic. And we're gonna call that that person from the browser.
So the browser will connect to a phone number and do a two way call.
Speaker 1: Cool. Yeah. I'm really excited because this is something which I think lots of people oftentimes, we end up having tools in different places. Right? So for example, especially when it comes to telecommunications and telephony, we always, like, separate so that you have your email account or a phone, like, application or something separate to all the places you have you there.
And, yeah, I'm not saying that's not bad, but when you start wanting to be efficient or maybe have some more smart and cool interactions, bringing those 2 together gets really powerful. And I think, like, what I could see here is and we could talk about, like, potential use cases. Look, we're not trying to sell you a thing, but kind of just tell you practically some of the ways in which you could be using these these tools. And I think like this, it could be a good way for you to, for example, like, quickly integrate communications without necessarily exposing PII. Like, you can have it so the person using the tool never sees a phone number, but it's still able to phone them.
Some of your favorite ride sharing apps kind of use a similar technology behind this if your driver ever calls you to be like, hey. I can't find you. But, anyway, I'll stop talking. Let's get on.
Speaker 0: No. No. Please do. A couple of other just bits of context. So we'll refer to the director's docs, obviously, a bunch today.
We'll take a look at some of the extension docs. As part of that, inside of these docs, there are a couple of existing Twilio guides, and one additional non Twilio guide. And I wanna talk about them before we crack on so you kinda understand the approach which we are going to use today. First of all, there is this guide here called use custom endpoints to create an authenticated API proxy, which is a lot of words. So to break that down, endpoints, custom endpoints are one of Directus' extension types, and they allow you to just create kind of what they sound like, arbitrary endpoints that you can hit.
We expose an express router, so it works just like that. You know, you set up route handlers, and then you can hit them. But within the context of directives, you can start doing stuff like checking if the user's authenticated in in directors or checking their permission sets and so on and so forth. So, this is an example where we actually just expose the full Twilio. Let's find it here, where we expose let me find it.
Twilio host. Yeah. Where we expose just a root URL. And then what we do is we check whether you are authenticated, and that's the key part right here, which means you can't just hit this endpoint from anywhere. Right?
You have to do it either with your Directus API token or cookie, or from within Directus itself. So that's 1. The second one is, another Twilio integration. This uses our automation tool, direct us automate. They're called flows each kind of, workflow.
And this one here allows you to send SMS notifications. That's kinda interesting.
Speaker 1: Can you do for these? Because, like, obviously, with SMS, when I'm talking to devs who are building into their applications, they're often either a couple of things. Either they wanna send a message, like, when a specific action occurs, Maybe they wanna do a batch, like, at the end of the day, or there's, like, a campaign going out, especially when you start getting to marketing and stuff like that. And the same with email, because we we also you we have email API. So, like, how can people trigger those, those things?
Those flows?
Speaker 0: Great question. Five ways. Event hooks. So something happens in your director's project often in one of your collections. A collection is a database with, like, additional director's metadata.
So when I say collection, you can think table, but it is not just a table. Right? When something happens in your database, you can immediately fire off an automation. So this can be, a new user is created, a new file is uploaded, or any of your tables are have CRUD operations, executed against them. They can run as blocking, as blocking triggers, which means the whole flow has to see its way to the end, and then the database transaction will execute so it, like, intercepts it.
And as a result, you can actually fail out. So, we have an example somewhere in our docs using a verification API where if you fail the verification, we actually just block you from signing up entirely. It just never commits to the database.
Speaker 1: Ah, it's
Speaker 0: really cool. On the other hand, it is cool because you can also manipulate data in the middle. Maybe you enrich it or stuff like that. That's really, really good. And then and then you have actions, which happen after data after data has, been committed or after a transaction has been committed, then it will run.
So that's event hooks. Then we have webhooks, so just inbound HTTP requests. We have a schedule. So, you know, you set up an interval using, the 6 point Chrome job syntax, and then we'll run the flow, which is how you could then batch. Or, 2 more, actually.
There's another flow so you can compartmentalize functionality and trigger other flows from core from, like, your your controller flow and path data in and backup and stuff like that. And then finally, manual. What manual does is in your data views where you've got your list of all your items in a collection or you're in an individual item in the editor, there's a button you can press that will pass in the IDs of the items that you've either checked in the collection or the page, and then send that into the payload as well. Manual flow triggers also have confirmation dialogues so you can pop up and collect a bit more information. There's the button there on the right.
And it can you can pop up a box, ask for arbitrary information, and then trigger the flow, which I think is a very, like I'm looking at thinking comms. So they're very communication type, you know, option here. You can go write a message and hit go, for example. So they're the triggers. There's a bunch of inbuilt operations.
You can also build custom operations, but that allows you to interact with your database, make it external web requests, just write some arbitrary JavaScript that can manipulate data in a little more of a clever way. But, yeah, that's something that's really cool
Speaker 1: about this tool. Yeah. No. Absolutely. And a thing which I'm kind of noticing is the number of different ways, the flexibility that is given to you to try and to to trigger these things in different ways allows you to put into put the automation into different parts of your application.
Especially, I'm loving the filtering functionality. I can already spin off a couple of great reasons why I'd use that, especially when you start to want to reduce computational load or con reduce things from blocking our operations from going through or vice versa when you actually do wanna filter stuff. So that's useful. I'm gonna play around with that next time I get a chance.
Speaker 0: So I wanna jump in. There's one more guide I wanna show because this guide is going to basically be the north star for our approach today. And it
Speaker 1: is this, which is filled
Speaker 0: a little bit with, but it's using external weather data in a custom panel extension. And you might be thinking, I don't really see the translation between this and using Twilio in a in a panel. So before I explain this, maybe we take a moment to explain the Twilio flow in this all the way from generating I think it'll come in quite nicely. I can share your screen or you can just talk. It's completely up to you.
Speaker 1: Well, I can start by just talking, and then we can, we can get even further. So we start with the Twibio voice API. So Twilio has a bunch of different APIs, and we have one that we focus on programmable voice. I would say one is more of a collection because even with invoice, there's a lot of diversity depending on what you want to do. In today's example, kind of like the external weather data, we essentially want to have a component in a web page, and this component is going to be able to make phone calls out to the users that are stored in the director's database.
Right. So in the director's back end. So what we're going to need to do is we need a couple of things. We need a browser component or a component that that lives in a browser. So essentially a browser that is able to make phone calls.
Your browser, unfortunately, doesn't have telephone APIs. So what your browser does is your browser can connect to Twilio, Twilio's servers. And then Twilio then handles and creates telephony using, old school telephony that, like, is really, really boring slash complex or really, really interesting depending on how what floats your boat, and then does all of that in the background. But what we do is we expose an SDK which you can build into your front end applications. Now there is one extra step which maybe adds a little bit of complexity, but I just wanna talk a little bit about that, which is just a bit of authentication and security.
Because we can't just hand anyone the keys to make phone calls from any number in the world. Right? So when you have a Twilio account, you have a phone number. And when your browser connects it with you, what happens first is there is an exchange of a token. A token must be generated, it's what we call it, and that browser must use that token to connect to Twilio.
Now that token gives it a couple things. It first says, hi. I am Nathaniel's computer, and I am connecting to Twilio, and I'd like to be able to make phone calls. Also, it says I have a phone number identity. So, like, a a a phone number which is attached to my identity.
So when I do make phone calls, I will come across as if this phone call is coming from said telephone number. And these things happen in the background. Now the SDK has a lot of, flexibility, so we start off with a few basic methods which you can use. And then if you want to build a really, really custom interface, there are a lot more events that we expose. But if you are looking to get started with Twilio voice, I would recommend heading over to the Twilio docs, which I am showing on my screen.
They often take you through starting your first phone call. This is from a server. You may want to start your first phone phone call, but then we also have these client side SDKs, and we talk you through how you use the client side SDKs. We have JavaScript SDKs, iOS, Android, and we even have React Native SDKs. I often like to say it's good to start with a quick start and then work backwards because the quick start builds all of that functionality, and then you can customize it as you are.
But then there is also the reference if you want to dig deeper into all of the methods and the things going on behind the scenes. Is there anything I've left out? I know we've talked about this before.
Speaker 0: No. You did mention the thing I hoped you would mention so I can explain why whether the data and Twilio are related. Before I jump in, actually, a reminder for those watching you, we've got a chat here. I'm watching it. So by all means, ask questions, thoughts, concerns, grievances even, and we'll address them as we go.
But let's come back to my screen. Right. Why does this matter? Extensions and directives live in 1 of 2 places. They live in the data studio, which is the web app, or they live in the data engine, which is the back end, an API side extension, you could call it.
The browser, because of just security in the browser and the way that we lock that down, can't always confidently make an external web request. Right? It can't go off to Twilio and say, hey. Go generate an access token for me. In this example, the same way it can't go out to a third party weather API confident.
Like, if you control both sides and you configure security on both sides, you'll be fine. But you often don't control the the vendor. You don't control Twilio. You don't control the weather API. So what do you do with this?
Well, you use an endpoint. Use an endpoint, which is an API extension. Use an endpoint first to actually make those external requests do what it needs. And then your front end extension, the panel in this case, and in this case in the tutorial, then calls an internal endpoint because it's that's what it is now. It's now gonna be like / Twilio token, that my direct test project slash Twilio token.
So it's now an internal API. So you you act you treat it like a proxy, which is actually not dissimilar to the post I showed earlier. To bring these together and make sure that you always have both of them and you don't have to deploy them separately, we have a concept called a bundle. So first, you create a bundle extension, which is an empty shell, then you add an endpoint, then you add a panel. And when you install the bundle, you get both of them together as as is required.
So that's gonna be more
Speaker 1: hearing you right. Just as a mental model, what I'm hearing is in this bundle, if this bundle was the application that fits into the panel, you kind of have the component, which would be the front end logic and then the endpoints can stand in for like a like almost like your server side. I know this is a weird way to think about it, but ways that you can query data and interact with other applications.
Speaker 0: Yes and no. The only thing I'll change there is query data because panel extensions, for example, can query collections in directors without needing a a server. So if it's within the bounds of your director's project and the services we provide, in fact, we have them the the the they are called
Speaker 1: Query external data. So data from outside. Correct.
Speaker 0: Correct. Because, for example, your front end, your front end, your app extensions is what we call them, your front end extensions, have immediate access to all of your data because you're in this authenticated, you know, box that you can work within. But, yes, exactly. So the reason I wanted to show this, this weather panel thing is because that's basically we're gonna follow a very similar approach here. We're gonna create a bundle.
We're gonna create an endpoint which will allow us to generate a token, then our panel will call that to grab the token and then use the voice SDK. So we've been talking for probably about minutes. I'd love to jump in. Now the format this is going to take, we decided just because, of of of the fiddliness of certain parts of this, is we are gonna go nice and slow, but we're going to present. We're gonna build it together.
You can watch, and this will be available on demand if you wanna play along. This will also get turned into a blog post, and hello there is on demand. This will also turn into a blog post you can follow if reading, you know, technical material is more your thing. So if you're watching along, I I would say don't try and play along necessarily, but, take advantage of the fact that chat is here because we're we're here to chat to you. Right?
Otherwise, this would just be a just a video, but this is a live event for a reason. Before we jump in, is there anything else you wanna add?
Speaker 1: Nothing comes to mind. Let's get going.
Speaker 0: Let's get going. So Why
Speaker 1: do we do this? Why don't we have you start with, like, spinning up the environment that we're gonna use, getting us set up, so that we are ready to start building the telephony parts? And then I can step in. I can focus on building the Twilio parts. I know we we've we will switch between them and then connect those together and then do a little test
Speaker 0: test as well. That sounds good. I actually had a little bit of a rundown that structure which looks slightly different. We'll follow yours, but as a result, this might end up being slightly more chaotic, but I like that. I like that format a little bit more.
The the gremlins have just returned home, so we'll see what happens in the next 10 minutes. So can you hear that? You can hear that. Yeah.
Speaker 1: Oh, now I can. Now I can.
Speaker 0: Yeah. Now you can. So here I have a brand new completely empty code editor. I am running Docker in the background. We'll be running Directus locally with Docker.
So if you're following along, you'll need that. And what we're gonna do first is we're going to create a Docker composed dot yml file. And I do just happen to have here sequel I do happen to just have a light one prewritten because, you don't wanna watch me write this. Go grab the latest version of Directus, expose it on port 8255, map some of the internal volumes that Directus uses to local directories. So when we first run this, it will create a database in the uploads and an extensions folder.
We need a key and secret, which you should replace with a random value. To me, replace with random value is random enough for today. The initial admin email and password, you, of course, can change that. We're gonna just use SQLite because I don't wanna we don't need anything more heavy, and so that will, pop the file inside of this, data file here. WebSockets are enabled, not that I think we're gonna use them today, but this exposes a WebSocket and GraphQL subscription interface for, subscribing to updates and directors.
This one line here is not in our quick start, in our docs, and it just will improve the developer experience of building extensions. Whenever we'll we'll set it running so whenever we save it or rebuild, whenever it rebuilds, it'll auto upload indirectus. So with that done, we're gonna go ahead and, just taking a quick look at the chat. Hello, Scott. And that's c collection that logs different tokens for Twilio or other APIs to variable use token by another key.
Then you have Internet access to modify tokens for phone numbers or something. This is to always be missing in Directus, and you end up doing this outside Directus UI. Hold that thought for some short period of time. We know. But today, we'll use environment variables here in, here in the Docker Compose file.
But we're not gonna that's not gonna be the approach today in the interest of time. And then Docker Compose. That should just do its thing, he says. There we go. Running all the first time setup, and then it will run-in just a moment at 8055.
So local host 8055. There is our brand new director's project.
Speaker 1: That was so quick.
Speaker 0: Yeah. I like it. It's pretty sick. And this is also full fact directives. It's not like a shitter version you run locally.
Like, it is the full thing when you use direct to this is what you use. The only caveat here is SQLite does not have geospatial plugins included out the box. So if you wanna use the mapping features, you'll wanna use just a different docker compose that's in our docs. It just takes a little longer to bootstrap, and it it wasn't necessary for today. Okay.
Right now, there are a bunch of directors collections that have been created out of the box. Directors doesn't alter your tables in order to run. Instead, we create this, I don't know, like 20 ish tables or prepended with directus underscore. That means if you wanna get rid of directus later, you can just delete the application, delete these tables, and it's like we were never there. But this handles all of the UI, all of the settings, all of the configuration, they all live here.
And the one thing I'm gonna do, because you can extend these, you can't delete these default fields, but you can add new ones, is for all the things that are here, avatar, email, title, you know, all of these, there isn't one for a phone number. So I am just gonna add phone because I think that's gonna be useful for later. Cool. I, out the box, have this one user here, but I think it would
Speaker 1: be So quick question. So when you added phone, you you did it as a string. Just question, can you do any sort of validation from there
Speaker 0: Yes.
Speaker 1: I can. On that input?
Speaker 0: Yeah. You can indeed. Over here, edit field validation.
Speaker 1: Nice. Nice. And and, validation, what kind of validation do you use? What other rules? What is it?
Speaker 0: Fantastic question. I think you could just throw in a red x to be honest. Yeah. It matches. You could
Speaker 1: But also, it's got a bunch of other ones. Nice. Nice. That's awesome.
Speaker 0: Yeah. Yeah. Yeah. It's pretty cool. And you can do, like, you know, logic you can do grouping.
Right? And or and stuff like that. We'll leave it, and we'll just trust ourselves to put phone numbers in. Right? Don't do that in the real.
I worked at another telephony company that offers APIs in the past. And you and I both know, no one ever knows how to put a phone number in correctly, and it's a huge pain in the ass.
Speaker 1: So enforced validation. Because many different places, actually regionally write their phone numbers differently. So the way Americans write their phone numbers, especially compared to Europeans, Even, like, recently, we I had been I had built an app. Go to Singapore. We're testing the app.
The app fails because Singaporean numbers just have way more digits than we had accounted for.
Speaker 0: So Interesting.
Speaker 1: Make sure you, like, keep it flexible for all of these inputs. But anyway, phone number.
Speaker 0: Give me a phone number in whatever the format Twilio likes me. I think Twilio likes the plus.
Speaker 1: Plus? 44 Yeah. 79 4757 41 48.
Speaker 0: Why are you giving those me two numbers at a time? Anyway, whatever. Here. There. When we put you in.
This is a user now in our in our project. If I provided the email and the password, you would be able to, you know, log and enable the app access. You would be able to log in here. The password is hashed when you save it, but you could you could just pop it in here. Yeah.
Yeah. See? I see it in the chat here. I have to add a one in brackets. Like, it's a huge, honestly.
Also, Americans in particular, that one in the brackets and sometimes you put other numbers in the brackets too, Okay. Absolutely. Archaic. Anyway,
Speaker 1: it's it's like as it's as bad as them in the month before the day and the date.
Speaker 0: Let's I'm not even gonna
Speaker 1: Alright. But but seriously, though, there is international standards, ISO. I forget what the rest of the number is. But there is a Is it
Speaker 0: the E164 thing?
Speaker 1: I believe so. Yes. There is an international standard for phone yes. E164. That's what I meant.
So you know, ISO. I don't know why it where that came from in my brain. But, you should check this out. And what you can often do, there are lots of tools and one that is actually sponsored by Twilio where they can, change inputs to fit the format. So it's always international plus international code, then the digits with no spaces.
Speaker 0: But, interestingly, other telephony API company matches e164, but doesn't put the plus in front of it. So I don't think it's technically to standard, but it whatever. Twilio needs the plus. We've put the plus
Speaker 1: in.
Speaker 0: We we
Speaker 1: Twilio doesn't need the plus. Like, we will pop in
Speaker 0: the plus. Interesting. But
Speaker 1: but the the important thing that I recommend to people is that you use that format when you have it stored because it's then uniform across every single phone. Absolutely. I wanna do is have some people have that ability and some people don't. So whichever way you do it, store it in your in your, in your, database, in your back end as, like, just one format, and then have logic that separates it out and changes what it looks like to users based on regionalization.
Speaker 0: And not to derail us too much here, but Twilio does provide an API which formats phone numbers. I think it's called insights or lookup or something. Lookup. Lookup like the basic tier or whatever whatever will format the number for you. So you could introduce that as either a filter or an action event based trigger, and you could format it before it ever gets to your database.
You rely on, you know, the user to get it somewhat correct in order to know. You know, you drop the country code entirely, for example, and sometimes it won't know which country is it. But in any case, let's I feel I I feel our time slipping away. So we have set up a project. We've added this extra field.
I've added you in here. You'll be the guinea pig who gets the calls. Next in my little list was to add a bunch of environment variables and handle, like, all all of the Twilio configurations so we can focus on extension building. But I'm happy to get to the point where we first need a Twilio environment variable to do that. So it's up to you.
What do you wanna do?
Speaker 1: Why don't we jump to my screen and start from a console? I'm gonna start from the dashboard. Like,
Speaker 0: 5 times zoomed in, like 5 zoom in points, please.
Speaker 1: Would you like me to zoom in more?
Speaker 0: No. That's good. That's solid. Cool.
Speaker 1: Alright. Let's go. So the first thing we're gonna need, because we're going to be making phone calls, is we're going to need a phone number. So we're gonna come over here in our dashboard, and we're gonna find our active numbers. Now I actually went in and bought a phone number earlier.
And the reason I did this is because, phone regulations and some some of you maybe who've used Twilio in the past, Buying a phone number can be very, very quick and simple. Simple. However, there are regulations that come in from countries and, governments, and it's really good because it helps protect us from spam, which means you often have to upload, either ID or maybe address an address and other sorts of identification to say that you are who you say you are. So I had to do this. It literally I uploaded my ID with this number, and within half an hour, it was done.
I will say I have a at Twilio dot com email so that expedites it. But within 48 hours, we usually get 1 get it done for you. And you can still start building and sending messages to the phone number that was verified with your account. So, for example, when you create an account, you have a 2 f a number. You can start messaging that 2 f a number, but then start messaging all users.
You then need to have that extra level of, ID and regulation com regulatory compliance. Okay. So I'm based in the UK, so I think we should just use a UK phone number.
Speaker 0: Works for me.
Speaker 1: So now I have a UK phone number, and this is the first, I number that I'm going to hold on and keep into a safe place. So now I own a phone number. Now the thing is, for us
Speaker 0: Could I put could I pause you? Yes. Throw me the phone number in our little joint chat. I wanna show what I'm gonna do with it because then I don't need to show again what we're gonna do with them. If it's okay with you, give me 2 ticks.
Steal it stealing it for a moment. Over here in our Docker Compose file, we have these environment variables. I've added one called Twilio phone number. I'm gonna take the one that Nathaniel just sent me here, and there will be a series of other environment variables as Nathaniel goes around the UI. I will populate here.
A couple of them are sensitive, so I'm no longer going to show the Docker Compose. I'll show you what happens once we get them all populated, though. Okay. As you
Speaker 1: were. Awesome. So now that we have this, the next thing we're going to need, and it's just underneath, is a TwiML application. TwiML applications are pretty important. They are ways that we can essentially give Twilio some instructions of what what to do when phone calls happen.
We are going to create a new to more application, and we're going to call this directus for the workshop. Now, what you often have is you have a voice configuration. This says what we should what should happen when a phone call is made to or from this TwiML app. I'm going to come and fill this in in just one moment. But I'm gonna hit create.
So now we've got this director's Twilio workshop. We're gonna open it into a new tab. And I'm gonna come back and grab this SID. I need this SID for what we're going to do next. So this is the identifier of the application that we are going to be using.
Alright. One more thing that I need to do. I'm going to be using something called functions to do this. You don't actually need to use functions. You can write your own endpoints, and your own ways to do this.
I am going to be using this. I'm going to create a new function. I'm going to be creating a function that uses the Twilio client quick start, and I'm going to give it that AppSid that we just collected. I'm also going to give it a phone number. This phone number is the caller ID, and we're going to create it.
Drum roll. It's creating in the background Any second now. I know why it's failed to create
Speaker 0: Twilio cogs go brr.
Speaker 1: The reason why it's failed to create it is because, I did a practice run a couple of minutes ago, and they have the same name. So I'm just gonna quickly delete these and then start again. Create this, pop in a caller ID and pop in that ID. This time, touching wood, it should be fine. Uh-oh.
Okay. I might have to come back to this. Come on, folks.
Speaker 0: I can always do this step as well. Like, it's all good. We'll we'll we'll we'll get this.
Speaker 1: We'll get there.
Speaker 0: You got this.
Speaker 1: Okay. Once I've done this one, we'll we'll come back to it in a second. I think it's just, like, deploying, and it's actually going and taking down some assets, and it maybe needs to be taken a second. But we'll come back to this. Okay.
So we'll come back and do this later, but for now, we have our Twilio phone number. We have our Twilio API appsid, and then we also need one more thing. We need to get API keys and tokens. That's
Speaker 0: How many do you account set?
Speaker 1: Yep. As well. Yeah. Keys and tokens and then accounts set. And this is essentially how we can, authenticate with Twilio.
Give me a second. Just need to log in because I've been in for a certain amount of time, and I'm trying to access a secure page. And I need to turn over and hit my
Speaker 0: So when all is said and done, to generate tokens using a an endpoint in Directus and to do all the stuff we're gonna need to do later, there are 5 pieces of information we will need from Twilio. We need a phone number. We need the the TwiML app SID, which you've generated. I'll grab it off you in a moment. We need your account SID.
We need an API key and secret, which we're in the middle of generating now. We'll use the API key and secret to generate tokens, and we'll do that in the endpoint.
Speaker 1: Cool. Sending over the SIT and sending Lovely.
Speaker 0: This is the TwiML the TwiML app, Sid?
Speaker 1: These are the API keys and secrets, and the TwiML Sid begins with an a p. So if it starts with a s k, it is always a secret key. If it starts with a a p
Speaker 0: Man, you just sent you just sent me 3 long ass numbers, and I don't know it right. The first one is what?
Speaker 1: So if it starts with a s k, it's a secret key.
Speaker 0: Yeah. Right. Right. Right. Got you.
Got you. Got you. Got you. Got you.
Speaker 1: The one under the secret key is the, secret no. So the see. Yeah. Secret keys partner. Secretly keys is the secret secret?
Yeah. And then the last one that starts with an a p is the TwiML app.
Speaker 0: Yeah. Right. I'm gonna just say this again. The one that begins AP is the TwiML app.
Speaker 1: Yes.
Speaker 0: The one that begins 2 k is the API key.
Speaker 1: Is the API secret?
Speaker 0: Alright. And the one that begins SK is the
Speaker 1: API key.
Speaker 0: Right. Okay. Cool. That's why we double check. Can you imagine if we got much further and we're just like, why the hell isn't this working?
It's because I missed copy and pasted a key. Freaking hell, man. I need your account, Sid, too. And then we've got everything we need from the Twilio side.
Speaker 1: Account Sid
Speaker 0: asked. Thank you. And we need to just make sure that function can be deployed correctly. And that's linked to the TwiML app.
Speaker 1: Let me quickly go there and try this. I'm just gonna quickly hit this function. Alright.
Speaker 0: Good. We're literally still in Sab. I'm having a blast doing this with you, by the way. We should do it more often.
Speaker 1: Yeah. Alright. Now it works perfectly fine because there's nothing else that has the same name. And let me just quickly tell people what this generates. This generates a function with just a little bit of code that just says, that if this number is coming from from a Twilio client, it should be forwarded to, whoever it's going to be calling and vice versa.
Right? I'm
Speaker 0: gonna copy this It's kinda nice that you could just create it from the boilerplate and forget about it to a degree. I still need your account, Sid. And then we are all groovy. I mean, get onto building building. Yeah.
You didn't send it to me. Sid.
Speaker 1: It's the last one. A c. Oh, cool.
Speaker 0: Alright.
Speaker 1: And, last thing, I'm just gonna quickly grab this URL, head over to the TwilioTwiML app that we created, and pop it into our voice. And voila, we are done.
Speaker 0: Lovely. And what I will just say is the recording will be available on demand. We'll also write this up. So there was there was quite a few little moving parts there. They do all have purposes that, you know, that are important in this whole journey.
We'll detail them there as well so you can in case it hasn't quite sunk in, it can. Of course, we also have the chat if you wanna ask further questions now. But with that, can I take my screen share back? Yep. Wonderful.
So I popped all of those environment variables inside of the Docker Compose file, and now I just need to restart. So control c, up and enter. And now we restart the Docker container, and it will grab those variables and put them in the environment. So there we are. So now we're ready to actually go ahead and just start creating an extension.
So what we're gonna do is I'm gonna create a new a new, terminal over here. And, in here, this is this folder, I wanna get into this extensions directory. So cd extensions, and I'm gonna run the npx create directors extension. Extension. Extension.
That doesn't look right. Extension. Extend. That's correct. Latest.
Just to make sure I definitely have the latest version of that. So, I get to pick the extension type that it will boilerplate, and I actually want a bundle, which I just happen to know is the last in the list. So I went up. I can call it whatever I want. I suppose I'll call it, Twilio, Twilio.
I'll call it Twilio, whatever. Auto install dependencies. So just a reminder that a bundle isn't really an extension type in its own right. It's a shell where we can put multiple extensions. Now when these were originally created, they were actually to share dependencies and, you know, and reduce the overall code bundle size, But they also have this purpose of making sure you can distribute multiple extensions together.
So it's just going and scaffolding that now. And the moment that's done, we're gonna go ahead and add an extension straight into that bundle. So we'll just give that a moment there. There we go. We will go into this new Twilio directory, and we will go, we'll run npm run ads.
I believe that's what it is. And once again, we get to pick an extension type. Now if you remember, we're gonna build 2. We're gonna build a panel and an end point. The end point will generate the token.
So we're gonna do that first, make sure we can generate a token, then we'll move on to building the panel. So we want an endpoint, and we'll call this one Twilio token. We'll just do it in JavaScript, and it will go and add that to this, package here.
Speaker 1: And for those of you who are wondering why are we doing all of these Twilio tokens? Twilio tokens are because you're not going to actually put any of the credentials that we've just generated. Most of them none of them actually going to live in the browser, because that's unsafe. Someone could find them in the client. But what they do is they can be used by this function to create a temporary token, which then gets sent to the browser.
Does that make sense? So we use these tokens from Twilio or no. These credentials from Twilio, I'm gonna call them, to create tokens. That token, it uses the account SID API key and secret to say, I am a Twilio approved. But I am the person on this account making this request.
It then uses the TwiML appsid to say, this is the application I want to interact with and I would like to have permission to interact with. And then that generates a token which gets sent over to the browser, which can now interact with Twilio.
Speaker 0: Hang on a minute. Oh, did it did it update in the thing here? It does say extensions reloaded. That was just while it was in the middle of boiler plating. Just to I'm I'm just gonna restart the Docker container.
I don't think I actually need to do this. I just saw an error and I was like, let's work that out. So I think it should just be Twilio token. Twilio token. Oh, there it is.
There we go. So that so that is this wrap. Ahoy ahoy world. Ahoy, world.
Speaker 1: And for those of you who are wondering why we said ahoy, world. Ahoy was the greeting that was created for it wasn't created for, but it was used for phones when phones were first created.
Speaker 0: I thought it was the first word ever said down a phone line.
Speaker 1: Yeah. Yeah.
Speaker 0: Okay. Oh, holy world. Great. So we check that that works. Now in here, we wanna go ahead and actually, and generate a token.
So I'll just create a new endpoint, a new route handler here. So router dot post, and we'll call this one generate rec res. Again, if you've ever done any kind of Node. Js web development, this will feel very, very familiar to you with good reason. This is just the express route to the I was talking about
Speaker 1: it feels like express.
Speaker 0: Yep. Yep. Yep. That's exactly what this is. Now inside of here, we wanna go ahead and use the Twilio, helper library SDK.
What do you call it?
Speaker 1: From here, it will be the Twilio helper library.
Speaker 0: The Twilio helper library. And so we actually wanna go ahead and install that. So npm install Twilio. Fantastic. Now we wanna go ahead and, and use it.
So there is a page in the docs. Let's find it. I actually saved the link earlier. It's just shortcut here. This is the access tokens page, and it shows us how we can generate access tokens.
The access token oh my god. What are these kids doing? I swear they're getting, like, pamphlets, and they're just going, can you hear them?
Speaker 1: I can a little bit.
Speaker 0: Yeah. Like this. Anyway, so an access token is just this really, really long string here, that contains this information.
Speaker 1: Web token, just in case some people know. So you can break it apart into its pieces.
Speaker 0: Now we just wanna go ahead and generate them, and the docs, for Twilio provide these, these these different, snippets here. We are gonna be using the voice SDK in the browser. So we're actually gonna use create an access token, create an access token. So what we're gonna do here is is go ahead and copy and paste this, into this. Now there's a few things we're gonna do, we're gonna do ahead of time.
So we are going to one moment. We are going to, obviously, pull these to the top.
Speaker 1: Those we
Speaker 0: definitely need.
Speaker 1: We need to bring in our environment variables.
Speaker 0: We do need to bring in a a couple of our environment variables, or we could just use them use them directly from process to end. But I was gonna say this is an ESM environment, so we are just gonna very quickly change, change the way that we import Twilio here. So import Twilio from Twilio, and then the access token will be twilio.jwtdotaccess. That was just a small small, semantic change there, but it is important. Then we'll take the rest of this That should bring you in the environment.
You're dead right. You're dead right. And I believe that is exactly what I called them in the Docker Compose file, so I don't need to do anything with those. Then and this is now where we're moving into the, into the actual route handler itself. We're gonna go ahead and generate a ticket.
Speaker 1: Through that as well so that people know what's going on. So the outgoing application SID is the application SID we created earlier. So if you remember, I generated it, and he's going to pop that in. And then we also have an identity. Now remember, because this is a browser panel, this browser panel could be anyone.
Usually, you would decide a string to identify who is this browser. Quick question. Do we have access to who the logged in you Directus user is right here?
Speaker 0: We absolutely do, and we're gonna come back to this once we have the panel because the panel is gonna send an authenticated request to this endpoint. And within that authentication will come the ID of the user along with all the roles and permissions that that user holds. So for now, we'll just hard code it as a user, but we are gonna swing back around to this later and, as you said, actually provide the user ID.
Speaker 1: Cool. Alright.
Speaker 0: Now I don't think if we take a look, you know, alright. We're not doing incoming calls, but I think we'll just leave it as is. We generate a new access token with with all of these values we've set up. The only thing left to actually do is, is return this. Yeah.
Res.send, and we'll just send this value instead of
Speaker 1: the document. People are wondering, they're like, what is that voice grant stuff I am seeing? That's because you can you might want to give multiple permissions to different products with one token. So you can give a voice grant, a, a messaging grant, a conversations grant, a video grant. You could do all of that and send it in one token just to give that token lots of permissions rather than doing this if you're using multiple products.
Speaker 0: Absolutely. So with that, it's built, which is cool. This should generate a token for us if we go to slash willio token slash generate as a post request. Once again, it has the voice grounds. It has our account SID, API key, and secret.
It has our identity, which is, for now, just a fixed string, but we will update that in a moment. And then it will go ahead and generate a token and, and provide it as a JSON web token, which is what we're gonna need in our panel. So let's just quickly test this.
Speaker 1: Expect to see a string of epic proportions and randomness show up in a second, if this works.
Speaker 0: Yep. So Twilio token slash generate.
Speaker 1: And we do. Perfect.
Speaker 0: Lovely. So that's fantastic. That's actually really at its absolute core, all this endpoint needs to do. There are 2 things it doesn't do, which we're gonna do later. The first is actually identify the user, and the second is be authenticated at all.
Right now, any user on the web, if this was a hosted application, could hit this endpoint and generate tokens. Not good. So, later on, we're going to make sure that this is more locked down. But, for now, I think this is good.
Speaker 1: Yeah. And I think that and you can keep going while I say this. I think that people must remember on the web is just because a, URL is not publicly advertised does not mean that people will not be able to find it. And oftentimes, people use, like, just URLs are public to create really important private stuff like this and end up creating exploit, like, holes that the application can be exploited through. So make sure you protect this, outside of Demoland as well.
Okay. So we're creating now our actual panel.
Speaker 0: Yeah. Is that how you spell dialer?
Speaker 1: With yeah. That was perfect. You corrected yourself.
Speaker 0: Nice. We'll just do it with JavaScript again. So we're adding this to the bundle now. The nice thing about this is we only need to be running that npm run dev at a bundle level, and it will rebuild when the things under are updated as well.
Speaker 1: Cool. So
Speaker 0: I think you see the extension. Yeah. I let's, let's npm run dev this, and, let's take let's take a little look firstly around the code and then then what it does. So there is. That's like, where is it?
Oh, there we are, the dialer. The dialer is made up of 2 files, the index dot JS and the panel dot Vue. The front end of directives is built in Vue. JS. And therefore, when you're building these app extensions, they are also built in Vue.
Js. So we have an ID. This has to be unique across the whole system. So, you know, you can't have 2 conflicting extensions. It's generally best practice to prepend this with your author name, to, you know, namespace it somewhat.
But for now, I'll just be like Twilio dialer, whatever. We provide a name. This will show in the UI. Don't know why I keep writing it like that. We are going to put in an icon.
You can use any Google material icon. Descriptions, make own calls. Now all I want you to do for a moment is take in the fact that there is this option called text. And I'm gonna show you what that does in the actual directus UI in just a moment. Now the panel, is a view component.
It takes in the props from from the index JS. So here we have the text. Text is there. That's how data gets passed between this kind of configuration pane and the panel itself, and then it's just a view component. By default, out of the box, it comes with the options API.
You are, of course, completely, able to use the composition API, which is, I think, what we're gonna do today. I think most of you developers now kind of lean towards expecting to see that. So what I'm actually gonna do is delete no. I'm not gonna delete anything yet. I'm gonna show you what this panel does.
So let's create a new insights dashboard. We'll call this Twilio workshop, and we will add we will restart container. I didn't need to do that. I just needed to refresh the browser. That was it.
I couldn't remember what step I needed to take, so I'm like, let's do them all. There we go.
Speaker 1: Gotta be sure. Better safe.
Speaker 0: You gotta be sure. There's our Twilio guy. There's the icon of phone.
Speaker 1: I was really
Speaker 0: also pass in yeah. It was easy. Thanks. I mean You can also pass in these SVGs. Drop it.
Speaker 1: I'm still impressed.
Speaker 0: Cool. You can pop in SVGs too. And as you can see, the SVGs are all purple. That is the theme color of the director's projects. You can also use these CSS variables in the SVG, which is kind of nifty.
So they all feel, you know, like they belong. There's the text that this is the show header show header right here. You can add extra configuration if you want, and there it is. Show header, you can put some text in, Call people. There it is.
There's the text that came from the from this configuration options. I think it's called options pane. We don't want text, but, just wanna show you that's that's kinda how how it works. So now we're going to start now we're going to start ripping it apart. First thing I think we're going to do is we are going to let's just have a think here.
I think we're going to remove all the options. I don't think we need options in this.
Speaker 1: No.
Speaker 0: It has you know, it's it's going to just show the users.
Speaker 1: Like an example is, for example, a lot of companies are international. So they end up having, like, a German number, a UK number, a different number. So I'm saying I'm probably seeing you could have, like, as an option, a drop down to be, like, I wanna phone this person, but from this number because they're in Germany, and they wanna use the German number. So they it feels familiar to them, something like that.
Speaker 0: Absolutely. Absolutely. I think what we'll do here is we'll just empty that out to a div and onto the let's just let's just rock on. Let's just you know? Yeah.
I love some boiler plating, but we're just gonna we we get we're gonna go from scratch. So but and I'm gonna use setup here, so we'll use the composition API. I'm not gonna bother reloading the browser because nothing's gonna show up. It's gonna be an empty box. So now we're at the point where with this blank slate, we can really talk about every line of code we're gonna write, help you understand what it does, and build this extension that will call this this endpoint we've created, which is now an internal API endpoint.
We'll instal and configure the voice SDK, and we will eventually just make a phone call. I'm gonna pause for just a just a moment. We're about halfway through our time, and this is comfortable. This is a good spot to be in. Does anyone have any questions in the chat?
And, Nathaniel, too, you're kinda seeing this set up, I think, for, you know, one of the first few times. Do you have any questions so far?
Speaker 1: No questions. I'm curious. I'm really excited about some of the the options as well. So you know how it had text. What are the types of things we can put into the options?
So, like, I I just said, like, a drop down list, but are there other kinds of, interactions or ways we can select?
Speaker 0: Yeah. Yeah. Yeah. All of the built in they're called interfaces in Director, so form input, you know, you could we call an interface. You can use any of the built in interfaces.
So you have the the WYSIWYG. You have a codes input box that does some syntax highlighting. What the hell is going on? You have a text box that, you know, can be integer or float type. Like, you can enforce that.
You have sliders. You have relationships. You can actually pull data from collections and select an item within the collection. All of the built in interfaces and directives are exposed to you through through this.
Speaker 1: Interesting. Good to know. Good to know.
Speaker 0: Yep. Yep. Yep. And you can also in fact, if I just if I just undo this slightly, there's other, like, meta information you can provide. You can, hide values, make them like a password It says width full.
You can also do width half and put 2 things side by side. So we give you some flexibility around how that looks and
Speaker 1: feels. And last but not least, like, because I'm thinking, like, we're making this panel and it's kind of just a demo one. But people can people, share panels maybe for other users to to maybe try out?
Speaker 0: Yeah. So, on the director's marketplace, you can publish them on npm. If you boilerplate it with, the CLI, which I boiler plated mine with, we everything's set up. You can just push it straight to NPM, and in a few hours, you'll see it appear in the marketplace.
Speaker 1: Awesome.
Speaker 0: Yeah. Cool. Right. So let's move into the panel dot view. Let's move into the panel dot view.
So we're starting from scratch. What we're gonna do here? First thing we're gonna do is in is import all of the composables that come with the view, with the directors extensions SDK that we're gonna use today. So we're gonna import use API. We'll talk about what that does in just a moment.
And use items. Once again, we'll talk about what that does in just a moment.
Speaker 1: Is related to how well, I know we're gonna talk about in just a second. No. Yeah. These are things that are coming from Directus that we can use Yeah. In our component.
Speaker 0: Correct. And, actually, I might just take this moment to pause and show you inside of the composables right here. These components make working with direct this easier. Use API effectively wraps your API request with all of the authentication that comes in your that is in your Directus client. So you could, of course, just use fetch.
But then how does your your how does your endpoint know it's you? But if you instead use the use API, which, I think, yes, actually, it's under the hood. It also sends all of your client details. And that's how we're gonna know which users there, whether they're authenticated and so on and so forth.
Speaker 1: And this is really because I'm guessing it means you don't need to write, like, all of that metadata into
Speaker 0: your
Speaker 1: access to your endpoint URL.
Speaker 0: We're just gonna use the use API composable instead. UseStores allows you to go in and actually access information, use information within your directors project itself. So you can access things like all of the permissions users hold, data about the collections, the metadata about collections. And the other one I imported was the specific use items composable. And this will allow you to query data in your director's project directly from your panel.
So we're not going off to a back end to do this. We're doing this within the client itself.
Speaker 1: And so In
Speaker 0: turn, it knows what you have access to and will honor the access control of your logged in user.
Speaker 1: So yeah. So this is like takes away the need to query a database because you are building an application over inside slash beside your database.
Speaker 0: Absolutely. Absolutely. You know, I think a lot of people see directors as a CMS or see directors as a back end for an external application. But through a Directus insights and through, like, these panels and through modules, which is another extension type, which is these. So they add they basically give you a blank slate, which you can build.
Yeah. It's the most low level extension type, I suppose. It's a good base to actually just build your application within the Data Studio itself. So, yeah, pretty pretty nifty. So we're gonna use use API to make that API call to get our token.
We're gonna use use items to populate the drop down list of all of the users that we can call. We're also just because, just because we're in a, a view app here, we're just gonna import graph. There's not nothing. We don't need to explain that terribly. That's just a kind of quite boilerplatey stuff.
Now we're going to create an instance of use API. We call it API. Use API. And we're also going to now create our instance of use items as well. So we are going to pull out the items from use items.
Now the signature here is a little bit wild, so bear with me. The first thing we need to pass in as shown here, I don't know why it's using this. Maybe I've called it a font that doesn't exist, but why the hell does it look like this? Anyway, the first thing we need to pass in is a ref that contains a string of the collection name we're querying. So we don't just pass in the string, we pass in a ref.
Cool. We can we can rock on there. We can literally just put in ref. Not a problem, and we had to import it to do this. And we're gonna we're gonna query the directus views as collection.
Speaker 1: So use item The second now gives you access to Yeah. All of the Directus users. You can just pull them in.
Speaker 0: Yeah. Because that is a collection in your database like any other. Now we do have a distinction between system collections and user collections. User collections you create, System collections are these kind of 20 I showed you earlier out of the box. In fact, we haven't got any user created collections in this project.
We're not gonna use them. But, yes, you can query these just like you can any other any other collection. So that's completely correct. And the second thing we we provide is a query. Now directors has quite a robust I'll show you here quite a robust query language.
Here it is. Not query parameters. That's what I was looking for. So you can specify what fields are returned. You don't need everything.
Right? You might only just need the ID and the title of a blog post, you know, for example. You can apply filters. You can do searches. You can do, like, patch basic pagination, you know, by limiting how many per page and what page you're on and what the offset is and so on and so forth.
You can apply sorting and just more. Now we're gonna do that just to specify what fields we want returned because I don't want that huge object for every user. I just want a little bit a little bit less. So we're going to pass in fields. And we we want yeah.
Speaker 1: Yeah. And and Go ahead. You can keep typing, but I'm guessing this is something, like, that people should always be doing because it makes your your moving smaller chunks of data around, so only getting the things you need rather than Got it. Like, I feel like it's a very early in career developer move to just, like, pull down the entire database to get one field from one user.
Speaker 0: And what's really, really nice about this is we put we expose a GraphQL, you know, API, but we also expose a REST API. And now what I think is one of the core value propositions of GraphQL, which is you you construct these complex queries that only bring back what you need, you can do regardless. You can really pick what's right for you. And this works with, this works with relational data as well. Here in the items, so in the use items composable, I could, for example, let's say there's a relation, right, called, I don't know, posts.
I could be like post stock title, and I can start getting the relational data too. So it's really powerful.
Speaker 1: So in in that case, you almost end up querying 2 tables. Right? Because you're querying a table and then querying Yeah. That's critical.
Speaker 0: And that's where being very selective about what you're bringing back is really critical because another valid fields query is this. Give me everything on this level. Give me everything one level down. And you know what? You know, you can do that.
This is incredibly computationally expensive. But you could do this. I mean, you could. You could. But at any level, you could do this.
You could be like, you know, give me everything in the you give me everything in the posts collection, for example. So, you know, we give you that flexibility. You know, you can blow your own shit off.
Speaker 1: There's great power. Great responsibility.
Speaker 0: You you absolutely got it. Now, what's gonna come back from here is in fact, this might be a point where if I just console log items, we can just get a little look in on what's actually happening here.
Speaker 1: Oh, I'm guessing we're gonna see user 1, Nathaniel Okeno.
Speaker 0: Yeah. And there's 2 users. There's the admin too. Yes. My user.
I just got phone. Account. Right? You know what? We could apply a filter here that says, just give me users who have phone numbers.
I'm not going to do that. But if I refresh here, there's the array. The array has 2 users, the admin, no phone, Nathaniel, as we expect. Awesome.
Speaker 1: Cool.
Speaker 0: What else what else is important here? I might just rename this users because items is a little bit of a weird word to use when they are users. So that's just a convenience thing, I think. And then what we're gonna do now is populate a a select, a drop down. And then when you select something, we're just gonna bind it to a variable in here.
So we'll just create that variable now. All we want is their phone number. Right? We don't care about the rest of the objects. We just care about the phone number, and that can start off with a value of null.
Now that we've pulled in all these users, let's actually display up here. And now I have the kind of pleasure of showing you the component library. Here's something else. This is the component playground. These are components we use within the data studio that we expose to extension authors.
So we are going to use the v select, and it has all of the kind of styling applied. Really, really nice to kinda out the box. This is what it looks like. We need to v we need to bind it with a with a variable, which is why I just created phone number. Phone number will go in there, and you pass in items.
Items have text and value. Now our items do not have text and value. They have first name, last name, phone number, and so on and so forth. You can you can change which is which field is used for the text. So we'll we'll do, like, first name.
In reality, you would probably do, like, a computed, you know, a computed array that would add the first and last name together and display that. I am too lazy for that. We'll just display the first name. But that's what you would do in the real. Right?
So, that's I mean, that I I may as well copy it, to be honest. There we are. Yeah. Let's put it inside this div here.
Speaker 1: K. So we don't That is the value is going to be so I'm guessing the value is going to
Speaker 0: be the phone number
Speaker 1: that we Yep.
Speaker 0: Created earlier. Phone number.
Speaker 1: Yep.
Speaker 0: And the items, is going to be users.
Speaker 1: Okay. So it's gonna grab the list of users that we got.
Speaker 0: And then grab the list of users. As noted, we do not, we don't carry out value. As noted, it's interesting that it did this because you're meant to do this in Vue, when it's an attribute. So we have the item text, which is first name, and there was item value was the one under the item.
Speaker 1: So you can choose what is visible to click, but then what that value actually trick the way it adds to whatever. Okay. That makes sense.
Speaker 0: I mean, let let's make this easy. Let's just let's just, you know, print the value. So now if we refresh, there's our drop down admin and Nathaniel. When you pick Nathaniel, there's the
Speaker 1: top up. Blank when it was admin because admin doesn't have a number.
Speaker 0: Yeah. Because, actually, initially, it was, on, I think I need to put in, like, a select. It's unset to begin with. It's null. So whatever.
We would need to put in, like, a select user default setting.
Speaker 1: Doesn't have a number. So
Speaker 0: The admin doesn't have one, though. But, yeah, originally, this isn't because admin has nothing. It's because it's null. But whatever, like yeah. Small small nuance, small small edge case kind of thing there.
So now we have that, then we are
Speaker 1: I think we need
Speaker 0: I mean, that's probably we need a we need a button. We do need a button. Can actually I think yeah. Yeah. We do.
Let's use another component for that. Let's look at here. We have the button, shock horror. I mean, it's just the v button. We actually need to do nothing else.
I'm not even gonna bother copying that, to be honest. V he says and then makes a typo. V button, call user. And then we will when it's clicked, we will start call. And, of course, we need a function, Let's get this const stop call.
I think it needs to be an async function for later. I just happened I mean, we could change it later, but we'll do it out there. So there you go. That will start, and then we'll we'll grab the value of phone number at that point. When we start a call, we will then go and grab the token.
Tokens have a short lifespan, so you really wanna grab them at the point you're gonna use them all very soon before. So we'll we'll go and handle that.
Speaker 1: Spend the token time time to time to live. It is not recommended for you to just, like, create one that lasts the whole year. You want ones that are gonna last a short amount of time.
Speaker 0: Yeah. Because they can they I mean, if they're intercepted, they're usable, basically. So, yeah, you do only want them to live They wanna run a short while. So we obviously haven't done anything with the use API yet, but I think you broadly understand what it's about to do. Do you have any questions?
I'm pretty happy with how it's shaping up.
Speaker 1: I like how quickly you can build the especially with the component library, how quickly you can build the dysfunctionality, with all of and I'm guessing the great thing is, like, with stuff like that, you're standing on the shoulders of giants, of heroes where, like, they have done all the sorts of things to, like, think like, I saw you change in the width of the button, like, really easy just dragging across and stuff. Yeah. That is really, really useful.
Speaker 0: This one's my favorite personally. It's called fancy select, and this is just a select 2 items, a divider and a third item. And it's just a select, but look how pretty that is.
Speaker 1: I love how the pass.
Speaker 0: And that's used and that's used inside of the UI as well. We actually used it when we, when we or did we use it actually? Nope. Lied to you. I used it earlier today.
No. So there you go. Right. Okay. Save
Speaker 1: and refresh.
Speaker 0: There's the button. The button just runs this function. Now with the point where we can go and get the Twilio voice SDK. So let's let's go ahead and do that. And, yeah, that's a really good point, Alex, in the chat.
This makes customizations feel native to the by using the component library, it all feels native. Don't get me wrong. Obviously, it lacks polish. It needs some padding. But, actually, to be fair, just by adding padding
Speaker 1: It would be a really good job.
Speaker 0: Yeah. Yeah. Yeah. Yeah. Right?
We're we're lazy, so this is what you get today, but you could Speak
Speaker 1: for yourself. I'm joking.
Speaker 0: Speak for you. Yeah. I'm I'm the one with the keyboard, so I'm speaking for both of us. Hey. Right.
Let's go and install npm install, hang on a minute.
Speaker 1: Twilio and I think voice SDK.
Speaker 0: It is. It is. Npm install at Twilio slash voice SDK.
Speaker 1: Yeah.
Speaker 0: Not my first rodeo, mister Academy.
Speaker 1: I have made this mistake multiple times.
Speaker 0: Now Cool. Before we continue, there is one more piece of configuration. And it does involve going back to that, to the, Docker composed file and adding one more environment variable. Let me let me shove this up. We're still here underneath the eyes.
Hello. But I just wanna get it to the point where I'm not about to leak all the information. So I will get rid of that now. Okay. Back it back here.
We're back here. Just above the cursor, a couple of lines are all those environment variables I don't wanna show you, but we do have to add one more. You might be thinking, pretty damn sure I've added enough of these now. Like, I I don't don't wanna do this. But what we do need to do is, let's find it.
I did write because it's long. I did write it earlier. Needs to add this environment variable. Why? What the hell is this?
As mentioned earlier, the director's data studio, doesn't allow request to external necessarily without perfect configuration allow requests to third party services, like to 3rd party servers or whatever. And that's a security precaution. That's great. But we are going to be connecting directly from our browser to a phone number. I think, strictly speaking, we could probably build this as an endpoint too and use the endpoint as like a middleman proxy, but we don't we don't have time for that.
The easiest way to do it is this environment variable where we're basically changing the content security policy, to allow the connection to this WebSocket URL, which is what the voice SDK is gonna do in a bit.
Speaker 1: I was wondering. I was like, have we ever seen this before? Like, but now that makes sense. So you are giving It
Speaker 0: took login. It
Speaker 1: took Yeah. Yeah. So you said
Speaker 0: to work that out.
Speaker 1: We are making sure that the, the director's browser I'm gonna call it the director's browser, which has these extra security walls around it. We're just like, yo, let, WebSocket connections to this Twilio u URL happen. Awesome.
Speaker 0: Yes. And otherwise, that will error. And while we were putting this together, that error, it's like I had to add that environment variable for it to work. It's pretty descriptive. The error tells you it's a CSP, a content security policy problem, and it's on this connect source value.
And that it was while trying to access this this, URL. So, you know, it it was pretty easy to work out, but let's save ourselves the the pain and do it now. So so we've installed the SDK. Yeah.
Speaker 1: Talk about. So we've installed the SDK, and as I'm talking, you can maybe, like, type. So with the voice SDK, what we start, we bring in the SDK, and we bring in specifically a device. The idea of a device is a device is anything that can connect to Twilio, because the device right now, it's gonna be a browser, but it could be a phone if you're using the, like, react native or the iOS or Android SDKs. But we are bringing in a device, and that device needs to have permissions, and we give those permissions from a token.
But we don't have a token now. So how are we gonna get this token from our endpoint? Great.
Speaker 0: We've kind of spoken about it already. We're gonna use this use API composable. Call our now internal endpoint slash, slash Twilio dash token slash generate as a post request, we'll then get the we'll then get the value here. So, the way we're gonna do that, we've already created this, is we are going to, pull out the data value that comes back. I'm already gonna just call it token.
Await API dot post because it is just an Axios instance. Ultimately, I'm gonna go to / Twilio token slash generate. That will return a string, which is the token, which we can then remove these question marks. We'll pop this directly in here. We are That's how you pass this device.
Yes. We're ready to register the device. There is one more thing I would just wanna take a moment to do. And, it's not I've I've not taken note of it, but I just wanna derail this for a moment. I did oh, shall I do it?
Shall I do it after? It's the whole sending over the sending over the correct user and authentic. I think we'll make the request first, and then we'll we'll see what happens. So we have a device, and then let's just console log device. Realistically, we're either gonna see a device or we're gonna see an error because that token's invalid.
There is no there is no other outcome. It's one of those two things. Extensions reloaded. I hit save. So we're gonna refresh this.
Open the console. Go to you. Hit call user, and that's the device. Rock on. What else is important here?
Oh, no. No. No. No. We're not done.
We need to also do the device. We need to register the device. That's my bad. That extension's reloaded. I might just rename I think it's alphabetical because, again, lazy.
Oh, being being too hopeful there, I think. Okay. Whatever. Cool user. Oh, problem.
Why? WebSocket received error undefined. Oh, I think oh, I didn't restart the I just needed to because I changed the environment error.
Speaker 1: That was the error he told us we were going to see, and he walked right
Speaker 0: into it. But there it is, by the way. Refuse to connect to this URL because it violates the following content security policy directive, connect source self HTTPS. So they were there, and then I added on to the end of it the WSS, you know, Twilio voicing. The Twilio token generate is, I feel like you probably came into this, into this session a little bit later on, John.
But here here it is. We built it first. So, yes, what we've built is a bundle. In the bundle, it's an endpoint and the panel. The panel calls the endpoint.
The endpoint talks to Twilio, comes back, returns it to the panel. So, yes, it is now a direct test custom endpoint, by virtue of this file here. Okay. Let's do that again. When you see an error in a workshop and you're like, damn.
I hope this isn't gonna derail everything, but no. There there we go. No errors. So we're good. No errors.
And we did see there it did a post to the Twilio token generate endpoint. It returned in 25 milliseconds with the
Speaker 1: a a device, register device with Twilio, and say, hey, device. I'm authenticated. I am now ready to start making calls and receiving calls if you set up to do that.
Speaker 0: Let's do this, and then we'll go back in the in up the the endpoint because that is there's no problem now for its hard coding user in the endpoint. But in the real, you should not be doing that. So we'll cover that at the end as like a let's it's not a next step. It is critical, but we will treat it as if it's a next step because I wanna I wanna get a call. I wanna get a call going.
I'm getting impatient now, as you know. That is the person I am. Okay. So, let's now yeah. And once the so there's one other thing here, which is this device doesn't register like that.
Instead, it emits an event when the device has been successfully registered. Sometimes that takes a moment. I think that it also pops up and, like, asks you for, you know Yes. So My hat says
Speaker 1: why register can take a couple of seconds is because sometimes it needs to ask permissions to use your microphone, which could take you one second, 2 seconds. In Kevin's case, where he's already done like a we we've done this before
Speaker 0: It doesn't show up. So it's
Speaker 1: given it permission. So it's not going to do that. So while it may seem lightning quick for him and you might be like, why do we have to do this and then wait for it to finish? It's not always gonna be like that for all your users. So then what we use are these events where we say when the device has been registered, then we want to do something.
Now what a lot of people do, especially if they're creating dial up panels, is you might have you might register a device when someone opens the dialer. Right? So that it's quicker that when they click a call, they're already registered. And then you can already, like, say that something's gone wrong. You are not authenticated to use this dialer straight away once they open it.
Different
Speaker 0: Can I ask you a question? Yes. The the tokens don't last very long, and we we use the token in the code when we register the device. And I don't think we use the token again. But what happens if the token expires between registering the event and actually trying to make the call?
At what point have the handshake happened?
Speaker 1: The handshake happens when you register the event when you register the device. Right?
Speaker 0: Not when you make the call.
Speaker 1: Not when you make the
Speaker 0: call. Oh, interesting.
Speaker 1: Is you also get a event when your token's about to expire and when your token expires. What we recommend people do is when your token's about to expire, generate a new token. So hit that API call then start a new token get a new token.
Speaker 0: Yeah. Exactly.
Speaker 1: Again, this limits your surface area for exploitation. So it's it may seem like a little bit of a faff, but trust me, you do not wanna be hit with a crazy Twilio bill because someone's hijacked your phone call and used it to call premium numbers that paid themselves.
Speaker 0: That. So we're gonna make a call here. The call is going to be an object. I'm going to save it up here because we want to start the call later. We're gonna wanna handle hanging up.
So we'll need access to that up to that object in the in the global scope. So we're going to go const, call, I think we'll call it, and we'll just again initialize that with a value of null. Now it's time to actually make the call. So we'll set the value of this ref here, into device dot and yeah. Thank you.
But my uncertainty was creeping in there and it has a params object and the value is going to be phone number, this one here, dot value. Because it's a And it's that didn't get the raw value.
Speaker 1: You might be like, why connect and why is it that params too? Because there are a couple of things. You can clone phone numbers, but, like, with Vince with you, you can actually phone video call rooms. So let's say people having a video room, you can literally dive in to it from here. You might want to dial another client, which isn't gonna have a phone number.
It might have, like, a a name attached to it, like the user that we have. So, there could be a couple of things. We're using phone numbers here, but that could be a few other things, which which is why there is a bit more flexibility in I don't wanna say ambiguity, but a bit more flexibility of what could go into that params. Yeah.
Speaker 0: Alright. This is everything we need to actually make a call. We're not done. We're not gonna get any UI that we've made a call. There's gonna be no ability to hang up.
There's none of that, but I I think this is a moment we can actually try this out.
Speaker 1: Alright.
Speaker 0: That's it. You know, we've got 33 lines of code with a few lines of white space, and I think this might be all we need. So your phone number's in there.
Speaker 1: Yeah.
Speaker 0: Let's ready for the error? I am. I am
Speaker 1: ready for an error.
Speaker 0: There it is.
Speaker 1: Allow. You've hit call. I am getting a phone call. I'm gonna mute my mic and just join the phone call.
Speaker 0: Hi. Hey. Yeah. You sound you sound suitably terrible as phone calls do. I can't I can't I can't be bothered.
I literally can't be bothered to figure out sharing your audio. So anyway, the thing is like, you should share my audio. I'm like, I can't be bothered.
Speaker 1: I was speaking on the phone. He could hear me. Just because we're not sharing audio via the the stream, you couldn't hear me. So next time, I won't mute my microphone. But his browser is you couldn't hear me.
So next time, I won't mute my microphone. But his browser called my phone. Hey. There was no indication we did it. There was no indication it ended.
Speaker 0: So there there's some things we need to work out now. But we're basically sound. Yeah.
Speaker 1: There were
Speaker 0: some sound things.
Speaker 1: So, Twilio just built in we have, like, these audio, like, files that, it's, like, plays a sound when you connect. It plays a sound when you disconnect. But, visually, there are no cues. Now you can customize the sounds that you that are in there to have something that's like your own UI. And, like, what we're gonna do next is you probably should change your UI so people can see visually what state the call is in.
Speaker 0: We're at the point now where we are polishing this. When we get back to disconnecting the call, I think we'll, I'll slow back down. But for the next couple of minutes, I'm gonna speed run this because this is just little view UI, you know, things. So we do this. We currently have this div here that shows start call pick phone number.
So I'm gonna create a new ref called show call. Sure. Let's make that false because at the beginning, there is no call being made. The call, I believe, also emits events. So call dot value is this, then we'll go ahead and say call dot value dot on.
And there is a ring ring.
Speaker 1: There is a Yeah. I don't know if it's answered or connected off the top of my head. I will check it out later, but it's subject to tell you it's connected, and then one to tell you when it's I think
Speaker 0: we're gonna be lazy and we'll just do ringing and disconnected because disconnected is by either hand, I think. It's just disconnected. It has been dis
Speaker 1: phone ended. Whether you hung up or they hung up. There is another way to, like, distinctly choose between which person hung up, but we're not gonna be using that today.
Speaker 0: Exactly. So show call dot value becomes true. And then on disconnect disconnect, we'll set it back to force. Then in here, we'll say v if not show call, do all of this. And then, oh, just some just some chat right here.
Loving it, but the, the potential tying this ability with other business use cases like customer engagement, etcetera. Yeah. I mean, I see, like, customer, like, outbound call centers as being, like, rich for this. We'll talk about that more more a little bit later because I have some thoughts on where this could go in the future with more time. Also, the possibility to include the verification style systems, generate a confirmation code in direct us.
You read it out. You know, you could, send it via Twilio and then confirm it on the phone, stuff like that. Yep. Excellent. Yeah.
I love the part with the browser called the phone. So did we. I'm I'm glad it worked.
Speaker 1: The first time. Right?
Speaker 0: The confidence in it. Yeah. We also need, I suppose, just a v l's here, and we'll just say call in let's do it more like this. Call ongoing. Not that.
E. I just wanna No. I'm just
Speaker 1: gonna say, what is that p else?
Speaker 0: No bloody clue. The or the first result having a mad one. And then I think we'll just want another button. But this one is end call. And exactly.
And we'll do an end call function, which I will just create, and we'll deal with it in a moment. Const end call. I don't doesn't hurt anyone.
Speaker 1: Yeah. I was it doesn't have to be, but right
Speaker 0: in there. Yeah. So that's the UI. It'll call ongoing end call, and then there's an end call button. It will do nothing.
We we do actually need to tie this up to ever get back to that first state by pressing the button. And I think called dot value dot disconnect, the thing where we have a connect, there is also a disconnect. And then call, show call dot value force. I think it's handled by this, but, whatever. I wanted to work first time, so we're just gonna we're just gonna keep throwing some redundancy in there.
I think that's groovy. So extensions reloaded. Let's try this out. Nathaniel, call. Nice.
Speaker 1: Good. Call's coming in.
Speaker 0: Answer.
Speaker 1: Hello? Testing. Testing. 123.
Speaker 0: Yeah. I hear you twice through through the browser and through our streaming system, and, it's it's twice too much, to be honest. Bye. Oh, forget that. It did hang up the call.
Stereo. Yeah. It did it did hang up the call.
Speaker 1: Dun dun dun. Oh.
Speaker 0: I don't know what this is. I did hang up the call. Just before we get to this, because I think this might be in the voice SDK. But I'm not convinced. Get on proxy.
Log is read only and not configurable. Now that means logs being used somewhere inside of the call dot disconnect. Alright. Call dot underscore disconnect. Alright.
We are yeah. It's here. It's somewhere in here. We are going into the depths of the of the SDK, the voice SDK, and I have a better idea. I have a better idea on how to handle this.
Call.value.onerror. Yeah. Damn. Does that even work?
Speaker 1: I I do not know. I I I am desperately looking up the voice SDK to see
Speaker 0: what Honestly honestly, my guy, it's always the end of our it's always the end of our Workday. Yeah. It's a frantically look up anything. I'm swallowing the error. It's not an error if you if you swallow it and don't display it to the user.
Speaker 1: Is it. You're you're absolutely right. There is an error. But like, sorry. There is, on error event.
Speaker 0: Oh, I just I'd made a guess there. But I'm gonna call you again.
Speaker 1: Hello? How are you? Yeah.
Speaker 0: Yeah. I I don't care how you are, mate. Sorry. Bye. Okay.
Interesting. We'll pause on that. I'm gonna I'm gonna refresh and call you one more time, but I'm gonna hang up because we actually haven't tested that side. Sorry. You're gonna hang up the other way.
I've I've been the one to hit end call.
Speaker 1: Okay.
Speaker 0: Interesting. Look. Works great. Call ended. Question.
It's when Question. I disconnect.
Speaker 1: Yeah. Question. You, when you disconnect
Speaker 0: works. Yeah. Here.
Speaker 1: So you hit disconnect. Do wait. Hold on. I wanna quickly check something because, you've got on disc. That's on disconnect.
Speaker 0: I'm
Speaker 1: not sure, actually. Mhmm. I'm not sure.
Speaker 0: Neither am I. Neither am I. Refresh, reboot, pick up your changes. The changes are happening. Look.
When I hit save, just watch it. Extensions reloaded and other UI changes were displaying. So I'm confident that happy to call this a a success, to be honest. Now there are a few other things we need to do. We need to like, I I think we must tighten this up a little bit because it's currently a little too open for everyone.
Because right now do here
Speaker 1: is anyone who gets access to the URL gets a token that allows them to phone anybody they want and charge it to you.
Speaker 0: Agree. So, Wreck, I want to say it's accountability. But just in case it isn't, I'm gonna just oh, do you wanna know the way I'm gonna do this is I'm gonna go, object dot keys rec, and we can work from there. Oh, was that too hasty? Oh, was that too hasty?
Is it building? Oh, but it's still building. It's it's packaging the whole Twilio SDK t k and and that's why it's just taking a hot minute there. So we're gonna do this. What's the best way of doing this?
I think what I'll do is in the panel is I'll just pause on I'll just comment all of this out briefly. I don't actually wanna be making calls. Interesting there. Refresh and call. And over in this terminal here, great.
We have
Speaker 1: You have accountability.
Speaker 0: Paul, last in the chat, obviously, you can lock this down in direct, but imagine inside of Twilio, there are also options to lock down your numbers. Zip rank as well. No?
Speaker 1: Lockdown ask that question. I am locked down the
Speaker 0: Obviously, you can lock this down in direct test. We might need to expand on what that means. But I imagine inside of Twilio, there are options to lock down your numbers or SIP trunk as well.
Speaker 1: You're not I mean, these on your numbers.
Speaker 0: Tokens are the way to do that. Yeah.
Speaker 1: These tokens are the lock. Yeah.
Speaker 0: So you wanna make sure you're securing the generation of them. So And, accountability.
Speaker 1: Yeah. The generation of these tokens is essentially how they are locked, and only someone who essentially only someone with your credentials can create tokens, which means only someone
Speaker 0: with your
Speaker 1: credentials can create calls.
Speaker 0: I'm gonna pause you for clarification. Lockdown calling premium numbers or long distance
Speaker 1: Yes. Oh, yes. Yes. Yes. Yes.
Yes. Yes. Yes. You can. I can actually show you that in the browser.
So, there is
Speaker 0: I'll I'll pop over to you while I just do this. There you go. See yours now.
Speaker 1: No worries. So you have voice geographic permissions. So eventually, let's go back to that. Voice geographic permissions. And give it a second.
It will load. And so you've got, programmable voice and SIP trunking as well. And you've got, they give you also an average cost of how much things will be. You've got low risk and high risk. This is a connection.
This is not just countries, so it's not entire countries that are, high risk. Although it is could be a large proportion of countries, large percentage of that country. It is specifically network carriers in specific countries that have been known to have a higher risk of toll fraud, so you can block them. So I can, like, block the whole of North America. I can block specific country and so on.
And then you can also pop in a number to check if it's got permissions at all. So that's another way to just, like, lock it down, and this is great because it's on an account level. So your whole account can be locked down.
Speaker 0: All good? Yep. I did I did the changes. So at the top of the at the top of the, route handler, we inside of this, request, this rack, you get this object called accountability. Accountability contains the following properties, user role, whether or not they're an admin, whether or not they have app access, IP, user agent origin, and permissions.
So you can further go on and expand, but all we care about are you logged in, and authenticated with director? So so that's all this does. It says, hey. If you don't have a user ID, go away. Now I think about it, there might be more you wanna do here because you could just jam an accountability object and user.
So there's probably some other levels of, of restriction you wanna do here. For example, checking the user's role, which then will return they don't have a role because they're not a valid user. But I think this is I think this is okay. And then here in identity being
Speaker 1: Yeah. User, it can be
Speaker 0: There you go. Rec.accountability.com. So which is the ID.
Speaker 1: Name of the user that we're logged in on in the system?
Speaker 0: No. It's the UUID.
Speaker 1: Okay. UUID. Cool.
Speaker 0: It's the UUID of the user. I mean, if if you want to see, we can just console log.
Speaker 1: Well, because I was gonna show how it appears in the Twilio logs when a call
Speaker 0: comes in. Sure. Give that a moment just to reload one more time.
Speaker 1: No worries.
Speaker 0: Again, it's bundling that whole Twilio, helper library, and so it just takes a moment to build. We'll hit that.
Speaker 1: Did you uncomment the call?
Speaker 0: No.
Speaker 1: Yeah.
Speaker 0: That would help.
Speaker 1: Alright. We'll make this a short call, just so we can show you the logs. So now only authenticated users on directors can use this application. They he's gonna call me. I'm gonna answer.
I'm gonna keep it on for one second. He's gonna end the call. My phone call ends. And then I'm just gonna refresh my logs so that we can see the latest call that happened, which was 838. Yep.
Which was this one, and we can see here it's complete from a client, and it was from client. And then this was the UUID that he talked about. I can actually show you a previous call. Remember, it used to be hard coded to user. If I get to this one over here, we can see it was client user before, and now it's client and then the user ID.
Speaker 0: That's cool. Cool. So, I mean, I I think and I thought about it more actually. I may update the docs. I've just thought about it in this moment.
The user actually this doesn't prove the user is authenticated. It proves that there is an accountability object with a user I with a user value that is not foresee. That's what I check against. But what you may wanna do is expand this further, use the permission, service, check they have certain permissions, which they either will or won't have. That is more direct us, that's locked into direct us and it will say no if they don't exist.
So just a thought there. What we did was a lightweight, like, check, but it is not foolproof. And I've just realized in this moment that that's the case. But that's fine for this. We've acknowledged it.
We've shared that with you, and we've given you an approach. Now I think that's it for, like, what what we can do here. But what what more could we do? Firstly, we need to handle that rejection state better when I hung up. Can't be bothered now, but just I'll figure it out.
It'll find its way into the blog post that'll accompany this. One thing that's really cool if I just come back to my screen share is these are real users. Right? And they're queried using the composables that are exposed to view to to this view component here, this extension. But you have access to all the collections.
So let's say, for example, you have, customer calls or customer notes, customer note whatever, a timeline of events and they exist in your project, you could select the user, get maybe their latest notes, then call them. So now you have context. Additionally, insights dashboards have this concept of a global relational variable. So what this will do is user, is you select directors users in here. Let's say we want first name and last name in here.
Let's not have them overlapping each other. You could select a user from here, and this now contains the UUID of that user or the object of that user. I can't remember. But you could feed that into this panel. You could feed it into the panel that gets customer information.
So you can have multiple parts of your dashboard all changing because you selected the user once in this global relational value panel. So there's so much. There's so so much you can do with this. And I'm just really excited for more people to see directors insights as a really valid app builder surface more than just, more than just insights and BI. So with a couple more minutes to to go, if anyone in the question if anyone in the chat has questions, please do chatter and let us know.
Nathaniel, do you have any any closing thoughts while we wait for those?
Speaker 1: No questions. But the thing is, like, I'm I'm just really trying to think about, like, other ways. So, like, there's obviously, like, building your own mini contact center. Because contact centers are, like, big and expensive, and actually sometimes what you need is you don't want this massive, like, stood up, like, huge at scale contact center. You just wanna be able to have the ability to contact your users just really, really quickly, and you could start building applications like this.
You can then also because you're using Twilio phone calls, you can access, like, a lot of other Twilio functionality. Like, we've got, like, voice intelligence transcriptions where, like, you have a phone call. At the end, you can run AI operators on it to just be like, yo, this person, like, that person asked for a manager, or the person was happy. We can just do sentiment analysis and have that, like, just pop straight into a panel, for example, because you are just connected to that ecosystem as well. So, there is way more than just the calling calls that you can do, but, it all starts with, like, ring ring.
Speaker 0: Yeah. And I suppose you can query APIs for that data as well from within here as we have just demonstrated, and we spoke about with the weather API, you know, example way up top. You can just call off to arbitrary third party APIs and bring data in via custom endpoints. So, yeah, there were no other questions in the chat, so I'm pretty confident at this point saying I think we are off the clock, which is wonderful. This has been awesome.
Thank you so much for joining me for this. I had a really fun time putting this together and delivering it with you.
Speaker 1: Always enjoy hanging out with you. Next time we go on a roller coaster journey, we should write another workshop as well.
Speaker 0: Which is what happened. Sorry. That that that's what happened. We we wrote this basically while while going to a theme park together.
Speaker 1: We had a
Speaker 0: long, long, long, long drive, but something could came of it. Weekends. Well, on that note, thank you so much everyone for joining in. We will see you somewhere. Bye.
Speaker 1: Bye.
Speaker 0: Oh, wait. Where can people find you? Oh, online at Twilio dot.
Speaker 1: They can email me at nocennwall@twillio.com. I do check my emails, and, yeah, just say hi.
Speaker 0: I was ready for you to that. I don't check my emails, but you can send me an email there. Alright. Alright. We're done.
We're done. We're done. Bye.