Summary
Add download tracking and display download counts for each mod and tool on the site. Currently, there's no way to know how popular a mod is — users can't see which mods are most downloaded, and mod authors have no visibility into how many times their work has been downloaded. Adding download counters provides social proof, helps users discover popular mods, and gives authors useful feedback.
Current Behavior
- Mods and tools have download buttons that trigger a Stimulus controller (
mods#download)
- The download action fetches the file from a raw GitHub URL and triggers a browser download
- No download event is tracked or recorded anywhere
- No download count is displayed on mod cards or detail pages
- No way to sort by popularity
Proposed Solution
1. Firestore Download Counter
Add a download_count field to each mod/tool document in Firestore:
mods/{mod_id}:
name: "My Mod"
author: "DonovanMods"
download_count: 0 # <-- new field
...
2. Server-Side Download Tracking Endpoint
Create a new API endpoint that the Stimulus controller calls when a download is initiated:
# app/controllers/mods_controller.rb (or a new downloads_controller.rb)
def track_download
mod_id = params[:id]
# Increment download_count in Firestore
mod_ref = firestore.col("mods").doc(mod_id)
mod_ref.update({ download_count: Google::Cloud::Firestore::FieldValue.increment(1) })
head :ok
end
Route:
# config/routes.rb
post "/mods/:id/download", to: "mods#track_download", as: :track_mod_download
post "/tools/:id/download", to: "tools#track_download", as: :track_tool_download
3. Update Stimulus Download Controller
Modify the existing mods_controller.js Stimulus controller to fire a tracking request alongside the download:
async download(event) {
const url = event.params.url
const fileName = event.params.fileName
const modId = event.params.id // <-- new param
// Track the download (fire and forget — don't block the actual download)
if (modId) {
fetch(`/mods/${modId}/download`, { method: "POST", headers: { "X-CSRF-Token": getCSRFToken() } })
}
// Existing download logic continues...
const response = await fetch(url)
// ...
}
4. Display Download Count on Mod Cards
Show the download count on each mod card in the listing:
<div class="flex items-center gap-1 text-sm text-slate-400">
<svg class="w-4 h-4"><!-- download icon --></svg>
<span><%= number_with_delimiter(mod.download_count || 0) %> downloads</span>
</div>
Display formatting:
- 0-999: Show exact number (e.g., "842 downloads")
- 1,000-999,999: Show with comma (e.g., "1,234 downloads")
- 1,000,000+: Show abbreviated (e.g., "1.2M downloads")
5. "Sort by Most Downloaded" Option
Once download counts exist, add a "Most Popular" sort option to the mods page (ties into the search filters enhancement):
@mods = @mods.sort_by { |m| -(m.download_count || 0) }
Files to Modify
| File |
Change |
app/controllers/mods_controller.rb |
Add track_download action with Firestore increment |
app/controllers/tools_controller.rb |
Add track_download action for tools |
config/routes.rb |
Add POST routes for download tracking |
app/javascript/controllers/mods_controller.js |
Add tracking fetch call to download action |
app/views/mods/_mod.html.erb |
Display download count on mod cards |
app/views/tools/index.html.erb |
Display download count on tool cards |
app/models/mod.rb |
Add download_count attribute |
app/models/tool.rb |
Add download_count attribute |
Technical Considerations
- Firestore atomic increment: Use
FieldValue.increment(1) to avoid race conditions with concurrent downloads. This is an atomic operation in Firestore — no need to read-then-write.
- Rate limiting: Consider basic rate limiting on the track endpoint to prevent abuse (e.g., same IP can only increment once per mod per hour). This could be done with a simple in-memory cache or Firestore subcollection.
- Existing mods: All existing mods will have
download_count: nil — handle this with || 0 fallback in views and sorting.
- CSRF protection: The POST endpoint needs CSRF token validation. The Stimulus controller should include the Rails CSRF token from the meta tag.
- Analytics: Optionally log download events with timestamp and mod ID for more detailed analytics later (e.g., downloads per day/week charts).
Design Notes
- Download count displayed in
text-slate-400 (subtle, not competing with mod name/author)
- Small download arrow icon next to the count
- Position: Below the mod description, above the download button — or inline with the button
- On hover, could show "X downloads this week" if weekly tracking is added later
Testing
Summary
Add download tracking and display download counts for each mod and tool on the site. Currently, there's no way to know how popular a mod is — users can't see which mods are most downloaded, and mod authors have no visibility into how many times their work has been downloaded. Adding download counters provides social proof, helps users discover popular mods, and gives authors useful feedback.
Current Behavior
mods#download)Proposed Solution
1. Firestore Download Counter
Add a
download_countfield to each mod/tool document in Firestore:2. Server-Side Download Tracking Endpoint
Create a new API endpoint that the Stimulus controller calls when a download is initiated:
Route:
3. Update Stimulus Download Controller
Modify the existing
mods_controller.jsStimulus controller to fire a tracking request alongside the download:4. Display Download Count on Mod Cards
Show the download count on each mod card in the listing:
Display formatting:
5. "Sort by Most Downloaded" Option
Once download counts exist, add a "Most Popular" sort option to the mods page (ties into the search filters enhancement):
Files to Modify
app/controllers/mods_controller.rbtrack_downloadaction with Firestore incrementapp/controllers/tools_controller.rbtrack_downloadaction for toolsconfig/routes.rbapp/javascript/controllers/mods_controller.jsapp/views/mods/_mod.html.erbapp/views/tools/index.html.erbapp/models/mod.rbdownload_countattributeapp/models/tool.rbdownload_countattributeTechnical Considerations
FieldValue.increment(1)to avoid race conditions with concurrent downloads. This is an atomic operation in Firestore — no need to read-then-write.download_count: nil— handle this with|| 0fallback in views and sorting.Design Notes
text-slate-400(subtle, not competing with mod name/author)Testing