Halal Scanner is a web application for checking ingredient halal status from typed input and OCR text, then storing results and handling user reports with admin moderation. The halal verdict is deterministic and database-driven; AI is used only to extract text from product images so spelling mistakes do not change the result.
- Frontend is plain HTML, CSS, and JavaScript.
- Backend is Node.js + Express with JWT authentication.
- Data is stored in PostgreSQL (Supabase-compatible schema).
- AI is used only for OCR text extraction and cleanup with Cohere.
- OCR is handled in the frontend via Tesseract.js CDN.
- Ingredient analysis endpoint backed by a deterministic halal ingredient database and rule set.
- OCR text cleanup + label text extraction flow.
- User sign up and sign in.
- Save and delete scan results per user.
- Submit and track inaccuracy reports.
- Admin review workflow for report status updates.
- Testimonials create/list endpoints.
- User and admin dashboard pages.
- Admin overview metrics (total users excluding seeded defaults, total testimonials).
- User privacy controls: account and associated data deletion from dashboard.
- Dedicated Privacy Policy page linked from footer Quick Access.
- Added Admin Dashboard Overview tab with metrics cards.
- Added backend metrics route:
GET /admin/dashboard-metrics(alias:GET /api/admin/dashboard-metrics). - Added User Dashboard Privacy & Data tab with permanent account deletion flow.
- Added backend account deletion route:
DELETE /user/account(alias:DELETE /api/user/account). - Added
frontend/privacy-policy.htmland footer Quick Access link.
- Frontend: HTML, CSS, Vanilla JavaScript
- Backend: Node.js, Express, JWT, pg, Cohere SDK for OCR text extraction
- Database: PostgreSQL
- UI libraries: Font Awesome
halal-scanner/
frontend/
index.html
user-dashboard.html
admin-dashboard.html
privacy-policy.html
main.js
dashboard.js
config.js
styles.css
robots.txt
sitemap.xml
backend/
server.js
package.json
.env.example
ingredients.json
database/
schema.sql
push-schema.js
seed-users.js
- Node.js 20+
- PostgreSQL database (Supabase or compatible)
- Cohere API key
- Clone the repository.
git clone <repository-url>
cd halal-scanner- Install dependencies.
cd backend
npm install
cd ..
npm install- Create backend environment file.
- Copy
backend/.env.exampletobackend/.env, then update values. - Minimum required values:
PORT=3000
DATABASE_URL=postgresql://postgres:password@db.your-project-ref.supabase.co:5432/postgres
JWT_SECRET=your_jwt_secret_here
JWT_EXPIRES_IN=12h
COHERE_API_KEY=your_cohere_api_key_here
PG_FORCE_IPV4=true
# Optional fallback if DNS resolves unreachable addresses:
# PGHOSTADDR=1.2.3.4- Apply schema.
npm run db:push- (Optional) Seed default users.
npm run db:seed- Start backend.
cd backend
npm start- Open the app.
- Recommended: http://localhost:3000
- Alternative: open
index.htmldirectly and keep backend running.
From repository root:
npm run db:push- applybackend/database/schema.sqlnpm run db:seed- seed default users
From backend:
npm start- start Express servernpm run db:push- apply schemanpm run db:seed- seed users
Base URL (local): http://localhost:3000
POST /auth/signup- create userPOST /auth/signin- return JWT and user profile
POST /analyze-ingredients- analyze ingredients textPOST /extract-ingredients-ai- extract and clean ingredient text from OCR output
GET /user-saved-results- user-scoped saved results (frontend default)GET /api/saved-results- alias route; supports admin/global list behaviorPOST /save-results- save result payloadDELETE /saved-results/:id- delete saved result (ownership enforced)
POST /submit-report- submit reportGET /user-reports- user reportsGET /api/user/reports- user reports aliasDELETE /reports/:id- delete report (role and status rules enforced)
GET /admin/reports- list all reportsPUT /admin/reports/:id- update report status and admin noteGET /admin/dashboard-metrics- admin overview totals (excludes seeded default admin/user from total users)GET /api/admin/dashboard-metrics- alias route
DELETE /user/account- delete current user account and associated dataDELETE /api/user/account- alias route
GET /testimonials- list testimonials (frontend default)POST /testimonials- create testimonial (frontend default)GET /api/testimonials- alias routePOST /api/testimonials- alias route
GET /health- backend health JSON
Defined in backend/database/schema.sql.
Main tables:
users(UUID PK,is_adminflag)saved_results(JSONB payload per user)reports(status:pending,solved,rejected)testimonials(rating 1..5)
PORT- backend port (use3000locally to match frontend config)DATABASE_URL- PostgreSQL connection stringJWT_SECRET- JWT signing secretJWT_EXPIRES_IN- token expiry, default12hCOHERE_API_KEY- required for/extract-ingredients-aiOCR text extractionPG_FORCE_IPV4- settruewhen IPv6 egress is unreliablePGHOSTADDR- optional direct Postgres host override
backend/Dockerfileexposes and health-checks port3000.backend/Procfilerunsnode server.js.backend/koyeb.yamlmaps service port3000and required secrets.
- Comprehensive meta tags (title, description, keywords, author)
- Open Graph and Twitter card tags for social media sharing
- JSON-LD structured data for Organization, WebApplication, FAQPage, and BreadcrumbList
- Canonical URLs to prevent duplicate content issues
- Robots and crawler meta tags for search engine optimization
sitemap.xml- XML sitemap for all pages with proper priority and changefreqrobots.txt- Crawler directives excluding protected pages and backend files.well-known/security.txt- Security contact and policy informationprivacy-policy.html- Public privacy and data handling page- Mobile-friendly meta tags and viewport configuration
- Preconnect/DNS-prefetch for external origins
- Preload critical resources (stylesheets, main scripts)
- Prefetch secondary resources (dashboard scripts, pages)
- Semantic HTML structure with proper header/nav/section hierarchy
- Search engines can index the main website (
/index.html) - Protected pages (dashboards) are blocked from indexing via
noindexrobots meta tag - All public pages include relevant keywords and descriptive content
- JSON-LD schemas validate with Google's Structured Data Testing Tool
- Fork the repository.
- Create a feature branch.
- Make your changes.
- Test your changes.
- Open a pull request.
- Open an issue in the repository.