{"id":26045186,"url":"https://github.com/simran1002/refer-loop","last_synced_at":"2026-04-10T22:49:22.506Z","repository":{"id":279822669,"uuid":"940077778","full_name":"simran1002/refer-loop","owner":"simran1002","description":null,"archived":false,"fork":false,"pushed_at":"2025-02-27T18:45:50.000Z","size":215,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-07T19:36:40.796Z","etag":null,"topics":["fastapi","nodemailer","postgresql","python","rate-limiter","smtp"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simran1002.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-02-27T15:23:08.000Z","updated_at":"2025-02-27T18:49:54.000Z","dependencies_parsed_at":"2025-02-27T23:07:18.551Z","dependency_job_id":"f38d0d94-34c6-4c2e-87f0-03b1557d7b72","html_url":"https://github.com/simran1002/refer-loop","commit_stats":null,"previous_names":["simran1002/refer-loop"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/simran1002/refer-loop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simran1002%2Frefer-loop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simran1002%2Frefer-loop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simran1002%2Frefer-loop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simran1002%2Frefer-loop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simran1002","download_url":"https://codeload.github.com/simran1002/refer-loop/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simran1002%2Frefer-loop/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262601311,"owners_count":23335234,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fastapi","nodemailer","postgresql","python","rate-limiter","smtp"],"created_at":"2025-03-07T19:32:36.384Z","updated_at":"2026-04-10T22:49:22.481Z","avatar_url":"https://github.com/simran1002.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/FastAPI-009688?style=for-the-badge\u0026logo=fastapi\u0026logoColor=white\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Next.js_14-000000?style=for-the-badge\u0026logo=nextdotjs\u0026logoColor=white\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/PostgreSQL-4169E1?style=for-the-badge\u0026logo=postgresql\u0026logoColor=white\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Redis-DC382D?style=for-the-badge\u0026logo=redis\u0026logoColor=white\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Celery-37814A?style=for-the-badge\u0026logo=celery\u0026logoColor=white\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Docker-2496ED?style=for-the-badge\u0026logo=docker\u0026logoColor=white\" /\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Tailwind_CSS-06B6D4?style=for-the-badge\u0026logo=tailwindcss\u0026logoColor=white\" /\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eReferease\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\u003cstrong\u003eA production-ready SaaS Referral Engine with multi-tiered rewards, real-time updates, fraud detection, and background task processing.\u003c/strong\u003e\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#screenshots\"\u003eScreenshots\u003c/a\u003e \u0026bull;\n  \u003ca href=\"#features\"\u003eFeatures\u003c/a\u003e \u0026bull;\n  \u003ca href=\"#architecture\"\u003eArchitecture\u003c/a\u003e \u0026bull;\n  \u003ca href=\"#quick-start\"\u003eQuick Start\u003c/a\u003e \u0026bull;\n  \u003ca href=\"#api-reference\"\u003eAPI Reference\u003c/a\u003e \u0026bull;\n  \u003ca href=\"#project-structure\"\u003eProject Structure\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## Screenshots\n\n### Login \u0026 Registration\n\u003cimg src=\"screenshots/login.png\" alt=\"Login Page\" width=\"100%\" /\u003e\n\n### Dashboard\n\u003cimg src=\"screenshots/dashboard.png\" alt=\"Dashboard\" width=\"100%\" /\u003e\n\n### Leaderboard\n\u003cimg src=\"screenshots/leaderboard.png\" alt=\"Leaderboard\" width=\"100%\" /\u003e\n\n### Rewards Store\n\u003cimg src=\"screenshots/rewards.png\" alt=\"Rewards Store\" width=\"100%\" /\u003e\n\n### How It Works\n\u003cimg src=\"screenshots/how-it-works.png\" alt=\"How It Works\" width=\"100%\" /\u003e\n\n### Profile \u0026 Settings\n\u003cimg src=\"screenshots/profile.png\" alt=\"Profile\" width=\"100%\" /\u003e\n\n---\n\n## Features\n\n### Multi-Tiered Reward System\n| Tier | Threshold | Reward Rate | Tier Bonus |\n|------|-----------|-------------|------------|\n| Bronze | 0 – 9 referrals | 10 pts/referral | — |\n| Silver | 10 – 49 referrals | 15 pts/referral | +100 pts |\n| Gold | 50+ referrals | 25 pts/referral | +500 pts |\n\n**Points Formula:** `Total Points = (Referrals × Reward Rate) + Tier Bonus`\n\n### Fraud Detection Engine\n- **IP Rate Limiting** — Blocks excessive sign-ups from the same IP address (configurable threshold)\n- **Fuzzy Email Matching** — Uses `difflib.SequenceMatcher` to detect near-duplicate email addresses (e.g., `john@gmail.com` vs `j0hn@gmail.com`)\n- **Self-Referral Prevention** — Fuzzy-matches the referrer's email against the new user's email\n- **Audit Logging** — All flagged attempts are persisted to `fraud_logs` for review\n\n### Real-Time Updates (WebSockets)\n- Live dashboard updates when referrals are processed\n- Heartbeat mechanism to keep connections alive\n- Auto-reconnect with exponential backoff on the frontend\n\n### Background Task Processing (Celery + Redis)\n- **Welcome Email** — Triggered on every new registration\n- **Milestone Email** — Triggered when a referrer gains a new referral\n- Retry logic with configurable max retries and delays\n- Redis as both message broker and result backend\n\n### Frontend (Next.js 14 App Router)\n- **6 dedicated pages** — Dashboard, Leaderboard, Rewards, How It Works, Profile, Login\n- **Sidebar navigation** with active page highlighting\n- **Dark mode** toggle with OS preference detection and localStorage persistence\n- **Confetti animation** on tier upgrades\n- **Tier celebration modal** with auto-dismiss\n- **Social sharing** — Twitter/X, WhatsApp, LinkedIn, Email\n- **Responsive design** — Sidebar collapses to hamburger menu on mobile\n- **QR code** for referral link sharing\n\n### Security\n- **JWT via HttpOnly Cookies** — Tokens are never exposed to JavaScript\n- **Password validation** — Min 8 chars, uppercase, lowercase, digit, special character\n- **bcrypt hashing** — Passwords hashed with industry-standard bcrypt\n- **CORS** — Configurable allowed origins\n\n---\n\n## Architecture\n\n```\n┌──────────────┐     ┌──────────────┐     ┌──────────────┐\n│   Next.js    │────▶│   FastAPI    │────▶│  PostgreSQL  │\n│   Frontend   │◀────│   Backend    │◀────│   Database   │\n│  (Port 3001) │     │  (Port 8000) │     │ (Port 55432) │\n└──────────────┘     └──────┬───────┘     └──────────────┘\n                            │\n                    ┌───────┼───────┐\n                    ▼       ▼       ▼\n              ┌─────────┐ ┌───┐ ┌──────────────┐\n              │ Celery  │ │WS │ │  Fraud       │\n              │ Worker  │ │   │ │  Detection   │\n              └────┬────┘ └───┘ └──────────────┘\n                   │\n              ┌────▼────┐\n              │  Redis  │\n              │  Broker │\n              │(Port 56379)│\n              └─────────┘\n```\n\n**Clean Architecture layers:**\n- `models/` — SQLAlchemy ORM entities\n- `schemas/` — Pydantic validation \u0026 serialization\n- `repositories/` — Data access layer (async queries)\n- `services/` — Business logic (fraud detection, tier calculation)\n- `usecases/` — Application use cases (register user, get stats)\n- `api/routes/` — HTTP endpoint handlers\n- `api/websockets/` — WebSocket endpoint handlers\n- `tasks/` — Celery background tasks\n\n---\n\n## Quick Start\n\n### Prerequisites\n- Docker \u0026 Docker Compose\n- Git\n\n### 1. Clone the repository\n```bash\ngit clone https://github.com/simran1002/refer-loop.git\ncd refer-loop\n```\n\n### 2. Start all services\n```bash\ndocker-compose up --build -d\n```\n\nThis spins up 5 containers:\n| Service | Internal Port | Host Port |\n|---------|--------------|-----------|\n| FastAPI Backend | 8000 | 8000 |\n| PostgreSQL | 5432 | 55432 |\n| Redis | 6379 | 56379 |\n| Celery Worker | — | — |\n| Next.js Frontend | 3000 | 3001 |\n\n### 3. Open the app\n- **Frontend:** http://localhost:3001\n- **API Docs (Swagger):** http://localhost:8000/docs\n- **Health Check:** http://localhost:8000/health\n\n### 4. Test the referral flow\n```bash\n# 1. Register a referrer\ncurl -s -X POST http://localhost:8000/auth/register \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"username\":\"alice\",\"email\":\"alice@example.com\",\"password\":\"StrongPass1!\"}' | python3 -m json.tool\n\n# 2. Note the referral_code from the response, then register a referred user\ncurl -s -X POST http://localhost:8000/auth/register \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"username\":\"bob\",\"email\":\"bob@different.com\",\"password\":\"StrongPass1!\",\"referral_code\":\"ALICE_CODE_HERE\"}'\n```\n\n---\n\n## API Reference\n\n### Authentication\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| POST | `/auth/register` | Register a new user (with optional referral code) |\n| POST | `/auth/login` | Login and receive HttpOnly JWT cookie |\n| POST | `/auth/logout` | Clear the auth cookie |\n| GET | `/auth/me` | Get current user profile |\n\n### Referral System\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| GET | `/referral/stats` | Dashboard stats (tier, points, rank, recent referrals) |\n| GET | `/referral/leaderboard` | Top referrers ranked by points |\n\n### Password Management\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| POST | `/password/forgot-password` | Request password reset token |\n| POST | `/password/reset-password` | Reset password with token |\n\n### System\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| GET | `/health` | Health check |\n| WS | `/ws/stats/{user_id}` | Real-time referral updates |\n\n---\n\n## Project Structure\n\n```\nrefer-loop/\n├── backend/\n│   ├── app/\n│   │   ├── api/\n│   │   │   ├── dependencies/     # Auth dependency (JWT cookie extraction)\n│   │   │   ├── routes/           # HTTP endpoints (auth, referral, leaderboard, profile, password, health)\n│   │   │   └── websockets/       # WebSocket endpoint for live stats\n│   │   ├── core/\n│   │   │   ├── config.py         # Pydantic settings (env-based)\n│   │   │   ├── database.py       # Async SQLAlchemy engine \u0026 session\n│   │   │   ├── events.py         # In-process EventBus for WebSocket pub/sub\n│   │   │   └── security.py       # JWT, bcrypt, referral code generation\n│   │   ├── models/               # SQLAlchemy ORM models (User, Referral, FraudLog)\n│   │   ├── repositories/         # Data access layer (async queries)\n│   │   ├── schemas/              # Pydantic request/response schemas\n│   │   ├── services/             # Business logic (fraud detection, tier engine)\n│   │   ├── tasks/                # Celery tasks (welcome email, milestone email)\n│   │   ├── usecases/             # Application use cases\n│   │   └── main.py               # FastAPI app entrypoint\n│   ├── Dockerfile\n│   └── requirements.txt\n├── frontend/\n│   ├── app/\n│   │   ├── components/           # Reusable UI components\n│   │   │   ├── AppShell.tsx      # Sidebar layout shell\n│   │   │   ├── AuthForm.tsx      # Login/Register form\n│   │   │   ├── Confetti.tsx      # Confetti particle animation\n│   │   │   ├── Leaderboard.tsx   # Leaderboard table\n│   │   │   ├── LiveFeed.tsx      # Real-time referral feed\n│   │   │   ├── ProgressBar.tsx   # Tier progress bar with shimmer\n│   │   │   ├── ShareSection.tsx  # Referral link + social sharing\n│   │   │   ├── StatsCards.tsx    # Metric cards with gradients\n│   │   │   ├── TierBadge.tsx     # Tier indicator badge\n│   │   │   └── TierCelebration.tsx # Tier upgrade modal\n│   │   ├── hooks/                # Custom React hooks\n│   │   │   ├── useAuth.ts        # Authentication state\n│   │   │   ├── useTheme.ts       # Dark mode toggle\n│   │   │   └── useWebSocket.ts   # WebSocket connection manager\n│   │   ├── dashboard/page.tsx    # Dashboard page\n│   │   ├── leaderboard/page.tsx  # Leaderboard page\n│   │   ├── rewards/page.tsx      # Rewards store page\n│   │   ├── how-it-works/page.tsx # Guide \u0026 FAQ page\n│   │   ├── profile/page.tsx      # Profile \u0026 settings page\n│   │   └── page.tsx              # Root (auth redirect)\n│   ├── Dockerfile\n│   └── package.json\n├── docker-compose.yml\n├── screenshots/                  # README screenshots\n└── README.md\n```\n\n---\n\n## Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `DATABASE_URL` | `postgresql+asyncpg://...` | Async PostgreSQL connection string |\n| `REDIS_URL` | `redis://localhost:6379/0` | Redis connection |\n| `SECRET_KEY` | `change-me-...` | JWT signing secret |\n| `CORS_ORIGINS` | `[\"http://localhost:3001\"]` | Allowed CORS origins |\n| `TIER_SILVER_THRESHOLD` | `10` | Referrals needed for Silver |\n| `TIER_GOLD_THRESHOLD` | `50` | Referrals needed for Gold |\n| `MAX_SIGNUPS_PER_IP` | `5` | Fraud: max sign-ups per IP |\n| `FUZZY_EMAIL_THRESHOLD` | `0.85` | Fraud: email similarity threshold |\n\nSee `backend/app/core/config.py` for all configurable settings.\n\n---\n\n## Tech Stack\n\n| Layer | Technology |\n|-------|-----------|\n| Backend API | FastAPI (Python 3.12, async) |\n| Database | PostgreSQL 16 + SQLAlchemy 2.0 (async) |\n| Cache / Broker | Redis 7 |\n| Background Tasks | Celery 5 |\n| Frontend | Next.js 14 (App Router) + React 18 |\n| Styling | Tailwind CSS 3 |\n| Real-time | WebSockets (native) |\n| Auth | JWT (HttpOnly cookies) + bcrypt |\n| Containerization | Docker + Docker Compose |\n\n---\n\n## Author\n\n**Simran Yadav**\n- GitHub: [@simran1002](https://github.com/simran1002)\n- Email: simranyadav464@gmail.com\n\n---\n\n\u003cp align=\"center\"\u003e\n  Built with FastAPI, Next.js, Celery \u0026 Redis\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimran1002%2Frefer-loop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimran1002%2Frefer-loop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimran1002%2Frefer-loop/lists"}