precheckLogin already normalized the username with NFC, but the
NextAuth credentials authorize handler only trimmed it. This caused a
mismatch for accounts with accented/non-ASCII usernames: the precheck
passed while the actual sign-in lookup found no user and returned
'invalid username or password'.
Also normalize the password to NFC in both the precheck and the
authorize handler to match how register.ts hashes it.
- Serve /swf and /nitro-assets (~2.8GB) with 7-day Cache-Control plus
stale-while-revalidate so client opens stop re-fetching hundreds of
files while asset updates still propagate in the background
- Issue the SSO ticket and the online count query in parallel on the
client page to shave a round-trip off the critical render path
- Send the verification email after the response via after() so it
never blocks sign-up
- Invalidate the cached login lookup right after account creation so
the automatic sign-in always finds the fresh row
- Auto sign in with the submitted credentials and go straight to /me,
with a fallback to /login?registered=1 if sign-in is refused (e.g.
email verification required)
- Cache the register page's online/latest user queries to cut DB load
under traffic
- Fix terms checkbox label double-toggle cancelling the selection
- Add pages.register.redirecting translation to all locales
Recent optimization commits accidentally gutted next.config.ts, removing
the createNextIntlPlugin wrapper. This caused every page to crash at
runtime with 'Couldn't find next-intl config file', showing the error
page after a successful build.
Restores:
- next-intl plugin (./src/i18n/request.ts)
- Security headers (HSTS, X-Frame-Options, nosniff, etc.)
- Redirects from /admin/import/* to /admin/studio/*
- Cache headers for /assets and /images, AVIF/WebP image formats
- compress and productionBrowserSourceMaps
Keeps recent improvements: reactStrictMode and optimizePackageImports.
Per single furni import, patchLocalizedFurniDataEntries ran for every
language and did a full 100k-entry JSON.parse + scan + JSON.stringify on the
main thread. That CPU spike is now offloaded to the translation worker
(init/prepare/finalize reuses the same pure core helpers), so importing
never blocks the event loop. The main thread only does async file I/O and the
network LibreTranslate calls. Falls back to the same helpers on the main
thread if no worker is available.
Also cache readFurniData() by file mtime+size so the 100k-entry JSON is
parsed once per change instead of on every import/fix/reconcile read
(invalidated on write).