"Dunzo for skilled workers" β Find a verified plumber, electrician, or carpenter in under 5 minutes.
Built for India's 500M+ blue-collar workforce with smartphones but no digital presence.
Flutter App (Android/iOS)
β
β REST API + WebSocket
βΌ
Spring Boot Backend (Java 17)
β
βββ PostgreSQL (all data β users, jobs, otps)
βββ Redis (worker availability cache by pincode)
shramiklink/
βββ backend/ β Spring Boot API
β βββ src/main/java/com/shramiklink/
β β βββ controller/ β HTTP endpoints (REST API)
β β βββ service/ β Business logic
β β βββ entity/ β Database tables (JPA)
β β βββ repository/ β Database queries
β β βββ security/ β JWT auth filter
β β βββ config/ β Redis, WebSocket, Security config
β β βββ dto/ β API request/response shapes
β β βββ enums/ β Skill types, job status, etc.
β βββ Dockerfile
β βββ pom.xml
β
βββ flutter_app/ β Flutter mobile app
β βββ lib/
β β βββ main.dart β App entry point
β β βββ models/ β Data classes (Worker, Job, etc.)
β β βββ services/ β API calls (http package)
β β βββ providers/ β State management (Riverpod)
β β βββ screens/
β β β βββ auth/ β Login, OTP screens
β β β βββ worker/ β Worker dashboard, profile setup
β β β βββ employer/ β Home, search, booking screens
β β β βββ shared/ β Job detail screen
β β βββ utils/ β Constants, theme, router
β βββ pubspec.yaml
β
βββ docker-compose.yml β Runs backend + postgres + redis together
βββ .github/workflows/ β CI/CD (auto test + deploy)
- Java 17+
- Flutter 3.16+
- Docker + Docker Compose
- Android Studio or VS Code
# From the root shramiklink/ folder
docker-compose up --buildThis starts:
- PostgreSQL on port 5432
- Redis on port 6379
- Spring Boot API on port 8080
Verify it's running:
curl http://localhost:8080/api/auth/health
# β {"status":"UP","service":"ShramikLink"}cd flutter_app
flutter pub get
flutter run
β οΈ For Android emulator, the API URL10.0.2.2:8080automatically points to your computer's localhost. For a real device, updateapiBaseUrlinlib/utils/app_constants.dartto your computer's IP.
All protected routes require: Authorization: Bearer <token>
| Method | Endpoint | Body | Description |
|---|---|---|---|
| POST | /api/auth/send-otp |
{"phone":"9876543210"} |
Send OTP |
| POST | /api/auth/verify-otp |
{"phone":"...","otp":"123456","role":"WORKER"} |
Verify OTP β JWT |
| Method | Endpoint | Description |
|---|---|---|
| PUT | /api/workers/profile |
Update worker profile |
| GET | /api/workers/{id} |
View worker profile |
| PATCH | /api/workers/availability?status=AVAILABLE_NOW |
Toggle availability |
| GET | /api/workers/search?skill=PLUMBER&pincode=201001 |
Search workers |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/jobs |
Create booking |
| PATCH | /api/jobs/{id}/status?status=ACCEPTED |
Accept/complete job |
| POST | /api/jobs/{id}/rate |
Rate worker |
| GET | /api/jobs/worker |
Worker's job history |
| GET | /api/jobs/employer |
Employer's job history |
- Employers search "show me plumbers in 201001" thousands of times a day
- Going to PostgreSQL every time = slow + expensive
- Redis caches the result for 5 minutes in RAM = 10x faster
- When a worker changes status β
@CacheEvictclears that pincode's cache
- Without it: Flutter app must ask "any new jobs?" every 5 seconds = wasteful
- With it: Server pushes "new job!" the instant it happens = efficient + instant
- Workers get notified in real-time via STOMP over WebSocket
- Mobile apps can't use browser cookies
- JWT is a signed token stored on device β server verifies the signature without DB lookup
- Stateless = works across multiple server instances (horizontal scaling)
- Most workers don't remember complex passwords
- Phone number is the universal Indian identity β everyone knows their number
- Reduces support burden (no "forgot password" flow needed)
The 5% platform fee is calculated automatically in JobService.java:
BigDecimal platformFee = totalAmount.multiply(new BigDecimal("0.05"));| Metric | Numbers |
|---|---|
| 500 bookings/month | βΉ50,000+ revenue |
| βΉ99 per booking | Tier 1 city pricing |
| βΉ299/month worker subscription | Premium listing |
DATABASE_URL=jdbc:postgresql://your-db-host:5432/shramiklink
DB_USERNAME=shramiklink
DB_PASSWORD=<strong-password>
REDIS_HOST=your-redis-host
JWT_SECRET=<256-bit-random-string>
OTP_MOCK=false# On your server
git clone your-repo && cd shramiklink
docker-compose up -dPush to main branch β GitHub Actions automatically:
- Runs backend tests
- Builds Flutter APK
- Deploys new Docker image to your server
Add these GitHub Secrets: SERVER_HOST, SSH_PRIVATE_KEY
In application.properties, set app.otp.mock-enabled=false
Then in OtpService.java, implement:
// Fast2SMS (cheapest for India, βΉ0.15 per SMS)
// API: https://fast2sms.com/dev/bulk
private void sendSmsViaFast2SMS(String phone, String otp) {
// HTTP POST to Fast2SMS API
}- Visit 5 housing societies personally
- Onboard their regular plumbers/electricians
- Show employers the app β "find your usual guy here"
- 20 workers + 10 employers = first real traction
- Word of mouth β 5 housing societies β 50
Zero marketing budget. Zero travel. One city.