Skip to main content

SMS Radar Notifications - Complete Guide

What Is This?

Internal users can now receive text message alerts when their radar schedules detect important changes in their portfolio. This works exactly like email notifications, but sends an SMS instead.

How It Works (Simple Flow)


The Three Main Parts

Part 1: Frontend (React/Next.js)

What it does: Shows SMS toggle to internal users, saves their choice Files:
  • components/radar-schedules-sidebar.tsx - SMS checkbox UI
  • app/radar/hooks.ts - Manages smsEnabled state
  • app/radar/types.ts - Defines smsEnabled in schedule config
How it works:
  1. User opens Radar page
  2. If user is in internal table → SMS toggle appears
  3. User checks “SMS” when creating radar
  4. Frontend saves: { smsEnabled: true } to DynamoDB

Part 2: AWS Lambda (Python)

What it does: Executes radar, decides if alert should be sent, triggers SMS File: aws/radar/lambdas/processor/handler.py How it works (step by step):

Step 1: Lambda Gets Triggered

Step 2: Lambda Fetches Radar Schedule

Step 3: Lambda Runs AI Analysis

Step 4: Lambda Checks If SMS Should Be Sent

Step 5: Lambda Sends SMS (If Conditions Met)

Step 6: Lambda Calls Next.js API

Step 7: Lambda Saves SMS Status to DynamoDB

Part 3: Next.js API (TypeScript)

What it does: Receives request from Lambda, sends SMS via Twilio File: app/api/sms/radar-complete/route.ts How it works:

Step 1: Receive Request from Lambda

Step 2: Get User’s Phone Number

Step 3: Validate User Can Receive SMS

Step 4: Format the SMS Message

Step 5: Send SMS via Twilio

Step 6: Log SMS in Database

Step 7: Return Success to Lambda


Complete Example Flow

Let’s walk through a real example:

Setup

  • User: John (internal user)
  • Radar: “Alert me when my tech allocation exceeds 40%”
  • Schedule: Daily at 9:00 AM
  • SMS: Enabled ✅

Day 1: 9:00 AM - Radar Runs

1. EventBridge triggers Lambda
2. Lambda fetches schedule
3. Lambda analyzes portfolio
4. Lambda checks if SMS should be sent
5. Lambda saves result
Result: No SMS sent (condition not met) ✅

Day 2: 9:00 AM - Radar Runs Again

1. EventBridge triggers Lambda (same as Day 1) 2. Lambda fetches schedule (same as Day 1) 3. Lambda analyzes portfolio
4. Lambda checks if SMS should be sent
5. Lambda calls send_completion_sms()
6. send_completion_sms() calls Next.js API
7. Next.js API receives request
8. Next.js returns success to Lambda
9. Lambda saves result
10. John receives text message 📱
Result: SMS sent successfully! ✅

Why This Design?

Why Lambda → Next.js → Twilio?

Why not Lambda → Twilio directly?
  1. Separation of concerns: Lambda handles radar logic, Next.js handles user communication
  2. Reuse existing code: Next.js already has Twilio integration, SMS logging, user validation
  3. Security: Twilio credentials stay in Next.js environment variables
  4. Consistency: All SMS (chat, radar, etc.) go through the same Next.js API
  5. Easier debugging: Can test Next.js API independently of Lambda

Why Check sms_opt_in in Next.js?

Why not check in Lambda?
  • Lambda doesn’t have direct Supabase access (uses DynamoDB)
  • Next.js already has user data access patterns
  • Keeps user preference logic in one place
  • Easier to add more SMS validation rules later

Key Files Summary


Testing Checklist

1. Add yourself to internal table

2. Create a test radar

  • Go to Radar page
  • Click “New Alert”
  • Enter prompt: “Alert me when my net worth changes”
  • Check “SMS” toggle ✅
  • Save

3. Trigger manually

  • Click “Run Now” on your radar
  • Wait 10-30 seconds

4. Check Lambda logs (CloudWatch)

5. Check your phone

  • You should receive a text message 📱

6. Check database


Troubleshooting

”SMS toggle doesn’t appear”

→ You’re not in the internal table

”SMS status is SKIPPED”

→ Check smsReason in DynamoDB:
  • SMS_NOT_ENABLED: User has sms_opt_in = false
  • NO_PHONE_NUMBER: User has no phone number
  • SKIPPED_TRIGGER_NOT_MET: Radar ran but condition not met

”SMS status is FAILED”

→ Check Next.js logs for errors:
  • Twilio API error?
  • Phone number format invalid?
  • Twilio account balance?

”Lambda timeout”

→ Check CloudWatch logs:
  • Is Next.js API responding?
  • Network connectivity issue?

Cost

Per SMS: ~$0.008 (Twilio fee) Monthly estimate (10 internal users, 5 radars each):
  • 10 users × 5 radars × 30 days = 1,500 SMS/month
  • 1,500 × 0.008=∗∗0.008 = **12/month**

Summary

What you built:
  1. ✅ Frontend: SMS toggle for internal users
  2. ✅ Lambda: Check smsEnabled flag and trigger SMS
  3. ✅ Next.js API: Send SMS via Twilio
  4. ✅ Database: Log all SMS activity
How it works:
  1. User enables SMS on radar
  2. Lambda runs radar on schedule
  3. If trigger met → Lambda calls Next.js API
  4. Next.js sends SMS via Twilio
  5. User receives text message
Key insight: Lambda doesn’t send SMS directly. It calls your Next.js API, which handles all the SMS logic (validation, Twilio, logging). This keeps your code clean and reusable.
Status: ✅ Ready to deploy
Next step: Deploy Lambda changes to AWS, test with internal user