Skip to content

Add a dev launch profile and a no-cache header for static files - #53

Merged
malinfossum merged 3 commits into
mainfrom
chore/dev-launch-settings
Aug 21, 2026
Merged

Add a dev launch profile and a no-cache header for static files#53
malinfossum merged 3 commits into
mainfrom
chore/dev-launch-settings

Conversation

@malinfossum

Copy link
Copy Markdown
Member

Two housekeeping items from docs/backlog.md, both about the local development loop rather than the product. Neither touches the API surface, Identity, or the frontend.

launchSettings.json

Wend.Api reads its connection string only in the Development environment, so every run needed ASPNETCORE_ENVIRONMENT set by hand first. Forgetting it fails with ConnectionStrings:WendDb is not configured, which reads as a missing user-secret rather than a missing environment variable. The profile sets the environment and nothing else.

No applicationUrl on purpose. Program.cs binds Kestrel explicitly with ListenLocalhost(Wend:Port), and an explicit Listen call overrides ASPNETCORE_URLS, so an applicationUrl would be dead config that only logs an override warning. The address stays owned by the Wend:Port seam.

The app still refuses to boot outside Development (no production email sender), so the profile makes the intended run easier without weakening that guard.

Dev-only Cache-Control: no-cache on static files

UseStaticFiles sends no Cache-Control at all, so the browser applies its own heuristic and a normal reload keeps serving JS and CSS from an earlier :5174 session. Two "bugs" in the 2026-07-08 accessibility sweep were cache ghosts, and the standing workaround has been to hard-reload before every browser check.

Development now sends no-cache — which still stores the response but revalidates, so an unchanged file costs a 304 rather than a resend. Production keeps the default, where caching static assets is the point.

MapFallbackToFile takes the same options because it serves index.html through its own static-file pipeline rather than the middleware above; without that the shell alone would still come back from cache.

What to check

  • staticFiles.OnPrepareResponse is set only inside if (app.Environment.IsDevelopment()) — the production path must keep the default StaticFileOptions.
  • Both UseStaticFiles and MapFallbackToFile receive the same options object.
  • Two guards in ApiSmokeTestsStatic_files_are_no_cache_in_development and The_shell_is_no_cache_in_development. Both were verified red on this branch with Program.cs reverted (2 failed / 0 passed), then green with it back.
  • WendApiFactory pins UseEnvironment("Development"), so the production branch is not covered by a test. It is a one-line if with no behaviour of its own; flag it if you would rather see it exercised.

Verification

  • dotnet test255 passed, 0 failed (253 before, +2 new). The README's test count moves with it.
  • dotnet run --project Wend.Api in a shell with no ASPNETCORE_ENVIRONMENT set: boots, /api/health 200, /css/app.css and /boards/42 both answer Cache-Control: no-cache against the running server.

README

The Run it section documented the manual environment step and stated "There is no launchSettings.json", so it is corrected here rather than left to drift — that coupling was the reason these two items were queued together.

Two housekeeping items from docs/backlog.md, both about the local
development loop rather than the product.

launchSettings.json: the app reads its connection string only in the
Development environment, so every run needed ASPNETCORE_ENVIRONMENT set
by hand first. Forgetting it fails with "ConnectionStrings:WendDb is not
configured", which reads as a missing user-secret rather than a missing
environment variable, and has cost that confusion more than once. The
profile sets the environment and nothing else.

Deliberately no applicationUrl: Program.cs binds Kestrel explicitly with
ListenLocalhost(Wend:Port), and an explicit Listen call overrides
ASPNETCORE_URLS, so an applicationUrl would be dead config that only logs
an override warning. The address stays owned by the Wend:Port seam.

Static files: UseStaticFiles sends no Cache-Control at all, so the browser
applies its own heuristic and a normal reload keeps serving JS and CSS
from an earlier :5174 session - two "bugs" in the 2026-07-08 accessibility
sweep were cache ghosts, and the standing workaround was to hard-reload
before every browser check. Development now sends no-cache, which still
stores the response but revalidates, so an unchanged file costs a 304
rather than a resend. Production keeps the default.

MapFallbackToFile takes the same options because it serves index.html
through its own static-file pipeline, not the middleware above; without
that the shell alone would still come back from cache.

Two guards in ApiSmokeTests, one for a static asset and one for the shell,
both verified red against this branch with Program.cs reverted. 255/255
green, and the count in the README moves with them.

The README's Run it section documented the manual environment step and
stated there is no launchSettings.json, so it is corrected in the same
commit.
The backlog is the source of truth for what is knowingly deferred, so an
item this branch closes should not still read as open. The entry keeps the
trap that made it worth writing down and gains what was done about it, the
two guards, and the launchSettings.json half of the same housekeeping pass.
@malinfossum
malinfossum merged commit e231d0f into main Aug 21, 2026
1 check passed
@malinfossum
malinfossum deleted the chore/dev-launch-settings branch August 21, 2026 13:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant