I hate COVID-19, keeping us all couped up inside, but you know what I do love, Cards Against Humanity, and Blazor, and Azure Functions. So all of that combined with some free time and free Azure credits has produced this monstrosity.
This game should contain about 7k black prompt cards and about 24k White response cards, so I think that is just about every card ever made.
NOTE: As per CAH's T&Cs, I am not making anything off this and anyone who wants it can have it
Why the fuck not?
- Frontend: React 19 + TypeScript with Vite
- Backend: Azure Functions v4 (.NET 8.0) with Isolated Worker Model
- State Management: Redux Toolkit
- Infrastructure: Azure Static Web Apps + Azure Functions + Azure Table Storage
- Deployment: GitHub Actions + Bicep IaC
- Real-time: Long Polling for state synchronization
- Storage: ActorTableEntities v2.1.0 for actor-based table storage with blob locking
- Local Development: Azure Static Web Apps CLI
- .NET 8.0 SDK
- .NET 6.0 SDK (for Azure Functions)
- Azure CLI (for deployment)
- Azure Functions Core Tools (for local development)
- .NET 8.0 SDK
- Node.js 20.x+
- Azure Functions Core Tools v4
- Azure Static Web Apps CLI (installed as dev dependency)
- Azure Storage Emulator (Azurite) or Azure Storage connection string
cd api
dotnet restore
dotnet build --configuration ReleaseThe Azure Static Web Apps CLI provides local development with automatic API routing without CORS issues.
-
Set up local.settings.json for Azure Functions:
cd api/CardsAgainstHumanity.Api cp local.settings.json.example local.settings.json # Edit local.settings.json with your storage connection strings
-
Option 1 - Use SWA CLI (Recommended):
First, start the API in one terminal:
cd api/CardsAgainstHumanity.Api func startThen, in another terminal, start the SWA CLI:
cd web npm install npm startThe app will be available at
http://localhost:4280with API automatically routed through/api/*. -
Option 2 - Run separately (for debugging):
Terminal 1 - Start the API (Azure Functions):
cd api/CardsAgainstHumanity.Api func startTerminal 2 - Start the React app:
cd web npm install npm run devThe React app will be available at
http://localhost:5173and will connect to the API athttp://localhost:7071/api.
The infrastructure is managed using Bicep templates in the infrastructure/ directory.
-
Login to Azure:
az login
-
Create Resource Group:
az group create --name rg-cards-against-covid --location eastus
-
Deploy Infrastructure:
az deployment group create \ --resource-group rg-cards-against-covid \ --template-file infrastructure/main.bicep \ --parameters infrastructure/parameters.json
Deployment is automated via GitHub Actions:
- PR Build (
.github/workflows/pr-build.yml): Builds and validates on pull requests - Release (
.github/workflows/release.yml): Deploys infrastructure and applications to Azure
-
Create an Azure Service Principal:
az ad sp create-for-rbac --name "github-cards-against-covid" --role contributor \ --scopes /subscriptions/{subscription-id}/resourceGroups/rg-cards-against-covid \ --sdk-auth -
Add the output as a secret named
AZURE_CREDENTIALSin your GitHub repository.
.
├── api/ # .NET 8.0 Backend
│ ├── CardsAgainstHumanity.Api/ # Azure Functions backend
│ ├── CardsAgainstHumanity.Application/ # Shared business logic
│ ├── CardsAgainstHumanity.sln # .NET solution file
│ └── Directory.Build.props # Build properties
├── web/ # React + TypeScript frontend
│ ├── src/ # React components and logic
│ ├── public/
│ │ └── staticwebapp.config.json # Static Web App routing config
│ └── swa-cli.config.json # SWA CLI local development config
├── infrastructure/ # Bicep infrastructure templates
│ ├── main.bicep # Main infrastructure template
│ ├── parameters.json # Environment parameters
│ └── README.md # Infrastructure documentation
└── .github/workflows/ # GitHub Actions workflows
├── pr-build.yml # PR validation workflow
├── release.yml # Deployment workflow (dev/staging)
└── tag-release.yml # Production deployment workflow
Versions are now manually managed in project files (.csproj). Update the <Version>, <AssemblyVersion>, and <FileVersion> properties as needed.
Current version: 1.0.0
The api/CardsAgainstHumanity.Application library contains shared business logic and is used by the API project.
These rules may be lightly adapted for me and my friend, as it was built for us and not you, so STFU.
http://stcardshumanity.z33.web.core.windows.net/
Literally type a name for the lobby, click start
Enter your name and click, Join game
You should now have joined the game
You can also lock the game so others cant join
Hit the New round button to bring up a prompt 'black' card
If you dont like it, you can change the prompt and users can reset their responses, or you can simply restart the round and start it again
Top right nav is all your cards
If you dont like them, you can mix it up by replacing one, or scrolling to the bottom of the cards page and changing them all.
When you find the card(s) to play, click select, then scroll to the bottom and hit Respond
Once everyone has voted you can have a look at their responses, or read them out if you like
You can then vote for your favourite, even yourself you scumbag.
Then you can hit the Reveal winner button to see who was the most offensive.
When you start a new round the leaderboard on the front Stats page is updated to reflect the last round winner.
When the game is over the person with the most black card round wins is the champ.
This project uses ActorTableEntities v2.0.0, a lightweight actor-based locking mechanism for Azure Table Storage:
https://github.com/micklaw/Actor-Table-Entities
ActorTableEntities provides:
- Quick response times (no queuing overhead)
- Actor-based concurrency control with blob locking
- Simple API for entity operations
- Support for .NET 8 and Azure Functions v4 isolated worker model
- Cost-effective alternative to Durable Entities for low-to-medium scale scenarios
Free and open source as per Cards Against Humanity's terms and conditions.