A proof of concept online store created with Angular for the frontend, .NET Core for the backend, and Stripe as the payment gateway.
- Introduction
- Project structure & architecture
- Prerequisites
- Local setup — quick start (Docker)
- Local setup — dev mode (API + Angular separately)
- Configuration (appsettings, environment variables, Stripe)
- Database: migrations, seeding, and common tasks
- Running & debugging
- CI / Docker compose & production notes
- Stripe webhooks & payments
- Troubleshooting — common problems
- Contributing
- Useful commands
SkiNet is a proof-of-concept e-commerce application built with .NET 9 (API) and Angular 20 (client). It demonstrates a real-world stack using Entity Framework, Redis caching, Stripe payments, JWT authentication, and Docker for local services.
Use this document as a single-stop guide for getting the app running locally, understanding the architecture, and troubleshooting common issues.
At a glance (top-level folders):
API— .NET Web API project (controllers, authentication, payments, data access wiring).Core— domain models, interfaces, specifications (business layer abstractions).Infrastructure— EF Core DbContext, repositories, data access implementation, migrations.client— Angular 20 application (UI).docker-compose.yml— local services (SQL Server, Redis).skinet.sln— solution file.
Key architectural points:
- Clean-ish architecture: Core (domain) → Infrastructure (persistence) → API (presentation).
- Specification pattern implemented for flexible querying.
- Uses Redis for caching products/listings.
- Stripe integration for payments and webhook handling.
- Docker & Docker Compose
- .NET SDK 9
- Node.js (recommended versions noted in repo: ^20.19.0, ^22.12.0, or ^24.0.0)
- Git
- (Optional) mkcert if you want HTTPS for local Angular dev server
- (Optional for payments) Stripe account + Stripe CLI
- Clone the repo:
git clone https://github.com/TryCatchLearn/skinet.git
cd skinet- Restore .NET packages:
dotnet restore- Start required services (SQL Server + Redis) via Docker Compose:
docker compose up -dEnsure you do not have another SQL Server on port 1433 or Redis on 6379.
-
Create
API/appsettings.json(see Section 6) and populate the Stripe keys if you want payments to work. -
Run the API from the
APIfolder:
cd API
dotnet run- Browse to
https://localhost:5001(or the port displayed bydotnet run).
If you prefer running the Angular app separately (useful for hot reload):
- In the repo root, install client dependencies:
cd client
npm install- Generate or install a local certificate (the repo uses mkcert):
cd client/ssl
mkcert localhost- Run API:
cd ../API
dotnet run- Run client (in a separate terminal):
cd client
ng serveOpen the client on the default Angular dev server (usually http://localhost:4200) or the HTTPS port if configured.
Create API/appsettings.json with the following structure (replace placeholders):
{
"Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } },
"StripeSettings": {
"PublishableKey": "pk_test_REPLACEME",
"SecretKey": "sk_test_REPLACEME",
"WhSecret": "whsec_REPLACEME"
},
"AllowedHosts": "*"
}PublishableKeyandSecretKeyare from your Stripe account.WhSecretis the webhook signing secret from the Stripe CLI when using local forwarding.
Other secrets (DB connection string, JWT keys) are typically defined in the API project configuration (appsettings or secrets manager) — inspect API/Program.cs and the startup wiring.
- Migrations are located in the
Infrastructure/APIprojects depending on how the repo is arranged. Typical commands:
# from the API (or project with DbContext)
dotnet ef migrations add <Name> -s API -p Infrastructure
dotnet ef database update -s API -p Infrastructure-
If you use the included Docker SQL Server, ensure it is running (
docker compose up -d) before runningdatabase update. -
The project includes seed data and product import scripts (check
Infrastructurefor seed classes). Running the app may seed on startup.
- Use
dotnet runfor the API (inspect console for URLs). - Use
ng servefor the client. - For Visual Studio/VS Code, open
skinet.slnand run with debugger attached.
docker-compose.ymlbrings up SQL Server and Redis for local dev.- For production deployments, move secrets to environment variables or a key vault and configure appropriate production connection strings (Azure SQL, managed Redis).
- To test webhooks locally, install Stripe CLI and run:
stripe login
stripe listen --forward-to https://localhost:5001/api/payments/webhook -e payment_intent.succeeded- Copy the
whsec_...value printed in the terminal intoappsettings.jsonasWhSecret.
-
Docker port conflicts: ensure no other service uses ports 1433 (SQL Server) or 6379 (Redis).
-
Azure SQL transient error (SqlException 40613): This occurs when Azure SQL is paused/unavailable or the connection is throttled. If you see
SqlException 40613:- Confirm the database is online in Azure Portal.
- If using Serverless with auto-pause, resume the DB and restart the App Service.
- Add retry logic for transient errors or use built-in EF Core resiliency (EnableRetryOnFailure).
-
Stripe webhooks not hitting locally: ensure Stripe CLI is forwarding and
WhSecretmatches the CLI output. Use--forward-toto correct URL. -
Angular HTTPS issues: use mkcert or configure the dev server to accept self-signed certs.
- Fork the repo, create a feature branch, commit, and open a pull request.
- Follow repository code style and add tests for new features.
git clone https://github.com/TryCatchLearn/skinet.git
dotnet restore
docker compose up -d
cd API
dotnet run
cd client
npm install
ng serveThanks to Neil Cummings for his .NET Core and Angular course. It gave me the foundation for this project, and I’ve expanded it with my own additions.
























