Course Builder: Create a Slack Notification Provider

  1. Setup the Event for Notification

    • Identify the event that triggers the Slack notification. For instance, use the new purchase created event which is fired after a Stripe checkout session is completed.
  2. Create a New File for Slack Notification

    • Make a new file, sendCreatorSlackNotification.ts. This will handle sending notifications to Slack.
  3. Define the Notification Handler

    • Write the core logic to handle the Slack notification. Remove unnecessary code and focus on setting up the notification sender.
    // Example skeleton for the handler
    const sendCreatorSlackNotification = () => {
      // Handler logic here
  4. Setup the Configuration

    • Add configurations required for Slack, like Slack token and Channel ID. The Slack token is used as the API key to send messages.
  5. Create the Slack Provider

    • Make a new file, slack.ts, to define the Slack notification provider configuration.
  6. Implement the Provider

    • Use Slack’s Web API to send messages. Ensure your provider can send messages to different channels by configuring options.
    const SlackProvider = {
      sendNotification: (options) => {
        // Logic to send notification
  7. Setup in Middleware

    • Integrate the Slack notification provider into the middleware so it can use the notification logic. Ensure it’s correctly added to the list of providers.
  8. Handle Errors Gracefully

    • Ensure your handler can manage errors effectively. Log errors but ensure they don't crash your system.
  9. Testing

    • Test the system to ensure the notification provider works as expected. Create necessary environment variables and set up your Slack workspace to receive notifications.
  10. Update Environment Variables

    • Add necessary tokens and IDs to your environment variables to avoid hardcoding sensitive information.

By following these steps, you will have a functional Slack notification provider integrated into your system, keeping you up-to-date with events like new purchases.


[00:04] So I want to create basically a Slack notification. So to do that we're gonna come in here and I'm in packages core and we're looking at ingest and we have the commerced and there's the new purchase created event and currently we use that to send a post purchase email but we can use that same event and that event I believe gets kicked off here. So after we get the event checkout session completed, so this is a Stripe webhook handler basically, At the very end of that we get the new purchase created and that gets sent along with the purchase ID. So that's great. That's exactly what we want to then do a notification on the wherever we want really but what I want to do is new file send creator slack notification And that is going to look like this.

[01:22] So I actually don't mind, and I'm gonna just delete a bunch of it, but I'm gonna do it like this. So I'm gonna come in here and come through the handler and just remove all that stuff. So I don't need that, but I do want to send creator a Slack notification. So that's good. Notification.

[01:52] And this is the handler. So we move the handler down here like that and do this like so and we can replace these also. Boom, like that. Put the config down here. This might be more effort than it's worth.

[02:17] This is something where like having a template might be kind of nice. So send post purchase Slack. Purchase Slack like so. It's the same event. Looks like that.

[02:37] And let's see, one, two, I don't know if I'm missing something over here, there's that. And just for now, we'll return. Yes. Oops. I don't know what's going on here.

[02:58] Let's see. Yeah, great. So come here, I'm just going to reformat that. There we go. So we're not using anything, that makes sense.

[03:11] What's missing here is we have an email provider and we pass that in if we come down here to create ingest middleware this is where all of those providers are created and one thing that we do not have at all is a slack provider and that's one that we would want to make really at the end of the day so you see we have vert-git, deep-gram, open-ai, party-kit, stripe, these are all things that we we use and we absolutely want to also create a slack provider that we can use. So kind of looking at these, this is the shape of them and Creating a provider definitely has, you know, there's stuff we got to think about when we do, one of the things that we're using in there is the, so when you look at the ingest we're using like the email provider and that actually comes from NextAuth, so just thinking about it we're gonna end up with a new file just call it slack.ts and you could do lots of stuff here because you could you know like you could have discord that would work fine What kind is this? This is a party...

[04:39] What would we call that? Notification provider? Like, just thinking about what type of like when this thinking about what what what what type of of API we're looking for here So it ends up looking like that. And we have the provider config and the type, I'm gonna call it notification and options type. The config is, what, you know, it's like, what are we trying to do here?

[05:26] I don't need that. Well, actually, so what would we do here? Like a slack. I would do the API key I don't remember what we need for slack so we're gonna open products We do this a lot over here. Just kind of come down.

[05:53] I think that's all in Skill API. Let's see. Slack, post sale to Slack. All right. So we have a Slack token, we have a channel.

[06:17] I'll just go ahead and, well, we have post so it's the slack token slack token is the API key and I would assume almost every notification that we'd want to do would need an API key. So I'm going to leave that name, ID, options, this is going to be a. So this is what's interesting. So we can be like, instead of Slack, we're gonna say notification provider, right? API key...

[07:03] And I mean a notification provider could be basically anything at the end of the day, like any kind of different channel that we might decide that we wanted. Otherwise, it kind of looks the same. Looks like this. This one's gonna be called Slack. It's gonna have a name of Slack and it's going to be of notification type.

[07:32] This is gonna be our Slack provider, so this is the provider itself. And that's down here, mock Slack provider, Mock Slack, mock Slack, notification, API key. And we don't have that or that. What is missing now? It says get mixed in.

[08:14] It ends up looking like that because the options are kind of repeated inside of the providers. So now we have this but it doesn't actually do anything and going back to here we're going to say what would we say? Like send message basically I would assume I'm kind of gonna think about what what those messages end up looking like and what they might look like for other channels and not just just for Slack right like that's the that's the deal and that's like harder to think about for me anyway it's how do we do that and this goes look up here I'm gonna look up at Slack, and we have the Slack web API. I'll go ahead and grab that, come back over here. This will go in CD packages, core, We use that Slack web API.

[09:27] I think it just gets baked right into here. I think, you know, it's one of those things where like the notification could probably be decided later. Let's grab that. That exists in here. Wank that in here.

[09:45] What's that saying? Not used yet. Come over here. Post to Slack. So here is the just the kind of core of the thing is post a message right so to me send a notification and you could have all of these things maybe like the options here might be what we're looking for so I'm gonna take those actually and this this wants a web client that's interesting we might not use that it's fine so come down here and just above that, drop that in there.

[10:35] Looking back at our party kit, where was the... Here, we're going to notification provider Config, we'll have send notification. It looks like that. That looks good. Return, blink blink blink, and here we do that.

[11:18] Is it not? Consumer config. Oh no, that's... There we go. And then web client post to channel, response, response.

[11:39] There we go. And then WebClientPostToChannel, response, response, inline that variable. And Now we're just looking at this, right? So this is what it ends up looking like. We'll do this.

[11:52] I'm just gonna copy that over. I'm gonna copy all that over. And That ends up, I'm gonna do that, equals send options. I actually don't want a web client as part of my options here. Come in here, I just don't need it because I'm gonna make it.

[12:21] We'll make the client here with an API key. We'll post that message. It has all the right stuff. Post to, well I'm going gonna change that to notification options. You got these attachments so it is very slack like.

[12:49] And in some ways not mind a whole lot that it looks like that. That it is so tied to Slack. This is like, it's the only one right now, and how would we make this, and how would we expand that and upgrade it is like an open question in terms of another channel. And to me, frankly, you'd need another channel to use at that point whether you know like and it could literally be anything so it's just something to think about what that actually means we don't need that So technically here I feel like you could now send a message like all you wanted in terms of what you might send and I think you can configure so this has configuration we have the API key you could have like a default channel ID might be nice ID might be nice. It feels like something that's the optional appear default channel ID is optional and options we have our options here, we're dealing with those.

[14:26] So options come in and you can say equals. You can say equals Channel looks like this let me say something like const channel like so yeah like so yeah if not channel there we go we'll throw a little error here fun yeah so we have a slack provider and armed with that, I think there's like a place where, let me see if we can, I'm gonna try to find this string party providers we want our notification to show up there I think that's the only place so that's in source core providers there Type provider type, that's all the same thing. So now the notification will show up as just one of our acceptable types of providers. There's different ways to access those. Let me see, I'm trying to think of other ones that I might be able to look up.

[16:16] Look up LLM. Let's see what we got. Let's see what we got. Yeah, that should be fine. So that should be built, so we now should have access to that.

[16:42] And what I want to do then is where I need this right now, right? I don't necessarily, we're gonna want it all over in different places, but for now I can just do like, notification provider, let's say. Right, so now we end up with the core ingest. This is a little mock one because this one doesn't matter it's just here to just I guess we could do like the I don't remember what it's called. Let's see.

[17:40] Slack. Slack provider. Is like this, and that looks like that. Nice, so we have that, and the deal with the ingest here is we come back into AppLand, and we come back into ProAWS, and come down to ingest. One thing that I'm doing is I'm putting the providers here so you end up with this this stack so you end up with looks like that right so wait let's make a file.

[18:21] We're gonna make a Slack provider specifically. And we're gonna say, just looking at that again. So we're gonna export const slack provider. Does this, I don't remember what, what would we call this? Where are you at, Slack provider?

[18:54] This way? Where'd it go? It's just called Slack. There it is. Like, yo!

[19:06] We're not picking up on that yet check my check my build core is building Is that exported? Yeah. Oh, punt over here. I just might need to have the build kicked. So I'm going to do that.

[19:35] Then, I guess also, well, I don't know, show up over here, because it's the same thing. So technically that should look like slack. And I just need to debug why this would, do I need to add it here? We definitely want to Add these while we're at it. Okay.

[20:25] Provider type, notification, already added that. Let's see, let's have the transcript and stuff is stuffed in there. Check the package. Providers. So, oh, well, maybe it's there now.

[20:42] When you add a new one I've noticed it often. Couldn't find... Yeah, I mean, it's clearly there. I don't know what it's... What it's malfunction is here.

[20:59] Anyway, So we have that. None of those are what we actually want for Slack. We have an API key. And that is process, we're gonna say, environment.slacktoken. Import that, that doesn't exist over here, So that's something that we're gonna have to Add our token for that's in the core so here Just add it down here It's optional If you don't have it then you wouldn't be able to kick it in.

[21:54] So, put that down here. Slack token. I can actually grab that token. Do I have any other Slack specific stuff? It's like the channel ID but I feel like that can come in through the options when we do that, right?

[22:17] Like it comes in there. We have the node environment because of the production switch, which we can send. All this is like an argument to our notification thing, right? Except for Web Client. So we just need the select token.

[22:33] I can grab that. I'm gonna do it off-screen Let's see. I'm going to go ahead and move this too, just to do the environment. And set this here, Slack token. And I can also set that over here in Vercel, just like I like to do this immediately while I'm thinking about it.

[23:47] Come over here. And I'll move that here too. Alright. So, that should get us where we want to be as far as the token. That's nice.

[24:26] Yeah, so I think the option there is probably to do something like... Oh, this shows up now. So TypeScript caught up to us eventually, that's good. So instead I could like have a API key as optional and optional, this is kind of, I mean, is it required? I don't know.

[24:51] Send notifications and like if you're using that and you don't have it, then we're just going to throw an error. And that works for me. For notification provider, nice. No channel found, Take the API key, come in here. This will eventually catch up because we made it so and you could also pump a default channel in as far as that goes.

[25:30] I might set that up actually. Create new channels and I wanna do that down here. And you can say create and I'm gonna create a channel and ding ding, pro AWS. Oh, there's a private channel. And I think there's a TA, I don't know what it is right now.

[26:02] Come in here and you have to invite TA sales announcer. So this is our bot. And now it's gonna be in the channel. And then I can do this where, view channel details, and I can copy the channel ID, and then we can come over here and we can say default channel ID, who knows what that is, and this is the slack channel ID so that can be codified here this could be even better if we took this and put it in the environment just off screen over here So slack default channel ID equals All right, then you want to put that in here as such, and put it in here as such. Nice.

[27:19] Then we can say environment. Cool. So if those exist, they exist. If not, that's fine also. Oh, I want to just go back to the Vercell page probably.

[27:41] So I can set that default channel. Go here, ProAWS, settings, environmental variables, default channel ID, Save. Cool, so now that is nice and set up. And what that now gives us, or it should give us anyway, is, bring this back over, the ability to access that, which I didn't do it here. Let's see.

[28:23] Ingest-config. That's going to be the ingest server. And Here you need to set up a notification provider. I'm gonna use that Slack provider that we just made. So now we have a notification provider.

[28:44] And that will get, when we create the ingest middleware, we'll use this notification provider. And finally, finally, we can come in here to ingest and we have our commerce stuff send creator notification. We might use email here actually but I'm gonna put the notification provider in there. I don't know what's going on. Why does it not like it?

[29:17] Oh, it sent it all out there. Oh, it's because the... All right, So this is where we can be like, okay, so this gives us our handler so we can say, wait, step, run. First here we want to load the new purchase, so we need to do that. I believe that's correct.

[29:58] This is any, but our notification, what does that look like? New purchase created event. It's just the purchase ID. So we should be good here, I promise, yeah. If not new purchase, throw new non-retryable error.

[30:29] And that's an ingest thing. If there is no purchase, then we're gonna throw that error. It won't keep retrying if it doesn't find a purchase. All right, so then we're going to send the actual Slack notification and to me, That ends up looking a lot like this, right? Except we don't have that, but we can come down here.

[30:54] And I'm going to grab all of that. And we're going to say notification provider. Send notification. Notification provider. Send notification.

[31:15] Wow, that's a lot. So that goes away. We could say default channel ID. Default channel ID. Oh, I need the purchase info.

[31:44] Whatever that may be. I don't think pluralize is in here. I'm gonna find pluralize up here and just copy it over. Dependency, where you got pluralize. Way down here, get pluralize, cool.

[32:07] I set that up here. Trying to get it in alphabetical order I think that actually might require types so we'll add those that's from lodash And Lowe's. That's from Lodash. And import from Pluralize. Thought I just did that.

[32:51] Guess not. So the rest of it is just figuring out how to get this purchase info. So let's see where that came from. It's not like a purchase info. Where do we get that?

[33:09] Do we have one of those? I feel like we might actually because a lot of this is just ported over. So what is that? That. Packages core source, get purchase info, payments provider config.

[33:30] So here, do we have a... So, get payment provider dot get purchase info what does that look like what does that look like might need to Be a little trickier with that so get purchase info Takes two arguments check out session ID and the adapter so ID and then the adapter here is actually the db. Wait. So to get the we're going to have the. All right.

[34:46] Db. Get. All right, db.get. What does this have on it? Oh, I should bring them all out.

[35:21] Let's see what it got. That's a purchase. Ah, so it's got a merchant session ID. But it's not going to be expanded generally. Oh, now we want the merchant session, right?

[35:44] So purchase info. Purchase info you know, what we can probably do here, let's see. So event, stripe, come into here and instead, look, what do we got? Because we loaded a bunch of stuff here, right? So we have the checkout session completed event, which comes with the full event.

[36:27] So, oops, event checkout session completed, Stripe, commerce, Checkout session completed, stripe. Commerce. Stripe checkout session. Purchase, create. Start checkout session.

[36:57] Purchase, create. I'm gonna add checkout session ID and then, yeah, because that ends up being here too. Yep, Cool. And send event. So come over to this event and we're going to say check out session ID.

[37:24] And make that a mandatory part of what we're doing. And now we're going to make Life much easier here because we can say event data checkout session ID. Do that. Place that here. Do that.

[37:45] We can just return this and we can say purchase info boom We also want to load the purchase though, so I mean I guess we can we'll say const purchase looks like that info nice so that should give us both of those come down here we got all that I'll just return the response. Now we can take this, so we have this and then we come up to create, where is that, course builder core functions. One of those is send a creator slack notification. Nice. You know, it's like, it's interesting.

[39:15] Because like if I if not notification provider right yeah I didn't even got gonna bother if it doesn't exist. Got the trigger. I'm adding that to this. We'll then just automatically add it to the core functions. The other way to do that is to, you can target it and add it instead of, this loops over all of these and maps them.

[40:01] Like if you come up to where we configure ingest in the config section. So we just map through those and calls create function on them. It's just for convenience, so anybody that does that will be fine. With this it'll throw an error which isn't great but maybe you just return honestly if it's not like here instead of tossing an error, you could just, you could do this. Console log, no notification provider return.

[40:46] Error. Yeah, whatever. Oh, that, I mean, that's not an error and we just want to bail out. Say root URL, somebody, sometimes these have links, so we're just checking. Nope.

[41:09] And honestly I think, I think that'll just work. Let's see so we'll come to here interesting that's the root of the site Maybe this needs a little kick in the pants. Start that back up. I'm gonna check my environment just to be sure here. Sometimes it gets switched into prod and that isn't where I wanna be right now.

[41:54] Oh, we're in dev. Good. Hopefully the site's back. If not, then what the? And what the?

[42:08] That's not cool. That's not cool. I don't remember what my... Nice. I need to open the database up.

[42:37] I don't know why the root was doing an error like that. That wasn't cool. That's not it. I'm gonna open the database. That's prod.

[42:52] Connect to pro AWS and dev. Come into events. So that's a content resource. Get that over here. Come into here.

[43:19] Just like that. Buy it up. Buy it up. Ah, nice. Kind of like that.

[43:53] I don't think I have stripe turned on so this is probably not gonna work and I'm probably gonna have to do it again. I don't know, might be the right one. Hey. That's interesting. This comes in but the thing doesn't show up.

[44:21] I'll come back to that. I don't know, we're just gonna, where am I at? Hey. So yeah, It works. Nice.