Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

88 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RecipeManager

Clean-architecture recipe API (ASP.NET Core 10 + EF Core + PostgreSQL) with a React 19 / Vite frontend.

RecipeManager/
  RecipeManager.Domain/            entities, guard clauses
  RecipeManager.Application/       use cases, validators (FluentValidation/FluentResults)
  RecipeManager.Infrastructure/    EF Core DbContext, migrations
  RecipeManager.Api/               controllers, DI/startup, Swagger
  RecipeManager.UnitTests/         xUnit + NSubstitute
  RecipeManager.IntegrationTests/  xUnit + WebApplicationFactory (EF InMemory)
  recipe-manager-frontend/         React 19 + Vite + MUI

Prerequisites

Tool Version Notes
.NET SDK 10.0 All projects target net10.0. Pinned in RecipeManager/global.json with rollForward: latestFeature.
PostgreSQL 16 or newer Accessed via Npgsql. Default host/port localhost:5432.
Node.js 20 LTS or newer; 24 recommended Only needed for the frontend. engines declares the >=20 floor; recipe-manager-frontend/.nvmrc pins 24, which is what CI installs and what the project is tested on. nvm use in that folder picks it up.

Install on Windows:

winget install Microsoft.DotNet.SDK.10
winget install PostgreSQL.PostgreSQL.18 --interactive
winget install OpenJS.NodeJS.LTS

Open a new terminal afterwards so PATH picks up the new tools.

Backend

Run everything below from the RecipeManager/ folder (the one holding RecipeManager.sln).

dotnet restore RecipeManager.sln
dotnet build RecipeManager.sln

Database

Program.cs applies EF migrations at startup (app.MigrateDatabase()), so the API creates and updates the schema on first run — but it will fail to start if PostgreSQL is not reachable.

Create the role and database once (run from an elevated-enough shell; you'll be prompted for the postgres superuser password set during install):

& "C:\Program Files\PostgreSQL\18\bin\psql.exe" -U postgres -c "CREATE ROLE recipemanager LOGIN PASSWORD 'your-password';"
& "C:\Program Files\PostgreSQL\18\bin\createdb.exe" -U postgres -O recipemanager DbRecipeManager

RecipeManager.Api/appsettings.json holds a password-less template:

Host=localhost;Port=5432;Database=DbRecipeManager;Username=recipemanager;Timeout=90

Supply the password locally via user-secrets so it never reaches git (the API project already has a UserSecretsId):

dotnet user-secrets --project RecipeManager.Api set "ConnectionStrings:DefaultConnection" "Host=localhost;Port=5432;Database=DbRecipeManager;Username=recipemanager;Password=your-password"

In deployment, override the same key with the ConnectionStrings__DefaultConnection environment variable.

To apply migrations manually instead of at startup:

dotnet tool install --global dotnet-ef
dotnet ef database update --project RecipeManager.Infrastructure --startup-project RecipeManager.Api

Run the API

dotnet run --project RecipeManager.Api --launch-profile https
  • HTTPS: https://localhost:7231 (Swagger UI at /swagger)
  • HTTP: http://localhost:5249

Trust the local HTTPS certificate once, otherwise the browser and the Vite proxy will reject it:

dotnet dev-certs https --trust

Tests

dotnet test RecipeManager.sln

Unit tests with an HTML coverage report (requires dotnet tool install --global dotnet-reportgenerator-globaltool):

pwsh ./run-coverage.ps1

Frontend

cd recipe-manager-frontend
npm install
npm run dev

Serves on http://localhost:3000 — the origin the API's CORS policy (AllowReactApp) allows, so don't change the port without updating RecipeManager.Api/Startup/ServiceInitializer.cs.

.env.development points VITE_API_URL at https://localhost:7231/api. Delete or blank that variable to fall back to the relative /api path, which vite.config.ts proxies to the same backend.

Start the API first — the frontend has no mock backend.

Frontend checks

Run these before opening a pull request; nothing runs them for you yet.

npm run lint
npm run build

npm run build is tsc -b && vite build, so a type error fails it before Vite bundles anything. For a faster loop while working, npm run typecheck runs the same check without producing dist/. There is no npm test — no frontend test runner exists yet.

Continuous integration

.github/workflows/ci.yml runs on every pull request to main and every push to main, in two parallel jobs on ubuntu-latest:

Job Steps
Backend dotnet restore --locked-modedotnet build (Debug) → dotnet test (84) → vulnerable-package check
Frontend npm cinpm run typechecknpm run lintnpm run buildnpm audit --audit-level=high

Two things are worth knowing before a run surprises you:

  • NuGet restores from committed lock files. Every project has a packages.lock.json, and CI restores in locked mode. Change a package version and CI fails with NU1004 until you run dotnet restore RecipeManager.sln --force-evaluate and commit the updated lock files.
  • CI builds Debug on purpose. A Release build makes every integration test fail: the IntegrationTest environment throws in RELEASE builds by design, and WebApplicationFactory uses that environment name. See ADR-005 and ADR-013.

The checks are not yet required to merge — that is a branch-protection setting on main.

Docker

RecipeManager.Api/Dockerfile builds the API alone (no database container). Build from the RecipeManager/ folder so the COPY paths resolve:

docker build -f RecipeManager.Api/Dockerfile -t recipemanager-api .

The image needs a reachable PostgreSQL; pass the connection string via ConnectionStrings__DefaultConnection. Note that Host=localhost resolves to the container, not your machine — use host.docker.internal (Docker Desktop) or a compose service name instead.

Troubleshooting

You must install or update .NET to run this application / Framework 'Microsoft.NETCore.App', version 'X' not found The solution built, but the matching runtime is missing. Install the .NET 10 SDK (above); dotnet --list-runtimes should show a 10.x entry for both Microsoft.NETCore.App and Microsoft.AspNetCore.App.

API throws on startup with a Npgsql connection or authentication error PostgreSQL is not running, or the credentials are wrong. Check the service with Get-Service postgresql* in PowerShell, and confirm the password is set in user-secrets — the template in appsettings.json deliberately has none.

relation "recipes" does not exist when querying in psql PostgreSQL folds unquoted identifiers to lowercase, and EF creates the table as "Recipes". Quote it: SELECT * FROM "Recipes";

Frontend requests fail with a certificate error Run dotnet dev-certs https --trust.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages