Case study · AI / NLP
Noor Al-Qalb
A Flask web app that reads how you feel, detects the emotion with an NLP model, and answers with a Quranic verse, its translation and audio recitation.

Why I built it
When people feel anxious, sad or grateful, they often look for words that fit the moment. Finding a relevant passage in a large text takes time and knowing where to look.
I wanted to see whether a text-emotion model could do that matching: the user describes a feeling in their own words, and the app responds with a fitting verse in a calm, readable way.
Because this is religious content, accuracy and humility mattered more than cleverness. The app uses AI only to pick the emotion; the verses themselves are a fixed, curated set, not generated text.
Goals
- Detect the emotion in free-form text a user types
- Return a relevant verse with its translation and a short explanatory note
- Let the user listen to the recitation without leaving the page
- Keep the interface calm, fast and usable on a phone
- Be upfront that the model can misread tone
How it works
- 01
Emotion detection
The Flask backend sends the user's text to a pretrained DistilBERT emotion model through the Hugging Face Inference API, receives a score for each emotion, and keeps the highest one.
- 02
Curated verse set
A JSON file maps six emotions (sadness, joy, love, anger, fear, surprise) to five verses each. Every entry holds the Arabic text, translation, topic, a tafsir source and a short note for the reader.
- 03
Verse display and audio
The front end picks a verse for the detected emotion and renders it. The play button fetches the recitation from the Al-Quran Cloud API, and multi-ayah ranges play one after another.
- 04
Deployment
The Flask app is deployed on Vercel, while the heavy model runs on Hugging Face, so the app stays light and easy to host.
What it does
Emotion detection
Classifies the feeling behind a sentence into one of six emotions.
Verse and translation
Shows the Arabic verse, its English translation and a short note.
Audio recitation
Plays the verse in the browser, including multi-verse ranges.
Fallback handling
Falls back to a safe default emotion if the model returns a label with no verses.
Server-side API key
The Hugging Face token stays on the backend and is never exposed to the browser.
Responsive layout
A clean Bootstrap interface that works on phones and desktops.
What went wrong, and the fix
A pretrained emotion model can misread short or ambiguous text.
Added an honest note on the welcome screen telling users the prediction may be wrong, so the app is a tool for reflection, not an authority.
The model can return an emotion that has no verses in the dataset.
Added a fallback in the backend so the user always gets a verse instead of an empty result.
Some verses are ranges, and the audio API plays one ayah at a time.
Split ranges like 2:255-257 into single ayahs and queued them, playing the next recitation when the previous one ends.
The model is too heavy to run inside a serverless deployment.
Kept inference on Hugging Face's API and deployed only the lightweight Flask app, keeping the API token server-side.
Gallery
What I learned
- Using AI for one narrow job (classification) and a curated dataset for the sensitive content keeps the output trustworthy.
- A fallback for every external call matters when your app depends on two third-party APIs.
- Being clear about a model's limits builds more trust than hiding them.
What's next
- Add more verses per emotion so results feel less repetitive
- Support more emotions and show the model's confidence
- Add Arabic and Urdu input, since the current model handles English text
- Let users save favourite verses
Have something in mind?
Tell me what you're building. I'll reply with questions, a rough plan and a realistic timeline.
Start a conversation