Skip to main content

Introduction to TecMeli

TecMeli is a robust Android client for Mercado Libre, designed following Senior Engineering standards. It implements a modular, secure, and highly scalable architecture that demonstrates best practices in modern Android development.

What is TecMeli?

TecMeli is a production-ready Android application that provides:
  • Advanced Product Search: Real-time product discovery with reactive state management
  • Detailed Product Views: Image galleries, technical specifications, and descriptions
  • Secure OAuth 2.0 Authentication: Automatic session management with background token refresh
  • Modern UI: Fluid interface built entirely with Jetpack Compose and Material 3
  • Robust Network Layer: Safe API call executor with semantic error mapping
This project was built as a demonstration of Clean Architecture principles and modern Android development best practices, making it an excellent learning resource for Android developers.

Technology Stack

TecMeli leverages the latest and most powerful tools in the Android ecosystem:
AreaTechnologies
LanguageKotlin + Coroutines + Flow
UIJetpack Compose + Material 3
Dependency InjectionDagger Hilt
NetworkingRetrofit + OkHttp + Gson
ArchitectureClean Architecture + MVVM
TestingMockK + MockWebServer + JUnit

Key Dependencies

From the project’s libs.versions.toml:
[versions]
kotlin = "2.3.10"
composeBom = "2026.02.01"
hilt = "2.59.2"
retrofit = "3.0.0"
okhttp = "4.11.0"

Architecture Overview

TecMeli implements Clean Architecture optimized for Mercado Libre’s authentication flow. The application is structured in three main layers:

1. Presentation Layer (ui)

Built entirely with Jetpack Compose, featuring:
  • Home screen with product search
  • Product detail screen with image gallery
  • Navigation using Navigation 3
  • Material 3 theming

2. Domain Layer (domain)

Contains pure business logic:
  • Models: Domain entities like Product and ProductDetail
  • Use Cases: Business operations like GetProductsUseCase
  • Repository Interfaces: Contracts for data access

3. Data Layer (data)

Handles data operations:
  • Remote APIs: Retrofit interfaces for Mercado Libre API
  • DTOs: Data transfer objects for network responses
  • Mappers: Convert DTOs to domain models
  • Repository Implementations: Concrete implementations of domain contracts
package com.alcalist.tecmeli.domain.usecase

class GetProductsUseCase @Inject constructor(
    private val repository: ProductRepository
) {
    suspend operator fun invoke(query: String): Result<List<Product>> {
        return if (query.isBlank()) {
            Result.success(emptyList())
        } else {
            repository.searchProducts(query)
        }
    }
}

State Management

TecMeli uses a sealed class UiState<T> to represent all possible UI states:
UiState.kt
sealed class UiState<out T> {
    object Loading : UiState<Nothing>()
    data class Success<T>(val data: T) : UiState<T>()
    data class Error(val message: String, val exception: Throwable? = null) : UiState<Nothing>()
    object Empty : UiState<Nothing>()
}
This pattern provides:
  • Type Safety: Compile-time guarantees about state handling
  • Exhaustive When: Ensures all states are handled in UI
  • Reactive Updates: Automatic UI updates via StateFlow

Security & Authentication

TecMeli implements OAuth 2.0 with automatic token refresh:
1

Request Interception

Every request to the Mercado Libre API automatically includes the access token via AuthInterceptor
2

Authentication Challenge

When the server returns a 401 Unauthorized, the TokenAuthenticator intercepts the response
3

Token Refresh

A new token is requested synchronously from the auth endpoint
4

Automatic Retry

The original failed request is retried with the new token - completely transparent to the user
AuthInterceptor.kt
class AuthInterceptor @Inject constructor(
    private val tokenRepository: TokenRepository
) : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {
        val originalRequest = chain.request()
        
        // Skip auth for token endpoint
        if (originalRequest.url.encodedPath.contains("oauth/token")) {
            return chain.proceed(originalRequest)
        }

        val token = tokenRepository.getAccessToken()
        val requestBuilder = originalRequest.newBuilder()
        
        token?.let {
            requestBuilder.addHeader("Authorization", "Bearer $it")
        }
        
        return chain.proceed(requestBuilder.build())
    }
}

Project Structure

com.alcalist.tecmeli/
├── core/               # Infrastructure (Network, DI, Utilities)
│   ├── di/             # Hilt Modules
│   ├── network/        # Executors, Interceptors, Logger
│   └── util/           # UiState, DateUtils
├── data/               # Data Layer Implementation
│   ├── mapper/         # DTO → Domain transformations
│   ├── remote/         # Retrofit APIs and DTOs
│   └── repository/     # Repository implementations
├── domain/             # Pure Business Logic
│   ├── model/          # Domain entities
│   ├── repository/     # Repository contracts (interfaces)
│   └── usecase/        # Use cases
└── ui/                 # Presentation Layer
    ├── navigation/     # Navigation setup
    ├── screen/         # Compose screens
    └── theme/          # Material 3 theming
TecMeli requires valid Mercado Libre API credentials to function. You’ll need to register your application on the Mercado Libre Developer Portal to obtain these credentials.

What’s Next?

Now that you understand what TecMeli is and its architecture, let’s get it running on your machine:

Installation

Set up your development environment and clone the project

Configuration

Configure API credentials and build the application

Build docs developers (and LLMs) love