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
Add Stripe payment integration across the project:
- Add @stripe/stripe-js dependency
- Configure Stripe environment variables (secret key, publishable key, webhook secret) for dev, local, and production environments
- Add Product/Price IDs for monthly, quarterly, and annual subscription tiers
- Extend subscription plan data with voiceMinutesPerDay quotas (30/45/60 minutes per tier)
- Update .gitignore to exclude implementation_plan.md
Update implementation_plan.md with a detailed refactor plan that splits
`chatInitActor` into two independent actors (`loadQuotaActor` +
`loadHistoryActor`) and redesigns the history loading flow to follow
local → network → save semantics so the UI sees local data first,
then network data.
Key changes outlined in the plan:
- Add new events: `ChatQuotaLoaded`, `ChatHistoryLocalLoaded`,
`ChatHistoryNetworkLoaded`, `ChatHistorySyncDone`
- Remove dead-code `ChatInit` event
- Extend `ChatState` with `quotaLoaded` and `historyLoaded` flags
- Use an `always` barrier in `guestSession.initializing` and
`userSession.initializing` so both tasks must complete before
transitioning to `ready`
- Guest init runs `loadQuota` + `loadHistory` in parallel; non-guest
init runs `chatWebSocket` + `loadHistory` as independent tasks
Also adds `implementation_plan` to .gitignore.
- Reorganize env example files into a dedicated env-example/ directory for clarity
- Update .gitignore to ignore env files (with examples now in env-example/)
- Unify CDN credentials (CF_ZONE_ID / CF_API_TOKEN) to be sourced from .env.local in both test and production deploys
- Update git_hooks/post-receive to copy production env example from new location
- Update deploy scripts (pre_release_web.sh, release_web.sh) to copy the appropriate env example into .env.local before building
- Update _deploy_lib.sh purge_cdn_cache to source from .env.local instead of .env
Replace broad `.env*` ignore rule with explicit entries for real env files (`.env`, `.env.local`, `.env.development`, `.env.test`, `.env.production`) while preserving `.env.example` and adding exceptions for the new `.env.development.example`, `.env.test.example`, and `.env.production.example` templates.
Add environment-specific example files to document required variables for development, test, and production setups, including API base URLs, WebSocket endpoints, API timeouts, Auth.js secret, OAuth credentials (Google, Facebook), and Cloudflare CDN configuration.
Introduce a tracked .env.example file documenting all required environment
variables (app env, API/WebSocket base URLs, timeouts, Google/Facebook OAuth
credentials, Cloudflare CDN zone/token). Update .gitignore to allow this
file despite the blanket .env* ignore rule. Also simplify the push
success/failure output in scripts/deploy/_deploy_lib.sh by removing
verbose troubleshooting hints.
Add allowBuilds configuration for sharp and unrs-resolver packages
to permit their postinstall scripts to run, and ignore the local
.pnpm-store directory.