WriteFluency is an interactive web application designed to help users practice and improve their English writing skills through listening and transcription exercises.
The application provides real-world English listening comprehension exercises based on current news articles. Users can listen to AI-generated audio and transcribe what they hear, receiving instant feedback on accuracy with detailed text comparison analysis.
This repository follows a microservices architecture orchestrated by .NET Aspire, featuring:
- WriteFluency.WebApi: REST API providing endpoints for propositions, text comparisons, and authentication
- WriteFluency.NewsWorker: Background service that automatically fetches news articles, generates summaries, and creates audio exercises on a cron schedule
- WriteFluency.DbMigrator: Database migration service ensuring schema is up-to-date before other services start
- Angular 21: Modern, server-side rendered (SSR) web application with Material Design components
- OpenTelemetry: Integrated telemetry and monitoring with Application Insights support
- AppHost (.NET Aspire 9.3): Orchestrates all services with dependency management, health checks, and service discovery
- PostgreSQL 14.3: Primary relational database for storing propositions, user data, and news articles
- MinIO: S3-compatible object storage for audio files and images
- Docker Compose: Alternative deployment option for development environments
WriteFluency/
βββ src/
β βββ host/ # .NET Aspire Orchestration
β β βββ WriteFluency.AppHost/ # Aspire AppHost - orchestrates all services
β β βββ WriteFluency.ServiceDefaults/ # Shared service configurations (telemetry, health checks)
β β
β βββ propositions-service/ # Backend Microservice
β β βββ WriteFluency.WebApi/ # REST API layer
β β βββ WriteFluency.Application/ # Application logic and services
β β βββ WriteFluency.Application.Contracts/ # DTOs and interfaces
β β βββ WriteFluency.Domain/ # Domain models and business logic
β β βββ WriteFluency.Infrastructure/ # Data access, external APIs, file storage
β β βββ WriteFluency.NewsWorker/ # Background worker for news processing
β β βββ WriteFluency.DbMigrator/ # Database migration service
β β βββ WriteFluency.Shared/ # Shared utilities and extensions
β β
β βββ webapp/ # Angular Frontend
β βββ src/app/ # Application components
β βββ src/api/ # Auto-generated API clients (OpenAPI)
β
βββ tests/
βββ WriteFluency.Application.Tests/ # Application layer tests
βββ WriteFluency.Infrastructure.Tests/ # Infrastructure layer tests
Users can:
- Select a complexity level (Beginner, Intermediate, Advanced) and subject/topic
- Listen to AI-generated audio based on real news articles
- Transcribe what they hear
- Receive instant accuracy feedback with detailed text comparison
The verification system uses a sophisticated algorithm combining:
- Needleman-Wunsch Alignment: Global sequence alignment for optimal text matching
- Levenshtein Distance: Edit distance calculation for accuracy measurement
- Token-based Analysis: Word-level comparison with contextual awareness
- Visual Feedback: Highlighted differences showing correct, incorrect, and missing text
- OpenAI GPT Integration: Generates contextual text summaries from news articles
- Google Cloud Text-to-Speech: Creates natural-sounding audio with configurable voices
- Automated News Pipeline: Background worker fetches articles, validates images, generates content, and stores results
- ASP.NET Core Identity with JWT tokens
- Google OAuth integration
- Secure password management
- .NET 9 with C# 13
- ASP.NET Core Minimal APIs
- Entity Framework Core with PostgreSQL provider
- .NET Aspire for cloud-native orchestration
- FluentResults for functional error handling
- Microsoft.Extensions.AI for AI abstraction
- Angular 21 with standalone components
- Angular Material for UI components
- RxJS for reactive programming
- Server-Side Rendering (SSR) for performance
- OpenTelemetry for observability
- PostgreSQL 14.3 - Relational database
- MinIO - S3-compatible object storage
- Docker & Docker Compose - Containerization
- Kubernetes - Production deployment (K8s manifests available)
- OpenAI API (GPT-4) - Text generation
- Google Cloud Text-to-Speech - Audio generation
- News APIs - Article sourcing (configurable)
- .NET 9 SDK
- Node.js 20+ and npm
- Docker Desktop (for running dependencies)
- Visual Studio 2022 or JetBrains Rider (recommended) or VS Code
-
Clone the repository
git clone https://github.com/yourusername/WriteFluency.git cd WriteFluency -
Configure secrets (appsettings or user secrets)
{ "OpenAI": { "Key": "your-openai-api-key", "BaseAddress": "https://api.openai.com/v1" }, "TextToSpeech": { "ApiKey": "your-google-cloud-api-key" } } -
Run the AppHost
cd src/host/WriteFluency.AppHost dotnet runThe Aspire dashboard will open automatically showing all services, logs, and metrics.
-
Access the application
- Frontend: http://localhost:4200
- API: http://localhost:5000
- Aspire Dashboard: Shown in terminal output
-
Start infrastructure services
docker-compose -f docker-compose.services.yml up -d
-
Run database migrations
cd src/propositions-service/WriteFluency.DbMigrator dotnet run -
Start the API
cd src/propositions-service/WriteFluency.WebApi dotnet run -
Start the web application
cd src/webapp npm install npm start
Run all tests:
dotnet testRun specific test projects:
dotnet test tests/WriteFluency.Application.Tests
dotnet test tests/WriteFluency.Infrastructure.Testsdotnet ef migrations add MigrationName \
-p ./src/propositions-service/WriteFluency.Infrastructure/WriteFluency.Infrastructure.csproj \
-s ./src/propositions-service/WriteFluency.WebApi/WriteFluency.WebApi.csprojThe DbMigrator service automatically applies migrations on startup when using Aspire.
For manual migration:
cd src/propositions-service/WriteFluency.DbMigrator
dotnet runcd src/host/WriteFluency.AppHost
./build-k8s-images.shUse this command to regenerate manifests without rebuilding images and without interactive prompts for AppHost inputs:
cd src/host/WriteFluency.AppHost
aspirate generate --skip-build --non-interactive \
-pa wf-infra-minio-user=minioadmin \
-pa wf-infra-minio-password=admin123 \
-pa wf-infra-postgres-password=postgres \
-pa wf-infra-redis-password=admin123Parameters passed with -pa:
wf-infra-minio-user: MinIO root user.wf-infra-minio-password: MinIO root password.wf-infra-postgres-password: Postgres password.wf-infra-redis-password: Redis password.
./deploy-k8s.shThe application includes:
- Health checks for all services and dependencies
- OpenTelemetry tracing and metrics
- Aspire Dashboard for local development
- Application Insights support for production
- Deliverability runbook for self-hosted SMTP (SPF/DKIM/DMARC, complaint and bounce thresholds, and incident playbook):
src/users-service/WriteFluency.Users.WebApi/Email/DELIVERABILITY_RUNBOOK.md
- Swagger/OpenAPI: API documentation at
/swagger(development only) - Aspire Dashboard: Service orchestration and monitoring
- Hot Reload: Both .NET and Angular support hot reload during development
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the terms specified in LICENSE.
- OpenAI for GPT API
- Google Cloud for Text-to-Speech API
- .NET Aspire for cloud-native orchestration
- Angular Team for the excellent framework
- News providers for article content
Run AppHost and validate users-service foundation:
- Start orchestration:
cd src/host/WriteFluency.AppHost dotnet run - Probe users-service health:
curl -i http://localhost:5100/health
- Verify users DB migration applied:
- Check
wf-users-db-migratorlogs in Aspire dashboard forUsers DB migrations applied successfully. - Connect to PostgreSQL and confirm Identity tables exist in
wf-users-postgresdb(for exampleAspNetUsers,AspNetRoles).
- Check
- Confirm existing flows still boot:
wf-propositions-apiandwf-propositions-news-workershould be healthy in Aspire.
Google and Microsoft login are exposed by users-service under /users/auth/external/*.
users-service and propositions-service share the same UserSecretsId, so set credentials once (for example from src/propositions-service/WriteFluency.WebApi):
cd src/propositions-service/WriteFluency.WebApi
dotnet user-secrets set "Authentication:Google:ClientId" "<google-client-id>"
dotnet user-secrets set "Authentication:Google:ClientSecret" "<google-client-secret>"
dotnet user-secrets set "Authentication:Microsoft:ClientId" "<microsoft-client-id>"
dotnet user-secrets set "Authentication:Microsoft:ClientSecret" "<microsoft-client-secret>"Configure these redirect/callback URLs in provider consoles:
- Google:
https://localhost:5101/users/signin-google - Microsoft:
https://localhost:5101/users/signin-microsoft
- Run AppHost:
cd src/host/WriteFluency.AppHost dotnet run - Open users Swagger at
https://localhost:5101/users/swagger. - Use these endpoints:
GET /users/auth/external/providersGET /users/auth/external/google/start?returnUrl=/users/swagger/index.htmlGET /users/auth/external/microsoft/start?returnUrl=/users/swagger/index.html
- Start endpoint redirects to provider login, then back to Swagger with query params:
- Success:
?auth=success&provider=<google|microsoft> - Error:
?auth=error&provider=<google|microsoft>&code=<error_code>
- Success:
Frontend can reuse the same start endpoint by passing an allowlisted frontend callback URL in returnUrl (for example http://localhost:4200/auth/callback).