{"id":48676180,"url":"https://github.com/dahln/dahln.stack","last_synced_at":"2026-06-08T06:01:06.338Z","repository":{"id":65520167,"uuid":"593055304","full_name":"dahln/Dahln.Stack","owner":"dahln","description":"My preferred stack - .NET and React","archived":false,"fork":false,"pushed_at":"2026-04-13T00:56:01.000Z","size":7848,"stargazers_count":5,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-05-28T04:00:03.639Z","etag":null,"topics":["asp-net-core","csharp","dotnet","react","sqlite","template","webapi"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dahln.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["dahln"]}},"created_at":"2023-01-25T05:39:05.000Z","updated_at":"2026-04-13T00:56:05.000Z","dependencies_parsed_at":"2024-01-24T19:45:15.098Z","dependency_job_id":"30ae6016-4451-4eac-9698-c157a805e5c2","html_url":"https://github.com/dahln/Dahln.Stack","commit_stats":null,"previous_names":["dahln/blazortemplate","dahln/blazorwasmandapitemplate","dahln/dahln.stack"],"tags_count":18,"template":true,"template_full_name":null,"purl":"pkg:github/dahln/Dahln.Stack","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dahln%2FDahln.Stack","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dahln%2FDahln.Stack/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dahln%2FDahln.Stack/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dahln%2FDahln.Stack/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dahln","download_url":"https://codeload.github.com/dahln/Dahln.Stack/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dahln%2FDahln.Stack/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34050225,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asp-net-core","csharp","dotnet","react","sqlite","template","webapi"],"created_at":"2026-04-10T15:16:55.368Z","updated_at":"2026-06-08T06:01:06.314Z","avatar_url":"https://github.com/dahln.png","language":"JavaScript","funding_links":["https://github.com/sponsors/dahln"],"categories":[],"sub_categories":[],"readme":"[![Build and Release Packages](https://github.com/dahln/Dahln.Stack/actions/workflows/BuildReleasePackages.yml/badge.svg)](https://github.com/dahln/Dahln.Stack/actions/workflows/BuildReleasePackages.yml)\n[![Deploy](https://github.com/dahln/Dahln.Stack/actions/workflows/Deployment.yml/badge.svg)](https://github.com/dahln/Dahln.Stack/actions/workflows/Deployment.yml)\n[![PR Validation](https://github.com/dahln/Dahln.Stack/actions/workflows/pr-validation.yml/badge.svg)](https://github.com/dahln/Dahln.Stack/actions/workflows/pr-validation.yml)\n[![Latest Release](https://img.shields.io/github/v/release/dahln/Dahln.Stack?label=Latest%20Release)](https://github.com/dahln/Dahln.Stack/releases/latest)\n\n\n\n- [ ] DEMO: Coming soon\n- [x] Release-driven Fedora deployment workflow\n- [x] Add badges\n\n## Overview\nDahln.Stack is am Opinionated .NET 10 + React starter template using a **decoupled proxy** architecture. The API and frontend run as independent processes during development and are deployed as separate applications behind Nginx in production.\n\n## 2026 Announcement \u0026 Update\nWith the latest updates, I have decided to refocus this template project on React. Working with Blazor WASM is fun, and I'm passionate about Blazor. However, over the past 2 years the only Blazor work I have done has been my own 'passion projects', and even some of those projects are now in React. I'm rebranding the project to 'Dahln.Stack', emphasizing that this is my preferred stack choice, at the moment. This rename will make future technology pivots more fluid. I have branched the current Blazor version and will keep that, and other archived branches, as a reference. Until recently my changes have been in another branch, and in order to finish the template restructuring I must now bring them into the master branch - your patience is appreciated while I finalize my current changes.\n\n## Solution Layout\n- `Dahln.Stack.API`: ASP.NET Core Web API, controllers, and Identity endpoints\n- `Dahln.Stack.App`: React + Vite frontend\n- `Dahln.Stack.Service`: business logic and database orchestration\n- `Dahln.Stack.Database`: EF Core DbContext, entities, and migrations\n- `Dahln.Stack.Dto`: shared DTOs and enums\n- `Dahln.Stack.Test`: unit tests for service logic\n\n![Architecture-Image](https://github.com/dahln/Dahln.Stack/blob/b2723fc1f21b5b9b75edf0678ff45065da551ca1/ArchitectureDiagram.png)\n\n\n\n## Technologies\n- .NET 10\n- ASP.NET Core Web API\n- React + Vite\n- ASP.NET Core Identity with cookie auth and 2FA support\n- Entity Framework Core + SQLite\n- Bootstrap + Bootstrap Icons\n- Scalar/OpenAPI in development\n\n## Local Development - Quick Start\n\nTwo terminals are required.\n\n### Terminal 1 - API\n\n```\ndotnet run --project Dahln.Stack.API\\Dahln.Stack.API.csproj --launch-profile https\n```\n\nAPI runs at: **https://localhost:7001**  \nScalar API docs (dev only): **https://localhost:7001/scalar**\n\n### Terminal 2 - Frontend\n\n```\ncd Dahln.Stack.App\nnpm install        # first time only\nnpm run dev\n```\n\nFrontend runs at: **https://localhost:5173**\n\nAll `/api/*` requests from the frontend are proxied to `https://localhost:7001` by Vite - no CORS configuration needed.\n\n### Trust the dev certificate (first time only)\n\n```\ndotnet dev-certs https --trust\n```\n\n### Open the app\n\nNavigate to **https://localhost:5173**\n\nThe SQLite database is created and migrations are applied automatically on first API startup.\n\n\n## Authentication And Email\nAuthentication uses ASP.NET Core Identity and stores user data in your database.\n\nSMTP2GO is optional but recommended if you want email-driven flows such as:\n- email confirmation\n- password recovery\n- email/username changes\n\nWithout SMTP configuration, the application still runs, but email-dependent account flows are limited.\n\n## Database Commands\nRun these from the solution root:\n\n```\ndotnet ef migrations add InitialCreate --project Dahln.Stack.Database --startup-project Dahln.Stack.API\n```\n\n```\ndotnet ef database update --project Dahln.Stack.Database --startup-project Dahln.Stack.API\n```\n\n## Ignore Local App Settings Changes\nIf you want to keep local configuration changes out of git:\n\n```\ngit update-index --assume-unchanged .\\Dahln.Stack.API\\appsettings.json\n```\n\nTo reverse it:\n\n```\ngit update-index --no-assume-unchanged .\\Dahln.Stack.API\\appsettings.json\n```\n\n## Deployment\n\nDeployment runs through the `Deployment.yml` GitHub Actions workflow. It deploys automatically when a GitHub Release is published, and it also runs after `Build and Release Packages` completes successfully. You can still run it manually with `workflow_dispatch`: provide a `release_tag` to deploy a specific release, or leave `release_tag` empty to deploy the latest release.\n\nThe workflow targets Fedora x64, downloads the release assets on the GitHub runner with the built-in `GITHUB_TOKEN`, uploads the packages to the server over SSH, and configures the server in place. No GitHub login or token is left on the server.\n\nBefore the first deployment:\n\n1. Create the Fedora server.\n2. Point your DNS record at the server IP and allow it to propagate.\n3. Configure these repository secrets:\n\n- `SERVERADDRESS`\n- `SERVERPORT`\n- `SERVERUSERNAME`\n- `SERVERKEY`\n- `APPLICATIONDOMAIN`\n- `APPLICATIONNAME`\n- `APPLICATIONUSER`\n- `APPLICATIONAPIPORT`\n\nThe workflow derives the rest from `APPLICATIONNAME` and the standard deployment layout:\n\n- Deploy root: `/opt/${APPLICATIONNAME,,}`\n- API deploy path: `/opt/${APPLICATIONNAME,,}/api`\n- App deploy path: `/opt/${APPLICATIONNAME,,}/app`\n- systemd service: `kestrel-${APPLICATIONNAME,,}`\n- Nginx site name: `${APPLICATIONNAME,,}`\n- API executable: `${APPLICATIONNAME}.API`\n- API release asset: `${APPLICATIONNAME}.API-{tag}-linux-x64.zip`\n- App release asset: `${APPLICATIONNAME}.App-{tag}.zip`\n- API route prefix: `/api`\n\nThe deployment workflow then:\n\n- updates Fedora packages with `dnf`\n- installs the required dependencies from the former Fedora installer\n- configures `firewalld`\n- creates the application system user when missing\n- deploys the API and app packages with `rsync`\n- verifies that `index.html` exists after app deployment\n- creates or updates the systemd service\n- creates or updates the Nginx site configuration\n- enables SELinux proxy access for Nginx and labels the static app files for Nginx access\n- provisions a Let's Encrypt certificate the first time `APPLICATIONDOMAIN` is set and SSL is not already configured\n\nSubsequent releases update the deployed files and restart the service stack. Certificate setup is skipped after SSL is already configured.\n\nThe SSH user must be `root` or have passwordless `sudo`, because the workflow installs packages and writes system files non-interactively.\n\n## License\nThis project uses the Unlicense. See `LICENSE` for the full text.\n\n## Resources\n- [Identity API with WebAPI](https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity-api-authorization?view=aspnetcore-8.0)\n- [EF Core CLI](https://learn.microsoft.com/en-us/ef/core/cli/dotnet)\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdahln%2Fdahln.stack","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdahln%2Fdahln.stack","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdahln%2Fdahln.stack/lists"}