Sathsara K.
  • Home
  • About
  • Projects
  • Case Studies
  • Blog
  • Contact
Hire me
  • Home
  • About
  • Projects
  • Case Studies
  • Blog
  • Contact
Sathsara K.
© 2026 Sathsara. Built with intent.
Back to Blog
Smart Cycle
ReactJune 30, 202615 min read

Smart Cycle

View GitHub Repository
#React#Vite#TailwindCSS#React Router#Axios#React Toastify#Lucide React#ESLint

Smart Cycle is a modern, responsive frontend for an intelligent waste management and recycling system. Built with React and Vite, it provides intuitive interfaces for Residents, Drivers, Personnel, and Admins to manage schedules, donations, and recycling operations efficiently.

Table of Contents

  • • Introduction: Why This Project Is Harder Than It Looks
  • • Why Role-Based Architecture Is a Core Design Decision
  • • Frontend: A Unified React Application with Role-Aware Routing
  • ↳ Key Frontend Technologies
  • ↳ API Communication Layer
  • • Backend: Spring Boot as the Domain Authority
  • ↳ Responsibilities by Layer
  • • Designing Around Real-World Workflows, Not CRUD
  • • Authentication and Authorization Model
  • ↳ Authentication Flow
  • ↳ Security Design Principles
  • • Domain Model: Waste Management as a Workflow System
  • • API Design: Contracts Between Frontend and Backend
  • ↳ Why DTOs Matter
  • • Real-Time Feedback Without Real-Time Complexity
  • • Styling and UI System
  • • Why Vite for Frontend Performance
  • • Backend Architecture: Why Layered Design Works Here
  • ↳ Why Not Microservices?
  • • Key Backend Technologies
  • • Database Design Overview
  • • Testing Strategy
  • • Full-Stack Integration Philosophy
  • ↳ Frontend Responsibilities
  • ↳ Backend Responsibilities
  • • What This System Represents
  • • Conclusion

Smart Cycle: Engineering a Role-Based Full-Stack Waste Management Platform

Introduction: Why This Project Is Harder Than It Looks

On the surface, a waste management platform might sound like a simple booking-and-tracking app. In reality, it is one of the more demanding categories of software to design well, because it isn't built around a single type of user performing a single type of action. It's built around four different actors, residents, drivers, recycling center operators, and administrators, who all touch the same underlying data, but need entirely different tools, permissions, and views to do their jobs.

This is the core problem Smart Cycle was built to solve: how do you design one coherent system that serves four very different workflows without turning into either four disconnected apps or one tangled mess of conditional logic?

The answer combines a React-based, role-driven frontend with a Spring Boot backend that owns all business rules, security enforcement, and workflow orchestration. Rather than treating the frontend and backend as loosely related pieces that happen to talk over HTTP, Smart Cycle treats them as two halves of a single operational system, each with clearly defined responsibilities, but tightly coordinated through a strict API contract.

Why Role-Based Architecture Is a Core Design Decision

Most systems that need to serve multiple types of users take one of two paths: build separate applications per user type, or build one application riddled with if (user.role === 'admin') checks scattered across the codebase. Both approaches tend to rot over time, separate apps duplicate effort and drift apart, while heavily branched UI logic becomes a maintenance nightmare as the number of roles grows.

Smart Cycle instead adopts role-aware routing, permissions, and workflows inside a single, unified system.

The four supported roles are:

  • Resident, requests pickups, tracks collection status, manages payments and rebates
  • Driver, views assigned routes, executes collections, updates completion status
  • Recycling Center Operator, manages intake, processing, and rebate calculations
  • Administrator, schedules resources, assigns drivers, oversees the entire operational pipeline
  • All four roles authenticate against the same backend and consume the same underlying services, but each is routed to a dashboard and set of capabilities tailored specifically to their responsibilities. Shared concerns like authentication, notifications, and profile management are implemented exactly once, while dashboards render conditionally based on the authenticated user's identity and permissions.

    The payoff of this design is consistency. A bug fix in the authentication flow benefits every role simultaneously. A new notification type doesn't need to be re-implemented four times. And because everything runs through the same codebase, there's a single source of truth for how the system behaves.

    Frontend: A Unified React Application with Role-Aware Routing

    The frontend is a single React application, not four separate ones. This is made possible by structuring routing around role-based route resolution rather than duplicating pages or apps per user type.

    In practice, this means:

  • Role-based route guards, routes check the authenticated user's role before rendering, redirecting unauthorized users away from views they shouldn't access
  • Conditional dashboard rendering, the same routing layer renders a completely different dashboard component depending on whether the logged-in user is a resident, driver, operator, or admin
  • A shared UI component library, buttons, forms, cards, modals, and layout primitives are built once and reused everywhere, so visual consistency doesn't depend on four teams (or four codebases) staying in sync
  • Key Frontend Technologies

  • React 19, the core UI library, providing the component model the entire frontend is built on
  • React Router DOM, handles client-side routing and is where the role-based route guards live
  • TailwindCSS, a utility-first CSS framework used for consistent, fast styling across every dashboard
  • Axios, the HTTP client used for all communication with the Spring Boot backend
  • React Toastify, provides lightweight, non-blocking notifications for user actions (success messages, errors, warnings)
  • Lucide React, a lightweight icon library used throughout the interface
  • Vite, the build tool and development server
  • API Communication Layer

    Rather than scattering fetch or axios calls throughout individual components, Smart Cycle centralizes all API communication through Axios, configured with interceptors. This centralization handles three concerns consistently across the entire application:

    1. Attaching authentication tokens to outgoing requests automatically, so individual components never need to manually manage auth headers

    2. Handling unauthorized responses globally, if a request comes back with a 401, the interceptor can redirect to login or refresh the session in one place, rather than requiring every component to handle this case independently

    3. Standardizing error handling, API errors are caught and formatted consistently, so error messages shown to the user (via React Toastify) follow a predictable pattern

    This keeps networking logic out of UI components entirely. Components focus purely on rendering and user interaction; the Axios layer handles everything related to talking to the server.

    Backend: Spring Boot as the Domain Authority

    If the frontend is responsible for usability, the backend is responsible for correctness. This is a deliberate split: the frontend controls what users can see, but the backend controls what users can do. No business rule is ever trusted to the client, everything that matters is re-validated and enforced server-side.

    The backend follows a classic layered architecture:

    Controllers → Services → Repositories → Database

    Responsibilities by Layer

  • Controllers, the entry point for HTTP requests. Their job is narrow: parse the incoming request, delegate to the appropriate service, and shape the response. They contain no business logic themselves.
  • Services, this is where the actual business rules and workflow logic live. Whether a pickup request can be cancelled, whether a driver can be reassigned, how a rebate is calculated, all of this logic sits in the service layer.
  • Repositories, handle all database access, built on top of Spring Data JPA. They abstract away raw SQL and give services a clean, object-oriented way to persist and query data.
  • Entities, the domain models that map directly to database tables (Users, CollectionRequest, Vehicle, etc.)
  • This layering matters because it decouples business logic from both the UI and the persistence mechanism. If the database technology changed, or the frontend framework changed, the service layer, which encodes the actual rules of how waste management operations work, would remain untouched.

    Designing Around Real-World Workflows, Not CRUD

    A generic backend for this kind of system might expose endpoints like createCollectionRequest, updateRequest, and deleteRequest. Smart Cycle deliberately avoids this pattern.

    Instead, the API surface is designed around the real-world actions that actually happen in a waste management operation:

  • Request a pickup
  • Cancel a request
  • Assign a driver
  • Complete a collection
  • Process payment
  • This distinction matters more than it might initially seem. A generic updateRequest endpoint tells you nothing about what changed or whether that change was even valid, it's just a database write with a fancy name. An assignDriver endpoint, on the other hand, can enforce exactly the rules that should apply to that specific action: is the driver available, is the request in a state where assignment makes sense, does the person making the request have permission to assign drivers?

    In other words, a collection request isn't just a row in a table, it's a workflow that moves through a defined sequence of states, and the API is designed to reflect that reality rather than hide it behind generic CRUD verbs.

    Authentication and Authorization Model

    Security in Smart Cycle is handled through JWT-based authentication with Spring Security.

    Authentication Flow

    1. A user registers or logs in

    2. The backend validates credentials and issues a JWT

    3. That token is stored in an HTTP-only cookie (not local storage, which is more vulnerable to XSS-based token theft)

    4. Every subsequent request passes through Spring Security filters, which validate the token before the request is allowed to reach a controller

    Security Design Principles

  • Passwords hashed using BCrypt, passwords are never stored in plaintext or in a reversible format
  • Role-based access control (RBAC), permissions are tied directly to the four defined roles, and enforced at the backend regardless of what the frontend displays
  • HTTP-only cookie storage for tokens, reduces the attack surface for client-side token theft
  • Centralized security configuration, authentication and authorization rules live in one place rather than being duplicated across controllers
  • Global exception handling for unauthorized access, unauthorized or unauthenticated requests are caught and handled consistently, rather than leaking inconsistent error formats
  • Domain Model: Waste Management as a Workflow System

    Rather than modeling the system as a static set of database tables, Smart Cycle models it as a sequence of state transitions:

    1. A resident creates a pickup request

    2. An admin schedules the request and assigns resources

    3. A driver executes the collection

    4. The system records completion

    5. Payment and rebate processing occurs

    This workflow-first mindset shapes the core entities:

  • Users (Resident, Driver, Admin)
  • CollectionRequest
  • CollectionSchedule
  • Vehicle
  • Payment
  • RecyclingRebate
  • WasteBin
  • Route
  • Each entity is designed as a participant in this broader operational sequence rather than an isolated record. A CollectionRequest, for example, isn't just a static row, it carries a status that reflects exactly where it sits in the pickup-to-payment lifecycle.

    API Design: Contracts Between Frontend and Backend

    Smart Cycle uses DTOs (Data Transfer Objects) as a strict boundary between the frontend and backend, rather than exposing raw JPA entities directly through the API.

    Why DTOs Matter

  • Prevents frontend dependency on database structure, if a database column is renamed or restructured, the frontend doesn't need to know or care, as long as the DTO contract stays stable
  • Allows backend refactoring without breaking clients, internal entity changes can happen freely as long as the DTO shape is preserved
  • Enables role-specific response shaping, a resident and an admin querying the same underlying CollectionRequest can receive different fields depending on what's relevant (and permitted) for their role
  • Keeps entities internal to the system, database structure is treated as an implementation detail, not a public interface
  • This means React components consume exactly the data they need, nothing more, nothing less, rather than being handed an entire domain model and having to figure out which fields matter.

    Real-Time Feedback Without Real-Time Complexity

    It would be easy to reach for WebSockets or an event-streaming system to make Smart Cycle feel responsive. Instead, the project makes a deliberate trade-off toward simplicity:

  • React Toastify handles immediate feedback for user-triggered actions (e.g., "Pickup request submitted")
  • Status polling is used to keep request statuses reasonably up to date without maintaining persistent socket connections
  • API responses provide immediate state confirmation, so the UI can update optimistically based on what the backend just confirmed
  • This keeps the system's operational complexity low while still giving users a responsive experience. Real-time infrastructure like WebSockets is powerful, but it also introduces connection management, scaling considerations, and failure modes that aren't justified at this stage of the system's scale.

    Styling and UI System

    The interface is built with TailwindCSS, using a utility-first approach rather than hand-written custom CSS per component.

    This choice provides:

  • Consistent styling across all four role-based dashboards, since utility classes enforce a shared design vocabulary
  • Faster iteration speed, styling changes happen directly in markup without context-switching to separate CSS files
  • Reduced CSS maintenance overhead, there's no sprawling stylesheet to manage or accidentally break
  • Strong design consistency across components built by potentially different contributors over time
  • Lucide React supplies a lightweight, consistent icon set, keeping the visual language coherent without adding meaningful bundle size or performance overhead.

    Why Vite for Frontend Performance

    Vite was chosen as the build tool and dev server for a few concrete reasons:

  • Instant development server startup, since Vite doesn't bundle the entire app before serving it in development
  • Fast hot module replacement (HMR), so changes to a component are reflected almost immediately in the browser
  • Efficient ES module-based bundling for production builds
  • Smooth scaling across multiple dashboards, as Smart Cycle has four distinct role-based interfaces (each with its own set of pages and components), development speed has a direct, compounding effect on how quickly features can be built and tested
  • Backend Architecture: Why Layered Design Works Here

    Microservices are often treated as the default choice for "serious" or "scalable" backend systems. Smart Cycle deliberately avoids that path in favor of a modular monolith.

    Why Not Microservices?

  • The domain is tightly connected, pickup requests, scheduling, driver assignment, and payments are deeply interrelated; splitting them into separate services would mean constant cross-service communication for operations that are naturally a single transaction
  • Shared workflows span multiple roles, a single collection request touches resident, admin, and driver logic in sequence, which doesn't map cleanly onto independently deployed services
  • Distributed complexity is unnecessary at this scale, network calls between services, distributed transactions, and service discovery all add operational overhead that isn't justified by the current scale of the system
  • Deployment simplicity is more valuable right now than the theoretical scalability microservices offer
  • Instead, the layered monolith architecture provides:

  • Clear separation of concerns, even without physical service boundaries
  • Easier debugging, since a single request's full execution path lives in one codebase and one process
  • Faster development cycles, without the overhead of coordinating changes across multiple deployed services
  • A maintainable structure that can still evolve, if specific parts of the system genuinely need to scale independently in the future, the existing layered structure makes it easier to extract them later, rather than forcing that complexity in from day one
  • Key Backend Technologies

  • Spring Boot 3.5.6, the core application framework
  • Java 21, the language runtime
  • Spring Security + JWT, authentication and authorization
  • Spring Data JPA / Hibernate, object-relational mapping and repository abstraction
  • MySQL 8, the relational database
  • Maven, dependency management and build tooling
  • JUnit + Mockito, testing frameworks for unit and integration tests
  • Database Design Overview

    The database schema is structured around operational entities, not just isolated, independently designed tables. Core models include:

  • Users and role hierarchy
  • Collection workflows
  • Scheduling system
  • Payments and rebates
  • Vehicle and route management
  • Notifications and reporting
  • Every table is designed with its place in the broader operational workflow in mind, for example, the scheduling tables are built to connect naturally to both collection requests and vehicle/route assignment, rather than existing as disconnected reference data.

    Testing Strategy

    The backend testing strategy covers three layers:

  • Unit tests for services, validating business logic in isolation, independent of the database or HTTP layer
  • Integration tests for API flows, verifying that controllers, services, and repositories work correctly together end-to-end
  • Context tests for application configuration, confirming that the Spring application context loads correctly with all beans wired as expected
  • Together, these tests protect three things: business logic correctness, API stability, and consistent enforcement of security rules across the system.

    Full-Stack Integration Philosophy

    It's worth stating plainly: Smart Cycle is not "a React app with a Spring Boot API bolted on." It is designed and reasoned about as one system split across two layers, where each layer has a clear and non-overlapping set of responsibilities.

    Frontend Responsibilities

  • User experience
  • Role-based UI rendering
  • API consumption
  • Client-side validation (for usability, not as a security boundary)
  • Backend Responsibilities

  • Business logic enforcement
  • Security and authorization
  • Data persistence
  • Workflow orchestration
  • Because these responsibilities are cleanly separated, neither layer can function correctly on its own, which is intentional. It forces architectural discipline: the frontend can never assume it's the source of truth for what's allowed, and the backend never has to guess at what the user intended, because the API contract (via DTOs and action-based endpoints) makes intent explicit.

    What This System Represents

    None of the individual technologies in Smart Cycle, React, Spring Boot, MySQL, TailwindCSS, are unusual or cutting-edge on their own. The engineering value of the project isn't in tool selection; it's in how those tools were assembled to solve a genuinely awkward problem: coordinating four different types of users around one shared, evolving set of real-world operations.

    The value lies specifically in:

  • Clean separation of roles, without duplicating the entire application per role
  • Workflow-driven backend design, instead of generic CRUD that hides what's actually happening
  • Consistent, well-defined API contracts via DTOs
  • Strong, backend-enforced security boundaries
  • A unified full-stack architecture that treats frontend and backend as one coordinated system rather than two loosely connected ones
  • Conclusion

    Building Smart Cycle required more than picking a tech stack off a shelf. It required designing a system where multiple real-world actors, residents, drivers, recycling center operators, and administrators, could interact with shared operational workflows safely, consistently, and without stepping on each other.

    The result is a full-stack architecture where:

  • The frontend adapts fluidly to whoever is logged in
  • The backend enforces every business rule, regardless of what the client sends
  • The database models real operational processes, not just abstract data storage
  • The system stays scalable and maintainable without taking on complexity it doesn't yet need
  • Built for a cleaner, smarter, and more structured approach to waste management.

    All ArticlesReact
    Sathsara

    Sadeesha Sathsara

    Backend & DevOps Developer

    Writing on async systems design, automated CI/CD pipelines, containerization, and backend patterns.

    More in React

    Nexa WebJune 30, 2026 · 5 min readUser Management SystemJune 30, 2026 · 5 min readDigital Marketplace Havest LankaJune 30, 2026 · 5 min readProduct ManagementJune 30, 2026 · 5 min read

    Keep Reading

    More Articles

    Rubik's Cube Algorithm Development Framework
    ProjectSystems
    July 1, 2026

    Rubik's Cube Algorithm Development Framework

    Read
    Dynamic island on windows
    ProjectSystems
    July 1, 2026

    Dynamic island on windows

    Read
    Workflow Automation Platform with plugin based architecture
    ProjectArchitecture
    July 1, 2026

    Workflow Automation Platform with plugin based architecture

    Read
    Microservices Healthcare Platform on Kubernetes
    ProjectArchitecture
    July 1, 2026

    Microservices Healthcare Platform on Kubernetes

    Read
    Ecolife
    ProjectWeb Systems
    June 30, 2026

    Ecolife

    Read
    TriSense
    ProjectPython
    June 30, 2026

    TriSense

    Read
    Nexa App
    ProjectReact Native
    June 30, 2026

    Nexa App

    Read
    Nexa Web
    ProjectReact
    June 30, 2026

    Nexa Web

    Read
    Wizard Shopping
    ProjectHTML, CSS, JavaScript, JAVA
    June 30, 2026

    Wizard Shopping

    Read
    User Management System
    ProjectReact
    June 30, 2026

    User Management System

    Read
    Digital Marketplace Havest Lanka
    ProjectReact
    June 30, 2026

    Digital Marketplace Havest Lanka

    Read
    tripma
    Projectfullstack
    June 30, 2026

    tripma

    Read
    theatre booking system
    Projectfullstack
    June 30, 2026

    theatre booking system

    Read
    Product Management
    ProjectReact
    June 30, 2026

    Product Management

    Read
    Fine System
    ProjectWeb Systems
    June 30, 2026

    Fine System

    Read