Gabriel
Inspiration
Online grooming rarely looks obviously dangerous in the moment. It's built out of small, deliberate steps: a stranger being unusually flattering, steering a conversation private, testing boundaries, then normalizing what should never be normal. By the time a parent or guardian actually reads the messages, they're often staring at hundreds of lines of casual-looking chat with no idea which parts, if any, actually matter.
We wanted to build something that doesn't replace a parent's judgment, but gives them somewhere to start, without ever reducing a child's safety to a single scary number.
What it does
Gabriel takes a chat transcript, pasted in directly or uploaded as a real export from WhatsApp, Discord, LINE, or Telegram, and scores it against the four documented stages of grooming behavior from Luring Communication Theory:
- Trust-building
- Risk assessment
- Isolation / secrecy
- Desensitization
Instead of a verdict, it returns a stage-by-stage timeline: which messages triggered which stage, why, and how far the conversation progressed. When multiple people are in the conversation, it identifies the likely participants and flags a possible person of interest. Every upload is tied to a user account and saved to a history page, so a parent can revisit a past analysis instead of re-uploading it.
And every result page carries the same message: this is not an automated accusation. If the timeline is concerning, escalate to a real channel like KPAI or Kominfo Aduan Konten.
How we built it
The stack spans three services:
- Frontend: Next.js 16 (App Router)
- Backend: Spring Boot 4.1 / Java 21
- AI service: a standalone Python FastAPI service
- Database: Postgres, hosted on Supabase
- Deployment: Railway
The AI service is grounded explicitly in Luring Communication Theory rather than keyword-matching, and its stage-scoring is validated against PAN12, an academic benchmark corpus built for sexual-predator identification research. That gives the detection logic an actual research basis instead of being guessed at.
Auth is a deliberately simple opaque bearer token (no JWT, no external identity provider), so we could focus engineering time on the transcript pipeline itself. We split work by layer (frontend, backend, AI service) and used Claude Code as an AI pair-programmer for a substantial part of the backend's scaffolding and debugging.
Challenges we ran into
- Bleeding-edge frameworks outran our tooling's training data. Spring Boot 4.1 quietly moved Jackson to a new package namespace and split
RestClientautoconfiguration into its own starter, and Next.js 16 changed routeparamsinto a Promise. Both required actually reading the installed library source instead of trusting assumptions. - A CORS-vs-auth ordering bug. Adding token authentication introduced a subtle issue where the auth filter intercepted CORS preflight requests before Spring's own CORS handling ever ran, producing a bare
Failed to fetchin the browser with no useful error. The fix was lettingOPTIONSrequests bypass auth entirely. - Real-world chat exports are messy. WhatsApp's locale-specific formats use periods instead of colons in timestamps and sprinkle in invisible bidirectional Unicode marks, which broke naive regex parsing until we handled both explicitly.
- A hard ethical rule: no synthetic grooming content anywhere in the repo. That meant sourcing evaluation fixtures from established academic research (PAN12) rather than writing our own.
Accomplishments that we're proud of
We didn't just claim things worked. We verified them, live. A full register, upload, analyze, history round trip ran end-to-end against a real deployed Supabase database, not just a green test suite.
We're also proud that the product's ethical framing isn't an afterthought bolted onto a "risk score." Every single screen, from the analysis result to the history detail page, reinforces that this is a tool for human review, never an automated accusation, and always points toward real reporting channels when something looks serious.
What we learned
We learned how genuinely gradual and structured real grooming behavior is, which reshaped how we designed the UI: a timeline that shows progression, rather than a single alarming score, turned out to be both more honest and more useful.
On the engineering side, we learned not to trust assumptions against a framework newer than our own training data. Reading the actual installed source caught real breaking changes before they became runtime failures. And we learned that best-effort parsing of real-world data (chat exports in particular) needs to be designed for messiness from day one, not patched in after the first failure.
What's next for Gabriel
Next is closing the loop with real detection accuracy: expanding the PAN12-based evaluation set and tuning the AI service against more edge cases, like a single severe spike buried in an otherwise benign conversation, guilt-tripping manipulation, or slow escalation-then-backoff.
We'd also like:
- A browser extension or lightweight mobile view, so a parent doesn't need to manually export and upload a chat.
- Multi-language support beyond Indonesian/English casual chat.
- A direct integration path with organizations like KPAI, so a concerning result can lead somewhere real, not just a suggestion on screen.
Built With
- fastapi
- node.js
- openrouter
- postgresql
- python
- railway
- springboot
- supabase
Log in or sign up for Devpost to join the conversation.