Sandbox
@platformplatform/PlatformPlatform

Azure SaaS starter for Claude Code and .NET

PlatformPlatform is a cloneable blueprint for multi-tenant SaaS on Azure. It combines a .NET backend, React frontend, Bicep infrastructure, Aspire local setup, and a Claude Code multi-agent workflow so you can start from opinionated app structure instead of assembling the stack yourself.

441 stars52 forksC#Updated 1mo ago
Who it's for

Builders who want a ready-made SaaS base for Azure, .NET, React, and Claude Code.

What it delivers

You can start from a working enterprise SaaS blueprint instead of assembling the app, infra, and agent workflow from scratch.

What it does

Multi-tenant SaaS app

Includes signup, login, account settings, user management, billing, sessions, and a back-office dashboard.

Claude Code workflow

Ships with `.claude/` rules, skills, agents, hooks, and reference files for agent-led feature work.

Developer CLI

Provides the `pp` command for installing the CLI, running the local stack, and setting up deployments.

Azure deployment setup

Uses GitHub Actions, Bicep, and Azure Container Apps for automated deployments.

Typed backend and frontend

Pairs .NET 10 and CQRS/vertical slice architecture with React 19, TypeScript, TanStack Router, and TanStack Query.

How to get it

  1. 1Open a PowerShell terminal as Administrator and run the following command to install…
    wsl --install
  2. 2From an Administrator PowerShell terminal, use winget (preinstalled on Windows 11) to…
    winget install Microsoft.DotNet.SDK.10
    winget install Git.Git
    winget install Docker.DockerDesktop
    winget install Microsoft.AzureCLI
    winget install GitHub.cli
  3. 3Install Node.js — the version must match .node-version. We recommend fnm which…
    # Option A: fnm (recommended)
    winget install Schniz.fnm
    
    # Option B: Node.js directly
    winget install OpenJS.NodeJS
  4. 4(Recommended) Install the Aspire CLI — provides the Aspire MCP server so Claude Code can…
    irm https://aspire.dev/install.ps1 | iex
  5. 5(Recommended) Install language servers for enhanced Claude Code support
    npm install -g typescript-language-server typescript
    dotnet tool install -g csharp-ls
  6. 6Install packages
    brew install --cask dotnet-sdk
    brew install --cask docker
    brew install git azure-cli gh

README

PlatformPlatform Resource Groups

App Gateway Account Main Cloud Infrastructure

GitHub issues with enhancement label GitHub issues with roadmap label GitHub issues with bug label

Quality Gate Status Security Rating Reliability Rating Maintainability Rating

👋 Welcome to PlatformPlatform

Kick-start building top-tier B2B & B2C cloud SaaS products with sleek design, fully localized and accessible, vertical slice architecture, automated and fast DevOps, and top-notch security.

Ships with signup and login via Google or email one-time password, Stripe-powered subscription and payment management with plan upgrades, downgrades, and invoicing, feature flags with A/B-rollout, plan-gating, and per-user/tenant overrides, and a back-office dashboard with MRR and revenue trends, plan distribution, and tenant growth.

Built to demonstrate seamless flow: backend contracts feed a fully-typed React UI, pipelines make fully automated deployments to Azure, and a multi-agent workflow built on Claude Code's native Agent Teams where PlatformPlatform-expert agents collaborate to deliver complete features following the opinionated architecture. Think of it as a ready-made blueprint, not a pile of parts to assemble.

What's inside

  • Backend - .NET 10 and C# 14 following the principles of vertical slice architecture, DDD, CQRS, and clean code
  • Frontend - React 19, TypeScript, TanStack Router & Query, ShadCN 2.0 with Base UI for accessible UI
  • CI/CD - GitHub actions for fast passwordless deployments of docker containers and infrastructure (Bicep)
  • Infrastructure - Cost efficient and scalable Azure PaaS like Azure Container Apps and PostgreSQL
  • Developer CLI - Extendable .NET CLI for DevEx - set up CI/CD is one command and a couple of questions
  • AI rules - 30+ rules & skills, refined and battle-tested over a year of daily use, capturing our opinionated patterns
  • Multi-agent development - Agent Teams workflow where specialized Claude Code agents with deep PlatformPlatform expertise collaborate end-to-end

Follow our up-to-date roadmap.

Show your support for our project - give us a star on GitHub! It truly means a lot! ⭐

Back office

Operate the platform from a dedicated SPA on its own hostname, secured by Entra ID Easy Auth:

  • Dashboard - KPI tiles for total accounts, blended MRR, all-time revenue, active users, and live sessions; trend cards for MRR, revenue, tenant growth, plan distribution, user logins; activity feeds for recent signups, payments, logins, and Stripe webhook events
  • Accounts - Search and filter every tenant; drill into detail with owner, plan, and signup activity
  • Users - Cross-tenant user list with role and last-seen filters; drill into per-user profile and tenant
  • Invoices - Paginated invoice ledger across every account with Stripe drift detection so finance can reconcile what's in Stripe vs. what landed in the database
  • Billing events - Authoritative event log of subscription, payment, and billing transitions, filterable by event type and account, with deep-link from dashboard cards
  • Feature flags - Four levers (System / Subscription plan / Account / User) plus A/B-rollout with rich telemetry; declared in C# and surfaced as a strongly-typed React hook; back-office UI for rollouts and overrides
PlatformPlatform Back Office

User-facing SaaS product

Production-ready end-user surfaces — fully localized, accessible, and ready to brand as your own product:

  • Signup - Tenant signup with email one-time password or Google OAuth (OpenID Connect with PKCE)
  • Login - Same OTP and Google sign-in flows, with UNLOCK shortcut on localhost so dev mail is optional
  • Welcome - First-run guided flow for naming the account, uploading a logo, and inviting colleagues
  • Account settings - Owner-editable account name, logo, and danger-zone account deletion
  • User management - Invite users, change roles (Owner/Admin/Member), bulk delete, and recycle-bin restore
  • Subscription & billing - Embedded Stripe Checkout & Payment Element, prorated upgrades/downgrades, billing-info editing, scheduled-downgrade banner, dunning, and payment history with invoices and credit notes
  • User profile - Personal profile with avatar upload (Gravatar fallback), first/last name, email, and job title
  • User preferences - Theme (light/dark/system) and zoom per device, language per profile
  • Sessions - Active session list with device type, browser, and OS, plus one-click revocation of any session
PlatformPlatform Demo

Getting Started

TL;DR: Requires .NET 10, Node, and Docker. Clone the repo and dotnet run from developer-cli/ to start Aspire.

Prerequisites

For development, you need .NET, Docker, and Node. And GitHub and Azure CLI for setting up CI/CD.

Install prerequisites for Windows
  1. Open a PowerShell terminal as Administrator and run the following command to install Windows Subsystem for Linux (required for Docker). Restart your computer if prompted.

    wsl --install
    
  2. From an Administrator PowerShell terminal, use winget (preinstalled on Windows 11) to install any missing packages:

    winget install Microsoft.DotNet.SDK.10
    winget install Git.Git
    winget install Docker.DockerDesktop
    winget install Microsoft.AzureCLI
    winget install GitHub.cli
    
  3. Install Node.js — the version must match .node-version. We recommend fnm which auto-installs the exact version via the Developer CLI. When using an IDE like Rider, ensure the active fnm version matches .node-version.

    # Option A: fnm (recommended)
    winget install Schniz.fnm
    
    # Option B: Node.js directly
    winget install OpenJS.NodeJS
    
  4. (Recommended) Install the Aspire CLI — provides the Aspire MCP server so Claude Code can inspect AppHost resources, logs, and traces:

    irm https://aspire.dev/install.ps1 | iex
    

    Verify with aspire --version. Restart your terminal if the command is not yet on PATH.

  5. (Recommended) Install language servers for enhanced Claude Code support:

    npm install -g typescript-language-server typescript
    dotnet tool install -g csharp-ls
    
Install prerequisites for Mac

Open a terminal and run the following commands (if not installed):

  1. Install Homebrew, a package manager for Mac

  2. Install packages

    brew install --cask dotnet-sdk
    brew install --cask docker
    brew install git azure-cli gh
    
  3. Install Node.js — the version must match .node-version. We recommend fnm which auto-installs the exact version via the Developer CLI. When using an IDE like Rider, ensure the active fnm version matches .node-version.

    # Option A: fnm (recommended)
    brew install fnm
    
    # Option B: Node.js directly
    brew install node
    
  4. (Recommended) Install the Aspire CLI — provides the Aspire MCP server so Claude Code can inspect AppHost resources, logs, and traces:

    curl -sSL https://aspire.dev/install.sh | bash
    

    Verify with aspire --version. Restart your terminal if the command is not yet on PATH.

  5. (Recommended) Install language servers for enhanced Claude Code support:

    npm install -g typescript-language-server typescript
    dotnet tool install -g csharp-ls
    
Install prerequisites for Linux (Ubuntu/Debian)

Open a terminal and run the following commands (if not installed):

  1. Install basic tools

    sudo apt update && sudo apt install -y git wget curl libnss3-tools
    
  2. Add Microsoft package repository

    source /etc/os-release
    wget https://packages.microsoft.com/config/$ID/$VERSION_ID/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
    sudo dpkg -i packages-microsoft-prod.deb
    rm packages-microsoft-prod.deb
    
  3. Install .NET SDK and Docker

    sudo apt-get update && sudo apt-get install -y dotnet-sdk-10.0 docker.io docker-compose-v2
    
    sudo systemctl enable --now docker
    sudo usermod -aG docker $USER
    
  4. Install Node.js — the version must match .node-version. We recommend fnm which auto-installs the exact version via the Developer CLI. When using an IDE like Rider, ensure the active fnm version matches .node-version.

    # Option A: fnm (recommended)
    curl -fsSL https://fnm.vercel.app/install | bash
    
    # Option B: Node.js directly
    curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -
    sudo apt-get install -y nodejs
    
  5. (Recommended) Install the Aspire CLI — provides the Aspire MCP server so Claude Code can inspect AppHost resources, logs, and traces

    curl -sSL https://aspire.dev/install.sh | bash
    

    Verify with aspire --version. Restart your terminal if the command is not yet on PATH.

  6. Trust the HTTPS development certificate

    echo 'export SSL_CERT_DIR="$HOME/.aspnet/dev-certs/trust:${SSL_CERT_DIR:-/usr/lib/ssl/certs}"' >> ~/.bashrc
    
    source ~/.bashrc
    
    dotnet dev-certs https --trust
    
  7. Log out and log back in to apply Docker group and shell configuration changes.

  8. (Recommended) Install language servers for enhanced Claude Code support

    npm install -g typescript-language-server typescript
    dotnet tool install -g csharp-ls
    
  9. (Optional) If using Snap Chromium, trust the certificate in its sandbox

    certutil -d sql:$HOME/snap/chromium/current/.pki/nssdb -L >/dev/null 2>&1 || (mkdir -p $HOME/snap/chromium/current/.pki/nssdb && certutil -d sql:$HOME/snap/chromium/current/.pki/nssdb -N --empty-password)
    dotnet dev-certs https --trust
    
  10. (Optional) Install GitHub CLI and Azure CLI (needed for CI/CD setup)

(type -p wget >/dev/null || (sudo apt update && sudo apt-get install wget -y)) \
&& sudo mkdir -p -m 755 /etc/apt/keyrings \
&& wget -qO- https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
&& sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
sudo apt-get update && sudo apt-get install -y gh
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

1. Clone the repository

git clone https://github.com/platformplatform/PlatformPlatform.git

We recommend you keep the commit history, which serves as a great learning and troubleshooting resource. 😃

2. (Optional) Install the Developer CLI

The PlatformPlatform CLI provides convenient commands for common tasks. From the cloned repository, install it globally to use the pp command from anywhere in your terminal.

cd developer-cli
dotnet run install

Restart your terminal to make the pp command available.

Developer CLI

3. Run the Aspire AppHost to spin up everything on localhost

Using Aspire, docker images with PostgreSQL, Blob Storage emulator, and development mail server will be downloaded and started. No need to install anything, or learn complicated commands. Simply run this command, and everything just works 🎉

With the CLI installed:

pp run # First time downloading Docker containers will take several minutes

Pass an optional base port (e.g. pp run 11000) to run a parallel stack from another worktree.

Or without the CLI:

cd application/AppHost
dotnet run

On first startup, Aspire will prompt for stripe-enabled -- enter true to configure Stripe integration (see the optional Stripe setup section below) or false to skip.

Once the Aspire dashboard fully loads, click to the WebApp and sign up for a new account (https://app.dev.localhost:9000/signup). A one-time password (OTP) will be sent to the development mail server, but for local development, you can always use the code UNLOCK instead of checking the mail server.

3.1 (Optional) Set up Google OAuth for "Sign in with Google" on localhost

PlatformPlatform supports authentication via Google OAuth using OpenID Connect with PKCE. This is optional for local development since email-based one-time passwords work without any configuration. The Aspire dashboard prompts whether to enable Google OAuth on first startup.

Google Cloud Console setup
  1. Go to Google Cloud Console
  2. Create a new project (e.g., "YourProduct OAuth")
  3. Navigate to APIs & Services > Credentials
  4. Configure OAuth consent screen (first time only):
    • App name, support email, audience (External), contact info
    • Agree to Google API Services: User Data Policy
  5. Create OAuth client ID:
    • Application type: "Web application"
    • Name: "YourProduct Localhost"
  6. Add Authorized redirect URIs (Google does not allow https://app.dev.localhost:9000/):
    • https://localhost:9000/api/account/authentication/Google/login/callback
    • https://localhost:9000/api/account/authentication/Google/signup/callback
  7. Note the Client ID and Client Secret

Aspire parameter configuration (two restarts required):

  1. First restart: Aspire prompts whether to enable Google OAuth. Enter true to enable or false to skip. Once entered, restart Aspire.
  2. Second restart: Aspire prompts for the Client ID and Client Secret. Enter the values from the Google Cloud Console, then restart Aspire to apply the configuration.

All values are stored securely in .NET user secrets and persist across restarts.

3.2 (Optional) Set up Stripe sandbox for localhost

PlatformPlatform includes a comprehensive Stripe integration for subscription management and payments: embedded Stripe checkout and payment elements, prorated plan upgrades and downgrades, tax management, localized UI and invoice text, refund overview in billing history, telemetry events for the subscription lifecycle, grandfather pricing for existing subscribers, dunning and failed payment recovery, and full sync between Stripe and the local database via webhooks. The Stripe Dashboard must be set up and configured according to the Stripe Dashboard setup guide below before enabling Stripe in Aspire.

Stripe Dashboard setup

Each developer needs their own Stripe sandbox. The local database stays in sync with Stripe via webhook events -- when payments, subscriptions, or billing details change in Stripe, webhook events update the local database with matching customer and subscription IDs. If developers share a sandbox, webhook events from one developer's actions would corrupt another developer's local database.

  1. Create a sandbox: Go to Stripe Dashboard and create an account. Click the account picker (top-left) > Sandboxes > Create. Name it dev-yourname and open it. All subsequent steps are performed inside your sandbox.
  2. Create products: Navigate to Product catalog > + Create product. Create a Standard product with Recurring / Monthly pricing (e.g., 19 EUR), then a Premium product (e.g., 39 EUR). Important: Click More pricing options and add standard_monthly and premium_monthly respectively in the Lookup key field.
  3. Disable non-card payment methods: Go to Settings (gear icon) > Payments > Payment methods. Turn off every payment method except Cards (and Cartes Bancaires which cannot be disabled)
  4. Limit to 1 subscription: Go to Settings > Payments > Checkout and Payment Links, scroll to Subscriptions, and enable Limit customers to 1 subscription. Add link to https://app.dev.localhost:9000/account/billing
  5. Configure failed payment recovery: Go to Settings > Billing > Subscriptions and emails > Manage failed payments, and configure desired retry behavior
  6. Configure email notifications: Go to Settings > Billing > Subscriptions and emails > Email notifications and customer management, and enable all settings as you see fit. Set "Use your own custom link" to https://app.dev.localhost:9000/account/billing
  7. Enable 3D Secure: Go to Settings > Billing > Subscriptions and emails > Manage payments that require confirmation, and check off Enable 3D Secure. The embedded Stripe components support showing e.g. Visa and Danish MitID multi-factor confirmation dialogs
  8. Set invoice prefix: Go to Settings > Billing > Invoices. In the Invoice numbering section, change the Invoice prefix to something meaningful for your organization, and optionally reset the Invoice sequence if needed
  9. Disable payment link in invoice emails: Go to Settings > Billing > Invoices and uncheck Include a link to a payment page in the invoice email
  10. Set up Tax: Go to More > Tax > Locations > + Add test registration and follow the guide. Below is an example for a Danish company (adapt based on your business):
    • Fill out the "Add head office address" side pane with your company address. Click Continue
    • In "Add Tax registration" select your country (e.g., Denmark) and I'm already registered. Click Continue
    • Select Domestic (e.g., "registered in Denmark"). Click Continue
    • Select No to "Do you want to collect VAT on cross-border sales...". Click Continue
    • Select Yes to "Have your sales of goods or digital services... been less than EUR 10,000". Click Continue
    • Select Start collecting immediately in "Schedule tax collection". Click Continue
    • Select Software as a service (SaaS) - business use in "Confirm your tax rates" (should show 25% for Denmark). Click Start collecting
  11. Get API keys: Navigate to Developers > API keys. Note the Publishable key (pk_test_...) and Secret key (sk_test_...). These will be needed for the Aspire configuration below.

Aspire parameter configuration (two restarts required):

  1. First restart: Aspire prompts for the Publishable key and Secret key (API key). Once entered, the Stripe CLI container starts and connects to Stripe. Find the generated webhook signing secret in either:
    • The Stripe Dashboard under Developers > Workbench > Webhooks -- click the three-dot menu on the event destination to reveal the signing secret
    • The stripe-cli container logs in the Aspire dashboard (look for "Your webhook signing secret is whsec_...")
  2. Second restart: Aspire prompts for the Webhook secret. Enter the whsec_ value from the previous step.

All values are stored securely in .NET user secrets and persist across restarts.

4. Set up CI/CD with passwordless deployments from GitHub to Azure

Run this command to automate Azure Subscription configuration and set up GitHub Workflows for deploying Azure Infrastructure (using Bicep) and compiling application code to Docker images deployed to Azure Container Apps:

cd developer-cli
dotnet run deploy # Tip: Add --verbose-logging to show the used CLI commands

You need to be the owner of the GitHub repository and the Azure Subscription, plus have permissions to create Service Principals and Active Directory Groups.

The command will first prompt you to login to Azure and GitHub, and collect information. You will be presented with a complete list of changes before they are applied. It will look something like this:

![Configure Continuous Deployments](https://

Files in the repo

Repository payload11 top-level entries
  • .claude
  • .github
  • application
  • cloud-infrastructure
  • developer-cli
  • .gitattributes
  • .gitignore
  • .mcp.json
  • AGENTS.md
  • LICENSE
  • README.md

Discussion (0)

Ask about usage, or say what you built with it

Sign in to join the discussion.

No comments yet. Be the first to say what this is good for.

More templates

CopilotKit/
OpenBot

Open-source AI coworkers that each get a computer of their own: a browser, files and tools, with every action decided before it happens and recorded after. Bring any AG-UI agent.

4.6k
Donchitos/
Claude-Code-Game-Studios

Turn Claude Code into a full game dev studio — 49 AI agents, 72 workflow skills, and a complete coordination system mirroring real studio hierarchy.

25k

A self-organizing Obsidian vault that gives AI coding agents persistent memory. Claude Code, Codex CLI, Gemini CLI.

4.6k
idavidov13/
agentic-playwright

Production-grade Playwright + TypeScript Scaffold for Agentic Testing. Harness for all major AI coding agents baked in.

163
gavishap/
omnia-vault

Omnia Vault - the all-in-one project brain: an Obsidian LLM wiki, Graphify code graphs, a living plan that triages new videos against itself, and a Claude Code ⇄ Codex relay. Everything your project knows, in one clonable vault.

60

🎬 Tạo video "so sánh kiến thức" ngắn tự động — HyperFrames + AI voice, 1 template nhiều chủ đề.

169