The same pattern appears in charts.erb, federation.erb, and node_detail.erb. Browsers cache these files aggressively. After a deployment, users continue running the old JS until they hard-refresh manually.
Root cause
Sinatra serves public/ as static files with no fingerprinting. The templates embed asset URLs as bare paths with no version query parameter.
APP_VERSION is already resolved at startup from git describe --tags --long --abbrev=7 (see application/identity.rb) and is available in the template context, but it is never appended to asset URLs.
Proposed fix
Add an asset_url(path) helper in html_helpers.rb that appends ?v=<APP_VERSION>:
This is a one-liner per include, requires no build step change, and uses version data already computed at boot. After each release the URL changes, browsers fetch fresh files.
CSS assets (e.g. base.css) and any inline import statements in ES module scripts (e.g. in charts.erb) should get the same treatment.
## Problem
All JavaScript assets are served with static paths and no cache invalidation mechanism:
```erb
<script src="/assets/js/theme.js" defer></script>
<script src="/assets/js/background.js" defer></script>
<script type="module" src="/assets/js/app/index.js"></script>
```
The same pattern appears in `charts.erb`, `federation.erb`, and `node_detail.erb`. Browsers cache these files aggressively. After a deployment, users continue running the old JS until they hard-refresh manually.
## Root cause
Sinatra serves `public/` as static files with no fingerprinting. The templates embed asset URLs as bare paths with no version query parameter.
`APP_VERSION` is already resolved at startup from `git describe --tags --long --abbrev=7` (see `application/identity.rb`) and is available in the template context, but it is never appended to asset URLs.
## Proposed fix
Add an `asset_url(path)` helper in `html_helpers.rb` that appends `?v=<APP_VERSION>`:
```ruby
def asset_url(path)
"#{path}?v=#{PotatoMesh::Application::APP_VERSION}"
end
```
Replace all static asset references in templates with the helper:
```erb
<script src="<%= asset_url('/assets/js/theme.js') %>" defer></script>
<script src="<%= asset_url('/assets/js/background.js') %>" defer></script>
<script type="module" src="<%= asset_url('/assets/js/app/index.js') %>"></script>
```
This is a one-liner per include, requires no build step change, and uses version data already computed at boot. After each release the URL changes, browsers fetch fresh files.
CSS assets (e.g. `base.css`) and any inline `import` statements in ES module scripts (e.g. in `charts.erb`) should get the same treatment.
<!-- github-sync-id:4700963930 -->
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
All JavaScript assets are served with static paths and no cache invalidation mechanism:
The same pattern appears in
charts.erb,federation.erb, andnode_detail.erb. Browsers cache these files aggressively. After a deployment, users continue running the old JS until they hard-refresh manually.Root cause
Sinatra serves
public/as static files with no fingerprinting. The templates embed asset URLs as bare paths with no version query parameter.APP_VERSIONis already resolved at startup fromgit describe --tags --long --abbrev=7(seeapplication/identity.rb) and is available in the template context, but it is never appended to asset URLs.Proposed fix
Add an
asset_url(path)helper inhtml_helpers.rbthat appends?v=<APP_VERSION>:Replace all static asset references in templates with the helper:
This is a one-liner per include, requires no build step change, and uses version data already computed at boot. After each release the URL changes, browsers fetch fresh files.
CSS assets (e.g.
base.css) and any inlineimportstatements in ES module scripts (e.g. incharts.erb) should get the same treatment.