⚠️ CRITICAL RULE FOR CONTRIBUTORS: We have a strict assignment policy. You MUST request assignment on an issue and wait for a maintainer to assign you before writing any code. Any Pull Requests submitted without assignment will be closed automatically to prevent duplicate work.
Thank you for wanting to contribute to SahiDawa! Every PR you submit helps protect a real person from a fake medicine. Read this guide fully before submitting your first contribution — it will save you time and help your PR get merged faster.
- Code of Conduct
- How to Get Started
- Development Setup
- Project Structure
- Contribution Workflow
- Types of Contributions
- Coding Standards
- Commit Message Format
- Pull Request Guidelines
- Issue Guidelines
- GSSoC 2026 Contributors
- Getting Help
This project follows a strict Code of Conduct. We do not tolerate discrimination, harassment, or disrespect of any kind. By contributing, you agree to uphold these standards.
Read the full Code of Conduct.
- Go to Issues
- Filter by label:
good-first-issue(beginners),intermediate,advanced,ml,i18n,agent - Read the issue fully, including the Acceptance Criteria section
- Comment: "I'd like to work on this"
- Wait for a maintainer to assign it to you (usually within 12 hours)
Do not submit a PR for an unassigned issue. We work this way to avoid duplicate effort.
# Fork the repo on GitHub, then:
git clone https://github.com/YOUR_USERNAME/sahidawa-india.git
cd sahidawa-india
git remote add upstream https://github.com/ORIGINAL_OWNER/sahidawa-india.git# Always branch from main
git checkout main
git pull upstream main
git checkout -b feat/your-feature-name
# or: fix/your-bugfix-name
# or: i18n/tamil-translation
# or: docs/setup-guideFollow the Coding Standards below.
# Frontend tests
cd apps/web && npm run test
# API tests
cd apps/api && npm run test
# ML service tests
cd apps/ml && pytest
# Lint check
npm run lintgit add .
git commit -m "feat(scanner): add barcode decode for QR codes"
git push origin feat/your-feature-name- Go to your fork on GitHub
- Click Compare & pull request
- Fill out the PR template completely
- Link the issue:
Closes #123 - Wait for review — we respond within 24 hours
| Tool | Version | Install |
|---|---|---|
| Node.js | >= 18.0.0 | nodejs.org |
| Python | >= 3.10 | python.org |
| Docker | >= 24.0 | docker.com |
| Git | Any recent | git-scm.com |
| Supabase CLI | Latest | supabase.com |
Copy .env.example to .env.local (frontend) and .env (API). You need:
# Supabase — free at supabase.com (no credit card)
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_anon_key
# Cloudinary — free at cloudinary.com
CLOUDINARY_CLOUD_NAME=your_cloud_name
CLOUDINARY_API_KEY=your_api_key
CLOUDINARY_API_SECRET=your_api_secret
# Redis — free at upstash.com (no credit card)
UPSTASH_REDIS_REST_URL=your_redis_url
UPSTASH_REDIS_REST_TOKEN=your_tokenFor i18n contributors (translations): You do NOT need any environment variables. Just edit the JSON file and run
npm run dev.
cp .env.example .env
# Fill in your keys, then:
docker compose -f docker-compose.dev.yml up --build# Terminal 1 — Local Database (Supabase)
# Ensure Docker is running in the background first
npx supabase start
# Terminal 2 — Frontend
cd apps/web
npm install
npm run dev # http://localhost:3000
# Terminal 2 — API
cd apps/api
npm install
npm run dev # http://localhost:4000
# API Docs: http://localhost:4000/api/docs
# Terminal 3 — ML Service (optional for Phase 1/2 work)
cd apps/ml
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --reload --port 8000If you encounter No matching version found errors while running npm install, it may be caused by the canary package versions currently used in this project.
Try running:
npm install --legacy-peer-depsor:
npm install --forceIf the issue still persists, you may temporarily downgrade package versions locally to get the project running on your machine.
⚠️ Important: Do not commit modifiedpackage.jsonorpackage-lock.jsonfiles created during local downgrades. Revert those changes before pushing your PR.
Each Indian language has a dedicated issue. Pick one unclaimed language.
- Open
apps/web/messages/en.json - Copy the entire file
- Create
apps/web/messages/[language-code].json - Translate every value (keep the keys in English — only translate values)
- Do NOT translate: URLs, component names, variable placeholders like
{count}
Example:
// en.json
{ "scan.button": "Scan Medicine", "scan.result.real": "This medicine is REAL" }
// ta.json (Tamil)
{ "scan.button": "மருந்தை ஸ்கேன் செய்யுங்கள்", "scan.result.real": "இந்த மருந்து உண்மையானது" }- Pick a component issue labeled
good-first-issue+frontend - All components go in
apps/web/components/ - Use shadcn/ui primitives wherever possible
- Must be accessible (keyboard navigable, proper ARIA labels)
- Fix typos, improve explanations, add usage examples
- All docs are Markdown files in
docs/
- Add medicine entries to
data/seeds/medicines.csv - Format:
batch_number,brand_name,generic_name,manufacturer,strength,form - Source only from official CDSCO drug database
- Uses
@zxing/browserlibrary - Component:
apps/web/components/scanner/ - Must work on mobile Chrome and Safari
- Needs to handle: Code128, QR Code, EAN-13, EAN-8 formats
- Uses Leaflet.js + OpenStreetMap
- Backend: PostGIS
ST_DWithinquery to find pharmacies within radius - Component:
apps/web/components/map/ - Must work offline (tiles cached by Workbox)
- Photo upload component for reporting suspicious medicines
- Use Cloudinary's upload widget or direct API
- Store:
cloud_name/sahidawa/reports/{medicine_batch}_{timestamp} - See Cloudinary docs
- All routes in
apps/api/src/routes/ - Use TypeScript — no
anytypes - Every route needs: input validation (Zod), error handling, rate limiting
- Write tests in
apps/api/tests/
Swagger/OpenAPI Documentation
- Access Instructions: You can open the interactive Swagger UI at
http://localhost:4000/api/docswhile the API is running. - Backend Guidelines: When adding new API routes to
apps/api/src/routes/, use the@openapiJSDoc annotations to document the request/response schemas. - Frontend Benefit: Frontend developers can use this UI instead of Postman to explore and test endpoints directly from the browser.
- Training data: Cloudinary photo submissions
- Task: Binary classification — real packaging vs suspicious/fake
- Target: TF Lite model running on-device (< 5MB)
- See
apps/ml/models/for model structure
- Self-hosted Whisper endpoint in FastAPI (
apps/ml/routers/voice.py) - Accept audio blob from browser MediaRecorder API
- Return transcript + detected language
- Handle all 22 Indian scheduled languages
- Knowledge base: NHP drug monographs + CDSCO guidelines (chunked + embedded)
- Vector store: pgvector in Supabase
- LLM: Sarvam AI (Indian language aware)
- Output: Triage recommendation + nearest doctor/pharmacy
- See
apps/ml/services/rag/
- LangChain agent that polls CDSCO every 6 hours
- Tools:
fetch_cdsco_alerts,lookup_medicine_db,send_district_notification - Runs as a cron job in
apps/ml/agent/ - This is the GSSoC Agents for India Track flagship feature
// ✅ Good — typed, descriptive, handles errors
async function verifyMedicine(
batchNumber: string,
): Promise<VerificationResult> {
if (!batchNumber || batchNumber.length < 4) {
throw new ValidationError("Invalid batch number");
}
// ...
}
// ❌ Bad — untyped, vague name, no error handling
async function check(b: any) {
// ...
}- Use TypeScript everywhere — no
anytypes - Use
async/awaitover.then()chains - All functions must have JSDoc comments for public APIs
- Use
zodfor all API input validation - Prefer
constoverlet, never usevar
# ✅ Good — typed hints, docstring, handles exceptions
def decode_barcode(image_bytes: bytes) -> BarcodeResult | None:
"""
Decode a barcode or QR code from raw image bytes.
Args:
image_bytes: Raw image data as bytes
Returns:
BarcodeResult with format and value, or None if no barcode found
"""
try:
# ...
except Exception as e:
logger.error(f"Barcode decode failed: {e}")
return None- Use Python type hints everywhere
- Write docstrings for all public functions
- Use
pydanticfor request/response models in FastAPI - All ML models must have evaluation metrics documented
- Use Tailwind utility classes only — no custom CSS unless unavoidable
- Mobile-first responsive design
- Test on 320px wide viewport (minimum)
- All interactive elements must have focus states
We follow Conventional Commits:
<type>(<scope>): <short description>
[optional body]
[optional footer: Closes #issue-number]
Types:
| Type | Use For |
|---|---|
feat |
New feature |
fix |
Bug fix |
docs |
Documentation only |
i18n |
Translation / language files |
style |
Code formatting, no logic change |
refactor |
Code restructure, no feature/fix |
test |
Adding or fixing tests |
chore |
Build process, dependencies |
perf |
Performance improvement |
agent |
AI agent-related changes |
Examples:
feat(scanner): add QR code support to barcode decoder
fix(map): correct pharmacy pin location offset on mobile
i18n(tamil): add complete Tamil translation for scanner UI
docs(setup): add Docker setup instructions for Windows
agent(cdsco): implement 6-hour CDSCO alert polling loop
test(api): add unit tests for medicine verification endpoint- My branch is up-to-date with
main(git pull upstream main) - I have formatted my code using Prettier (
npx prettier --write .) - All tests pass (
npm run testand/orpytest) - Lint passes (
npm run lint) - I have tested on mobile viewport (Chrome DevTools)
- I have written tests for new functionality
- I have updated documentation if needed
- My commit messages follow the Conventional Commits format
Same as commit messages:
feat(scanner): add ZXing barcode scanner component
Use the PR template (.github/PULL_REQUEST_TEMPLATE.md). Do not skip sections.
Always include:
- What you changed and why
- Screenshot/video for UI changes
Closes #issue-number
- A maintainer reviews within 24 hours
- You may get change requests — address them and re-request review
- Minimum 1 approving review required to merge
- Maintainer merges (contributors do not merge their own PRs)
- Search existing issues to avoid duplicates
- Check the Project Roadmap
Use the bug report template. Include:
- Steps to reproduce (numbered, specific)
- Expected behaviour
- Actual behaviour
- Browser + OS version
- Screenshot or screen recording if applicable
Use the feature request template. Include:
- Problem you're solving (not just the solution)
- Who benefits from this feature
- Rough implementation idea (optional)
Welcome! A few things specific to GSSoC:
Points are awarded per merged PR based on complexity:
good-first-issuePRs → lower complexity scoreintermediatePRs → medium scoreadvanced/ml/agentPRs → higher score- Cloudinary bounty PRs → bonus GSSoC leaderboard points (see Cloudinary bounty issues)
- One issue per contributor at a time — finish it before claiming another
- Do not open spam PRs (typo fixes, single character changes without an issue)
- AI-generated code is allowed only if you understand it, test it, and it works correctly
- If you use AI to generate code, disclose it in your PR description
- Check
docs/first - Ask in the
#helpchannel on our Discord - Comment on the issue with your specific question
- Do not DM maintainers for help — ask publicly so everyone benefits
| Channel | For |
|---|---|
| GitHub Issues | Bug reports, feature requests |
| GitHub Discussions | Questions, ideas, general discussion |
| Discord #help | Quick questions during development |
| Discord #introductions | Introduce yourself to the team |
Thank you for contributing to SahiDawa. You're helping protect real people from fake medicines. 🙏