Skip to content

timok19/AffirmationGenerator

Repository files navigation

Build and Test Fly Deploy

Affirmation Generator

1. Application Info

The Affirmation Generator is a web application designed to provide users with positive, uplifting affirmations in multiple languages to boost morale and mental well-being. It features a daily limit on affirmation generation to encourage mindful consumption and prevents overuse through rate limiting.

2. Getting Started

Prerequisites

Running Locally

  1. Clone the repository:

    git clone https://github.com/timok19/AffirmationGenerator.git
    cd AffirmationGenerator
  2. Configuration: Ensure you have the required API keys. For local development, use .NET User Secrets to avoid committing sensitive data:

    cd AffirmationGenerator.Server
    dotnet user-secrets init
    dotnet user-secrets set "Infrastructure:DeepLTranslatorClientOptions:ApiKey" "DEEPL_API_KEY"
    dotnet user-secrets set "Infrastructure:AffirmationClientOptions:BaseUrl" "https://www.affirmations.dev"

    Alternatively, update appsettings.json.

  3. Start the Application: Navigate to the server directory and run:

    dotnet run

    This will start the ASP.NET Core backend and automatically launch the React frontend via the configured SPA proxy. The application will be available at: https://localhost:7006 (or http://localhost:5095).

Running with Docker

  1. Build the image:
    docker build -t affirmation-generator .
  2. Run the container:
    docker run -p 8080:8080 -e Infrastructure__DeepLTranslatorClientOptions__ApiKey="DEEPL_API_KEY" -e Infrastructure__AffirmationClientOptions__BaseUrl="https://www.affirmations.dev" affirmation-generator
    Access the application at: http://localhost:8080

3. Architecture

System-Level Architecture

The application is built using a Client-Server model packaged into a single Docker container for easy deployment.

  • Backend: ASP.NET Core Web API (NET 10.0) acts as the server. It handles business logic, communicates with external APIs (Affirmation service, DeepL), enforces rate limiting, and serves the frontend as static files.
  • Frontend: A React Single Page Application (SPA) that provides the user interface. It consumes the backend API to fetch and display affirmations.
  • Deployment: The project uses a multi-stage Dockerfile. It builds the React frontend with Node.js, the .NET backend with the .NET SDK, and combines them into a final runtime image where ASP.NET serves the React static assets from wwwroot.

Code-Level Architecture

Backend (AffirmationGenerator.Server): The backend follows Clean Architecture principles, organizing code into distinct layers:

  • Api: Contains Controllers (AffirmationsController) that define endpoints and handle HTTP requests/responses. It also manages Rate Limiting policies.
  • Application: Contains business logic implemented using the CQRS pattern (e.g., GetAffirmationQuery, GetRemainingAffirmationsQuery).
  • Infrastructure: Implements interfaces for external services, such as:
    • AffirmationClient: Fetches raw affirmations from an external source.
    • DeepLTranslatorClient: Translates affirmations using the DeepL API.
  • Domain: Defines core data models (AffirmationLanguage) and error types.

Frontend (AffirmationGenerator.Client): The frontend is a React application built with Vite.

  • State Management: Uses React Hooks (useState, useEffect) within App.tsx to manage application state (current affirmation, language, remaining count).
  • API Communication: Uses Axios to communicate with the backend endpoints (/affirmations, /affirmations/remaining).
  • Styling: Utilizes Tailwind CSS v4 and DaisyUI v5 for responsive and modern UI components.

4. Configuration

To configure the application, you need to set up the following settings in appsettings.json or via Environment Variables (recommended for production):

Required Configuration:

{
    "Application": {
        "ClientOptions": {
            "ClientIpHeaderName": "",  // Optional
            "MaxRequestsPerDay": 10
        }
    }
    "Infrastructure": {
        "DeepLTranslatorClientOptions": {
            "ApiKey": "YOUR_DEEPL_API_KEY"
        },
        "AffirmationClientOptions": {
            "BaseUrl": "https://www.affirmations.dev"
        }
    }
}
  • Application:ClientOptions:ClientIpHeaderName: Optional. Specifies the HTTP header containing the client IP (e.g., X-Forwarded-For behind proxies/load balancers like Fly.io). If empty (default), uses the direct RemoteIpAddress from the TCP connection, suitable for local development and non-proxied environments.
  • Application:ClientOptions:MaxRequestsPerDay: Maximum number of affirmations per client IP per day (default: 10).
  • Infrastructure:DeepLTranslatorClientOptions:ApiKey: The API Key for the DeepL translation service.
  • Infrastructure:AffirmationClientOptions:BaseUrl: The base URL for the external affirmation provider service.

5. API Endpoints

The API provides the following endpoints (Swagger UI available at /swagger):

  • GET /affirmations?targetLanguage={language} Returns { text: string, remainingCount: int }. Fetches an English affirmation, translates to targetLanguage (enum value e.g. 1 = German, or name German). Rate-limited (10/day per IP).

  • GET /affirmations/remaining Returns { remainingCount: int }.

  • GET /affirmations/languages Returns sorted ["English", "German", "Czech", "French"].

6. React Components & Libraries

Libraries Used

  • React 19: Core UI library.
  • Vite: Fast build tool and development server.
  • Tailwind CSS (v4): Utility-first CSS framework.
  • DaisyUI (v5): Component library for Tailwind CSS.
  • Axios: Promise-based HTTP client for making API requests.
  • @tanstack/react-query (v5): Data fetching, caching, and synchronization.
  • TypeScript: Adds static typing to JavaScript for better developer experience and code quality.

7. CI/CD

GitHub Actions Workflows

  • tests.yml: Triggers on pull_request targeting main. Runs dotnet restore, build, test on AffirmationGenerator.slnx.
  • fly-deploy.yml: Triggers on push to main. Runs tests, then deploys to Fly.io using flyctl deploy.

8. Unit Tests

Run with:

dotnet test

9. Useful links