Skip to content

Feat: implement PWA support for offline access#684

Open
Papia-tech wants to merge 2 commits into
GitMetricsLab:mainfrom
Papia-tech:main
Open

Feat: implement PWA support for offline access#684
Papia-tech wants to merge 2 commits into
GitMetricsLab:mainfrom
Papia-tech:main

Conversation

@Papia-tech
Copy link
Copy Markdown
Contributor

@Papia-tech Papia-tech commented Jun 2, 2026

Related Issue


Description

This PR introduces Progressive Web App (PWA) support to the application to enable offline capabilities, resource caching, and standalone installability ("Add to Home Screen").


How Has This Been Tested?

Tested locally using a production-built environment to ensure proper service worker registration and manifest recognition:

  1. Ran npm run build followed by npm run preview to evaluate the production output.
  2. Inspected the application execution parameters under Chrome DevTools > Application > Manifest and verified that the configurations are valid.
  3. Inspected DevTools > Application > Service Workers to confirm that the background lifecycle agent is active.
  4. Performed cache evaluations using offline simulation mode to ensure that the core UI layout elements compile successfully without an active internet connection.

Screenshots (if applicable)

bREC.mp4

Type of Change

  • Bug fix
  • New feature
  • Code style update
  • Breaking change
  • Documentation update

Summary by CodeRabbit

  • New Features
    • Enabled Progressive Web App (PWA) capabilities with automatic service worker registration for improved offline functionality
    • Added web app manifest configuration with branding, colors, and app icons for better app installability
    • Implemented intelligent caching strategy for GitHub API requests to enhance performance and enable offline access

Added PWA support with configuration for caching and manifest.
Add service worker registration for PWA support.
@netlify
Copy link
Copy Markdown

netlify Bot commented Jun 2, 2026

Deploy Preview for github-spy failed.

Name Link
🔨 Latest commit d1aeb1d
🔍 Latest deploy log https://app.netlify.com/projects/github-spy/deploys/6a1f02da2c23820008d21741

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds Progressive Web App support by configuring the VitePWA Vite plugin with service worker registration, manifest metadata, and GitHub API caching rules, then registers the service worker at runtime before React bootstrap to enable offline access and installability.

Changes

PWA Service Worker and Build Configuration

Layer / File(s) Summary
PWA build configuration
vite.config.ts
VitePWA plugin added with manifest (app name, colors, display mode, start URL, icons), asset inclusion list, and Workbox runtime caching rules using NetworkFirst strategy for GitHub API traffic with expiration and allowed response status codes.
Service worker registration at runtime
src/main.tsx
Virtual PWA register module is imported and registerSW({ immediate: true }) is called before React initialization to activate the service worker and caching on app startup.

🎯 3 (Moderate) | ⏱️ ~20 minutes

🐰 PWA magic in the air, offline we'll go there,
Cached assets fast and true, manifest in view,
Service workers on the run, Progressive Web fun!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Feat: implement PWA support for offline access' clearly and concisely summarizes the main change: adding Progressive Web App capabilities for offline functionality.
Description check ✅ Passed The pull request description includes all required template sections with substantial, relevant content covering the issue reference, detailed implementation description, comprehensive testing methodology, and proper feature type classification.
Linked Issues check ✅ Passed All coding requirements from issue #683 are met: manifest configuration with icons/colors/display is added in vite.config.ts, service worker is registered in main.tsx, and Workbox caching strategy is configured for offline support.
Out of Scope Changes check ✅ Passed All changes in src/main.tsx and vite.config.ts are directly aligned with implementing PWA support as specified in issue #683; no unrelated modifications were detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main.tsx`:
- Around line 7-10: The call to registerSW({ immediate: true }) can throw and
block app initialization; wrap the registration in a try-catch (or call it
asynchronously after render) so failures don't break the app: locate registerSW
in src/main.tsx and change its invocation to be guarded by a try { await
registerSW({ immediate: true }) } catch (err) { /* log or noop */ } or call
registerSW().catch(...) so errors are caught and logged without preventing React
from mounting.

In `@vite.config.ts`:
- Line 19: The config currently sets orientation: 'portrait' which forces
portrait-only layout; update the exported Vite config (the object passed to
defineConfig / the default export in vite.config.ts) to use orientation: 'any'
(or remove the orientation key) so desktop/tablet/landscape users can view the
dashboard correctly; locate and change the orientation property in the config
object to 'any'.
- Around line 48-50: The cacheableResponse configuration is including status 0
(opaque/error responses) which can cache CORS/network failures; update the
cacheableResponse.statuses in the vite config (the cacheableResponse block) to
remove 0 and only include successful HTTP codes (e.g., [200] or other explicit
GitHub success codes you need) so only real successful responses are cached.
- Line 3: The project imports VitePWA from 'vite-plugin-pwa' in vite.config.ts
but the package isn't declared in the owning package.json; add "vite-plugin-pwa"
to that package.json (preferably under devDependencies), pick a compatible
version for your Vite setup, run the package manager install (npm/yarn/pnpm) to
update node_modules and lockfile, and commit the updated package.json and
lockfile so VitePWA import (VitePWA in vite.config.ts) resolves in CI and local
builds.
- Around line 21-34: The manifest icons in the icons array in vite.config.ts
reference src: 'crl.png' for sizes '192x192' and '512x512' but the actual
public/crl.png is 219x230 (non-square and wrong dimensions); fix by replacing
those entries to reference correctly-sized square icon files that exist in
public (e.g., crl-192.png and crl-512.png) or generate square 192x192 and
512x512 PNGs and update the src and sizes accordingly in the same icons array
while keeping type: 'image/png' and purpose: 'any'.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 20a38b00-33ec-4e67-b7d6-46c99db08996

📥 Commits

Reviewing files that changed from the base of the PR and between 53f820b and d1aeb1d.

📒 Files selected for processing (2)
  • src/main.tsx
  • vite.config.ts

Comment thread src/main.tsx
Comment on lines +7 to +10
// Import the service worker registration from the virtual module
import { registerSW } from "virtual:pwa-register";
// Register the service worker to handle automatic background updates
registerSW({ immediate: true });
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add error handling around service worker registration.

Calling registerSW({ immediate: true }) synchronously before React rendering means any error (unsupported browser, misconfigured plugin, HTTP context) will prevent the entire app from initializing. Users would see a blank page instead of a helpful error or the app functioning without PWA features.

🛡️ Recommended fix: Wrap registration in try-catch
 // Import the service worker registration from the virtual module
 import { registerSW } from "virtual:pwa-register";
-// Register the service worker to handle automatic background updates
-registerSW({ immediate: true });
+
+// Register the service worker to handle automatic background updates
+// Wrapped in try-catch to prevent blocking app initialization if SW fails
+try {
+  registerSW({ immediate: true });
+} catch (error) {
+  console.warn('Service worker registration failed:', error);
+  // App will continue to function without PWA features
+}

This ensures the app remains functional even if PWA features are unavailable.

📝 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
// Import the service worker registration from the virtual module
import { registerSW } from "virtual:pwa-register";
// Register the service worker to handle automatic background updates
registerSW({ immediate: true });
// Import the service worker registration from the virtual module
import { registerSW } from "virtual:pwa-register";
// Register the service worker to handle automatic background updates
// Wrapped in try-catch to prevent blocking app initialization if SW fails
try {
registerSW({ immediate: true });
} catch (error) {
console.warn('Service worker registration failed:', error);
// App will continue to function without PWA features
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main.tsx` around lines 7 - 10, The call to registerSW({ immediate: true
}) can throw and block app initialization; wrap the registration in a try-catch
(or call it asynchronously after render) so failures don't break the app: locate
registerSW in src/main.tsx and change its invocation to be guarded by a try {
await registerSW({ immediate: true }) } catch (err) { /* log or noop */ } or
call registerSW().catch(...) so errors are caught and logged without preventing
React from mounting.

Comment thread vite.config.ts
@@ -1,11 +1,63 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { VitePWA } from 'vite-plugin-pwa' // Import the PWA plugin
Copy link
Copy Markdown
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

🏁 Script executed:

#!/bin/bash
# Check if vite-plugin-pwa is declared in package.json
if [ -f package.json ]; then
  cat package.json | jq -r '.dependencies["vite-plugin-pwa"] // .devDependencies["vite-plugin-pwa"] // "NOT_FOUND"'
else
  echo "package.json not found"
fi

Repository: GitMetricsLab/github_tracker

Length of output: 82


Add vite-plugin-pwa to dependencies/devDependencies

vite.config.ts imports VitePWA from vite-plugin-pwa, but the repo-root package.json does not list vite-plugin-pwa in dependencies or devDependencies. Add it to the package.json that owns the Vite config to avoid module-resolution failures.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vite.config.ts` at line 3, The project imports VitePWA from 'vite-plugin-pwa'
in vite.config.ts but the package isn't declared in the owning package.json; add
"vite-plugin-pwa" to that package.json (preferably under devDependencies), pick
a compatible version for your Vite setup, run the package manager install
(npm/yarn/pnpm) to update node_modules and lockfile, and commit the updated
package.json and lockfile so VitePWA import (VitePWA in vite.config.ts) resolves
in CI and local builds.

Comment thread vite.config.ts
theme_color: '#0d1117',
background_color: '#0d1117',
display: 'standalone',
orientation: 'portrait',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Consider using 'any' for orientation to support desktop and tablet users.

Restricting orientation to portrait may provide a suboptimal experience for users on desktop, laptop, or tablet devices viewing the GitHub Tracker dashboard in landscape mode. Unless this is specifically a mobile-only application, orientation: 'any' is typically preferred.

📱 Suggested fix to support all orientations
         display: 'standalone',
-        orientation: 'portrait',
+        orientation: 'any',
         start_url: '/',
📝 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
orientation: 'portrait',
display: 'standalone',
orientation: 'any',
start_url: '/',
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vite.config.ts` at line 19, The config currently sets orientation: 'portrait'
which forces portrait-only layout; update the exported Vite config (the object
passed to defineConfig / the default export in vite.config.ts) to use
orientation: 'any' (or remove the orientation key) so desktop/tablet/landscape
users can view the dashboard correctly; locate and change the orientation
property in the config object to 'any'.

Comment thread vite.config.ts
Comment on lines +21 to +34
icons: [
{
src: 'crl.png',
sizes: '192x192',
type: 'image/png',
purpose: 'any'
},
{
src: 'crl.png',
sizes: '512x512',
type: 'image/png',
purpose: 'any'
}
]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if crl.png exists and report its dimensions
fd -t f "^crl\.png$" public/ -x file {} \; -x identify -format "%f: %wx%h\n" {} 2>/dev/null || echo "crl.png not found or 'identify' (ImageMagick) not available"

# List all PNG files in public directory that might be icons
echo -e "\nAll PNG files in public directory:"
fd -e png . public/

Repository: GitMetricsLab/github_tracker

Length of output: 203


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== vite.config.ts (around icons config) =="
if [ -f "vite.config.ts" ]; then
  sed -n '1,120p' vite.config.ts | nl -ba | sed -n '15,60p'
else
  echo "vite.config.ts not found"
fi

echo
echo "== Search for crl.png usage =="
rg -n "crl\.png" . || true

echo
echo "== Public PNG files =="
fd -e png . public/ | sort || true

echo
echo "== Dimensions via Pillow (crl.png, crl-icon.png) =="
python3 - <<'PY'
from PIL import Image
import os, sys

paths = []
for p in ["public/crl.png", "public/crl-icon.png"]:
    if os.path.exists(p):
        paths.append(p)

if not paths:
    print("No expected icon files found in public/.")
    sys.exit(0)

for p in paths:
    with Image.open(p) as img:
        print(f"{p}: {img.size[0]}x{img.size[1]}")
PY

Repository: GitMetricsLab/github_tracker

Length of output: 176


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate vite.config.ts =="
fd -t f "vite.config.ts" . || true

echo
echo "== Show vite.config.ts around 'icons' if found =="
path="$(fd -t f "vite.config.ts" . | head -n 1 || true)"
if [ -n "${path}" ] && [ -f "${path}" ]; then
  echo "-- file: ${path} --"
  # Print a small window around the first occurrence of "icons"
  awk '
    { if ($0 ~ /icons[[:space:]]*:/ && start==0) { start=NR-10; if (start<1) start=1; }
      if (start>0 && NR>=start && NR<=start+80) print NR ":" $0
      if (start>0 && NR>=start+80) { exit }
    }
  ' "${path}"
else
  echo "vite.config.ts not found in repo."
fi

echo
echo "== Search for crl.png usage =="
rg -n "crl\.png" . || true

echo
echo "== Public PNG files =="
fd -e png . public/ | sort || true

echo
echo "== Dimensions via Pillow =="
python3 - <<'PY'
from PIL import Image
import os

paths = ["public/crl.png", "public/crl-icon.png", "public/crl.png".replace("public/","")]
# Deduplicate existing paths
paths = [p for p in ["public/crl.png","public/crl-icon.png"] if os.path.exists(p)]

if not paths:
    print("No expected icon files found in public/.")
    raise SystemExit(0)

for p in paths:
    with Image.open(p) as img:
        print(f"{p}: {img.size[0]}x{img.size[1]}")
PY

Repository: GitMetricsLab/github_tracker

Length of output: 1777


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Search for crl-icon.png usage =="
rg -n "crl-icon\.png" . || true

echo
echo "== Install Pillow (needed for dimensions) =="
python3 -m pip -q install Pillow

echo
echo "== Dimensions via Pillow =="
python3 - <<'PY'
from PIL import Image
import os

paths = ["public/crl.png", "public/crl-icon.png"]
for p in paths:
    if not os.path.exists(p):
        print(f"{p}: MISSING")
        continue
    with Image.open(p) as img:
        print(f"{p}: {img.size[0]}x{img.size[1]}")
PY

Repository: GitMetricsLab/github_tracker

Length of output: 692


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 -m pip -q install Pillow
python3 - <<'PY'
from PIL import Image
img = Image.open('public/crl.png')
print(f"public/crl.png dimensions: {img.size[0]}x{img.size[1]} (expected 192x192 and 512x512 per vite.config.ts)")
PY

Repository: GitMetricsLab/github_tracker

Length of output: 157


🏁 Script executed:

python3 -m pip -q install Pillow
python3 - <<'PY'
from PIL import Image
img = Image.open('public/crl.png')
print('public/crl.png:', img.size)
PY

Repository: GitMetricsLab/github_tracker

Length of output: 99


Critical: PWA icons misconfigured—crl.png is 219x230 but declared as 192x192 and 512x512

vite.config.ts declares two manifest icons using src: 'crl.png' for sizes: '192x192' and sizes: '512x512', but public/crl.png is actually 219x230 (non-square / doesn’t match either declared dimension), so the manifest won’t match the intended icon set.

🎨 Recommended fix: reference correctly sized square icons for each declared size
         icons: [
           {
-            src: 'crl.png',
+            src: 'icon-192.png',
             sizes: '192x192',
             type: 'image/png',
             purpose: 'any'
           },
           {
-            src: 'crl.png',
+            src: 'icon-512.png',
             sizes: '512x512',
             type: 'image/png',
             purpose: 'any'
           }
         ]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vite.config.ts` around lines 21 - 34, The manifest icons in the icons array
in vite.config.ts reference src: 'crl.png' for sizes '192x192' and '512x512' but
the actual public/crl.png is 219x230 (non-square and wrong dimensions); fix by
replacing those entries to reference correctly-sized square icon files that
exist in public (e.g., crl-192.png and crl-512.png) or generate square 192x192
and 512x512 PNGs and update the src and sizes accordingly in the same icons
array while keeping type: 'image/png' and purpose: 'any'.

Comment thread vite.config.ts
Comment on lines +48 to +50
cacheableResponse: {
statuses: [0, 200]
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Major: Including status 0 in cacheableResponse may cache CORS errors.

The cacheableResponse.statuses array includes 0, which represents opaque responses (typically CORS errors or network failures). The GitHub API returns proper HTTP status codes, so caching status 0 responses will pollute the cache with errors, causing users to see stale error responses when offline.

🔧 Recommended fix: Cache only successful responses
               cacheableResponse: {
-                statuses: [0, 200]
+                statuses: [200]
               }

If the app needs to cache other successful GitHub API response codes, consider:

-                statuses: [0, 200]
+                statuses: [200, 201, 204]
📝 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
cacheableResponse: {
statuses: [0, 200]
}
cacheableResponse: {
statuses: [200]
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@vite.config.ts` around lines 48 - 50, The cacheableResponse configuration is
including status 0 (opaque/error responses) which can cache CORS/network
failures; update the cacheableResponse.statuses in the vite config (the
cacheableResponse block) to remove 0 and only include successful HTTP codes
(e.g., [200] or other explicit GitHub success codes you need) so only real
successful responses are cached.

@Papia-tech
Copy link
Copy Markdown
Contributor Author

Papia-tech commented Jun 2, 2026

Hi @mehul-m-prajapati I have successfully implemented and verified the PWA support locally. However, the GitHub Actions checks are failing due to pre-existing ESLint errors in Navbar.tsx, useGitHubData.ts, and Signup.tsx, which are outside the scope of my assigned issue (#683). Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🚀 Feature: Implement PWA Support

1 participant