# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview QR Rapido is an ultra-fast QR code generator built with ASP.NET Core 8.0, focusing on speed and multilingual support (PT-BR, ES, EN). It features tiered user access (anonymous, logged-in free, premium), OAuth authentication (Google/Microsoft), Stripe payment integration, and ad-free session management. **Key Performance Targets:** - QR generation: <1.2s (average), <0.4s (premium users) - Cache hit rate: >80% - First Contentful Paint: <2s ## Common Commands ### Development ```bash # Run locally (hot reload) dotnet watch run # Run locally (standard) dotnet run # Build for release dotnet build --configuration Release # Restore dependencies dotnet restore ``` ### Testing ```bash # Run all tests dotnet test # Run with coverage dotnet test --collect:"XPlat Code Coverage" # Run specific test class dotnet test --filter "QRRapidoServiceTests" ``` ### Frontend Build ```bash # Development mode with Vite npm run dev # Production build (Vite) npm run build # Preview production build npm run preview ``` ### Docker ```bash # Build and run all services (MongoDB, Redis, Nginx) docker-compose up -d # View logs docker-compose logs -f qrrapido # Build production image for ARM64 (OCI Ampere servers) docker buildx build --platform linux/arm64 -t qrrapido:latest . # Stop all services docker-compose down ``` ### Stripe Webhooks (Local Testing - WSL) ```bash # Forward Stripe webhooks to local HTTPS endpoint stripe listen --forward-to https://localhost:52428/pagamento/stripewebhook --skip-verify ``` ## Architecture ### Core Technology Stack - **Backend**: ASP.NET Core 8.0 (MVC + Razor Pages) - **Database**: MongoDB (users, QR history, sessions) - **Cache**: Redis (distributed cache) + MemoryCache (fallback) - **QR Generation**: QRCoder library with ImageSharp for logo overlay - **Authentication**: Cookie-based with OAuth (Google, Microsoft) - **Payments**: Stripe (subscriptions) - **Logging**: Serilog → OpenSearch/Console - **Frontend Build**: Vite for asset bundling ### Project Structure ``` Controllers/ # MVC controllers (Home, QR, Account, Premium, Pagamento, Health) Services/ # Business logic (QRRapido, User, Plan, Stripe, AdDisplay) ├── Monitoring/ # Resource and MongoDB monitoring └── HealthChecks/# Health check implementations Models/ # Domain models and ViewModels Data/ # MongoDbContext Middleware/ # Custom middleware (Language redirection, LastLogin update) Providers/ # Culture providers for localization Resources/ # .resx files for PT-BR, ES, EN localization Views/ # Razor views wwwroot/ # Static assets (CSS, JS, images) Tests/ # Unit tests (xUnit, Moq) ``` ### Key Services **QRRapidoService** (`Services/QRRapidoService.cs`): - Core QR generation with distributed cache support - SemaphoreSlim limits concurrent generations (default: 100) - Cache key based on content hash + settings - Optimized error correction levels for speed - Logo overlay with readability analysis **UserService** (`Services/UserService.cs`): - MongoDB user CRUD operations - QR history management (anonymous vs authenticated) - Premium status checks - Graceful fallback when MongoDB unavailable **AdDisplayService** (`Services/AdDisplayService.cs`): - Controls ad visibility based on user status - 30-day ad-free period after login - Premium users: permanent ad-free - Anonymous users: always show ads **StripeService** (`Services/StripeService.cs`): - Subscription creation and management - Webhook handling (checkout.session.completed, etc.) - Customer portal session creation ### Middleware Pipeline (Program.cs) 1. **LanguageRedirectionMiddleware**: Redirects root `/` to `/pt-BR/` or user's language preference 2. **Request Localization**: Sets culture based on route (`/{culture}/...`) → QueryString → Cookie 3. **Authentication/Authorization** 4. **Session** 5. **LastLoginUpdateMiddleware**: Updates user's last login timestamp ### Localization Strategy - Route-based culture: `/{culture:regex(^(pt-BR|es-PY)$)}/{controller}/{action}` - Default culture: `pt-BR` - Supported cultures: `pt-BR`, `es-PY` - Culture providers priority: Route → QueryString → Cookie - Resources in `Resources/SharedResource.{culture}.resx` ### MongoDB Collections - **Users**: User profiles, premium status, OAuth data - **QRCodeHistory**: Generated QR codes (linked to users or anonymous) - **AdFreeSessions**: Ad-free session tracking (30-day grants) - **DataProtectionKeys**: ASP.NET Core Data Protection keys (for Docker Swarm) ### Docker Swarm Deployment **Production** uses Docker Swarm with: - 2 replicas across 2 ARM64 servers (OCI Ampere) - Shared MongoDB for Data Protection keys (cross-replica cookie decryption) - Rolling updates: `start-first` strategy, 30s delay between updates - Health checks at `/healthcheck` endpoint - Exposed on port 5001 internally, proxied by Nginx **Staging** uses standalone Docker containers on 2 servers. ### CI/CD Pipeline (.github/workflows/deploy.yml) 1. **Test Job**: Runs on `ubuntu-latest` - Restore → Build → Test with coverage - Uploads coverage to Codecov 2. **Build-and-Push Job**: Runs on self-hosted ARM64 runner - Builds ARM64 Docker image - Tags: `latest` (main), `develop` (develop branch) - Pushes to private registry: `registry.redecarneir.us` 3. **Deploy-Staging**: SSH to 2 servers, pull image, run container 4. **Deploy-Production**: SSH to Swarm manager, update service with zero-downtime ### Configuration Management **appsettings.json** key sections: - `ConnectionStrings:MongoDB`: MongoDB connection string - `Authentication:Google/Microsoft`: OAuth credentials - `Stripe`: API keys and webhook secret - `Performance:MaxConcurrentGenerations`: Semaphore limit (default: 100) - `Premium:FreeQRLimit`: Daily limit for logged-in free users (10) - `Serilog:OpenSearchUrl`: Centralized logging endpoint - `ResourceMonitoring`: CPU/memory thresholds for alerts - `HealthChecks`: Timeout and test configurations **Environment-specific overrides**: - `appsettings.Development.json` - `appsettings.Production.json` ### Rate Limiting & Performance - Fixed window rate limiter: 600 requests/minute per IP on `/api` endpoints - Kestrel max connections: 2000 - QR generation timeout: 2000ms - Redis cache expiration: 60 minutes - MongoDB query timeouts: 5 seconds (health checks) ### Health Checks Endpoint: `/healthcheck` Checks: - **MongoDbHealthCheck**: Database connectivity, size metrics, test query - **ResourceHealthCheck**: CPU/memory usage, GC pressure - **ExternalServicesHealthCheck**: Stripe API availability ### Testing Strategy - **Unit tests**: Services layer (QRRapidoService, AdDisplayService, etc.) - **Mocking**: MongoDB and IDistributedCache with Moq - **Coverage**: Run `dotnet test --collect:"XPlat Code Coverage"` - Test files in `Tests/Services/` ### Known Quirks & WSL Compatibility - **StaticWebAssets disabled**: Set `ASPNETCORE_HOSTINGSTARTUP__STATICWEBASSETS__ENABLED=false` for WSL path issues (see Program.cs:38-39) - **DataProtection**: Uses MongoDB for key persistence in production (Docker Swarm), filesystem in development - **Frontend build**: Vite runs during Release build via MSBuild target (`BuildFrontend` in .csproj) - **Stripe local testing**: Use `stripe listen` in WSL (see README.md:345-347) ### Monitoring & Logging - **Serilog** → Console (development) + OpenSearch (production) - **ResourceMonitoringService**: Background service tracking CPU/memory every 30s - **HistoryCleanupService**: Cleans old anonymous QR history (7-day grace period, runs every 6 hours) - **MongoDbMonitoringService**: Tracks database growth and collection stats (disabled by default) ### Premium Feature Gates Check user premium status via `IUserService.GetUserAsync(userId)` → `user.IsPremium` Premium benefits: - Unlimited QR codes (vs 10/day anonymous, 50/day free) - No ads permanently - Priority generation (faster SemaphoreSlim release) - Dynamic QR codes (editable) - API access ### Ad-Free Logic See `AdDisplayService.ShouldShowAdsAsync()`: - Anonymous users: always show ads - Premium users: never show ads - Free logged-in users: 30-day ad-free period from login (configurable in appsettings) - Ad-free sessions tracked in MongoDB `AdFreeSessions` collection ### Security Considerations - OAuth secure flow with PKCE - HTTPS redirect enforced (non-dev environments) - Stripe webhook signature verification - Input sanitization on QR generation - Rate limiting on API endpoints - HSTS enabled in production - Forwarded headers support for reverse proxy (Nginx) ### Common Workflows **Adding a new QR type:** 1. Update `Models/ViewModels/QRGenerationRequest.cs` with new type enum 2. Add generation logic in `Services/QRRapidoService.cs` → `GenerateQRCodeOptimizedAsync()` 3. Update frontend form in `Views/Home/Index.cshtml` 4. Add localized strings in `Resources/SharedResource.{culture}.resx` **Adding a new language:** 1. Create `Resources/SharedResource.{culture}.resx` 2. Update `Program.cs` supported cultures array (line 214-218) 3. Update route constraint regex (line 354) 4. Add culture provider mapping if needed **Debugging slow QR generation:** 1. Check `_logger` output in `QRRapidoService.GenerateRapidAsync()` for timing 2. Verify cache hit rate in logs 3. Check semaphore wait time (max concurrent limit) 4. Review `Performance:QRGenerationTimeoutMs` in appsettings 5. Monitor resource usage via `/healthcheck` **Updating Stripe configuration:** 1. Update `appsettings.json` → `Stripe` section 2. Verify webhook secret matches Stripe dashboard 3. Test locally with `stripe listen --forward-to ...` 4. Update `StripeService.cs` webhook handlers if event types change