- Added Sentry configuration for edge features in `sentry.edge.config.ts`
- Added Sentry configuration for server-side in `sentry.server.config.ts`
- Created a sample API route to demonstrate error tracking in `src/app/api/sentry-example-api/route.ts`
- Developed a frontend page to trigger and log errors in `src/app/sentry-example-page/page.tsx`
- Configured client-side Sentry initialization in `src/instrumentation-client.ts` with Replay integration
- Implemented instrumentation registration logic in `src/instrumentation.ts`
Facebook OAuth login returns avatar URLs from
platform-lookaside.fbsbx.com (and occasionally graph.facebook.com).
next/image's optimizer rejects these with 400 Bad Request when they
are not in the allowlist, so chat/sidebar/subscription avatar
<Image> components all fail to render.
Add images.remotePatterns entries for both hosts. Three <Image>
consumers (message-avatar, user-header, subscription-user-row) need
no changes — they all pass the avatarUrl through verbatim and will
work once the optimizer accepts the host.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Next.js 16 ships Turbopack as the default bundler, but
@ducanh2912/next-pwa is webpack-only — the previous PWA setup
required `--webpack` on dev/build/"dev:proxy" scripts, accepting
a perf regression in exchange for working PWA install.
@serwist/turbopack (paired with the official 'serwist' package
and 'esbuild') is the Turbopack-native successor: it works with
the default bundler, no opt-out flag, and gives us a real TS
service worker source file we can read and edit.
What this commit does:
1. Swap deps in package.json:
- Remove @ducanh2912/next-pwa
- Add @serwist/turbopack, serwist, esbuild (all devDeps)
- Drop --webpack flag from dev / dev:proxy / build scripts
(Turbopack is restored as the bundler)
2. next.config.ts:
- Replace withPWAInit wrapping with withSerwist named import
- Update comment block to describe new architecture
3. New src/app/sw.ts: Serwist service worker source.
skipWaiting + clientsClaim + navigationPreload + defaultCache.
This file is compiled to a real SW at build time by Serwist.
4. New src/app/serwist/[[...slug]]/route.ts: catch-all Route
Handler that serves the compiled SW at /serwist/sw.js plus
Serwist's chunked runtime assets. Catch-all is required
because Serwist serves multiple files under /serwist/.
5. src/app/layout.tsx: replace <SwRegister /> with
<SerwistProvider swUrl="/serwist/sw.js"> from
@serwist/turbopack/react. The provider handles registration
+ lifecycle internally.
6. Delete src/app/_components/core/sw-register.tsx: replaced
by SerwistProvider.
7. .gitignore: add public/sw.js and public/workbox-*.js
(defensive — these are build artifacts that change hash
every build and shouldn't be committed).
8. Untrack public/workbox-3c9d0171.js: stale workbox runtime
from the previous next-pwa build, hash is build-specific
so it can never be regenerated correctly.
Not modified (intentionally):
- src/utils/pwa.ts: pure beforeinstallprompt browser-API wrapper,
library-agnostic, stays as-is.
- pwa-install-overlay / pwa-install-dialog: install UI flow
unchanged.
- public/manifest.json: still works; layout's metadata.manifest
points at it.
Verification:
- pnpm install resolved cleanly (added 24 pkgs, removed 209)
- npx tsc --noEmit passes (EXIT=0)
- Serwist provides named exports, not default — withSerwist and
createSerwistRoute are both named imports
PWA install flow was wired but unusable: pwaUtil.install() calls
deferred.prompt(), but Chrome only fires beforeinstallprompt when a
valid Service Worker is registered + a manifest is linked. The project
had both intent (manifest, usePwaInstall hook) but no live SW —
public/sw.js was a stale workbox build artifact from a previous
attempt with hardcoded chunk URLs that no longer matched any build.
What this commit does:
1. Add @ducanh2912/next-pwa@10.2.9 as devDependency.
2. Wrap nextConfig with withPWA({...}):
- dest: "public" SW outputs to public/sw.js
- disable: true skip SW generation in dev (HMR-friendly)
- register: false don't auto-inject registration
- workboxOptions.skipWaiting: true + clientsClaim: true — new SW
takes over immediately
3. Add --webpack flag to dev/build/dev:proxy scripts.
@ducanh2912/next-pwa is webpack-only; Turbopack (Next 16 default)
doesn't load webpack plugins. Per user decision to accept the perf
trade-off in exchange for a working PWA.
4. Delete stale public/sw.js (workbox will regenerate it at build
time with the correct chunk URLs).
5. Add src/app/_components/core/sw-register.tsx: a no-UI client
component that registers /sw.js in production. Mounted at the end
of <body> in layout.tsx. disable: true means dev mode skips
registration (no /sw.js to fetch anyway).
After this commit + pnpm build, public/sw.js is regenerated with
correct chunk URLs, registered on first prod load, and Chrome fires
beforeinstallprompt — usePwaInstall + pwaUtil.install() then trigger
the native install prompt end-to-end.
Configure Progressive Web App capabilities for production builds, enabling offline support and installability. PWA is disabled in dev to avoid HMR conflicts, and switches the build to webpack since PWA tooling requires it.