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
# 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 8000Each 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/
- 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. 🙏