 So, welcome to our next talk about MetaMOS approach to layered extensibility in open source. And yeah, I would ask you to settle down. And welcome to our speaker, Corey Yulun. Thank you. Yeah, it's your turn. Thank you. All right. So, I'm going to talk about MetaMOS approach to layered extensibility. Really quick. How many people know of our familiar with MetaMOS? Oh, okay. That's great. So, if you're not familiar with MetaMOS, MetaMOS the easiest way to say it is we're an open source Slack alternative. And so, I'm going to talk a little bit about MetaMOS and our approach. But first and foremost, we've always considered MetaMOS a platform. We consider it something we want to build on top of. In the very beginning, the actual binary was named platform for those who go way back. The original repo was named platform. So, it's something we've always started with this concept, right? So, if you think of chat or a message-based system as a platform, we were always really interested in what other open-source applications can you build on top of this platform, right? What sweet things can you build on top of this platform that allow them to interact with your users and allow you to create amazing products on top of it. So, in our world, we talk about things like embedding applications inside of MetaMOS, right? So, we want to give people the power to embed applications inside MetaMOS and then take MetaMOS and embed it into other applications, right? So, if you could imagine MetaMOS as sort of the central hub of all these different spokes, you know, what kind of things would you want to embed in MetaMOS, right? You can see things like HR applications, you know, ERP systems, company directory is a really popular one, right? Head tracks or whatever you call it, you know, active directory, operations, right? And you do this embedding through a lot of different ways. And we'll talk about these different ways, right? Some of those ways can be things like simple slash commands. It can be things like bots or it can even be things like really powerful plugins in our system. And I'll kind of explain how that works in our system. So really quick, MetaMOS has layers. So we're going to talk about each of these different layers. And it's meant to get sort of, it goes from easy to hard, I guess, is the best way to describe it. The top three things, the slash commands, webhooks, REST API and bots, and the plugin, that's what we call developer toolkit. So you'll hear me refer to that as developer toolkit. Sometimes you'll hear me refer to different names, but these are the, that's the area where we kind of focus a lot of our extension work, right? And then, you know, just being open source and having an open data platform are two other areas of extension. So I'll talk about those really quick as well. So MetaMOS is open source, right? For this audience, probably very obvious, right? But you have your typical open source goodness, right? You can fork, you can change what you want, heck, you can change everything, right? And we have customers and users who do that, and community members who do that. And that's amazing, and the power of that is really powerful, right? You could do whatever you want. Take it as a base, do whatever you want. The reality is, though, what we find, at least, is that can be really hard, right? You're forking a really large project, there's a lot of source code in there, there's a lot of things you have to do, you have to go do, you have to understand how to build, how to interact. And so we wanted to give people this layered approach, right? This layered approach of making it really easy to extend MetaMOS, right? And so one of those, several of those different ways, though, is we just have a, you know, what you see in the UI is accessible through our RESTful JSON web service. So all the UI that MetaMOS provides is actually just done through the web service, right? And one of the cool things of that is you'll see community members or other groups build different things, right? So here's a really great example of this team called Matterhorn, which is from our community, and they built this awesome terminal client for MatterMOS, right? So they took our RESTful JSON API service, they really wanted something to run in the terminal, and so they went ahead and built it. And so you can kind of see the power of that. And like I said, this audience is probably very familiar with it, with that kind of power, and this is an amazing, awesome example, but you also have to realize that's a lot of work to get to that point, right? So that's an interesting sort of base layer. Another piece of the base layer we like to talk about is just open data, right? MatterMOS is open data. You own 100% of your data, right? I always like to say one of the reasons why MatterMOS was built was because we were actually moving from a proprietary chat system, and we became extremely frustrated when we couldn't get our own intellectual property out of that system, right? It's our messages, it's our intellectual property, it's our content. And just to extract our content out of one of those proprietary systems was immensely painful, took a lot of resources to do, and it was very frustrating, right? And so for us, one of the core concepts even below open source is just this concept of open data, right? And so for us, a choice like SQL is just a very standard choice, right? We wanted a platform that was very ubiquitous, but we also wanted a platform that everyone knows how to analyze, build reports, get data out of, right? So there's no proprietary data models. There's nothing hitting, it's just a SQL database at the end of the day. It's a pretty standard schema, pretty easily understandable schema. Hook your own tools up to it, extract the information you want out of it. We internally do a lot of cool interesting charts and reports. Things like, as an example, you can go above and beyond what we give you, but things like how many custom emojis that people create, what is the most popular custom emoji, right? Who in your user community is the person who chats the most, right? So there's all these interesting kind of quantified self-sys data that you can just create generic SQL queries for and go rock on it. And so for us, that was one of our also kind of core concepts, right? So when you think about this layered extensibility approach, if you're starting with the data model, that data model is open, right? Then you layer on top of that, the open source model, right? Where everything's open source, work what you want, do whatever you want with it. And now from there, that's kind of the base that we build on top of, right? And so from there, I'll start getting into the specifics of how matter most, the things that we add on top of those two models. And this is what we call our developer toolkit. And so we'll kind of break down each of these, and I have samples and examples for each of these, but we have incoming and outgoing web hooks, we have slash commands, we have bots or REST APIs. And then we also have sort of, I think, some of the things that hopefully will show off the real power of this is just our extensions in terms of our client-side extensions and our server-side extensions. What we call client-side plugins and server-side plugins. So web hooks, there's two types of web hooks. There's an incoming web hook. It's basically, you can post a message to a public channel, a public, private, or direct message channel. It's a very simple, HTTP post request to a URL. You post it on that, it's designed to be very simple. It's designed to get, it's designed so you can get data in the system really easily. You post that URL, a message gets posted on the channel. Very simple, very simple to do, right? And it's, for us, it's slack compatible, meaning if you have a web hook that works in slack 99 times out of 100, it'll just work in matter most as well. The next is outgoing web hooks, right? The same thing for the outgoing web hooks. It's post, so it posts an automated response. So it'll actually key off a trigger, so it'll find a trigger word in your message, it'll take that message, it'll send it out to some outside service. That outside service will do something with that message and it'll get posted back into the trigger, into the channel, sorry. It's a very simple HTTP post request to a web service and once again, these are also slack compatible. So these are kind of two different ways, two very easy ways. So you can kind of, now we're kind of starting at the top and working down from easy to hard, right? There's a two very easy ways to get data into and out of the system. These ways don't actually take a whole lot of programming, they're much more just posting to web URLs. And here's some examples. So all these examples, I think all these examples you'll find on our community server, but these are real-world examples that we run. So the first is just an alarm and an alert that's saying our corporate matter most instance is actually running a high CPU utilization. The other one is from our GitHub integration, which is just posting in the channel saying like, hey, something was updated from GitHub. Those are two simple examples. The next is slash commands. So here's a little bit more work, but it's an easy way to integrate external applications. It's very similar to outgoing web hooks, but it can be used in any channel. Once again, it's a simple HTTP post request to a URL. That process, it's processed and the response is brought back into the channel, both built-in and custom slash commands, right? And it is the same thing, it's slack compatible. So that's, and once again, this is going down a little bit more, gives you a little bit more power, a little bit more flexibility. You can actually create arguments for your slash commands. You can create auto help for your slash commands. So you can do some really powerful things with them. And what we use it for our matter most is we actually use it to build. So we have this tool called MatterBuild. You issue a command like slash matter build, cut the release, five dot five. What's happening here is you can see Carlos is actually cutting a release for us. He issues that command. The first message or the piece in the middle is actually what's getting echoed back into his channel so he knows there's immediate visual feedback for him. He knows that like, okay, the release is on its way. He's cutting the release. The last message is actually echoed into another channel. So here's an example where he's issuing a slash command and two messages are going into different channels. And this last channel, this last message is basically telling the broader audience and the broader community who's ever in the MatterMost Release channel that, hey, we're cutting a release. The next is just bots. So bots is a great way to extend their framework. And what I mean by bots is it's really just community-built APIs, right? So we have a RESTful JSON web service. It's a great way to interact. We also have a WebSocket connection where real-time events are pumped through that connection. So MatterMost provides two official drivers that being JavaScript and Golang. And the community will provide a lot more, a lot of other ones like PHP, Python. I think there's a Haskell one out there. There's a whole bunch of them. But the key here is those drivers and what ability they give you. They give you sort of full control of the system from that user's perspective, right? They allow you to create very powerful bots, very powerful interactions. It allows you to see all the real-time events in the system with those things. And like I said, we provide two of those, the JavaScript and the Golang one. The JavaScript one is actually how we use it. So when you look at the web application or the mobile application, our mobile application is actually React and React Native. It's actually just using our JavaScript driver. So it's using our JavaScript driver to interact with the server. The Golang one, that's one we use in kind of a couple of different places. We use it all over the place for our unit testing and we use it all over the place for our performance testing as well. So those are two that we provide. And there's a whole bunch of other ones, like I said. I'm gonna talk a little bit about the Golang bot sample code. So we also provide just some sample code. It uses the Go driver to interact with the Mattermost server. And it'll show you how to do things like log into the server, create a channel, modify user, listen to web hook-in and listen to web socket events and all those kinds of things. And so here's some Go code of our sample bot. So if you look at the sort of first function, all it's doing is just logging in the user. So you can see client.login is a very simple call. All this call is doing is using the RESTful JSON API to talk to the server, to bring back a user and a session token for that user. We save off the user and then we're gonna use that information later on in the process. So after that, here's a very simple example of just sending a message to a debug channel. So here's an example. We call messages posts internally, so whenever you see something called posts, just think of message. Post includes all the metadata around the message, but that's how we, you'll hear me refer to it sometimes like that. So here's an example. If you look at line 162, we're just constructing a post object. We're assigning the channel ID. Here's an example where we want it to go into the debugging channel. We're saying what the message, the actual text of the message is that we want to show. The text of the message here can actually be, it can be quite large, it can also be marked down. So we support full markdown, which is pretty cool. You can do a lot of cool stuff with it. You can do code snippets. You could do latex, mathematics formulas in our system as well. So it gives you a lot of power. And so here we're just running a simple message. We're setting the root ID, which is basically saying this is a parent or this is a child of this root. We do some threaded messaging as well. That's all that is. And then basically what's happened there in the last couple of lines is we're just creating the posts. And it's that simple. It's just client.createPost. That post data goes into our system. It fires that message. It all goes down to the web sockets. And if you have a bot listening on the other side, the bot will actually receive that message as well. That's a very simple example of our bot messaging. And there's a lot of great examples out there. Here's a HuBot one. I think this one is actually running on our community server. I think if you just say HuBot, let's ship it. It'll echo back the ship it squirrel. But there's also a lot of other great examples out there of things like HuBot connecting into your CI CD system. There's a lot of great existing integrations out there. So plug in overview. So this is the part that really gets me excited. So what you saw up to this point was pretty standard stuff, right? It's stuff that Slack does, or it's just interacting with our APIs, right? But now we're getting into how do you want to really richly customize MatterMost. And we're gonna kind of talk about each of these different areas. But one of the things that we found is, is that the reality is most of our community base only wants to change or integrate with very specific portions of the UI, or very specific portions of the messaging, right? And so we identified a lot of those areas, and we just added, we added the ability for you to override either the UI, or hook into the backend system for processing. And so we'll talk about, I'll show some examples but we don't be able to go through all of them because there's way too many. But I'll talk through some of the examples of where we allow you to do this, and then show you how. But really quick, we kind of break it down into three different areas, sort of front end, back end, front end, or two different areas, front end and back end, the last two are actually both back end. But the first is just the ability to customize the user interface. We see this time and time again. A lot of users or community members really want to override the user pop-up, right? Or they want to add something to the left-hand sideboard, or they want to add something to the channel header, or they just want to completely render a different message in place, right? Think of the power of being able to embed an application inside MatterMos in the sense that when that message comes in, it gets posted as a very rich posting, right? So it's not just a, so think of something like a business analytics tool, right? Posting a really rich chart inside of MatterMos, right? It's not just a screenshot. It's an actual piece of that business analytics tool running inside MatterMos, right? Where you can drag and drop or drill through or do different business analytics right there, right? So that's some of the things that we really think about when we talk about wanting to customize UI. So it's not only customizing the stuff around it, but it's the ability to individually customize each post message. Then with that, we wanted to also sort of allow you to integrate really tightly on the back end, right? We wanted to allow you to create server-side plugins on these plugins function over RPC. We want you to be able to hook the system. We want to be able to either intercept messages or rewrite messages, or just kind of the last piece here is to extend the MatterMos REST API. So lots of times what we find is people want to create plugins. Those plugins have a lot of custom interactions, and they want to post back, or they want to call back into the MatterMos REST API, or they want to add new REST APIs on top. That's one of the cool things as well, is not only can you hook the back end and intercept messages, you can also just create custom REST API endpoints. And I'll show you some examples of why you would want to do that. But it's really cool and interesting. So customizing the interface. We're not going to go through all these, but here's all the areas that you can override, basically. And we're constantly adding new areas here. So you can kind of read through the function names. You probably get an idea. It's all really well documented. If you just go to developers.mattermos.com, you can see each of these methods in detail. You can see what you can actually customize, and there's a whole bunch of samples and demos out there that show you what's going on here. But this is just sort of a snapshot of all the different areas that you can customize. And I'll kind of walk through some of those examples, some of the interesting examples here. So channel header button. This is a request we get quite a bit, actually, which is just, I want to add my own button to the header in a channel. If there's more than, so we allow you to do that. If there's more than one button, it actually, the system's smart enough to create a dropdown so you can add in number of buttons. This is great for things like video conferencing integration. In fact, our built-in Zoom integration is actually just written as a MatterMos plugin. And there's a bunch of video integration plugins that are written like this, right? So it allows you to add a button to the channel header. And you can see really easily what's going on here. So this is JavaScript. We're initializing a function. It's just registry.registerChannelHeaderButtonAction. And in here you can see a couple different things, but basically a little bit of React and then an actual callback for that function. So basically what's going on here is we're just registering that button that's going to be displayed. And we're registering what happens when you click on it. So as you can see, here's the screenshot of the example. So this is actual Zoom integration. If you look, that's just our channel header. And there's a video conferencing button that's being added. So you can add any number of buttons right there. You can extend the interface and add any other button, any number of buttons right there. And so this is just our built-in Zoom integration, but it's actually doing it through our plug-in mechanism. The other really cool one is the ability to override post rendering. So I talked a little bit about this one in my business analytics example, where you want to show a custom post. You want that post to be very rich and interesting, right? And yeah, you want that post to be very rich and interesting. So it's more than simple text. It's more than a simple screenshot. I'm going to walk through another example like this. Once again, our Zoom plug-in does this actually. It uses a custom plug-in to render the post. So when you click that button from the previous screenshot, it actually throws a post in the channel that's a custom post with custom buttons on it. And when you click those buttons, it'll start a video conference. And you can kind of see what's going on here. So on the left is just an initialization of what's happening. If you notice, there's the register channel header from before. But right after that, what we're saying is we also want to register this custom post type. So each post, remember, or post is the metadata for what we call a message. A post can have a type. So in here, what he's saying is when you see a post type that equals custom Zoom, then let me render it for you instead of you just doing your default rendering. And what's happening here is on the right, there's some more React. And this is the actual React component that gets called when it sees that post. So when it sees a message in the channel, instead of just doing its normal markdown rendering or whatever rendering it wants to do, it's built-in rendering. This person here is actually overriding that rendering, saying, hey, call me instead. And when you call me, use this React component to render it. So in here, we're doing a whole bunch of interesting stuff, but it's basically rendered the React component using JSX or whatever. And it's basically like, hey, if the meeting started, then show this instead. If the meeting's ended, then show this message instead. So you can actually get messages that are changing what they're showing based on time and what state they're in. And what it looks like is like this. So when you click that button, a message gets posted to the channel that says, hey, here's your Zoom meeting link. And you could say, join that meeting. So anyone can click that button and join that meeting. What's not shown here, if I was the owner of that meeting, it would actually show me an extra button, which is end meeting. And I could click end meeting as the owner. And then this person would actually see the meeting being closed. The join button would no longer show up. And it would just be a render message in place now, saying, hey, there was a Zoom meeting and there is not one anymore. So you can see the real power of this, right? The ability to custom render whatever you want within the channel for a particular post type. And so the sky is the limit here, right? You could think of really cool business intelligence integrations, right? Really cool head track style information, ERP systems, sort of CI CD systems. We'll show some, I don't know if I can't remember if I have a minute, but Jenkins. Think of really cool Jenkins or GitHub renderings going on here. Some other really cool stuff is what we hear is people want to render components on the team sidebar. I'll show an example of this as well. But this is, if you think of, in Mattermost, there's a team side. There's what we call the left-hand side. In that left-hand side, there's teams. And there's a whole bunch of typically white space or empty space at the bottom. A lot of people want to add buttons into that empty space, right? And same thing. You can register a component. We use this, actually, in our GitHub plugin. So one of the plugins we provide is for GitHub. You could just really see once I get on the left, it's just really easy, hey, I want to register something to render in the team sidebar. On the right, here's the actual React component to show that rendering. Yeah, and you can see at the bottom, it's just returning what it wants to render. So the way this appears is like this. So if you look at the bottom left-hand corner, you can see all these custom buttons. And so this is our GitHub integration button. You can see what forks I have, if there's any messages waiting for me. And that's really cool and powerful, right? You can imagine really rich integrations and really rich applications that just want to take over pieces of the UI and allow a bunch of custom rendering. And what's even more cool is when you click on those things, you can either show custom pop-ups, or you can direct people into channels or certain messages. And you see this really powerful in our GitHub integration. I think we also have another Jira integration out there that overrides some of this stuff. But you can see the real power of this, right? The ability for people wanting to embed applications inside MatterMos. For them to take over pieces of the UI and allow them to do really extra cool and involved things. One of the other cool things you can do is you can actually rewrite the message client side. So you can register a hook that'll be called before the message is formatted into Markdown. And we actually use this in one of the plugins that we give away. It's called our wall-time plugin. It's actually very useful for me, at least. It runs on our community server. Our community is around the world in a lot of different time zones. A lot of our staff is around the world in different time zones. And what this plugin does, it allows you to say something like, hey, let's meet tomorrow at 10 o'clock. And I don't have to put, the person doesn't have to put whether that's Pacific Time or London Time or whatever, right? It actually renders it in their local time. It'll rewrite the message and render it. And it'll tell me, like, we think this is what it is in your local time. So once again, you can just see very simply, we're registering, register a message or format hook. Here's where just providing it a function that's gonna get called. That function is just gonna return the new text. So we're getting the text from the post where it allows us to rewrite it and it allows us to write it back out. Now, one of the cool things about doing this on the client side is now you can target it for each user, right? If I said, let's meet tomorrow at 10 o'clock, then for user one, that might be three hours later, right? For user two, that might be 10 hours later, right? So each of those individual users can get different renderings. And that's what ends up happening. So here's our wall time plugin. Here's some examples. Let's meet today at 10 a.m., right? And what they'll see, they'll see this first line, let's meet today at 10 a.m. What they'll see for your time zone is this second line. Let's meet today at 10 a.m. The stuff in parentheses is what was added from the message rewrite. Same thing. Let's meet today at noon. The stuff in parentheses is added from the message rewrite. And you can really start to see the power of this, right? The ability to hook the message and then rewrite it per user, right? So you can think of really interesting plugins that you'd wanna build. So that was all the sort of client side plugins. Now we're gonna talk about some of the server side plugins. Once again, here's all the server side plugins. We're not gonna show an example of all of these, but here's all the areas that you could hook the message. I think you can also hook into the web socket. But we'll go through some of these examples, at least the really cool ones. So here's an example where you can rewrite the message on the server side. So we just talked about rewriting the message on the client side. You can also rewrite the message on the server side. And there's actually lots of opportunities to hook the message. You can hook the message before it goes into the database. You can hook the message after it goes into the database. And those are really powerful concepts because if you hook the message before it goes into the database, you have a chance to rewrite it before it comes to the system of record, right? So let's say, I don't know, you're a big banker or whatever, and people are talking social security numbers or credit card numbers, right? You can have something that recognizes like, hey, I think that's a credit card number. And it could just rewrite that number so it never appears in the database, right? It just says, hey, x, x, x, x, x. Last four digits of the credit card. So you can do really cool stuff like that. You can also reject the message, right? So let's say somebody is typing in, you know, bad words. You can actually reject the message, say like, hey, we think this has some profanity in it. And you can send back, and you can echo back an ephemeral message to the actual individual user. So it won't go into the system of record, it won't go into the database, but that user can get a direct message back to them or ephemeral message back to them that says like, hey, we're blocking this message for these kinds of reasons. So you can see all these really cool states, right? You can see even see states where you sort of pause the message flow, right? Before it gets into the database, I'm gonna pause the message flow, go off to some other workflow, right? And then eventually allow that message to come back into the database. You can also hook the message after the fact, right? So you wanna let the message go into the system of record or into the database, but then after the fact, you wanna do a whole bunch of post-processing on it. I mean, so you can kind of think of really cool examples with that. One of the ones that we provide is just a very simple auto-link plugin. So we do this all over our community server. When I type in a big, long URL because I copied it from our JIRA instance, when I actually paste that message, the system hooks the message and re-renders it on the server side and it re-renders it as just a nice formatted link. And it actually will do the reverse. If I just type in mm-1001, it'll automatically link it to that URL. So you can think of all these really cool examples where you can just auto-link URLs. You can create text snippets. We do this as well. We have this saying inside MatterMos that we say zero out of five. There'd be, say it on a scale of zero out of five to five out of five. For us, zero out of five is like, yeah, I don't care, do whatever you want. Five out of five is like, no, this is really important to me. But when our community comes in and interacts with us for the first time, they have no knowledge of what those terms mean, right? Or lots of times we'll say stuff like LHS, left-hand side, right? So when we say something like that, we refer to left-hand sidebar. So we actually have an auto-link plugin that'll create auto-links to our documentation. We use the word lots of times mana internally for estimates. We come out of a former games company. And so we use the word mana a lot as our term for how we estimate stuff. And that can be really confusing for first-time community members. So we actually link out to the documentation that describes how we use that term. And so you can see the very simple abilities to hook the message on the server side. It allows you really powerful, rich interactions for users. Implementing HTTP handler on the server side. So I talked about this a little bit, but one of the cool things you can do is you can actually extend our REST API. So it allows you to create an endpoint. That endpoint or the request are destined for things like slash plugin slash your ID. And when a request gets routed to that, it'll actually, we'll route it all the way to your plugin. So you can kind of do whatever you want. So you can, with this, you can create really powerful scenarios. So here's a simple example of us hooking the server message. You can see on the top, it basically is echoing back an ephemeral message if there was an error. If not, we just handle like a slash support call. And I'll kind of show it. It'll make a little bit more sense when I talk about our welcome bot. But what's basically ended up happening here is a URL gets hit. When that URL gets hit, this handle support method call at line 76 gets called. And what it's basically doing is it's gonna join you to a couple channels. It's saying, oh, you wanted to be joined to the support channels? Okay, here I am on the server side, handling that from a request call. Like, hey, I'm gonna join you to the peer-to-peer channel and I'm gonna join you to the bugs channel. And then you can see here, I'm just responding out with some markdown. And so what this basically looks like or what ends up happening is we have a welcome bot in our community server. This welcome bot, when you join, it posts this message. It says, basically, what are you interested in? Let me help you, right? And it gives you three buttons. I'm interested in support. So what ends up, what's happening here is somebody clicked that button. I'm interested in support. And it goes back to this HTTP handler and it actually joins you to those two channels. So there's a great example of why you'd wanna extend the REST API, right? It allows you really powerful ability to do simple things like this. Yeah, that's it. Like I said, thanks. Really quick, we are hiring. And one other thing I wanna take 30 seconds to talk about is our mentorship program. So this is something new we're starting. We wanna help different people get involved, right? So we offer a shepherding experience where this is just, if you wanna help submitting your first pull request, our idea or goal is to encourage everyone in the community to go out there and either write plugins or integrations or however you wanna interact and respond, right? And so we wanna help people do that. And so that's one way of doing it. It's just sort of simple shepherding. If you want some general advice on how to submit a pull request, how to create an integration, we're definitely willing to help out there. One of the other things we're trying to start up is what we call our mentorship program. So this is focused on bringing more people to the Mattermost community. For us, it's gonna be an application process. It'll be a three month long and there'll be large commitments from our side. And that's it, questions. And this is where you can reach me. Coreat Matter, Coreat, our community server is probably the best place. I would encourage all you to join. Hi. Thank you for this in-depth presentation. Regarding the client side plugins, is it possible to rewrite some of the message based on the device type when you're using a mobile client? Rewrite the what on the message side? The content of the message. Like rewriting, putting in a different URL handler. Yeah, exactly. So when you're hooking the message on the client side, that message is actually the full rewrite. It's the full message before any of the markdown happens. So you can rewrite pretty much anything you want there before it gets rendered. You can also hook your own custom post. So if that's not enough, you can also hook your own custom post type. And when that post type is discovered or seen, then you can render whatever you want in excess. Does that answer your question? That's also possible to recognize the device type. So when you're using it on mobile clients? Oh, the mobile client. Yeah, so, ah, yeah, good question. We are working on the mobile client. So we want all these plugins to work. All the client side plugins, we want to work on the mobile client as well. Our mobile client is React Native. So we have a pretty good strategy for how that works. So that's in development, but it's not done yet. So you can hook those messages from the server today, but eventually you'll be able to do it from mobile as well. Okay, thank you. Hi. I was wondering what kind of argument would you use to try to convince a corporate entity to switch to something like muttamos rather than alternative proprietor. And did you like Slack? Yeah, the argument for using us, so there's lots of different reasons, but I think one is you control it, you own it, it's your own, you control your own privacy, right? So what we typically find is, it matter most is using a lot of different communities, but it's also used by a lot of different companies where they care about privacy, where they care about owning their own data, right? So we call it like, we use the term like open source Slack alternative, but I'd say probably the better term is Slack for paranoid people. That's where we get a lot of traction either in communities or Slack for people, Slack for people who are privacy conscious. But I think, and if you want more information, I can kind of share with you like, if you have a specific example for your company or your community about where we see ourselves, where we're how we do really well in those different environments. Are there any more questions? I'm gonna point the way up there. And I'll be up here for the next 10 minutes, and some of my staff is here as well, so if you guys wanna talk or ask certain questions or how to write some of these plugins, definitely come up and see me and we can describe that. Thanks. So you said you had an open API so you can write lots of different clients to interact with the matter most, and then you also mentioned there are some client-side plugins that writes custom React components for stuff. Does that restrict the clients to using React or how does that fit together? So the web application and the React native application or the mobile application are both written in React. So it's not necessarily strict. You could write just plain JavaScript, but for the rendering component, you would have to write a little bit of React, basically. So it's kind of one of those kind of two things, like we have, as an example, we allow you to hook the root post as well. So you could actually just like, let's say open up your own pop-up. That could be all of your own sort of generic JavaScript or Angular or Bootstrap or whatever you want it to be. It doesn't have to be React. Yeah, but if you're writing a matter most client, do you have to write it in a browser so you are able to redirect? Or if you want to create a matter most client, which is not running in the browser? Yeah, so if you want to create your own client, sorry, maybe I'm just gonna, if you want to create your own client, like the first example that I gave where it was the terminal interface, that was Matterhorn I think actually is written in Haskell. Someone can correct me if I'm wrong. I know it's not Go or JavaScript. I do know that. So yeah, you can create whatever client you want. When you do, you can use whatever language you want. The ones that matter most supports, or I shouldn't say supports. The ones where we can give off of the most support are in JavaScript would be React and React Native and on the server side is Go. Our server side plugins are GRPC, so in theory you could write in a non-Go language. I don't know if anyone has actually done that yet, but in theory it's possible. All right, thanks. Thank you. I'll be up here if anyone has any other questions.