Skip to content

Conversation

@Nachiket-Roy
Copy link
Contributor

@Nachiket-Roy Nachiket-Roy commented Dec 10, 2025

CLOSES : #5251

Summary by CodeRabbit

  • Chores
    • Integrated development profiling and debugging tooling
    • Implemented static file compression for optimized delivery
    • Added image optimization utilities for PNG to WebP conversion with automatic backups

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions
Copy link
Contributor

👋 Hi @Nachiket-Roy!

This pull request needs a peer review before it can be merged. Please request a review from a team member who is not:

  • The PR author
  • DonnieBLT
  • coderabbitai
  • copilot

Once a valid peer review is submitted, this check will pass automatically. Thank you!

@github-actions github-actions bot added the needs-peer-review PR needs peer review label Dec 10, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 10, 2025

Walkthrough

This PR integrates development and debugging tools (Silk, Django Debug Toolbar, LiveReload), adds WhiteNoise static file storage, restructures template configuration based on DEBUG mode, updates project dependencies, and introduces a PNG-to-WebP image conversion utility script.

Changes

Cohort / File(s) Summary
Development Tools Integration
blt/settings.py, blt/urls.py
Adds Silk profiling middleware and Django Debug Toolbar to INSTALLED_APPS and MIDDLEWARE when DEBUG is true; configures INTERNAL_IPS and wires URL routes for both tools in DEBUG mode only.
Template Configuration Restructuring
blt/settings.py
Implements conditional TEMPLATES configuration: DEBUG mode uses APP_DIRS=True with standard loaders and debug context enabled; non-DEBUG mode uses APP_DIRS=False with cached loader for production.
Static Files Storage
blt/settings.py
Adds WhiteNoise CompressedManifestStaticFilesStorage configuration for static file handling.
Dependencies
pyproject.toml
Adds django-silk ^5.0.1 and django-debug-toolbar ^4.3.0 to Poetry dependencies.
Image Conversion Utility
scripts/convert_images_to_webp.py
New script providing PNG-to-WebP image conversion with backup functionality; includes ensure_backup_dir(), convert_png(), and main() functions for bulk processing across defined source directories.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • blt/settings.py: Conditional TEMPLATES logic and integration of multiple middleware/storage configurations require verification of correct DEBUG-mode branching and tool initialization.
  • scripts/convert_images_to_webp.py: New file manipulation logic using PIL and shutil warrants review of error handling, backup strategy, and directory traversal correctness.
  • Dependency versions: Verify that django-silk ^5.0.1 and django-debug-toolbar ^4.3.0 are compatible with the current Django version and other installed packages.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main objective of adding static asset performance improvements (WhiteNoise, debug tools integration, and image optimization script), though it mentions lazy loading which is not evident in the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added files-changed: 2450 PR changes 2450 files pre-commit: passed Pre-commit checks passed labels Dec 10, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
blt/settings.py (1)

114-136: SilkyMiddleware enabled unconditionally in production.

silk.middleware.SilkyMiddleware at line 115 is outside the DEBUG block. This will intercept and profile every request in production, causing performance degradation and storing profiling data unnecessarily.

Move SilkyMiddleware inside the DEBUG condition:

 MIDDLEWARE = [
-    "silk.middleware.SilkyMiddleware",
     "django.contrib.sessions.middleware.SessionMiddleware",
     # ... other middleware ...
 ]

 if DEBUG:
-    MIDDLEWARE += ("livereload.middleware.LiveReloadScript", "debug_toolbar.middleware.DebugToolbarMiddleware")
+    MIDDLEWARE = ["silk.middleware.SilkyMiddleware"] + MIDDLEWARE
+    MIDDLEWARE += ["livereload.middleware.LiveReloadScript", "debug_toolbar.middleware.DebugToolbarMiddleware"]
     INTERNAL_IPS = ["127.0.0.1"]
🧹 Nitpick comments (1)
scripts/convert_images_to_webp.py (1)

43-45: Silent exception handling hides errors.

While the comment states this is "CI-safe by design," silently swallowing all exceptions makes debugging difficult. Consider logging the error at minimum, or re-raising after logging in non-CI environments.

-    except Exception:
-        # Silent failure by design (CI-safe)
-        pass
+    except Exception as e:
+        # Log but don't fail (CI-safe)
+        print(f"Warning: Failed to convert {png_path}: {e}")
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between ebbc77c and 210e2d7.

⛔ Files ignored due to path filters (296)
  • poetry.lock is excluded by !**/*.lock
  • website/static/_image_backups/images/bacon.png is excluded by !**/*.png
  • website/static/_image_backups/images/bch gold block.png is excluded by !**/*.png
  • website/static/_image_backups/images/bch qr.png is excluded by !**/*.png
  • website/static/_image_backups/images/close.png is excluded by !**/*.png
  • website/static/_image_backups/images/default-team-logo.png is excluded by !**/*.png
  • website/static/_image_backups/images/dummy-user.png is excluded by !**/*.png
  • website/static/_image_backups/images/googlelogo_color_272x92dp.png is excluded by !**/*.png
  • website/static/_image_backups/images/gsoc.png is excluded by !**/*.png
  • website/static/_image_backups/images/next.png is excluded by !**/*.png
  • website/static/_image_backups/images/prev.png is excluded by !**/*.png
  • website/static/_image_backups/images/report_issue.png is excluded by !**/*.png
  • website/static/_image_backups/images/slack_icon.png is excluded by !**/*.png
  • website/static/_image_backups/images/sorting-hat.png is excluded by !**/*.png
  • website/static/_image_backups/img/ChromeWebStore_Badge_v2_496x150.png is excluded by !**/*.png
  • website/static/_image_backups/img/TM.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/ci-build-passed.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/conflict-resolve.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/default_badge.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-api-64.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-bid-64.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-blog-96.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-branch-80.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-bug-96.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-bug-bounty-64.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-close-window-64.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-code-review-64.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-commit-git-80.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-complete-100.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-conference-80.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-contribution-64.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-dashboard-100.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-demo-60.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-dependency-60.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-discussion-100.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-documentation-64.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-edit-96.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-eslint-pluggable-and-configurable-linter-tool-for-identifying-and-reporting-on-patterns-in-javascript-96.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-fail-32.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-feedback-80.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-forum-96.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-host-64.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-ip-48.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-markdown-56.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-mentor-94.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-merge-40.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-milestone-50.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-newsletter-96.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-optimize-64.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-performance-goal-96.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-refactoring-60.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-request-review-48.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-run-into-men-100.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-security-configuration-40.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-security-shield-96.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-social-50.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-star-96.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-survey-96.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-tag-100.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-test-60.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-tutorial-64.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-webinar-100.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/icons8-wiki-64.png is excluded by !**/*.png
  • website/static/_image_backups/img/badges/linter-fail.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/adblock/adblock.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/adblock/adblock_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/adblock/adblock_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/adblock/adblock_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/adblock/adblock_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/adblock/adblock_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/adblock/adblock_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/adblock/adblock_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/adblock/adblock_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android-webview-beta/android-webview-beta.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android-webview-beta/android-webview-beta_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android-webview-beta/android-webview-beta_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android-webview-beta/android-webview-beta_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android-webview-beta/android-webview-beta_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android-webview-beta/android-webview-beta_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android-webview-beta/android-webview-beta_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android-webview-beta/android-webview-beta_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android-webview-beta/android-webview-beta_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android/android.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android/android_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android/android_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android/android_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android/android_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android/android_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android/android_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android/android_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/android/android_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/avant/avant.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/avant/avant_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/avant/avant_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/avant/avant_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/avant/avant_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/avant/avant_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/avant/avant_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/avant/avant_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/avant/avant_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/blisk/blisk.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/blisk/blisk_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/blisk/blisk_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/blisk/blisk_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/blisk/blisk_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/blisk/blisk_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/blisk/blisk_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/blisk/blisk_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/blisk/blisk_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/boat/boat.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/boat/boat_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/boat/boat_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/boat/boat_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/boat/boat_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/boat/boat_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/boat/boat_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/boat/boat_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/boat/boat_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/brave/brave.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/brave/brave_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/brave/brave_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/brave/brave_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/brave/brave_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/brave/brave_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/brave/brave_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/brave/brave_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/brave/brave_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/browser.html/browser.html.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/browser.html/browser.html_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/browser.html/browser.html_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/browser.html/browser.html_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/browser.html/browser.html_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/browser.html/browser.html_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/browser.html/browser.html_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/browser.html/browser.html_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/browser.html/browser.html_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/browser_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cent/cent.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cent/cent_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cent/cent_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cent/cent_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cent/cent_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cent/cent_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cent/cent_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cent/cent_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cent/cent_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile ios/chrome mobile ios_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile ios/chrome.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile ios/chrome_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile ios/chrome_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile ios/chrome_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile ios/chrome_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile ios/chrome_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile ios/chrome_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile ios/chrome_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile/chrome mobile_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile/chrome.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile/chrome_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile/chrome_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile/chrome_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile/chrome_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile/chrome_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile/chrome_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome mobile/chrome_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-beta/chrome-beta.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-beta/chrome-beta_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-beta/chrome-beta_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-beta/chrome-beta_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-beta/chrome-beta_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-beta/chrome-beta_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-beta/chrome-beta_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-beta/chrome-beta_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-beta/chrome-beta_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-canary/chrome-canary.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-canary/chrome-canary_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-canary/chrome-canary_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-canary/chrome-canary_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-canary/chrome-canary_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-canary/chrome-canary_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-canary/chrome-canary_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-canary/chrome-canary_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-canary/chrome-canary_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-dev/chrome-dev.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-dev/chrome-dev_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-dev/chrome-dev_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-dev/chrome-dev_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-dev/chrome-dev_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-dev/chrome-dev_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-dev/chrome-dev_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-dev/chrome-dev_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome-dev/chrome-dev_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome/chrome.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome/chrome_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome/chrome_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome/chrome_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome/chrome_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome/chrome_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome/chrome_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome/chrome_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chrome/chrome_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chromium/chromium.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chromium/chromium_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chromium/chromium_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chromium/chromium_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chromium/chromium_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chromium/chromium_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chromium/chromium_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chromium/chromium_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/chromium/chromium_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cm/cm.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cm/cm_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cm/cm_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cm/cm_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cm/cm_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cm/cm_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cm/cm_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cm/cm_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cm/cm_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/coast/coast.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/coast/coast_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/coast/coast_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/coast/coast_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/coast/coast_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/coast/coast_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/coast/coast_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/coast/coast_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/coast/coast_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/comodo-dragon/comodo-dragon_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cốc-cốc/cốc-cốc.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cốc-cốc/cốc-cốc_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cốc-cốc/cốc-cốc_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cốc-cốc/cốc-cốc_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cốc-cốc/cốc-cốc_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cốc-cốc/cốc-cốc_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cốc-cốc/cốc-cốc_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cốc-cốc/cốc-cốc_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/cốc-cốc/cốc-cốc_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin-zero/dolphin-zero.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin-zero/dolphin-zero_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin-zero/dolphin-zero_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin-zero/dolphin-zero_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin-zero/dolphin-zero_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin-zero/dolphin-zero_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin-zero/dolphin-zero_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin-zero/dolphin-zero_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin-zero/dolphin-zero_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin/dolphin.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin/dolphin_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin/dolphin_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin/dolphin_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin/dolphin_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin/dolphin_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin/dolphin_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin/dolphin_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dolphin/dolphin_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dooble/dooble.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dooble/dooble_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dooble/dooble_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dooble/dooble_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dooble/dooble_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dooble/dooble_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dooble/dooble_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dooble/dooble_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/dooble/dooble_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/duckduckgo mobile/duckduckgo mobile_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge-tile/edge-tile.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge-tile/edge-tile_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge-tile/edge-tile_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge-tile/edge-tile_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge-tile/edge-tile_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge-tile/edge-tile_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge-tile/edge-tile_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge-tile/edge-tile_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge-tile/edge-tile_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge/edge.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge/edge_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge/edge_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge/edge_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge/edge_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge/edge_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge/edge_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge/edge_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/edge/edge_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/epic/epic.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/epic/epic_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/epic/epic_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/epic/epic_24x24.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/epic/epic_256x256.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/epic/epic_32x32.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/epic/epic_48x48.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/epic/epic_512x512.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/epic/epic_64x64.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/firefox-beta/firefox-beta.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/firefox-beta/firefox-beta_128x128.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/firefox-beta/firefox-beta_16x16.png is excluded by !**/*.png
  • website/static/_image_backups/img/browser-logos/firefox-beta/firefox-beta_24x24.png is excluded by !**/*.png
📒 Files selected for processing (4)
  • blt/settings.py (4 hunks)
  • blt/urls.py (1 hunks)
  • pyproject.toml (1 hunks)
  • scripts/convert_images_to_webp.py (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Run Tests
  • GitHub Check: Run pre-commit
  • GitHub Check: docker-test
🔇 Additional comments (2)
scripts/convert_images_to_webp.py (1)

22-45: Overall implementation looks reasonable for the use case.

The function correctly handles backup, conversion to WebP, and re-optimization of the original PNG. The skip-if-exists check at line 27-28 prevents re-processing.

blt/settings.py (1)

165-211: Template configuration split is well-structured.

The conditional template loading with APP_DIRS=True for development and cached loaders for production is a good performance optimization pattern.

Comment on lines +104 to +107
"silk",
)

if DEBUG:
INSTALLED_APPS += ("livereload",)
INSTALLED_APPS += ("debug_toolbar", "livereload")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Silk enabled unconditionally in production.

"silk" is added to INSTALLED_APPS outside the DEBUG block, meaning it will be installed and active in production. This adds unnecessary overhead and potential security exposure.

Move silk inside the DEBUG condition:

     "channels",
-    "silk",
 )
 if DEBUG:
-    INSTALLED_APPS += ("debug_toolbar", "livereload")
+    INSTALLED_APPS += ("silk", "debug_toolbar", "livereload")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"silk",
)
if DEBUG:
INSTALLED_APPS += ("livereload",)
INSTALLED_APPS += ("debug_toolbar", "livereload")
"channels",
)
if DEBUG:
INSTALLED_APPS += ("silk", "debug_toolbar", "livereload")
🤖 Prompt for AI Agents
In blt/settings.py around lines 104 to 107, "silk" is currently added to
INSTALLED_APPS unconditionally; remove it from the global INSTALLED_APPS list
and instead append it only when DEBUG is True (e.g. inside the DEBUG block do
INSTALLED_APPS += ("silk",) or similar), so silk is enabled only in development;
ensure tuple/comma syntax is correct when appending.

Comment on lines 379 to +380
STATIC_ROOT = os.path.join(PROJECT_ROOT, "staticfiles")
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Django 5.2 STATICFILES_STORAGE deprecated STORAGES setting precedence

💡 Result:

Short answer: In Django 4.2+ (including 5.2) STATICFILES_STORAGE is deprecated in favour of the new STORAGES mapping. Django will use the storage configured under STORAGES["staticfiles"] as the staticfiles backend; STATICFILES_STORAGE is only used as the deprecated fallback when no STORAGES["staticfiles"] config is provided. See the STORAGES note in the 4.2 release notes and the SETTINGS docs. [1][2]

Sources

  • Django 4.2 release notes (STORAGES / deprecation of STATICFILES_STORAGE). [1]
  • django.conf.settings — STATICFILES_STORAGE doc (notes about STORAGES["staticfiles"] and deprecated STATICFILES_STORAGE). [2]

🏁 Script executed:

fd -t f "settings.py" | head -5

Repository: OWASP-BLT/BLT

Length of output: 121


🏁 Script executed:

sed -n '308,334p' blt/settings.py
sed -n '375,385p' blt/settings.py

Repository: OWASP-BLT/BLT

Length of output: 1135


Remove deprecated STATICFILES_STORAGE and update STORAGES["staticfiles"] to use WhiteNoise.

In Django 4.2+, STORAGES["staticfiles"] takes precedence over the deprecated STATICFILES_STORAGE setting. Line 380 is dead code since both STORAGES configurations (lines 316-318 and 331-333) already define the staticfiles backend.

To enable WhiteNoise compressed static files storage, remove the deprecated setting and update both STORAGES definitions:

-STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"

Update the GCS STORAGES block (around line 316):

         "staticfiles": {
-            "BACKEND": "django.contrib.staticfiles.storage.ManifestStaticFilesStorage",
+            "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
         },

Update the non-GCS STORAGES block (around line 331):

         "staticfiles": {
-            "BACKEND": "django.contrib.staticfiles.storage.ManifestStaticFilesStorage",
+            "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
         },

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +1264 to +1269

if settings.DEBUG:
urlpatterns += [
path("silk/", include("silk.urls", namespace="silk")),
path("__debug__/", include("debug_toolbar.urls")),
]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Duplicate debug_toolbar URL registration.

The __debug__/ URL pattern for debug_toolbar is already registered at line 1249. This block adds it again at line 1268, resulting in duplicate URL patterns when DEBUG=True.

Remove the duplicate debug_toolbar registration and keep only the silk URLs:

 if settings.DEBUG:
     urlpatterns += [
         path("silk/", include("silk.urls", namespace="silk")),
-        path("__debug__/", include("debug_toolbar.urls")),
     ]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if settings.DEBUG:
urlpatterns += [
path("silk/", include("silk.urls", namespace="silk")),
path("__debug__/", include("debug_toolbar.urls")),
]
if settings.DEBUG:
urlpatterns += [
path("silk/", include("silk.urls", namespace="silk")),
]
🤖 Prompt for AI Agents
In blt/urls.py around lines 1264 to 1269, the debug_toolbar "__debug__/" URL is
being registered a second time causing duplicate URL patterns; edit this
DEBUG-only block to remove the path("__debug__/", include("debug_toolbar.urls"))
entry and leave only the silk registration (path("silk/", include("silk.urls",
namespace="silk"))), ensuring imports remain correct and no other code relies on
this redundant registration.

Comment on lines +73 to +74
django-silk = "^5.0.1"
django-debug-toolbar = "^4.3.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Development tools added to production dependencies.

django-silk and django-debug-toolbar are development/debugging tools that shouldn't be installed in production. Additionally, django-debug-toolbar is already declared in dev dependencies at line 85 with version ^4.4.6, creating a version conflict with ^4.3.0 here.

Move these to dev dependencies and remove the duplicate:

 pyjwt = {extras = ["crypto"], version = "^2.0.0"}
-django-silk = "^5.0.1"
-django-debug-toolbar = "^4.3.0"

In the dev dependencies section, add silk:

 [tool.poetry.group.dev.dependencies]
 black = "^25.12.0"
 isort = "^5.13.2"
 ruff = "^0.14.8"
 pre-commit = "^4.5.0"
 selenium = "^4.39.0"
 webdriver-manager = "^4.0.2"
 chromedriver-autoinstaller = "^0.6.4"
 django-debug-toolbar = "^4.4.6"
 django-livereload-server = "^0.5.1"
 watchfiles = "^1.0.4"
+django-silk = "^5.0.1"

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In pyproject.toml around lines 73-74, django-silk and django-debug-toolbar are
incorrectly listed in production dependencies and django-debug-toolbar is
duplicated with a conflicting version at line 85; remove the two lines from the
main [tool.poetry.dependencies] (or equivalent production deps section), add
django-silk = "^5.0.1" to the dev dependencies section alongside the existing
django-debug-toolbar entry, and ensure the duplicate django-debug-toolbar =
"^4.3.0" is removed so only the dev dependency entry (keep ^4.4.6) remains.

Comment on lines +9 to +13
SOURCE_DIRS = [
"website/static/images",
"website/static/img",
"website/static/img/browser-logos",
]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Overlapping directories will cause duplicate processing.

website/static/img/browser-logos is a subdirectory of website/static/img. Since rglob("*.png") is used, PNGs in browser-logos will be processed twice - once when iterating website/static/img and again when iterating website/static/img/browser-logos.

Remove the subdirectory from SOURCE_DIRS:

 SOURCE_DIRS = [
     "website/static/images",
     "website/static/img",
-    "website/static/img/browser-logos",
 ]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
SOURCE_DIRS = [
"website/static/images",
"website/static/img",
"website/static/img/browser-logos",
]
SOURCE_DIRS = [
"website/static/images",
"website/static/img",
]
🤖 Prompt for AI Agents
In scripts/convert_images_to_webp.py around lines 9 to 13, the SOURCE_DIRS list
contains a nested path ("website/static/img/browser-logos") inside
"website/static/img", causing duplicate processing because rglob("*.png") will
find files twice; remove the nested "website/static/img/browser-logos" entry
from SOURCE_DIRS (or alternatively dedupe paths before walking) so each PNG is
processed only once.

@github-project-automation github-project-automation bot moved this from Backlog to Ready in 📌 OWASP BLT Project Board Dec 10, 2025
@Nachiket-Roy
Copy link
Contributor Author

@coderabbitai I may have converted more images than necessary. Could you please identify which high-impact images should specifically be prioritized for WebP? I haven’t updated the template image sources yet.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 10, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# First, read the conversion script to see which directories are targeted
echo "=== Conversion Script Source Directories ==="
cat scripts/convert_images_to_webp.py | grep -A 10 "SOURCE_DIRS"

echo -e "\n=== Finding all template files ==="
fd -e html -e htm . | head -20

echo -e "\n=== Finding image references in templates ==="
# Search for common image file references in templates
rg -n -i '\.(png|jpg|jpeg|gif|svg)' --type html -C 1 | head -100

Length of output: 11439


🏁 Script executed:

#!/bin/bash

# Get image sizes in the static directories
echo "=== Image sizes in static directories ==="
fd -e png -e jpg -e jpeg -e webp website/static --exec ls -lh {} | awk '{print $5, $9}' | sort -rh | head -30

echo -e "\n=== Image sizes in company_dashboard static ==="
fd -e png -e jpg -e jpeg -e webp company_dashboard/static --exec ls -lh {} | awk '{print $5, $9}' | sort -rh | head -30

echo -e "\n=== Image sizes in blt_site static ==="
fd -e png -e jpg -e jpeg -e webp blt_site/static --exec ls -lh {} | awk '{print $5, $9}' | sort -rh | head -30

Length of output: 492


🏁 Script executed:

#!/bin/bash

# Find the most frequently referenced images in templates
echo "=== Most frequently referenced images in templates ==="
rg -o -i '["\047][^"'\'']*\.(png|jpg|jpeg|gif|webp)["\047]' --type html | \
  sed 's/.*["\047]//; s/["\047].*//' | \
  sort | uniq -c | sort -rn | head -30

echo -e "\n=== Images in base/layout templates ==="
fd -g '*base*.html' -g '*layout*.html' --exec echo "=== {} ===" \; --exec grep -i '\.(png|jpg|jpeg|gif|webp|svg)' {} \;

Length of output: 411


🏁 Script executed:

#!/bin/bash

# Check homepage and landing pages for images
echo "=== Homepage template images ==="
fd -g 'index.html' -g 'home.html' -g 'landing.html' --exec echo "=== {} ===" \; --exec grep -i '\.(png|jpg|jpeg|gif|webp|svg)' {} \;

echo -e "\n=== Looking for logo files ==="
fd -i logo

echo -e "\n=== Looking for banner/hero images ==="
fd -i -g '*banner*' -g '*hero*' -g '*background*'

Length of output: 1284


🏁 Script executed:

#!/bin/bash

# Get image sizes in the website/static directory properly
echo "=== Image sizes in website/static (largest first) ==="
fd -e png -e jpg -e jpeg -e webp . website/static --exec ls -lh {} | awk '{print $5, $9}' | sort -rh | head -30

echo -e "\n=== Checking if WebP versions exist ==="
echo "PNG files:"
fd -e png . website/static/images website/static/img --exec basename {}
echo -e "\nWebP files:"
fd -e webp . website/static/images website/static/img --exec basename {}

Length of output: 34860


🏁 Script executed:

#!/bin/bash

# Find the most frequently referenced images in templates
echo "=== Most frequently referenced images in templates ==="
rg -o "static 'images/[^']+\.(png|jpg|jpeg|gif|webp)" --type html | \
  sed "s/static '//" | sed "s/'//" | \
  sort | uniq -c | sort -rn | head -20

echo -e "\n=== References to img/ directory ==="
rg -o "static 'img/[^']+\.(png|jpg|jpeg|gif|webp|svg)" --type html | \
  sed "s/static '//" | sed "s/'//" | \
  sort | uniq -c | sort -rn | head -20

Length of output: 2873


🏁 Script executed:

#!/bin/bash

# Look for base/layout templates properly
echo "=== Base and layout templates ==="
fd . website/templates -g '*base*.html' -g '*layout*.html'

echo -e "\n=== Images in base templates ==="
fd . website/templates -g '*base*.html' --exec echo "=== {} ===" \; --exec grep -i '\.(png|jpg|jpeg|gif|webp|svg)' {} \;

Length of output: 659


🏁 Script executed:

#!/bin/bash

# Find homepage and landing page templates
echo "=== Homepage templates ==="
fd . website/templates -g 'index.html' -g 'home.html' -g 'landing.html'

echo -e "\n=== Images referenced in key pages ==="
for file in website/templates/index.html website/templates/home.html website/templates/landing.html website/templates/base.html; do
  if [ -f "$file" ]; then
    echo "=== $file ==="
    grep -i '\.(png|jpg|jpeg|gif|webp|svg)' "$file" || echo "No images found"
  fi
done

Length of output: 550


🏁 Script executed:

#!/bin/bash

# Check what images are actually in the static directories
echo "=== All images in website/static/images/ ==="
find website/static/images -type f \( -name "*.png" -o -name "*.jpg" -o -name "*.jpeg" -o -name "*.webp" \) 2>/dev/null | sort

echo -e "\n=== All images in website/static/img/ ==="
find website/static/img -type f \( -name "*.png" -o -name "*.jpg" -o -name "*.jpeg" -o -name "*.webp" \) 2>/dev/null | sort

Length of output: 98955


@Nachiket-Roy, great question! Based on my analysis of template usage and file sizes, here's a prioritized list of images to convert to WebP format in your templates:

🔴 Critical Priority (Update First)

These images have the highest impact due to frequent use across multiple pages:

  1. images/dummy-user.pngimages/dummy-user.webp

    • Usage: 19+ references across templates
    • Pages: profile.html, users.html, domain.html, comments2.html, home.html, issue.html, search.html
    • Impact: Fallback avatar shown throughout the site
    • Current size: Relatively small, but extremely high frequency
  2. images/slack_icon.pngimages/slack_icon.webp

    • Usage: 3 references
    • Pages: organization integrations, dashboard
    • Impact: Shown in integration features

🟠 High Priority (Update Soon)

Visible on homepage and key landing pages:

  1. images/googlelogo_color_272x92dp.png.webp (1.5M size)

    • Usage: home.html
    • Impact: Homepage visibility
  2. img/logo.pngimg/logo.webp

    • Usage: social.html
    • Impact: Brand logo
  3. images/gsoc.png.webp

    • Usage: gsoc.html, features.html
    • Impact: Shown on features page
  4. images/bacon.png.webp (1.7M - largest in images/)

    • Usage: bacon.html, features.html
    • Impact: Large file size

🟡 Medium Priority (Feature Pages)

Images displayed on the features page (img/features/ directory):

  1. Feature showcase images (40+ images referenced in features.html):
    • coming-soon.png, web-stats.png, user-profile.png, trademark.png, teams.png, etc.
    • These are all referenced in features.html showing product capabilities
    • Already have WebP versions created

🟢 Low Priority (Defer)

  1. Browser logos directory (img/browser-logos/)
    • Total: 600+ PNG files (many over 1MB)
    • Usage: Limited references, mainly default browser icon
    • Recommendation: Defer these - they're rarely shown and displayed at small sizes
    • Notable: onion.png (2.3M), android.png (1.6M), web.png (1.2M), mihtool.png (1.2M)
    • Only browser_64x64.png is actually referenced in templates

📝 Recommended Action Plan

  1. Start with dummy-user.png - Update all 19+ template references to use .webp
  2. Homepage images next - googlelogo, slack_icon, logo.png
  3. Batch update feature images - All the img/features/ directory at once
  4. Skip browser logos for now - Minimal impact, can be addressed later if needed

Pro tip: Consider adding a <picture> element with fallback for better browser compatibility:

<picture>
  <source srcset="{% static 'images/dummy-user.webp' %}" type="image/webp">
  <img src="{% static 'images/dummy-user.png' %}" alt="User avatar">
</picture>

Would you like me to help generate a script to update all the template references in bulk?

@github-actions
Copy link
Contributor

❌ Tests failed

The Django tests found issues that need to be fixed. Please review the test output below and fix the failing tests.

How to run tests locally

# Install dependencies
poetry install --with dev

# Run all tests
poetry run python manage.py test

# Run tests with verbose output
poetry run python manage.py test -v 3

# Run a specific test
poetry run python manage.py test app.tests.TestClass.test_method
Test output (last 100 lines)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/silk/middleware.py", line 87, in __call__
    self.process_request(request)
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/silk/middleware.py", line 143, in process_request
    request_model = RequestModelFactory(request).construct_request_model()
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/silk/model_factory.py", line 231, in construct_request_model
    request_model = models.Request.objects.create(
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/models/manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/models/query.py", line 665, in create
    obj.save(force_insert=True, using=self.db)
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/silk/models.py", line 195, in save
    super().save(*args, **kwargs)
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/models/base.py", line 902, in save
    self.save_base(
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/models/base.py", line 1008, in save_base
    updated = self._save_table(
              ^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/models/base.py", line 1169, in _save_table
    results = self._do_insert(
              ^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/models/base.py", line 1210, in _do_insert
    return manager._insert(
           ^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/models/manager.py", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/models/query.py", line 1873, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/models/sql/compiler.py", line 1882, in execute_sql
    cursor.execute(sql, params)
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/backends/utils.py", line 122, in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/backends/utils.py", line 79, in execute
    return self._execute_with_wrappers(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/backends/utils.py", line 92, in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/backends/utils.py", line 99, in _execute
    self.db.validate_no_broken_transaction()
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/backends/base/base.py", line 521, in validate_no_broken_transaction
    raise TransactionManagementError(
django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/core/management/__init__.py", line 194, in call_command
    return command.execute(*args, **defaults)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/core/management/base.py", line 460, in execute
    output = self.handle(*args, **options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/core/management/commands/flush.py", line 52, in handle
    sql_list = sql_flush(
               ^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/core/management/sql.py", line 11, in sql_flush
    tables = connection.introspection.django_table_names(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/backends/base/introspection.py", line 110, in django_table_names
    existing_tables = set(self.table_names(include_views=include_views))
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/backends/base/introspection.py", line 57, in table_names
    return get_names(cursor)
           ^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/backends/base/introspection.py", line 51, in get_names
    for ti in self.get_table_list(cursor)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/backends/sqlite3/introspection.py", line 80, in get_table_list
    cursor.execute(
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/backends/utils.py", line 79, in execute
    return self._execute_with_wrappers(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/backends/utils.py", line 92, in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/backends/utils.py", line 99, in _execute
    self.db.validate_no_broken_transaction()
  File "/home/runner/.cache/pypoetry/virtualenvs/blt-yuw0N2NF-py3.11/lib/python3.11/site-packages/django/db/backends/base/base.py", line 521, in validate_no_broken_transaction
    raise TransactionManagementError(
django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.

----------------------------------------------------------------------
Ran 267 tests in 245.819s

FAILED (errors=2)
Destroying test database for alias 'default' ('file:memorydb_default?mode=memory&cache=shared')...

For more information, see the Django testing documentation.

@github-actions github-actions bot added the tests: failed Django tests failed label Dec 10, 2025
@Nachiket-Roy Nachiket-Roy marked this pull request as draft December 10, 2025 21:15
@github-actions github-actions bot added the last-active: 0d PR last updated 0 days ago label Dec 11, 2025
@Nachiket-Roy
Copy link
Contributor Author

@coderabbitai Should I keep all these images for now (over 2000), and start by replacing the large ones first, then the medium, and eventually the small ones so the changes don’t overwhelm anyone?

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 11, 2025

Tip

For best results, initiate chat on the files or code changes.

@Nachiket-Roy, your phased approach is smart from a review perspective, but I'd recommend a hybrid strategy that balances both impact and review manageability:

🎯 Recommended Strategy

Phase 1: High-Impact Images (Current PR)

Focus on images with high frequency × large size:

  1. dummy-user.png.webp (19+ references, site-wide impact)
  2. bacon.png.webp (1.7M file, features page)
  3. googlelogo_color_272x92dp.png.webp (1.5M, homepage)
  4. slack_icon.png.webp (integration pages)
  5. All img/features/*.png.webp (40+ images, single page - batch update)

Why: These provide immediate measurable performance gains and are manageable in one PR (~70 template updates).

Phase 2: Medium Priority (Follow-up PR)

  • Organization-specific images
  • Dashboard assets
  • Moderately sized images with moderate usage

Phase 3: Low Priority (Optional, Future PR)

  • Small icons
  • Rarely shown images

🧹 Important: Clean Up Low-Value Conversions

Browser logos directory (img/browser-logos/):

  • 600+ converted files, but only 1-2 are actually used in templates
  • Recommendation: Revert these WebP conversions to reduce repository bloat
  • These are displayed at tiny sizes where WebP savings are negligible
  • Keeping 600+ unused files adds maintenance burden and confuses future developers
# Suggest removing these WebP conversions:
rm -rf website/static/img/browser-logos/*.webp
# Keep only the ones actually referenced in templates

📊 Impact vs. Effort Matrix

High Impact, Low Effort:
├─ dummy-user.png (19 refs) ⭐ START HERE
├─ features/ directory (40 refs, batch update) ⭐
└─ Large homepage images (3-4 refs) ⭐

High Impact, Medium Effort:
├─ Dashboard/organization images
└─ Profile page images

Low Impact:
└─ Browser logos (600 files, 1-2 refs) ❌ REVERT

💡 Why Not Keep All 2000+ Files?

  1. Repository bloat: Adds megabytes of unused assets
  2. Developer confusion: "Which images should I use?"
  3. Maintenance burden: Need to keep PNGs AND WebPs in sync
  4. Limited benefit: Small icons compressed negligibly
  5. CI/CD impact: Larger repo clone times

Concrete Next Steps

  1. Clean up browser logos WebP (remove ~600 unused conversions)
  2. Focus this PR on Phase 1 (high-impact images only)
  3. Update templates for ~70 references (manageable review size)
  4. Measure before/after: Use Lighthouse to show performance gains
  5. Phase 2 in follow-up PR if needed

This approach gives you:

  • ✅ Manageable review size
  • ✅ Measurable performance wins
  • ✅ Clean repository
  • ✅ Clear rationale for each change

Would you like me to generate a script to:

  1. Identify and remove low-value WebP conversions?
  2. Create a list of template files to update for Phase 1?
  3. Generate <picture> element replacements for the high-priority images?

@github-actions
Copy link
Contributor

💬 Reminder: Unresolved Conversations

Hi @Nachiket-Roy!

This pull request has 5 unresolved conversations that need to be addressed.

Please review and resolve the pending discussions so we can move forward with merging this PR.

Thank you! 🙏

@github-actions github-actions bot added last-active: 1d PR last updated 1 day ago and removed last-active: 0d PR last updated 0 days ago labels Dec 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

files-changed: 2450 PR changes 2450 files last-active: 1d PR last updated 1 day ago needs-peer-review PR needs peer review pre-commit: passed Pre-commit checks passed tests: failed Django tests failed

Projects

Status: Ready

Development

Successfully merging this pull request may close these issues.

Optimize Static Assets, Large Images, and Enable CDN Delivery

1 participant