An autonomous AI comedy application that fetches multi-part jokes, predicts punchlines using Azure OpenAI, rates them across multiple dimensions, and delivers an immersive medieval-themed comedy showβall without user input.
- Passive Comedy Loop: Autonomous, never-ending comedy show
- AI Punchline Prediction: GPT-4 attempts to guess punchlines before reveal
- Medieval Dark Theme: Immersive Gothic UI with custom fonts
- Text-to-Speech: British male voice narration
- Audio Effects: Drum roll before reveals, trombone on failures
- Joke Ratings: Cleverness, Rudeness, Complexity, and Difficulty scores
- Leaderboards: Browse historical jokes by rating category
- Diagnostics: Health checks for all external dependencies
- .NET 10 SDK (Preview)
- Azure CLI (for deployment)
- Docker Desktop (for Aspire local development)
Single command to start everything:
dotnet run --project src/PoJoker.AppHostThis will:
- π Start the Aspire Dashboard for monitoring all services
- π¦ Spin up Azurite container for local storage (persistent across restarts)
- π Launch the Po.Joker Blazor application
- π Automatically wire up all service connections
The Aspire Dashboard will open automatically and show:
- All running services and their status
- Real-time logs from all services
- Distributed traces across requests
- Metrics and health checks
cd src/PoJoker.AppHost
dotnet user-secrets set "Azure:OpenAI:Endpoint" "your-endpoint"If you prefer not to use Aspire:
-
Start Azurite manually
azurite --silent --location ./azurite --debug ./azurite/debug.log
-
Run the application directly
dotnet run --project src/Po.Joker
# Unit tests
dotnet test tests/Po.Joker.Tests.Unit
# All tests with coverage
dotnet test --collect:"XPlat Code Coverage"
# E2E tests (requires browser)
dotnet test tests/Po.Joker.Tests.E2EThis application uses .NET Aspire for orchestration and service discovery.
PoJoker/
βββ src/
β βββ PoJoker.AppHost/ # π Aspire orchestrator (start here!)
β βββ PoJoker.ServiceDefaults/ # Shared service defaults (telemetry, resilience)
β βββ Po.Joker/ # Server-side Blazor + API endpoints
β β βββ Features/ # Vertical slice architecture
β β β βββ Jokes/ # Joke fetching from JokeAPI
β β β βββ Analysis/ # AI punchline prediction
β β β βββ Leaderboards/ # Historical joke rankings
β β β βββ Diagnostics/ # Health checks
β β βββ Infrastructure/ # Cross-cutting concerns
β βββ Po.Joker.Client/ # Client-side Blazor WASM
β βββ Po.Joker.Shared/ # DTOs and contracts
βββ tests/
β βββ Po.Joker.Tests.Unit/ # xUnit unit tests
β βββ Po.Joker.Tests.E2E/ # Playwright E2E tests
βββ infra/ # Bicep IaC templates
βββ docs/ # Documentation
| Component | Purpose |
|---|---|
| PoJoker.AppHost | Orchestrates all services, manages Azurite container |
| PoJoker.ServiceDefaults | OpenTelemetry, health checks, service discovery, resilience |
| Po.Joker | Main Blazor Server + WASM application |
| Azurite | Local Azure Table Storage emulator (Docker container) |
-
Configure OIDC authentication (recommended)
- Create an Azure AD App Registration
- Add Federated Credentials for your GitHub repository
- Set repository secrets:
AZURE_CLIENT_IDAZURE_TENANT_IDAZURE_SUBSCRIPTION_IDOPENAI_API_KEY
-
(Alternative) Use a Service Principal secret
- Create a Service Principal and a client secret in Azure AD.
- Add a repository secret named
AZURE_CREDENTIALSwith a JSON value like:
{
"clientSecret":"<client-secret>",
"subscriptionId":"<subscription-id>",
"tenantId":"<tenant-id>",
"clientId":"<client-id>"
}- The workflow should use the
azure/login@v2action with:
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}- Ensure the secret value is valid JSON and contains these keys exactly (case-sensitive):
clientId,clientSecret,tenantId,subscriptionId. - After adding the secret, the workflow includes a verification step (
az account showandazd --version) that will fail early if login doesn't succeed.
- Deploy via workflow
- Push to
mainbranch for automatic deployment - Use manual workflow dispatch for specific environments
- Push to
# Login to Azure
azd auth login
# Initialize environment (first time only)
azd init
# Provision infrastructure and deploy to Azure Container Apps
azd upThis will:
- Create Azure Container Registry, Container App Environment, and Container App
- Build and push the Docker image
- Deploy the application to Azure Container Apps
The application includes comprehensive monitoring:
- Request/response logging
- AI latency tracking
- Error rate monitoring
- Custom metrics for joke analysis
See docs/kql/ for monitoring queries:
error-rates.kql- Error monitoring and anomaly detectionai-latency.kql- AI service performance tracking
| Variable | Description | Required |
|---|---|---|
OpenAI__ApiKey |
OpenAI API key for punchline prediction | No* |
Azure__StorageConnectionString |
Azure Table Storage connection | No* |
APPLICATIONINSIGHTS_CONNECTION_STRING |
App Insights connection | No |
*Uses mock/local services when not configured
{
"JokeSettings": {
"CacheEnabled": true,
"RateLimitPerMinute": 60,
"SafeMode": true
}
}Comprehensive documentation with visual diagrams is available in the /docs folder:
- ProductSpec.md β Business logic, features, success metrics, and scope
- DevOps.md β CI/CD pipeline, environment secrets, deployment strategies
- LocalSetup.md β Day 1 onboarding guide, Docker Compose, troubleshooting
Full Detail Diagrams:
- Architecture.mmd β C4 System Context: Azure services, Managed Identity, all connections
- ApplicationFlow.mmd β User journey: Auth β Comedy loop β Leaderboard navigation
- DataModel.mmd β Entity Relationship Diagram: Joke, Performance Score, Leaderboard entities
- ComponentMap.mmd β Component tree: Frontend hierarchy + Backend service dependencies
- DataPipeline.mmd β CRUD workflow: Fetch β Predict β Rate β Store β Display
Simplified Diagrams (High-level Overview):
- Architecture_SIMPLE.mmd
- ApplicationFlow_SIMPLE.mmd
- DataModel_SIMPLE.mmd
- ComponentMap_SIMPLE.mmd
- DataPipeline_SIMPLE.mmd
View Diagrams:
- Copy
.mmdfile content - Paste into Mermaid Live Editor
- Or use VS Code Markdown Preview Mermaid Support
- Screenshots β UI mockups of all pages in
/docs/screenshots/ - Improvement Suggestions β ImprovementSuggestions.md
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β User Browser (WebSocket/HTTP) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββΌβββββββββββ
β Blazor Web App β
β (.NET 10) β
β β’ JesterStage β
β β’ Leaderboard β
β β’ Diagnostics β
βββββββββββ¬βββββββββββ
βββββββββββββββββββββΌββββββββββββββββββββ
β β β
ββββββΌβββββ ββββββββΌββββββββ βββββββΌβββββ
β JokeAPI β β Azure OpenAI β β Storage β
β Public β β (GPT-4) β β (Tables) β
β REST β β + Key Vault β β + Azuriteβ
βββββββββββ ββββββββββββββββ ββββββββββββ
See Architecture.mmd for detailed C4 diagram
| Endpoint | Method | Description |
|---|---|---|
/api/jokes/fetch |
GET | Fetch a random joke from JokeAPI |
/api/jokes/analyze |
POST | Get AI punchline prediction and ratings |
/api/leaderboard |
GET | Retrieve joke leaderboard |
/api/diagnostics |
GET | Health check status |
/health |
GET | Simple health probe |
- 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 MIT License - see the LICENSE file for details.
- JokeAPI for the joke database
- Azure OpenAI for AI capabilities
- Radzen Blazor for UI components