ShieldByte is a full-stack cyber fraud awareness platform built with SvelteKit and Supabase. Its main idea is simple:
- collect real scam-related news and fraud reports
- turn those reports into structured fraud data
- generate playable scam simulation missions from that data
- let users practice spotting scam clues in a browser game
- save user progress and generate simple AI feedback after each mission
The repo currently contains a working backend content pipeline and a working web gameplay surface. It also includes backend support for a WhatsApp flow and a duel challenge system.
The current codebase is strongest in:
- fraud article ingestion
- fraud relevance analysis
- fraud classification
- mission generation
- playable web missions
- progress tracking
- AI feedback
- duel mode
The current codebase is partial in:
- full account/auth product flow
- referral feature wiring
- full WhatsApp product surface
ShieldByte is trying to solve a practical problem: people usually read about scams, but they do not practice identifying them in realistic situations.
This repo implements a system that turns real scam cases into short interactive missions. Instead of giving only static advice, it creates a loop where the user:
- sees a suspicious message
- decides whether it is a scam
- taps suspicious parts of the message
- loses lives on wrong guesses
- earns XP on success
- receives feedback on what was missed
This makes the system part content pipeline, part game, and part learning tool.
The current web product in code includes:
- a homepage with recent scam cases
- a mission play screen
- article detail pages
- a profile dashboard
- a duel page for challenge comparisons
The current backend product in code includes:
- scheduled ingestion
- scheduled classification
- scheduled mission generation
- mission serving APIs
- attempt saving APIs
- lives and token APIs
- AI feedback generation
- challenge creation and submission
- WhatsApp webhook handling
The full repo flow works like this:
- fraud articles are fetched from external sources
- article text is cleaned and checked for fraud relevance
- relevant raw articles are classified into one of six fraud categories
- structured classification output is stored in Supabase
- missions are generated from classified fraud data
- the frontend loads active missions from Supabase
- the user plays a mission and submits the result
- XP, streak, rank, lives, and badges are updated
- AI feedback is generated for that mission result
- SvelteKit 2
- Svelte 5
- TypeScript
- Vite
- SvelteKit server routes
- Supabase
- PostgreSQL through Supabase
@supabase/supabase-jscheeriogroq-sdkrss-parserzod
- OpenRouter
- Gemini
- Groq
- Ollama
The code currently works with these exact categories:
UPI_fraudKYC_fraudlottery_fraudjob_scaminvestment_fraudcustomer_support_scam
These categories are defined in:
src/lib/server/constants.ts
The category-specific heuristics, clues, red flags, and tips are implemented in:
src/lib/server/fraud-signals.ts
Main files:
src/lib/server/news-ingestion.tssrc/lib/server/constants.tssrc/lib/server/web-scraper.ts
Purpose:
- fetch scam-related content from external sources
- filter weak or irrelevant content early
- deduplicate incoming articles
- store new articles in Supabase
Implemented source types:
- NewsAPI
- RSS feeds
- Reddit RSS feeds
- scraped pages
Important implementation details:
- ingestion runs multiple source fetches in parallel
- articles are cleaned with local text sanitization
- heuristic fraud checks run before database insert
- duplicate removal uses URL and title/source keys
- inserted rows go into
fraud_articles - run-level metrics go into
ingestion_runs
Important ingestion behaviors in code:
- target is at least 5 inserted articles per run
- articles can be dropped before insert if they look like advisories or non-scam content
- negative and positive pattern scoring is used before database write
Main file:
src/lib/server/fraud-signals.ts
Purpose:
- decide whether an article is a real scam case or just related discussion
- score category hints before calling an LLM
- provide fallback classification content when AI is weak or unavailable
Implemented logic includes:
- weighted keyword matching per fraud category
- scam incident pattern scoring
- non-scam context detection
- signal strength calculation
- relevance confidence estimation
- review status decision
This layer matters because the repo does not trust external content blindly. It tries to reject:
- awareness articles
- advisories
- policy writeups
- legal/crime reporting that does not describe a usable scam pattern
Main files:
src/lib/server/ai-classifier.tssrc/lib/server/extraction.tssrc/lib/server/phase1-ml.tssrc/lib/server/json-utils.ts
Purpose:
- convert raw article text into structured fraud data
Classification output includes:
fraud_typechannelscenario_summaryvictim_profilecluesred_flagstip
Provider order implemented in code:
- OpenRouter models if configured
- Gemini if configured
- Ollama if configured
- Groq as another supported path in the classifier flow
Other important classification details:
- JSON output is validated with Zod
- heuristic fallback classification exists
- ML-assisted category prediction exists
- confidence is estimated after reconciliation
- results can be auto-approved or marked
needs_review - raw articles with repeated failures are retried and can move to
failed - irrelevant articles can move to
irrelevant
Database behavior:
- reads from
fraud_articleswhere status israw - writes structured output back to
fraud_articles - logs metrics to
classification_runs
Main files:
src/lib/server/mission-generator.tssrc/lib/server/mission-rendering.tssrc/lib/server/missions.ts
Purpose:
- convert structured fraud data into a playable mission
Mission fields generated by the repo:
- simulation type
- sender
- message body
- clues
- difficulty
- tip
- simulation HTML
- variant number
Important implementation details:
- mission output is validated with Zod
- up to 3 variants can be generated
- clue text must match message body text
- non-English content is sanitized or replaced in some read paths
- rendered mission HTML is generated server-side
Mission rendering behavior:
- a simple HTML card is generated with a header and body
- simulation labels vary by type such as SMS, WhatsApp, email, or call transcript
Database behavior:
- generated missions are stored in
missions - active missions can be fetched by article, by random selection, or by mission ID
- old missions can be archived when force regeneration is used
Main files:
src/lib/server/classified-articles.tssrc/lib/server/missions.ts
Purpose:
- normalize database records for page rendering
What this layer currently does:
- reads classified articles for the homepage
- reads a single classified article for article detail pages
- reads active missions for gameplay
- builds fallback mission objects from article data when generated missions are missing
- sanitizes some non-English or unsafe display content before sending it to the UI
Main files:
src/routes/+page.server.tssrc/routes/+page.sveltesrc/lib/components/home/Hero.sveltesrc/lib/components/home/SwipeDeck.sveltesrc/lib/components/home/ThreatCard.sveltesrc/lib/components/home/TrainingDeck.sveltesrc/lib/components/home/MissionPanel.svelte
What the home page currently does:
- loads recent classified articles
- chooses a featured article
- tries to load a related mission for that article
- shows a queue of scam cases
- links users into article detail pages and gameplay
Main file:
src/routes/+layout.svelte
What it currently provides:
- app-wide navigation
- global fonts
- brand styling
- links to:
- Home
- Play
- Profile
Main files:
src/routes/articles/[id]/+page.server.tssrc/routes/articles/[id]/+page.svelte
What they do:
- load a classified article by ID
- show extracted scam information from the article
- connect article content to generated mission content when available
Main files:
src/routes/play/+page.server.tssrc/routes/play/+page.sveltesrc/lib/components/gameplay/GameplayEngine.sveltesrc/lib/gameplay/engine.ts
What the play flow currently does:
- loads either a random mission or a mission tied to a selected article
- supports optional difficulty and fraud type filtering
- supports a fallback mission if no generated mission exists
- sends the mission into the gameplay engine
The gameplay engine is one of the largest implemented pieces in the repo.
Main files:
src/lib/components/gameplay/GameplayEngine.sveltesrc/lib/gameplay/engine.tssrc/lib/server/gameplay.ts
- each mission lasts 60 seconds
- low-time threshold is 15 seconds
- player starts with 3 lives
- wrong actions consume lives
- lives regenerate over time
- the player first makes a
scamorsafeverdict - after that, the player taps suspicious message phrases
- clue text is matched inside the message body and wrapped as interactive segments
- mission ends on:
- success
- timeout
- failed
The code currently calculates:
- base XP
- speed bonus
- perfect multiplier
- streak multiplier
Current constants and rules in src/lib/gameplay/engine.ts:
- base XP starts at
100 - speed bonus is based on remaining time
- perfect run multiplier is
2 - streak multiplier is capped at
2 - failed missions return
0XP
Current implementation:
- max lives:
3 - one life regenerates every hour
- server-backed lives state exists
- client also shows countdown updates
- lives sync through
/api/lives
When a mission ends:
- a mission result summary is built locally
- attempt data is sent to
/api/missions/attempt - profile snapshot can be returned
- updated lives can be returned
- badge rewards can be returned
- rank-up info can be returned
- AI feedback request is triggered after the attempt save
Main files:
src/lib/server/gameplay.tssrc/lib/server/badge-engine.tssrc/routes/api/missions/attempt/+server.tssrc/routes/api/user/profile/+server.tssrc/routes/profile/+page.server.tssrc/routes/profile/+page.svelte
What this subsystem currently does:
- validates mission attempts with Zod
- records attempts in
mission_attempts - records XP ledger rows in
xp_transactions - updates
user_stats - calculates rank from XP thresholds
- updates streak logic
- awards badges
- returns profile-like data after mission completion
Current rank thresholds in code:
Rookie AgentField InvestigatorSenior AnalystCyber Commander
Current badge IDs in code:
speed_demonsharpshooterupi_guardiankyc_defenderviral_protectorweek_warriorperfect_weekmentorfraud_hunter
Important note:
- not every badge has a fully wired front-to-back feature flow yet
Main files:
src/lib/server/feedback-engine.tssrc/routes/api/feedback/generate/+server.tssrc/lib/server/gemini.tssrc/lib/server/openrouter.tssrc/lib/server/ollama.ts
Purpose:
- explain the missed scam clues after a mission
What it currently generates:
feedbackTextpatternIdentifiedactionableTipencouragement
Important implementation details:
- output is schema-validated
- output is saved to
feedback_log - provider fallback exists
- language is intentionally kept simple in the prompt design
Main files:
src/routes/api/challenges/create/+server.tssrc/routes/api/challenges/submit/+server.tssrc/routes/api/challenges/[code]/+server.tssrc/routes/duel/[code]/+page.server.tssrc/routes/duel/[code]/+page.svelte
What this subsystem currently does:
- creates a short challenge code
- stores challenger performance in
challenges - loads the same mission for the opponent
- accepts opponent result submission
- decides a winner based on:
- higher XP first
- lower time second
Current challenge statuses in code:
pendingcompleted
Main files:
src/routes/api/whatsapp/webhook/+server.tssrc/lib/server/whatsapp/state-machine.tssrc/lib/server/whatsapp/messenger.ts
What this subsystem currently does:
- verifies webhook requests
- receives incoming WhatsApp messages
- starts a mission when user sends
startorplay - stores session state in
whatsapp_sessions - fetches a random mission for the WhatsApp user
- allows simple clue matching through text replies
- handles quit/stop
- sends mission success or failure messages
Current WhatsApp state values in code and migrations:
IDLEIN_MISSIONWAITING_FOR_FEEDBACK
Important repo-backed limitation:
- this is a backend conversational path, not a full parallel product surface like the web app
Main files:
src/lib/server/auth.tssrc/routes/api/user/token/+server.ts
Current implementation:
- guest-like player IDs are created in the frontend
- backend can sign a player token with HMAC-SHA256
- protected routes can verify the player token
- this is lightweight request protection, not full user auth
Important current reality:
- there is no full Google auth product flow in the route tree
- there is no full session/account system beyond this lightweight token flow
//play/profile/articles/[id]/duel/[code]
GET /api/cron/ingestGET /api/cron/classifyGET /api/cron/generate-missionsGET /api/missions/randomPOST /api/missions/attemptPOST /api/feedback/generateGET /api/livesPOST /api/livesGET /api/user/profilePOST /api/user/tokenPOST /api/challenges/createPOST /api/challenges/submitGET /api/challenges/[code]GET /api/whatsapp/webhookPOST /api/whatsapp/webhookPOST /generate-mission
- cron routes require
x-cron-secret - lives update route requires token-based verification
- mission attempt route requires token-based verification
- mission random route is public
- generate mission route is a non-
/apiserver endpoint
The repo uses Supabase and includes the following migration files:
001_create_articles_table.sql002_create_missions_table.sql003_harden_phase1_pipeline.sql004_phase1_observability_and_retries.sql005_add_simulation_html_to_missions.sql006_add_gameplay_progress_tables.sql007_add_lives_to_user_stats.sql008_add_feedback_log.sql009_add_badges_table.sql010_add_whatsapp_sessions.sql010_whatsapp_sessions.sql011_add_referrals.sql012_add_challenges.sql013_add_irrelevant_phase1_status.sqlphase1_finalize.sql
Main tables used by current code:
fraud_articlesingestion_runsclassification_runsmissionsmission_attemptsxp_transactionsuser_statsuser_badgesfeedback_logwhatsapp_sessionschallenges
Referral-related tables exist in migrations:
referral_linksreferral_claims
Important note:
- referral database support exists, but matching app routes are not present in the current
src/routes
SUPABASE_URLSUPABASE_SERVICE_ROLE_KEYCRON_SECRETAPI_SECRET
NEWSAPI_KEY
GEMINI_API_KEYGEMINI_CLASSIFIER_MODELGEMINI_MISSION_MODELGEMINI_FEEDBACK_MODEL
GROQ_API_KEY
OPENROUTER_API_KEYOPENROUTER_API_KEY_2OPENROUTER_API_KEY_3OPENROUTER_CLASSIFIER_MODELSOPENROUTER_MISSION_MODELSOPENROUTER_FEEDBACK_MODELS
OLLAMA_BASE_URLOLLAMA_CLASSIFIER_MODELOLLAMA_MISSION_MODELOLLAMA_FEEDBACK_MODEL
PHASE1_CATEGORY_MODEL_PATHWHATSAPP_WEBHOOK_VERIFY_TOKEN
Current vercel.json schedules:
/api/cron/ingestat0 6 * * */api/cron/classifyat0 7 * * */api/cron/generate-missionsat0 8 * * *
Operational notes from code:
- ingestion route has an in-memory overlap guard
- cron routes expect
x-cron-secret - generation route supports a
forcequery parameter for regeneration
Main scripts from package.json:
npm run devnpm run buildnpm run previewnpm run preparenpm run checknpm run check:watch
Phase 1 and evaluation scripts:
npm run eval:phase1:exportnpm run eval:phase1:weaknpm run build:phase1:relevance-datasetnpm run build:phase1:category-datasetnpm run train:phase1:relevancenpm run eval:phase1:relevancenpm run eval:phase1:reviewnpm run eval:phase1:scorenpm run eval:phase1:gatenpm run run:phase1:cronnpm run train:phase1:modelnpm run verify:phase1:live
Script files currently present in scripts/:
build-phase1-category-dataset.mjsbuild-phase1-relevance-dataset.mjscheck-table.mjsestimate-phase1-gated-accuracy.mjsevaluate-phase1-accuracy.mjsevaluate-phase1-relevance-model.mjsexport-phase1-eval-sample.mjsexport-phase1-weak-label-candidates.mjsreview-phase1-sample.mjsrun-migration.mjsrun-phase1-cron.mjstest-endpoints.mjstest-phase2.mjstrain-phase1-ml-model.mjstrain-phase1-relevance-model.mjsverify-phase1-live.mjs
src/
app.d.ts
app.html
lib/
assets/
components/
gameplay/
home/
gameplay/
server/
whatsapp/
types/
routes/
api/
articles/
duel/
play/
profile/
docs/
scripts/
supabase/migrations/
static/
- Install packages
npm install- Copy the env template
copy .env.example .env-
Fill in the environment variables
-
Run the app
npm run devUseful checks:
npm run check
npm run buildBased on the current repo, these are the main gaps:
- no full Google auth flow in the current route tree
- referral feature is only partially present through SQL migrations
- WhatsApp flow is backend-first and simpler than the web flow
- status docs and SRS describe a broader target product than what the current routes expose
- some badges are defined ahead of their full feature support
If this repo is viewed as a project report, the correct summary is:
ShieldByte already has a working fraud-content pipeline, a working mission generation pipeline, a playable web mission loop, progression tracking, profile pages, AI feedback, and a duel challenge mode. It also has backend WhatsApp handling and migration-level support for referral-style growth features. The biggest missing parts are full auth/account flows, referral route wiring, and a more complete WhatsApp product surface.