Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,34 @@ TWILIO_CALLER_ID=
# spoken disclaimer plays. Ontario is one-party consent; keep the disclaimer.
TWILIO_RECORD_CALLS=

# ── SMS outreach (admin → /admin/sms, Twilio Messages API) ──────────────────
# Reuses TWILIO_ACCOUNT_SID / TWILIO_AUTH_TOKEN above. Needs an SMS SENDER —
# a Messaging Service (MGxxxx, preferred: A2P 10DLC + native opt-out) OR a plain
# SMS-capable number. Separate from TWILIO_CALLER_ID (Voice-only).
TWILIO_MESSAGING_SERVICE_SID=
TWILIO_SMS_FROM=
# SAFETY: dry-run until explicitly false. Dry-run logs + prices without sending.
SMS_DRY_RUN=true
# Cost planning: your Twilio per-segment price (CA long-code ≈ 0.0079 USD).
SMS_PRICE_PER_SEGMENT=0.0079
SMS_CURRENCY=USD
# CTA link + label placed in every message (defaults to NEXT_PUBLIC_SITE_URL/onboarding).
SMS_CTA_URL=
SMS_CTA_LABEL=Get started
# Throttle + quiet hours (recipient local time — TCPA/CASL friendly).
SMS_RATE_PER_SEC=1
SMS_QUIET_START_HOUR=9
SMS_QUIET_END_HOUR=21
SMS_TIMEZONE=America/Toronto
SMS_ENFORCE_QUIET_HOURS=true
# Groq model for AI personalization (defaults to GROQ_MODEL / llama-3.1-8b-instant).
GROQ_SMS_MODEL=
# Where Twilio POSTs delivery receipts + STOP replies. Defaults to NEXT_PUBLIC_SITE_URL.
# In dev, set to a tunnel (ngrok/cloudflared) so the webhook is reachable.
SMS_WEBHOOK_BASE_URL=
# Set false only if TLS/proxy termination prevents Twilio signature verification.
SMS_VALIDATE_SIGNATURE=true

# ── Web Push (device notifications, VAPID) ──────────────────────────────────
# Device push as an extra channel on createNotification (high-value types only).
# Generate a keypair: node -e "console.log(require('web-push').generateVAPIDKeys())"
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ Urban Company EnE.pdf
# Local MCP config (may hold a Supabase access token)
.mcp.json

# SMS outreach starter list — PII (real names + phone numbers). Loaded at runtime
# by /api/admin/sms/seed; must never be committed.
data/sms-seed-taskers.csv

# playwright-cli scratch (snapshots/screenshots)
.playwright-cli/
verify-wizard.png
Expand Down
7 changes: 7 additions & 0 deletions app/(admin)/admin/AdminShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
Coins,
Newspaper,
Globe,
Send,
} from 'lucide-react';
import { cn } from '@/lib/utils';
import NotificationsDropdown from '@/components/customer/NotificationsDropdown';
Expand Down Expand Up @@ -95,6 +96,12 @@ const NAV: ReadonlyArray<NavSection> = [
{ href: '/admin/pages', label: 'Pages', icon: Globe },
],
},
{
title: 'Growth',
items: [
{ href: '/admin/sms', label: 'SMS outreach', icon: Send },
],
},
{
title: 'Analytics',
items: [
Expand Down
Loading
Loading