AI Global Academy Join the waitlist

Courses / Backend: leads, data, notifications

Lesson 4.5 · 55 minNotifications: email and Telegram

Duration~55 min in the lesson + ~30 min homework
PrerequisitesCheckpoint lesson-4.4; a Resend account; access to the DNS settings of the domain from 3.3; a Telegram account.
Checkpointlesson-4.5

What you will have

One form submission produces four things: a database row, an email to you, a confirmation email to the visitor and a Telegram message. If a notification channel fails, the lead is still saved, and you have tested that.

Video

The video for this lesson is not recorded yet.

Prompts used in this lesson

Part 3 — A Telegram bot

Prompt to Claude
Purpose: I need the chat ID of my private chat with my new Telegram bot, without exposing the bot token.

Context: I put TELEGRAM_BOT_TOKEN in .env.local myself and I have just sent the bot a message from my Telegram account. Do not open or print .env.local or the token.

Done looks like: a script `npm run telegram:chat-id` that loads the env file, calls the Telegram Bot API method getUpdates, and prints only the chat id, chat type and first name of each chat that recently wrote to the bot. If there are no updates it tells me to send the bot a message and run it again.

Constraints: never print the token or a URL containing it.

Before you report: run it and show me the output.

Part 5 — Build the notifications

Prompt to Claude
Purpose: tell the owner about each new lead within seconds by email and Telegram, and send the visitor a confirmation email. A notification failure must never lose a lead.

Context: checkpoint lesson-4.4. /api/leads validates, checks spam protection and saves the lead. I set these variables myself in .env.local and Vercel: RESEND_API_KEY, EMAIL_FROM, OWNER_EMAIL, TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID. The Resend sending domain is verified. Do not open or print .env.local. Read docs/content.md and docs/design.md for tone and business details.

Done looks like:
- After a lead is saved, three notifications are sent: (1) owner email to OWNER_EMAIL with name, contact details, message, time and the lead id, with reply-to set to the visitor's email so I can answer by pressing Reply; (2) a short, friendly confirmation to the visitor's email, if one was given, with reply-to set to OWNER_EMAIL, saying the request arrived and what happens next — no marketing; (3) a Telegram message to TELEGRAM_CHAT_ID with the same facts as the owner email.
- Both emails have a plain-text version as well as HTML.
- Everything the visitor typed is treated as plain text and escaped wherever it is inserted into HTML or a formatted Telegram message.
- Order and failure handling: the lead is saved first. Notifications run only after a successful save. Each channel is independent, has a timeout of a few seconds, and on failure writes one log line naming the channel and the lead id — no personal data, no keys. The response to the browser is 201 whenever the lead was saved, whatever happened to the notifications.
- Honeypot and Turnstile rejections send nothing.
- Reliability on Vercel: a serverless function may be stopped after it responds. Make sure the notifications actually complete, using the approach the current Next.js documentation recommends, and tell me which approach you chose and why.
- The senders sit in their own module so section 5 can reuse them. docs/architecture.md documents the flow and the five variable names.

Constraints: use Resend's official Node SDK and the Telegram Bot API sendMessage method; check their current docs. Telegram text must stay within the API's message length limit, so truncate long visitor messages. Secrets are used only on the server.

Before you report: with the dev server running, submit one lead named "TEST notify" through the real endpoint flow and tell me what each channel returned. Then run the production build.

Do along

Pause the video where a step says so and do it on your own project.

  1. Pause after Part 2. Add your sending subdomain in Resend, create the DNS records, wait for verification, add DMARC.
  2. Create a Resend API key; fill the three email variables in .env.local and Vercel.
  3. Pause after Part 3. Create your bot, store the token, press Start and send the bot a message.
  4. Give Claude the chat-ID prompt; fill TELEGRAM_CHAT_ID; add both variables in Vercel.
  5. Pause after Part 5. Give Claude the prompt from Part 5, then adapt the message wording to your business.
  6. Submit a test lead locally with a second address of yours as the visitor.
  7. Pause after Part 6. Break the Telegram token, restart, submit, make the four checks, restore.
  8. After Part 7, commit, push and test on the live domain.

Check your work

  1. Submit one lead on the live domain with a second address of yours as the visitor. Expected: a new row in leads.
  2. Check the owner inbox. Expected: the alert, and Reply addresses the visitor.
  3. Check the visitor inbox. Expected: the confirmation, from your sending domain, not in spam.
  4. Check Telegram. Expected: the bot's message with the same lead.
  5. Locally, with the Telegram token broken: submit a lead. Expected: 201, row saved, email received, no Telegram message, one log line naming the channel.

Common problems

  • Domain stays unverified → a record was mistyped → compare each record with Resend's list character by character; Resend offers a restart of verification if it has not completed after 72 hours.
  • Telegram refuses the message with an error about the chat → you never pressed Start in the bot's chat, or the chat ID is wrong → write to the bot, run npm run telegram:chat-id again.
  • The form shows an error when a channel is down → the failure rule is not implemented → tell Claude: "the lead was saved, so return 201 whatever the notifications did", and repeat the Part 6 test.
  • You pasted a token into the chat by mistake → treat it as leaked → revoke it (in BotFather or Resend), create a new one, and update .env.local and Vercel.

Homework

About 30 minutes. Keep written answers in your own notes, outside the project folder. Give every test lead a name starting with TEST.

  1. Break the other channel. Repeat the Part 6 test locally with RESEND_API_KEY broken instead of the Telegram token. Done when: the lead got 201, the row is saved, the Telegram message arrived, no email came, the log has one line naming the channel, and after you restored the key a new lead produces all four results again.
  2. Read your emails as a customer. Open the visitor confirmation on your phone. Check the sender name, the subject, and that "what happens next" is a promise your business keeps, such as how soon you reply. Tell Claude what to change. Done when: you would be content to receive this email yourself. If anything changed, run the production build and commit without a tag.
  3. Inbox and speed. On the live domain, submit a lead with another address of yours as the visitor, at a different mail provider if you have one. Note whether the confirmation landed in the inbox or in spam, and count the seconds until your phone shows the Telegram message and the owner email. Done when: your notes hold the folder and both times, and your phone is set so that you actually notice both.

Save your work

git add -A
git commit -m "Lesson 4.5: email and Telegram notifications"
git tag lesson-4.5
git push
git push --tags