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.
- .NET 10.0 SDK
- Node.js (LTS recommended)
- pnpm package manager
- Docker (optional, for containerized run)
-
Clone the repository:
git clone https://github.com/timok19/AffirmationGenerator.git cd AffirmationGenerator -
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. -
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(orhttp://localhost:5095).
- Build the image:
docker build -t affirmation-generator . - Run the container:
Access the application at:
docker run -p 8080:8080 -e Infrastructure__DeepLTranslatorClientOptions__ApiKey="DEEPL_API_KEY" -e Infrastructure__AffirmationClientOptions__BaseUrl="https://www.affirmations.dev" affirmation-generator
http://localhost:8080
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 fromwwwroot.
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) withinApp.tsxto manage application state (current affirmation, language, remaining count). - API Communication: Uses
Axiosto communicate with the backend endpoints (/affirmations,/affirmations/remaining). - Styling: Utilizes Tailwind CSS v4 and DaisyUI v5 for responsive and modern UI components.
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-Forbehind proxies/load balancers like Fly.io). If empty (default), uses the directRemoteIpAddressfrom 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.
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 totargetLanguage(enum value e.g.1= German, or nameGerman). Rate-limited (10/day per IP). -
GET /affirmations/remainingReturns{ remainingCount: int }. -
GET /affirmations/languagesReturns sorted["English", "German", "Czech", "French"].
- 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.
- tests.yml: Triggers on
pull_requesttargetingmain. Runsdotnet restore,build,testonAffirmationGenerator.slnx. - fly-deploy.yml: Triggers on
pushtomain. Runs tests, then deploys to Fly.io usingflyctl deploy.
Run with:
dotnet test