- Real-time multiplayer maze-racing web app showcasing full‑stack delivery, secure APIs, cloud integrations, and resilient front-end UX.
- Stack: .NET 8 (REST API + SignalR), React + TypeScript, EF Core, Azure SQL/Blob/Key Vault, optional OpenAI, Swagger, GitHub Actions (Azure Static Web Apps).
- Highlights: JWT + refresh tokens, policy-based rate limiting, API versioning, server-side image processing, move validation, disconnect handling, auto-reconnect.
- Real‑time systems: SignalR groups, server‑side move validation, disconnect/reconnect flows.
- Secure APIs: JWT + refresh tokens, CORS, API versioning, rate limiting, SHA‑256 password hashing.
- Cloud/Azure: SQL Database with EF Core, Blob Storage (ImageSharp processing), Key Vault via DefaultAzureCredential.
- AI integration: Optional OpenAI‑driven maze generation with graceful local fallback.
- Frontend engineering: React + TypeScript, guarded routes, axios interceptors with token refresh, keyboard + mobile swipe controls.
- DevOps: GitHub Actions CI/CD deploying frontend to Azure Static Web Apps.
ASP.NET Core · SignalR · Entity Framework Core · Azure SQL Database · Azure Key Vault · Azure Blob Storage · JWT · Refresh Tokens · API Versioning · Rate Limiting · CORS · Swagger · React · TypeScript · Axios Interceptors · OpenAI · ImageSharp · GitHub Actions · Azure Static Web Apps
GridRunners is a multiplayer maze racing experience for the web. The project pairs a .NET 8 backend (REST API + SignalR hub) with a React 19 frontend so players can authenticate, gather in lobbies, and race through procedurally generated mazes. The stack leans on Azure services (SQL Database, Blob Storage, Key Vault, OpenAI) but falls back to local generation when cloud integrations are unavailable.
Backend/GridRunners.Core/– shared models, entity configurations, DTOs, and the maze generation abstractions used by every service.Backend/GridRunners.Api/– ASP.NET Core Web API that exposes authentication, user profile, and maze lobby endpoints.Backend/GridRunners.SignalR/– ASP.NET Core SignalR host that streams real-time gameplay updates and optionally drives maze creation through Azure OpenAI.frontend/– React + TypeScript client that manages auth, lobby flows, and the live maze UI (keyboard + swipe).
Key capabilities
- JWT authentication with refresh tokens. User accounts are provisioned on first-login and secured with SHA-256 password hashing.
- Rate limiting policies:
/Auth/logincapped at 5 requests per 5 minutes per IP, authenticated routes at 100 requests/min per user. - API versioning (url segments or
?api-version=), swagger UI enabled in Development. - SQL Server persistence via Entity Framework Core, including many-to-many relationships between users and games.
- Azure Blob Storage integration for profile images (images resized to a max 1024px before upload).
- Azure Key Vault + DefaultAzureCredential to hydrate secrets (JWT signing key, storage credentials).
Primary routes (/api/v1/…)
POST Auth/login,POST Auth/refresh,POST Auth/logout.POST MazeGame(create),GET MazeGame/available,POST MazeGame/{id}/join,DELETE MazeGame/{id}.PUT User/display-name,POST User/profile-image,GET User/profile.
Run locally
- Install .NET SDK 8.0 and ensure SQL Server (local or remote) is reachable.
- Configure secrets (environment variables or
dotnet user-secrets):ConnectionStrings__DefaultConnectionKeyVault__Url(if skipping Key Vault, provideAuth__Secretdirectly in appsettings)AzureStorage__AccountName,AzureStorage__ContainerName,AzureStorage__UserImagesPathAuth__Issuer,Auth__Audience,Auth__ExpirationHours,Auth__SecretKeyName
- Apply migrations:
dotnet ef database update --project Backend/GridRunners.Api - Run:
dotnet run --project Backend/GridRunners.Api(listens onhttps://localhost:7119by default).
Highlights
- Shares the same SQL database so hub events reflect REST mutations instantly.
- Authenticates via the same JWT issuer/audience; tokens are accepted via query string for WebSocket handshakes.
MazeGameHubkeeps players in SignalR groups, broadcasts movement, detects disconnects, and tears down empty lobbies.- Optional Azure OpenAI integration (
OpenAI.Enabled=true) generates balanced mazes; when disabled or failing, the fallback generator inMazeGameruns server-side.
Run locally
- Mirror the API configuration for
ConnectionStrings,KeyVault, andAuthentication. - Set OpenAI keys (if used) in Key Vault entries referenced by
OpenAIconfiguration. - Launch with
dotnet run --project Backend/GridRunners.SignalR(defaulthttps://localhost:7092).
MazeGamedomain model enforces lobby limits, winner tracking, grid validation, and supports both AI-generated and locally generated mazes.Userentity encapsulates password rules, refresh-token lifecycle, and profile metadata.- DTOs (
AuthDto,MazeGameDtos,UserDtos) define the serialized contracts consumed by both API and frontend.
Key capabilities
- Auth context that stores tokens in
localStorage, auto-refreshes on 401 responses, and drives guarded routes. - REST clients (
axioswith interceptors) for Auth/User/MazeGame endpoints, usingprocess.env.BACKEND_API_URL(defaults tohttps://localhost:7119/api/v1). - SignalR service that reconnects with backoff and handles move, start, and game-over events.
- Pages: login with live validation, profile & match history, lobby join/manage, real-time game board with keyboard + touch controls.
Run locally
- Install Node.js 18+.
- In
frontend/, create.enventries as needed:BACKEND_API_URL=https://localhost:7119/api/v1REACT_APP_API_URL=https://localhost:7092
- Install dependencies:
npm install - Start the dev server:
npm start(served athttp://localhost:3000).
| Component | Keys | Purpose |
|---|---|---|
| API | ConnectionStrings__DefaultConnection |
SQL Server connection string |
| API | Auth__Issuer, Auth__Audience, Auth__ExpirationHours, Auth__Secret or Auth__SecretKeyName |
JWT issuance settings |
| API | AzureStorage__AccountName, AzureStorage__ContainerName, AzureStorage__UserImagesPath |
Blob storage for profile images |
| API & SignalR | KeyVault__Url / Authentication__SecretKeyName |
Azure Key Vault endpoint to pull secrets |
| SignalR | OpenAI__Enabled plus secret key names (ModelIdKeyName, etc.) |
Toggle AI maze generation and point to Key Vault secrets |
| Frontend | BACKEND_API_URL, REACT_APP_API_URL |
REST base URL and SignalR hub URL |
- Player logs in (new usernames are auto-created) and lands on the profile page.
- Lobby view lists joinable games; creating a lobby immediately registers the creator as the first participant.
- When ready, players signal the hub to start—the hub generates/loads the maze, assigns colors/positions, and emits
GameStartedwith the grid state. - Clients send discrete move requests via SignalR; the server validates collisions, finishes, and broadcasts
PlayerMovedandGameOverevents. - Disconnect handling removes idle players and, if everyone leaves, cleans up the lobby/game records.