Fix mobile layout for mods table and pagination#6
Merged
Conversation
The Gemfile specifies ruby "3.4.9" but .ruby-version was still 3.4.8, causing CI to install the wrong Ruby version and fail with "Your Ruby version is 3.4.8, but your Gemfile specified 3.4.9". Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The CSP initializer was entirely commented out, leaving the application with no Content-Security-Policy headers. This is a security risk as it allows unrestricted loading of scripts, styles, and other resources. Configure CSP with sensible defaults for this app's needs: - default_src/script_src/connect_src: self + https - img_src/font_src: self + https + data URIs - object_src: none (blocks Flash/Java embeds) - style_src includes unsafe_inline for Tailwind compatibility - Nonce-based script protection via importmap Starts in report-only mode so violations are logged without breaking the site. Once verified in production, report_only can be removed. Fixes the medium-severity CSP bug reported in DonovanMods#76. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Tool#filename calls url.split("/") without checking if url is nil.
When a Firestore document lacks a fileURL field, url is nil and
calling .split on it raises NoMethodError, crashing the tools
index page.
Add a nil guard that returns nil early when url is absent, and
use URI parsing for consistency with how Mod#filename handles URLs.
Fixes the medium-severity Tool#filename crash reported in DonovanMods#76.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The author_slug method in the Displayable concern calls author.parameterize without checking if author is nil. If a single Firestore document lacks an author field, it raises NoMethodError and can crash the entire mods or tools index page since author_slug is called during rendering of every record. Return "unknown" as a safe fallback slug when author is nil, keeping the page rendering and producing a valid URL segment. Fixes the medium-severity author_slug crash reported in DonovanMods#76. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use string splitting instead of URI() to avoid URI::InvalidURIError on malformed Firestore URLs, matching the safer approach already used in Mod#filename (commit 2b66be7). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When switching Tailwind from darkMode: "media" to "class", the OS preference is no longer automatically respected. This adds a matchMedia check as fallback when no localStorage preference is saved, preserving the original behavior for first-time visitors. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements array-based pagination for the mods index when displaying all mods. Search results and author-filtered views show all matches without pagination, as requested in issue DonovanMods#55. - Add PaginationHelper with page windowing and ellipsis support - Add _pagination.html.erb partial with Prev/Next and page numbers - Paginate at 20 mods per page (configurable via DEFAULT_PER_PAGE) - Show "page X of Y" counter when paginated - Styled with existing Tailwind classes for light/dark mode
Covers paginate_array edge cases (empty collection, page clamping, custom per_page) and PaginationResult methods (first/last page, navigation, page_range with ellipsis). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The .gitignore only had .env.* (matching .env.local, .env.production, etc.) but not .env itself, so the base .env file was committed and tracked. While it currently contains non-secret config (project IDs, bucket names), tracking .env files is a security risk as developers may add secrets to it later. Changes: - Add .env to .gitignore so it is no longer tracked - Remove .env from git index (file stays on disk for existing devs) - Add .env.example template so new developers know which vars to set - Whitelist .env.example in .gitignore so the template is tracked Fixes the low-severity .env tracking bug reported in DonovanMods#76. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The _mod.html.erb partial passes mod.author (which contains spaces and mixed case) to mod_detail_path, producing ugly URLs with encoded spaces like /mods/Donovan%20Young/some-mod. Change to mod.author_slug which produces clean, parameterized URLs like /mods/donovan-young/some-mod, consistent with how the show action and author filtering already work. Fixes the low-severity ugly URL bug reported in DonovanMods#76. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The search input debounce was set to 200ms, firing a Turbo Frame request on nearly every keystroke. Increase to 400ms which still feels responsive but significantly reduces unnecessary requests and Firestore reads during active typing. Fixes the low-severity search debounce bug reported in DonovanMods#76. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The markdown helper created new CodeRayify and Redcarpet::Markdown instances on every call. On the mods index this means allocating these objects once per mod with a README. Extract into a memoized private method so objects are created once per request and reused for all subsequent renders. Fixes the low-severity markdown renderer performance bug in DonovanMods#76. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The require_master_key setting was commented out, meaning the app can boot in production without a master key. Without it, Rails credentials (including Firebase keyfile) can't be decrypted, causing confusing Firestore errors instead of a clear startup failure. Uncomment so production deploys fail fast if RAILS_MASTER_KEY is missing. The Kamal deploy config already provides this as a secret. Fixes the low-severity require_master_key bug reported in DonovanMods#76. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The firestore class method creates a new Google::Cloud::Firestore client on every call. Memoize with @FireStore ||= so the client is created once per class and reused. The Google Cloud Firestore client is designed to be long-lived and thread-safe. Fixes the low-severity Firestore client performance bug in DonovanMods#76. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reset class-level @FireStore instance variable after each test to prevent RSpec doubles from persisting via Firestorable's @FireStore ||= memoization pattern. This fixes 8 test failures where leaked doubles caused errors in subsequent examples. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use .positive? instead of > 0 - Break long line in PaginationResult.new - Use described_class instead of explicit class names in specs - Fix context descriptions to start with when/with/without Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The template now uses mod.author_slug instead of mod.author for cleaner URLs, so the test expectation needs to match. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
These are local MCP plugin directories that shouldn't be tracked. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaces inline toggleTheme() and DOMContentLoaded listener with a Stimulus theme_controller.js. Uses data-action and data-target attributes instead of global functions and getElementById, preventing potential conflicts with other scripts. The early-load FOUC prevention script in <head> is kept since Stimulus connects after DOMContentLoaded. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Merge nested conditional into outer if to satisfy RuboCop Style/SoleNestedConditional rule. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract filter_by_author, filter_by_query, paginate_mods, and render_index private methods to bring ABC size and method length below RuboCop thresholds. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace `return unless params[:x].present?` with `return if params[:x].blank?` per Rails/Blank cop preference. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…smatch Fix .ruby-version to match Gemfile ruby requirement (3.4.9)
…nil-guards-and-csp Fix/medium severity nil guards and csp
…anup-and-performance Fix: Code clean-up, security hardening, and performance improvements
Add dark/light theme toggle to header nav
Add pagination to mods listing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Table: - Remove fixed w-1/5 on Name column at mobile breakpoint so it fills available space when Author/Version/Description are hidden - Set Download column to w-auto on mobile, w-28 at sm+ - Show only file type (PAK/EXMODZ) on mobile, full "Download PAK" at sm+ - Reduce cell padding on mobile (p-2 -> sm:p-3) - Add whitespace-nowrap on download cell to prevent button wrapping Pagination: - Stack "Showing X to Y" and page controls vertically on mobile, side-by-side at sm+ (flex-col -> sm:flex-row) - Use flex-wrap + justify-center on page numbers so they wrap cleanly - Hide "Prev"/"Next" labels on mobile, keep chevrons only - Reduce padding on page number buttons for small screens Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
w-1/5) even though Author/Version/Week/Description columns are hidden. Now it fills available space on mobile. Download button shows only the file type (PAK/EXMODZ) on small screens to save space.Changes
_mods.html.erb— Make Name column width responsive (sm:w-1/5instead ofw-1/5), Download column auto-width on mobile_mod.html.erb— Hide "Download" label text on mobile (hidden sm:inline), reduce cell padding_pagination.html.erb— Stack layout vertically on mobile (flex-col sm:flex-row), flex-wrap page numbers, compact paddingTest plan
🤖 Generated with Claude Code