Category: Tutorials

  • How to add alert notifications in your app, the easy way.

    How to add alert notifications in your app, the easy way.

    It’s such a beautifully, useful and simple thing that I had to write about it…

    Sooner or later your app needs to tell you something: a CRON job failed, some queue is backing up, a quota is almost gone, a big customer just signed up. You don’t need a paid service, an SDK, or the joy of debugging email deliverability for this. A Slack Incoming Webhook is a secret URL you POST JSON to, and that’s the whole trick.

    Step 1 – Create the webhook

    In Slack: create an app (api.slack.com/apps > Create New App > From scratch), turn on Incoming Webhooks, then Add New Webhook to Workspace and pick a channel. You get back a URL like:

    https://hooks.slack.com/services/T00000000/B00000000/xxxxxxxxxxxxxxxxxxxxxxxx

    That URL is the credential. You don’t need anything else, no secrets, no IDs, nothing – those are for other Slack stuff. For “post a message to this channel”, the URL is enough.

    Step 2 – Store it as a secret

    Drop it in your environment, never in the repo:

    # .env  (git-ignored)
    SLACK_WEBHOOK_URL="https://hooks.slack.com/services/T00000000/B00000000/xxxx"

    Step 3 – A tiny reusable helper

    A few lines of code, no deps, and – importantly – best-effort: meaning a notification that fails will not take your app down with it.

    // notify.ts
    
    type NotifyOpts = { 
      title?: string; 
      level?: "info" | "warn" | "error" 
    };
    
    const EMOJI = { 
      info: "ℹ️", 
      warn: "⚠️", 
      error: "🚨" 
    } as const;
    
    export async function notify(
      text: string, 
      opts: NotifyOpts = {}
    ): Promise<void> {
      const url = process.env.SLACK_WEBHOOK_URL;
      if (!url) return; // no-op, don't blow up
    
      const emoji = EMOJI[opts.level ?? "info"];
      const heading = opts.title 
        ? `${emoji} *${opts.title}*\n`
        : "";
    
      try {
        await fetch(url, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ text: heading + text }),
        });
      } catch (err) {
        console.error("notify failed (non-fatal):", err);
      }
    }

    Use it anywhere

    await notify("Mr. Dude, stuff happened! ✅");
    
    await notify(
      `DB usage is at ${percent}% of the plan cap.`, {
        title: "Quota warning",
        level: "warn",
      });

    That’s a working alert system. Really.

    Want it to look nicer?

    Slack is really good at this stuff; the messages can carry Block Kit blocks for headings and compact key/value grids. Keep the top-level text too, it’s the fallback used in push notifications:

    body: JSON.stringify({
      text: "Quota warning", // fallback
      blocks: [
        { 
          type: "section", 
          text: { 
            type: "mrkdwn", 
            text: "🚨 *Quota warning*" 
          } 
        },
        { type: "section", fields: [
          { type: "mrkdwn", text: "*Used:*\n84%" },
          { type: "mrkdwn", text: "*Plan:*\nScaler" },
        ]},
      ],
    })

    Two rules, and you’re done

    1. Best-effort, always. Wrap the send in try/catch and do a no-op when the URL is missing. Your alerting is the least important thing in any request; it must never be the thing that breaks it.
    2. The URL is a secret. Anyone who has it can post to your channel. Keep it out of git, and if it leaks, regenerate it in Slack (Incoming Webhooks > remove/add); no code changes, just swap the environment variable.

    BTW, same pattern works for Discord and Telegram if Slack isn’t your thing; a different URL and a slightly different JSON body, basically same code; or use Python if you’re a guru :-).

    I’m honestly wondering if there’s an easier way. I’d probably use it.

    That’s it.
    Enjoy!


    Slack logo rendered with Krbn.

  • Visualizing Git diffs in Meld.

    Here’s a quick way of configuring your (Linux-based) Git installation to use the excellent Meld program by default for displaying/editing the outputs of the git diff and git merge commands (e.g. git diff «filename»).

    Install Meld

    …if you haven’t already (note that we assume Git to be present):

    # on Debian-based distros (ymmv)
    sudo apt-get install meld
    

    Viewing/editing file diffs via Meld

    Configure Git to use Meld as the default tool for git diff:

    git config --global diff.tool meld
    git config --global difftool.prompt false
    

    Now, rather than the classic git diff, simply use:

    git difftool
    

    Resolving merge conflicts via Meld

    Basically do the same for the git mergetool command:

    git config --global merge.tool meld
    git config --global mergetool.prompt false
    

    And then, instead of git merge, simply use:

    git mergetool
    

    …in the conflicting areas of your Git project.

    Full directory comparison

    Git supports full directory comparison via the following command:

    git diff --no-index «folder-inside-git-project» «folder-to-compare-against»
    

    While both useful and powerful, this command can be quite difficult to use, especially is you have a large tree structure. However, it just so happens that this is another aspect where Meld shines. Just run:

    meld «folder A» «folder B»
    

    And you will be able to visualize and edit the entire set off differences of both folder structures (including files).

    Enjoy!

    Notes:

    • The *tool.prompt false bits are needed to prevent the prompting of the user on each command invocation (which is the default behaviour).
    • The full directory comparison mode supported by Meld is obviously available for any folders, not just those inside Git projects.
    • I’m using Ubuntu 12.10, your setup may require different configuration options (although if you have a decently recent Git you should be fine).