fullstackhero is distributed as source you own. The template scaffolds the full codebase, modules and framework are consumed via ProjectReference, and nothing about your running app comes from a fullstackhero NuGet package — only the fsh CLI and the dotnet new template ship to NuGet (the kit’s Directory.Build.props turns IsPackable off for everything else).
That’s a deliberate trade. You can change anything; in exchange, taking upstream fixes is a git workflow, not a package bump. There is no dotnet update fullstackhero. This page is the honest version of what that workflow looks like.
How upstream ships
mainis the only long-lived branch and stays releasable; stable releases are cut fromv*tags (e.g.v10.0.0). See Contributing.- The changelog is the upgrade manual. Entries are dated, explain why a change happened, and call out required actions — e.g. “grant the new
Webhooks.*permissions or those users get403” or “wipe your Postgres data volume after the Aspire 13.4 bump”. Read every entry between your base and your target before you merge anything. - One caution: tags below v10 (
2.0.4-rcand older) belong to the previous generation of the kit. Don’t try to merge across that rewrite boundary — v10 is the baseline. And if the release you’re after isn’t tagged yet, mergeupstream/mainat the commit matching its changelog entry instead of waiting on a tag.
The upgrade workflow
The mechanics depend on how you got the code, because that determines whether git can do the heavy lifting.
If you cloned or forked the repo
You share history with upstream, so this is an ordinary merge.
# One-time setupgit remote add upstream https://github.com/fullstackhero/dotnet-starter-kit.git
# Each upgradegit fetch upstream --tagsgit log --oneline HEAD..upstream/main # what you're behind on# → read /docs/changelog/ for the same range — note any "action required" items
git checkout -b chore/upstream-mergegit merge v10.1.0 # a release tag, or upstream/main for latestConflicts land exactly where you’d expect: files you customized that upstream also changed. Resolve them knowing that you are the source of truth for your customizations and upstream is the source of truth for everything you never touched.
You can also cherry-pick a single fix instead of taking a whole release — git cherry-pick <sha> with the commit from the changelog or the GitHub history — but track what you’ve picked, or the eventual full merge gets confusing.
If you used GitHub’s “Use this template”
Your repo has the same files but no shared history, so the very first merge needs:
git merge v10.1.0 --allow-unrelated-historiesExpect that first merge to be noisy (git can’t tell “unchanged” from “both added”). After it lands, you have a common ancestor and every later merge behaves like the cloned-fork case.
If you scaffolded with fsh new / dotnet new fsh
This is the manual one, and we won’t pretend otherwise. The template renames everything — FSH.Starter becomes MyApp across namespaces, project files, folder paths, and the solution — so upstream commits don’t apply to your tree, and there’s no shared history either.
The realistic approach:
- Read the changelog entries for the range you’re taking.
- View the upstream diff for each change:
git diff v10.0.0..v10.1.0 -- src/Modules/Ticketsagainst a local clone of the kit. - Re-apply by hand, translating
FSH.Starter.*names to yours. Small, surgical fixes port in minutes; sweeping refactors are a judgment call on whether they’re worth taking at all.
For larger teams planning to track upstream closely, a plain fork (keeping the FSH.Starter names) is the smoother path — renaming is cosmetic, mergeability is structural.
Verify after the merge
The kit’s test suite is the safety net — 1,600+ backend tests plus NetArchTest boundary checks, and 200+ Playwright E2E tests across the two React apps. Use all of it:
dotnet build src/FSH.Starter.slnx # warnings are errorsdotnet test src/FSH.Starter.slnx # integration tests need Docker
# New release may carry new EF migrations — review, then applydotnet run --project src/Host/FSH.Starter.DbMigrator -- list-pendingdotnet run --project src/Host/FSH.Starter.DbMigrator -- apply
# Frontends, if you took client changescd clients/admin && npm install && npm run build && npx playwright testcd clients/dashboard && npm install && npm run build && npx playwright testThe Architecture.Tests project deserves a special mention: if your customizations accidentally violated module boundaries in a way that conflicts with an upstream change, it fails loudly instead of letting the merge compile into something subtly wrong.
Finally, work through any action-required items from the changelog entries you just absorbed — permission grants, config keys, volume wipes. Those don’t show up as compile errors.
Make the next merge cheap
Every conflict you’ll ever resolve comes from editing a file upstream also edits. You control that surface:
- Put custom work in your own modules. A new
Modules.{Name}+.Contractspair is yours alone — upstream will never touch it, so it merges for free. See adding a module. - Don’t modify
src/BuildingBlocks. It’s the shared framework under every module and the highest-traffic code upstream maintains — the kit’s own rules treat it as protected. Changes there put you in conflict with the most actively fixed code in the repo. - Prefer extension points over editing shipped modules in place. Swappable interfaces (storage providers,
IInvoicePdfRenderer, event handlers on published events) let you change behavior without forking the file that implements it. When you must change a shipped module, keep the edit small and leave a comment marking it as yours — future-you resolves that conflict. - Frontend dependencies are yours.
clients/adminandclients/dashboardeach have their ownpackage-lock.json; upstream pins what it ships, but auditing and updating npm packages on your schedule is your responsibility, like any app you own.
Checklist
git fetch upstream --tags- Read the changelog from your base to your target; list action-required items
- Merge (or re-apply) on a branch — never directly on
main - Resolve conflicts: yours wins on customizations, upstream wins on untouched code
dotnet build+dotnet test(Docker running), frontend builds + E2E if clients changedDbMigrator -- list-pending, review, thenapply- Apply changelog action items (permissions, config, infra)
- Deploy
Related
- Changelog — the dated record of every change, with action items.
- Install — the acquisition paths this page’s workflow depends on.
- CLI — what
fsh update,info, anddoctoractually do. - Contributing — branch and release model (
main+v*tags).