Skip to content

feat(frontend): offline support via service worker#516

Open
netchampfaris wants to merge 1 commit into
developfrom
feat/offline-support
Open

feat(frontend): offline support via service worker#516
netchampfaris wants to merge 1 commit into
developfrom
feat/offline-support

Conversation

@netchampfaris

Copy link
Copy Markdown
Contributor

What

Adds offline support to the Gameplan SPA so the app shell loads and cached data is served when the network is unavailable.

How

  • Service worker (gameplan/www/gameplan-sw.js) precaches built assets listed in a build-time manifest and serves them when offline.
  • Vite plugin (offlineAssetManifest() in vite.config.ts) emits gameplan-offline-assets.json (CSS/JS/font URLs) at build time.
  • offline.ts registers the service worker and exposes isBrowserOffline() / isNetworkError() helpers.
  • Data layer: staleOnError + cacheKey added to useList/useDoc calls so cached responses are served on network failure.
  • Router: hydrates community/space data from cache and skips NotFound route validation when offline or on network errors.

Notes

Frontend-only behavior change plus one new backend static file (the service worker). No schema or API changes.

Precache the app shell and serve cached data when the network is
unavailable:

- gameplan-sw.js: service worker that precaches built assets listed in a
  build-time manifest and serves them offline.
- vite.config.ts: offlineAssetManifest() plugin emits
  gameplan-offline-assets.json (CSS/JS/font URLs) at build time.
- offline.ts: registers the service worker and exposes isBrowserOffline()
  / isNetworkError() helpers.
- data layer: add staleOnError + cacheKey to useList/useDoc so cached
  responses are served on network failure.
- router.ts: hydrate community/space data from cache and skip route
  validation (NotFound) when offline or on network errors.
@greptile-apps

greptile-apps Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 4/5

The offline shell caching path needs a fix before merging.

  • The service worker can reuse server-rendered shell HTML across browser-profile sessions.
  • Some stale-on-error caches are not scoped to the active user.
  • Offline route validation can proceed with missing space data.

gameplan/www/gameplan-sw.js, frontend/src/data/users.ts, frontend/src/router.ts

Security Review

The service worker can cache user-specific /g HTML under a shared shell key, and some stale-on-error resource caches are not scoped to the active session.

Reviews (1): Last reviewed commit: "feat(frontend): add offline support via ..." | Re-trigger Greptile

try {
const response = await fetch(request);
if (isHtmlResponse(response)) {
await cache.put(APP_SHELL_URL, response.clone());

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.

P1 security Shared Shell Stores Session Data

This stores every navigation response as the single /g shell, but the /g page is rendered with per-request boot data such as the CSRF token. If one user populates the service-worker cache and another user later opens the app from the same browser profile while offline or after a navigation fetch failure, the app can boot with the previous user's HTML and stale CSRF data, causing wrong session state or failed API writes.

Comment on lines 49 to +50
cacheKey: 'Users',
staleOnError: 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.

P2 security User Cache Crosses Sessions

This stale-on-error cache is keyed only as Users, so a same-tab account switch can reuse the previous account's user list when the next fetch fails. The UI can then show another account's people, roles, or profile metadata instead of failing closed for the current session.

Comment thread frontend/src/router.ts
Comment on lines +807 to +810
if (isRouteValidationUnavailable()) {
communityState.scope(communityId)
return
}

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.

P2 Missing Space Proceeds Offline

When route validation is unavailable, this branch scopes the requested community and lets navigation continue even though getSpace() returned nothing. A deep link to an uncached or deleted space while offline can render the matched route without a valid space instead of showing NotFound, leaving page components to operate on missing route state.

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown

UI Test Results

✅ All passed — 42/42 tests passed in 2m 50s.

Spec Tests
command-palette.cy.ts 5 5 0 0 11s
comment.cy.js 1 1 0 0 40s
community-composer.cy.ts 3 3 0 0 6s
community-discussions-actions.cy.ts 1 1 0 0 7s
community-merge-url-healing.cy.ts 1 1 0 0 4s
community-mobile-home.cy.ts 1 1 0 0 3s
community-naming.cy.ts 3 3 0 0 5s
community-scoped-links.cy.ts 3 3 0 0 3s
community-shell.cy.ts 3 3 0 0 3s
community-smoke.cy.ts 3 3 0 0 3s
community-spaces-guardrails.cy.ts 2 2 0 0 3s
discussion.cy.js 1 1 0 0 27s
drafts-comment.cy.ts 2 2 0 0 8s
member-management.cy.ts 2 2 0 0 5s
mobile-more-pages.cy.ts 4 4 0 0 6s
new-discussion.cy.ts 2 2 0 0 10s
onboarding.cy.js 1 1 0 0 2s
page.cy.js 1 1 0 0 2s
project.cy.js 1 1 0 0 11s
search-privacy.cy.ts 1 1 0 0 3s
task.cy.js 1 1 0 0 7s
Total 42 42 0 0 2m 50s

Results for commit 01e55fc.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant