Back to projects
Exavatar logo

Exavatar

API for dynamic generation and customization of avatars via URL parameters, designed to optimize profile management in scalable applications.

Public API Avatar

This document details the architecture, domain design, and technical implementation of Exavatar, a rendering engine and dynamic avatar generation API. This solution addresses a recurring friction point in web and mobile application development: managing default profile images or placeholders when the end user fails to provide one.

Utility and Workflow

The core problem this project solves is the absence of a temporary visual identity in user interfaces, which typically requires each development team to implement redundant logic for generating initials or conditionally loading images on the client side.

Exavatar shifts that responsibility entirely to the server. The tool acts as a REST API that, through structured URL parameters, instantly returns an avatar. It can serve a static asset from a predefined collection (e.g., animals or characters in WEBP/PNG format) or dynamically generate an SVG on the fly featuring the user’s initials over a solid color background.

The main application flow operates as follows:

  1. Request Reception: A client makes an HTTP GET request to the API with specific parameters (set, id, size, format, color, text).
  2. Domain Evaluation: The application core interprets the URL parameters to instantiate the main entity (Avatar). If the text parameter is provided, the application determines that it must compile and return a dynamically generated SVG. Otherwise, it validates the size, collection, and format attributes to construct a valid file path.
  3. Repository Resolution: Depending on the execution environment (Development vs. Production), the application layer delegates the physical loading of the image to the corresponding infrastructure adapter (local or network-based).
  4. Response: The server returns the image binary or the SVG string with the correct HTTP headers and configured caching, minimizing computational load on subsequent requests.

Deep Analysis: Architecture and Data Modeling

The source code design (mainly located in src/core/) is a strict implementation of Domain-Driven Design (DDD) structured under the Hexagonal Architecture (Ports and Adapters) pattern. This technical decision is not by chance; it was adopted to completely isolate the business logic and generation rules from the presentation layer (Astro) and the infrastructure layer (network/file system).

General Architecture

The separation of concerns ensures that the core (domain) has no external dependencies, making the code inherently testable and scalable.

flowchart TD
    subgraph Presentation ["Presentation (Astro / API Routes)"]
        API["Route /api/avatar"]
    end

    subgraph ApplicationLayer ["Application Layer"]
        AS["AvatarService"]
    end

    subgraph DomainLayer ["Domain Layer (Core)"]
        A["Avatar : Entity"]
        VO1["AvatarSize : Value Object"]
        VO2["AvatarColor : Value Object"]
        VO3["AvatarId : Value Object"]
        VO4["AvatarSet : Value Object"]
        VO5["AvatarText : Value Object"]
        Repo["AvatarRepository : Port"]

        A --> VO1
        A --> VO2
        A --> VO3
        A --> VO4
        A --> VO5
    end

    subgraph InfrastructureLayer ["Infrastructure Layer (Adapters)"]
        LRepo["LocalAvatarRepository"]
        GRepo["GitHubAvatarRepository"]
    end

    API --> AS
    AS --> Repo
    AS --> A
    LRepo -.-> Repo
    GRepo -.-> Repo

Data Modeling and Business Logic

The business logic resides in the Value Objects and the Aggregate Root entity (Avatar). These ensure that the application never processes an invalid state.

  • Avatar Entity: Orchestrates validation and transformation. It exposes the needBuild() method, which intelligently determines the execution flow (reading a static file vs. generating an SVG) by evaluating whether the AvatarText Value Object contains a valid value.
  • Value Objects:
    • AvatarSize: Validates allowed limits and resolutions (e.g., restricting between 16px and 512px).
    • AvatarColor: Normalizes hexadecimal values and calculates secondary logic (such as automatic text contrast for SVG based on the luminance of the background color).
    • AvatarId, AvatarSet and AvatarFormat: Ensure that the requested identifier belongs to a valid collection and that the output format is supported (webp, png, svg).
classDiagram
    class Avatar {
        +AvatarSet set
        +AvatarId id
        +AvatarSize size
        +AvatarFormat format
        +AvatarColor color
        +AvatarText text
        +String filepath
        +String filename
        +fromUrl(URL url) Avatar$
        +needBuild() boolean
    }
    class AvatarService {
        -AvatarRepository repository
        +generate(URL url) Promise<AvatarResult>
    }
    class AvatarRepository {
        <<interface>>
        +load(Avatar avatar) Promise<AvatarResult>
    }

    AvatarService --> AvatarRepository : Uses
    AvatarService ..> Avatar : Builds

The orchestrator service, AvatarService, applies dependency injection via the constructor. At runtime, the system injects GitHubAvatarRepository to fetch static files from the production repository, or LocalAvatarRepository to read from the local disk during development.

Technology Stack

The tool stack was strictly selected for performance and type control.

TechnologyRole in Architecture
AstroPresentation framework and Server-Side Rendering (SSR). Handles API routing and delivers ultra-fast responses through the Edge Network without injecting JavaScript into the client.
TypeScriptMain programming language. Fundamental for modeling in the Domain layer, ensuring rigorous compliance with interfaces between ports and adapters.
VitestUnit testing environment. Allows testing the domain layer and AvatarService in complete isolation by injecting simulated repositories (mocks).
BiomeJSOnly static analysis tool (linter) and formatter. Configured to use tab indentation and single quotes, completely replacing Prettier and ESLint for higher execution speed.
VercelDeployment infrastructure. Uses Serverless/Edge Functions directly via @astrojs/vercel for processing and global CDN delivery of the generated images.

The rigorous integration of DDD principles, advanced static typing, and a pure hexagonal architecture in a modern JavaScript environment results in a system with zero coupling between its rendering engine and its file distribution infrastructure. This abstraction allows scaling, switching hosting platforms, or adding new algorithmic generation formats without requiring alterations to the domain logic.