Skip to content

NathanHor22/codex-hackathon

Repository files navigation

Jaga — scam protection for every Malaysian family

Jaga checks suspicious calls and messages in Bahasa Malaysia, English, Manglish, Mandarin, and Tamil, then gives a clear plain-language verdict. The website includes a live text checker and Agora device support; the Telegram bot is available at @jagaguardianbot.

Stack

  • Next.js 15 App Router, React 19, and TypeScript
  • Tailwind CSS v4 and Framer Motion
  • OpenRouter as the primary scam-analysis provider
  • Groq as the secondary provider and speech-to-text service
  • Offline keyword detection as the final, zero-configuration fallback
  • Agora RTC and Conversational AI support

Analysis fallback chain

The website endpoint and Telegram webhook both call the same server-only analysis service and use the same system prompt:

  1. OpenRouter is tried first when OPENROUTER_API_KEY is configured.
  2. If OpenRouter is missing, rate-limited, times out, returns invalid JSON, or otherwise fails, Jaga tries Groq when GROQ_API_KEY is configured.
  3. If Groq is unavailable or fails, Jaga uses the existing offline keyword detector.

Provider responses are validated before use. Invalid statuses, malformed fields, empty content, or invalid arrays trigger the next fallback. API errors and private message content are never returned to the website or Telegram user.

Project structure

app/
  [locale]/                    Localized website and guardian pages
  api/analyze/route.ts         Website analysis endpoint
  api/telegram/webhook/route.ts Telegram webhook endpoint
  api/agora/                   Agora token endpoint
  api/transcribe/route.ts      Groq speech-to-text endpoint
components/                    Website UI and Agora call components
lib/
  analysis.ts                  Shared result type and offline detector
  telegram.ts                  Telegram copy and bounded result formatter
  server/analysis.ts           Shared OpenRouter/Groq/offline provider chain
  server/telegram.ts           Telegram secret validation and delivery
messages/                      English, BM, and Mandarin translations
legacy/                        Original static prototype (reference only)

Local setup

Install dependencies and copy the environment template:

npm install
Copy-Item .env.example .env.local
npm run dev

Fill in only the services you use in .env.local. OpenRouter and Groq keys are optional because the checker can run offline. The Telegram webhook requires both TELEGRAM_BOT_TOKEN and TELEGRAM_WEBHOOK_SECRET.

OPENROUTER_API_KEY=
OPENROUTER_MODEL=~openai/gpt-latest
GROQ_API_KEY=
GROQ_MODEL=llama-3.3-70b-versatile
TELEGRAM_BOT_TOKEN=
TELEGRAM_WEBHOOK_SECRET=
APP_URL=https://codex-hackathon-cyan.vercel.app

Keep the existing Agora variables from .env.example when using the live guardian. Next.js loads .env.local automatically, and the file is gitignored.

Vercel configuration

In the Vercel project, open Settings → Environment Variables and add the same variables for the Production environment. Redeploy after saving them so the server functions receive the new configuration.

For the Telegram bot, configure at minimum:

  • TELEGRAM_BOT_TOKEN
  • TELEGRAM_WEBHOOK_SECRET — choose a strong random value accepted by Telegram (letters, numbers, _, and -)
  • APP_URL=https://codex-hackathon-cyan.vercel.app

Configure one or both AI provider keys. With both keys present, OpenRouter remains primary and Groq remains secondary.

Telegram webhook setup

Production webhook URL:

https://codex-hackathon-cyan.vercel.app/api/telegram/webhook

Deploy the application and Vercel environment variables before registering the webhook. This PowerShell example prompts securely instead of placing credentials in shell history:

$jagaBotTokenSecure = Read-Host "Telegram bot token" -AsSecureString
$jagaWebhookSecretSecure = Read-Host "Telegram webhook secret" -AsSecureString
$jagaBotTokenPlain = [Net.NetworkCredential]::new("", $jagaBotTokenSecure).Password
$jagaWebhookSecretPlain = [Net.NetworkCredential]::new("", $jagaWebhookSecretSecure).Password
$jagaWebhookBody = @{
  url = "https://codex-hackathon-cyan.vercel.app/api/telegram/webhook"
  secret_token = $jagaWebhookSecretPlain
  allowed_updates = @("message")
} | ConvertTo-Json

Invoke-RestMethod `
  -Method Post `
  -Uri "https://api.telegram.org/bot$jagaBotTokenPlain/setWebhook" `
  -ContentType "application/json" `
  -Body $jagaWebhookBody

Remove-Variable jagaBotTokenPlain, jagaWebhookSecretPlain, jagaWebhookBody

The webhook secret entered here must exactly match TELEGRAM_WEBHOOK_SECRET in Vercel.

Check registration with getWebhookInfo without printing the bot token:

$jagaBotTokenSecure = Read-Host "Telegram bot token" -AsSecureString
$jagaBotTokenPlain = [Net.NetworkCredential]::new("", $jagaBotTokenSecure).Password
Invoke-RestMethod -Method Get -Uri "https://api.telegram.org/bot$jagaBotTokenPlain/getWebhookInfo"
Remove-Variable jagaBotTokenPlain

Confirm that url matches the production endpoint and inspect last_error_message if Telegram reports delivery problems.

Never commit .env.local, real credentials, copied request headers, or terminal output containing secrets. Never paste or display secrets in issues, screenshots, chat, or logs.

Verification

npm test
npx tsc --noEmit
npm run build
git diff --check

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors