AWS Builder Center
Building Oru on AWS: Gamifying Waste Management with AI and Live Collection Tracking

Building Oru on AWS: Gamifying Waste Management with AI and Live Collection Tracking

Discover how we built Oru, a platform that rewards responsible waste actions and brings neighborhoods to life through digital guardians. This deep dive explores its AWS serverless architecture, AI-assisted photo verification, secure QR workflows, live collection tracking and human review, along with the challenges and lessons behind the deployed prototype.

# Building Oru: A Gamified Waste-Action Platform on AWS
*How we connected citizen participation, photo verification, neighborhood guardians and collection tracking through a serverless architecture.*
**Live application:**  https://main.d2yv74n1dn7go4.amplifyapp.com  **Source code:**  https://github.com/Joohhnnyyy/Oru  **Track:** Waste and Energy, Environmental Hacks — WeMakeDevs × AWS
## The Problem We Wanted to Address
Responsible waste management depends on small actions repeated consistently: separating wet and dry waste, using the right collection point, handing waste to collectors and reporting overflowing bins.
These actions often happen without feedback. A resident may make an effort but never see how it contributes to the neighborhood. A collector may complete a route without a useful way to communicate their location. A municipal officer may receive complaints without a shared view of collection points, local activity and unresolved issues.
We built Oru to connect these perspectives.
Oru turns supported waste actions into Green Credits, XP and changes in a shared neighborhood world. Citizens interact with digital guardians tied to local territories, collectors share their location and confirm pickups, and municipal teams review submissions and monitor activity.
The aim is to make participation tangible while giving the underlying system enough structure to distinguish a submitted claim, an approved action and an operational event.
## The Product: Three Connected Experiences
### Citizens
Citizens can explore their neighborhood, find registered collection points, scan supported QR codes, submit photo evidence, report waste hotspots and track their rewards.
The experience connects individual progress to territory health. An approved action can improve a neighborhood’s health score, giving residents a shared reason to return.
Each territory has guardian artwork that reflects its state. For example, territories with health at or below 30 display a sad guardian variant.
This creates an emotional feedback loop, but the score has a specific meaning: it represents activity within Oru. It is not a scientifically measured environmental-quality index.
### Collectors
Collectors can display rotating QR codes for supported handovers, start and stop foreground GPS sharing, and explicitly confirm that a nearby bin has been emptied.
This last distinction matters. A truck passing a bin does not prove that a pickup happened. Oru treats location and pickup confirmation as separate events.
### Municipal Teams
Municipal users can access territory summaries, manage registered QR sources, review uncertain photo submissions and synchronize territory boundaries with Amazon Location geofences.
Human review is part of the normal workflow. Automated assessment can help process evidence, but uncertain cases still need a person to make a decision.
## Architecture at a Glance
Oru uses a React web frontend hosted on AWS Amplify Hosting, with an AWS serverless backend deployed in the Mumbai region, `ap-south-1`.
The architecture has three major paths:
1. Authenticated API requests for profiles, scans, rewards and operational actions. 2. An asynchronous photo-verification workflow. 3. A geographic tracking pipeline for trucks and territory visits.
```text CITIZENS / COLLECTORS / ADMINS | React Web Application AWS Amplify Hosting | +-------------------+-------------------+ | | Amazon Cognito Presigned Upload Authentication | | Amazon S3 | | Amazon API Gateway Amazon EventBridge JWT Authorization | | AWS Step Functions AWS Lambda | | Evaluate Submission +---------+----------+ | | | +--------+--------+ Amazon DynamoDB Amazon Location | | Profiles, rewards, Maps, trackers, Amazon Rekognition Groq Vision territories, geofences Moderation Assessment submissions | | | | +--------+--------+ Geofence Events | | Approve / Reject / Amazon EventBridge Human Review | | Lambda DynamoDB Updates | Territory Visit Records
Cross-cutting: AWS CDK | IAM | Secrets Manager | CloudWatch | Lambda Powertools ```
The current visual-assessment provider is Groq. AWS supplies the surrounding storage, moderation, orchestration, authentication and reward-processing infrastructure.
## Frontend Architecture
The deployed web application uses React, TypeScript and Vite, with React Router for navigation.
Several libraries support specific product needs:
| Tool | Purpose | |---|---| | React and TypeScript | Application UI and typed frontend logic | | Vite | Development and production builds | | React Router | Page navigation | | Tailwind CSS | Styling | | MapLibre GL JS | Rendering the interactive geographic map | | ZXing | Browser QR scanning | | i18next | Translation support | | Framer Motion | Interface animation |
The frontend connects user interactions to backend workflows. A successful button click is only the beginning: the application must also represent permissions, upload progress, pending verification, rejected evidence and completed rewards.
Photo submission is a good example. Uploading an image does not mean the action has been approved. The frontend submits the evidence, then retrieves the submission’s status while the backend processes it.
The map also has an accessible fallback. If map tiles or WebGL are unavailable, users can still access territory, bin, hotspot and truck lists.
### Hosting and Deployment
The current frontend deployment uses AWS Amplify Hosting.
The application is built locally, packaged and uploaded to the Amplify application. Git-based automatic deployments are not configured in the current deployment.
This gave us a working public HTTPS application while leaving deployment automation as a clear next improvement.
HTTPS also matters functionally: browser location access requires a secure context, apart from local development exceptions.
## Authentication and Authorization
Amazon Cognito handles authentication. The frontend sends a Cognito-issued token with requests, and API Gateway uses a JWT authorizer to validate access to protected routes.
Backend handlers then enforce permissions for the requested operation.
The roles include citizens, collectors and municipal administrators. Their permissions differ:
- Citizens can submit evidence and report supported issues. - Collectors can send truck-location updates and confirm pickups. - Administrators can manage QR sources and review submissions.
Hiding a control in the frontend does not protect its API. The backend checks the role independently.
During deployment verification, a citizen attempting a collector GPS mutation received a `403` response. That check helped confirm that the role boundary existed beyond the interface.
The web application currently keeps authentication tokens in memory. A full page reload requires signing in again. Account and API responses are excluded from service-worker caching.
## Backend Structure and Infrastructure as Code
AWS Lambda implements the backend’s individual operations, with Amazon API Gateway exposing HTTP routes.
The code is organized around responsibilities such as onboarding, scans, submissions, wallets, bins, collectors, maps and administration.
Shared packages hold request schemas, domain types and reward rules. This helps keep frontend and backend expectations aligned without duplicating business logic across clients.
Infrastructure is defined with AWS CDK in TypeScript and divided into six stacks:
| Stack | Responsibility | |---|---| | Data | DynamoDB table and photo-evidence bucket | | Auth | Cognito user pool, client and role groups | | Geo | Maps, tracker, geofences and map access | | API | HTTP API, authorizer, Lambda handlers and permissions | | Workflow | Photo evaluation and human-review state machine | | Scheduler | Scheduled territory-health updates |
These are infrastructure boundaries, not a claim that Oru needs six independent microservices. They make the resources easier to understand and deploy while keeping the application’s architecture relatively small.
CDK also makes an important review step possible: inspecting infrastructure differences before deployment.
## DynamoDB Data Model
Oru stores its application data in a DynamoDB table with a partition key, `PK`, and sort key, `SK`.
Different entity types use explicit prefixes:
| Record | Example Key Structure | |---|---| | User profile | `USER#<userId>` / `PROFILE` | | Reward ledger entry | `USER#<userId>` / `LEDGER#<timestamp>#<suffix>` | | QR source | `QR#<sourceId>` / `METADATA` | | Territory | `TERRITORY#<territoryId>` / `METADATA` | | Photo submission | `SUBMISSION#<submissionId>` / `METADATA` | | Scan cooldown | `USER#<userId>` / `COOLDOWN#<sourceId>` | | Photo fingerprint | `IMGHASH#<hash>` / `METADATA` |
This structure supports direct access to known records and groups related user records under the same partition.
Secondary indexes support additional access patterns, including submission status. TTL fields are used for temporary records such as cooldowns.
However, TTL cleanup is not the enforcement mechanism. DynamoDB may remove expired items later, so the scan handler compares the stored expiration time with the current time when deciding whether an action is allowed.
That distinction keeps application behavior independent of background cleanup timing.
## QR Verification: From Scan to Reward
A QR code is easy to photograph and share. Oru therefore checks more than whether a camera can decode it.
The scan path is:
```text Scan QR | Validate request and authenticated user | Load registered QR source | Check active status and cooldown | Verify signature or rotating token | Check location proximity | Calculate rewards | Commit ledger, balances and cooldown together | Return result to the frontend ```
### Static Collection Points
Registered bins and e-waste points use signed QR payloads.
The backend verifies the signature against the registered source and checks that the submitted location is within its allowed radius.
The current defaults differ by source type: static-bin checks use a 75-meter radius unless configured otherwise, while e-waste checks use 100 meters.
### Collector QR Codes
Collector handovers use rotating HMAC-protected tokens with short validity windows.
The backend verifies the token and checks proximity within 150 meters. It uses a recent collector location when available, with a registered-location fallback in the current implementation.
These checks reduce simple replay and remote-scanning abuse. They do not make browser GPS a trusted physical sensor or prove that a real waste handover occurred.
### Atomic Reward Updates
After verification, the backend calculates rewards and writes the related changes through a DynamoDB transaction.
The transaction includes the action ledger, user balances, cooldown and territory update. Supported collector handovers can also reward the collector.
The cooldown write has a condition, so two parallel requests cannot both receive a reward merely because they both passed an earlier read.
This is a central design principle in Oru: reward integrity belongs in the database operation as well as the request handler.
## Photo Verification: An Asynchronous Workflow
Photo assessment takes longer and has more failure modes than a normal profile request.
Oru separates uploading evidence from evaluating it:
```text Create submission | Receive presigned upload URL | Upload JPEG directly to S3 | S3 Object Created event | EventBridge rule | Step Functions execution | Evaluate submission | +-- Auto-approved --> Commit reward transaction | +-- Rejected -------> Store decision and reasoning | +-- Needs review ---> Wait for municipal decision ```
Direct S3 uploads keep image bytes out of the ordinary API request path. The browser receives a presigned URL rather than AWS credentials.
The proof bucket blocks public access, requires encrypted transport and applies a 90-day object-expiration lifecycle in the current configuration.
### Stage 1: Validate the Submission
The evaluator loads the submission and checks its state.
It also checks the object size against a 5 MB limit and reads the uploaded image.
A submission that has already been evaluated is recognized before normal processing begins. Conditional writes provide another layer of protection against repeated state changes.
### Stage 2: Detect Exact Duplicate Images
The evaluator computes a SHA-256 fingerprint of the image bytes and conditionally records it.
An existing fingerprint causes the new submission to be rejected as an exact duplicate.
This is deliberately limited. Re-encoding, cropping or otherwise changing an image can produce a different fingerprint. Exact-byte matching is useful protection, but it is not perceptual duplicate detection.
### Stage 3: Screen with Amazon Rekognition
Amazon Rekognition checks moderation labels and extracts image labels.
Images with moderation flags are rejected by the current policy. If screening is unavailable, the submission goes to human review.
An unavailable dependency therefore does not automatically become an approved action.
### Stage 4: Assess Visible Evidence
The evaluator sends the image and a bounded prompt to Groq for visual assessment.
The current deployed model identifier is configured as `qwen/qwen3.8-27b`. Its credential is retrieved on the server from AWS Secrets Manager.
The prompt asks the model to assess visible evidence relevant to the claimed action. It explicitly discourages guessing geography, ownership or internet origin from visual style.
That wording came from a practical lesson: an image can support the presence of separated waste without proving who separated it, where it happened or whether the uploader owns the image.
The response must contain a valid boolean decision, a score between zero and one, and nonempty reasoning. Incomplete or malformed responses are routed to review.
### Stage 5: Apply Decision Rules
The current evaluator uses these rules:
| Result | Action | |---|---| | Negative evidence decision or score below `0.35` | Reject | | Positive decision with score from `0.35` to below `0.75` | Human review | | Positive decision with score at least `0.75` | Eligible for automatic approval | | Automatic daily approval cap reached | Human review | | Screening or assessment unavailable | Human review |
The score is a model-generated signal. It is not a calibrated probability that a real-world action happened.
Automatic approval is currently capped at three photos per user per application day. This limits automated reward exposure while preserving a review route.
### Stage 6: Commit Rewards
An automatic approval uses a transaction to update the submission, daily counter, user balance, ledger and territory activity.
The submission’s expected state is part of the transaction condition. This helps prevent a repeated workflow invocation from independently awarding the same submission again.
Transient AI requests use retry handling, but retries are only part of resilience. The state checks and database conditions are what protect reward writes.
## Human Review with Step Functions
Flagged evidence enters a Step Functions task-token wait state.
A Lambda function stores the callback token against the submission. When a municipal reviewer resolves the case, the backend uses the callback mechanism to resume the waiting workflow.
The review task has a seven-day timeout, and the state machine has an eight-day overall timeout.
This avoids keeping a Lambda function running while waiting for a person. The workflow can pause while its state remains visible.
Oru also distinguishes a rejected claim from a broken workflow: rejection ends in a successful terminal state because the system completed its evaluation. Infrastructure failure and an unfavorable product decision are different outcomes.
## Geographic Architecture
Oru uses H3 cells to organize neighborhoods into territories.
H3 provides geographic cell boundaries and identifiers. Amazon Location provides the base map, tracker and geofence capabilities, while MapLibre renders the map in the browser.
The map combines several independently refreshed layers:
| Layer | Source | Current Refresh Behavior | |---|---|---| | Territories and guardians | Map API and DynamoDB | Approximately two minutes | | Collection points and estimated fill | Registered QR-source records | Approximately two minutes | | Truck positions | Live-truck API | Approximately 15 seconds | | Selected truck trail | Amazon Location history | Loaded on selection | | Base map | Amazon Location Maps API v2 | Requested as needed |
Different refresh rates avoid treating every map layer as equally dynamic.
## Truck Tracking and Territory Visits
A collector explicitly starts location sharing in the web application.
While the collector page remains open and permissions are available, it sends GPS updates approximately every ten seconds.
```text Collector browser GPS | POST /v1/collector/location | Lambda validates role and request | +--> DynamoDB latest truck position | +--> Amazon Location Tracker | Linked geofence collection | ENTER / EXIT event | EventBridge | Geofence-event Lambda | Territory visit records ```
DynamoDB supports the application’s latest-position view. Amazon Location maintains tracking history and evaluates positions against linked geofences.
Administrators can synchronize H3 territory boundaries into the geofence collection. This connects the game’s neighborhood units to operational location events.
Current browser tracking is foreground-only. It depends on an open page, HTTPS, location permission and device connectivity. Reliable unattended tracking would need a different operational setup, such as a native background-location implementation or dedicated hardware.
## Bin Status: Estimates and Confirmations
Oru currently has no physical bin-fill sensors.
The system estimates fill using elapsed time since pickup, including a configured increase of approximately 2.5 percentage points per hour. A citizen’s full-bin report can mark the estimate as full.
A nearby collector must explicitly confirm pickup to reset it. Damage remains recorded until a repair is confirmed.
The reporting APIs also apply proximity and rate checks. Citizen reports require a location within 300 meters, and pickup confirmations require a collector within 100 meters.
These controls make reports more useful, but the resulting status still needs to be
Any opinions in this article are those of the individual author and may not reflect the opinions of AWS.
Enjoyed reading this content? Let the author know!

Your likes, comments, shares, and saves help creators reach more builders.

Loading recommendations

Loading article