secure dev tunnel: strip /__nextjs debug endpoints while keeping HMR
This commit is contained in:
parent
12ff3e70e9
commit
f5a913201a
5 changed files with 181 additions and 17 deletions
50
opencode.md
50
opencode.md
|
|
@ -46,10 +46,11 @@ picks which one to show based on theme and device.
|
|||
|
||||
### Scripts
|
||||
```bash
|
||||
npm run dev # next dev --turbopack (a server may already be running on :3000)
|
||||
npm run build # next build --turbopack
|
||||
npm run start # next start
|
||||
npm run lint # eslint
|
||||
npm run dev # node scripts/dev-server.mjs (dev + HMR; strips dev-only debug for non-local access)
|
||||
npm run dev:next # next dev --turbopack (raw, UNPROTECTED escape hatch — don't use behind the tunnel)
|
||||
npm run build # next build --turbopack
|
||||
npm run start # next start
|
||||
npm run lint # eslint
|
||||
```
|
||||
Useful checks before handing work back: `npx tsc --noEmit`, `npx eslint <files>`,
|
||||
`npm run build`.
|
||||
|
|
@ -100,6 +101,8 @@ src/app/
|
|||
Clock.tsx → live clock (useSyncExternalStore + interval)
|
||||
JokerLogo.tsx → site logo with a click easter egg
|
||||
SlBackground.tsx → animated ASCII train background (terminal theme)
|
||||
scripts/
|
||||
dev-server.mjs → custom dev server: live updates minus the dev-only debug surface
|
||||
```
|
||||
|
||||
### How UI selection works
|
||||
|
|
@ -233,12 +236,28 @@ list reordering, not free placement. Don't confuse the two.
|
|||
`59` is duplicated in `skeuo.css` (`.win-window.maximized` height,
|
||||
`.win-window.centered` bottom / max-height) — keep them in sync. Note
|
||||
`useDesktopIcons.ts` has its **own** `TASKBAR_HEIGHT = 48` for the icon grid.
|
||||
- Exposing the **dev** server over a tunnel needs the tunnel host in
|
||||
`allowedDevOrigins` (`next.config.ts`). Without it Next dev rejects the
|
||||
cross-origin HMR WebSocket, so the client never hydrates — the page is SSR
|
||||
only: icons all stacked at `(0,0)`, buttons dead. Changing `next.config.ts`
|
||||
needs a dev-server restart. For a public URL prefer a production build
|
||||
(`npm run build && npm run start`): no HMR socket, so nothing to reject.
|
||||
- **Serving the dev server through the tunnel: read this.** `npm run dev` does
|
||||
**not** run `next dev` directly — it runs `node scripts/dev-server.mjs`, a
|
||||
custom server that wraps Next's request handler. It keeps the live-update
|
||||
path (`/_next/hmr`, Fast Refresh) but returns `404` for Next's dev-only debug
|
||||
endpoints (`/__nextjs*`: launch-editor, original stack frames, source maps,
|
||||
node-inspector attach, server restart, …) and for `*.map` whenever the
|
||||
request did **not** arrive over loopback without proxy headers. Those
|
||||
endpoints are unauthenticated, and Next wires them in unconditionally, so
|
||||
`next.config.ts` cannot disable them — that is what makes a publicly
|
||||
tunnelled dev server unsafe. Net effect:
|
||||
`localhost:3000` keeps the full dev experience; the LAN/tunnel get a plain,
|
||||
live-reloading site. Use `npm run dev:next` only if you explicitly want the
|
||||
raw, unprotected server (never point the tunnel at it).
|
||||
- `allowedDevOrigins` (`next.config.ts`) still matters: the tunnel host and any
|
||||
LAN origin must be listed or Next rejects the HMR WebSocket with a 403 (the
|
||||
client then never hydrates — SSR only, icons stacked at `(0,0)`, dead
|
||||
buttons). Keep it tight (private ranges + the one exact tunnel host); a
|
||||
`**.dvorakmortonxd.dev` wildcard would let any subdomain drive the dev
|
||||
server. Changing `next.config.ts` needs a dev-server restart.
|
||||
- `devIndicators: false` in `next.config.ts` hides Next's on-screen dev badge.
|
||||
- For a fully public URL a production build (`npm run build && npm run start`)
|
||||
is still the gold standard: no dev server, no debug endpoints, no HMR socket.
|
||||
- The SMP service shortcut opens `SMP_APP` (in `apps.tsx`, registered in
|
||||
`APP_BY_ID` only, like `ALACRITTY_APP`) — a Minecraft-style join menu that
|
||||
reads live data from `/api/ping?url=minecraft://…`.
|
||||
|
|
@ -257,6 +276,17 @@ list reordering, not free placement. Don't confuse the two.
|
|||
- There is **no test suite**. Verification is `tsc --noEmit`, `eslint`, and
|
||||
`next build`.
|
||||
- A dev server may already be running on port 3000; check before starting one.
|
||||
Two dev servers on this repo collide on `.next/dev/lock`, so stop the old one
|
||||
(and delete the stale lock) before starting the custom one.
|
||||
- Dev-server guard check: `curl -s -o /dev/null -w '%{http_code}' \
|
||||
http://localhost:3000/__nextjs_server_status` must be `200` (localhost keeps
|
||||
debug), while the same path through the LAN IP or `beta.dvorakmortonxd.dev`
|
||||
must be `404`. Note a request from this host to its **own** LAN IP is routed
|
||||
over loopback, so `localAddress` reads `127.0.0.1` — a same-host curl to the
|
||||
LAN IP does NOT exercise the non-loopback branch. Test that branch through
|
||||
the tunnel or from another machine. HMR is fine as long as a real
|
||||
`/_next/hmr` WebSocket upgrade returns `101` and then sends a frame (the HMR
|
||||
client appends `?id=self.__next_r` from the served HTML).
|
||||
- The desktop layout is geometry-heavy. When changing grid maths, a small
|
||||
standalone script mirroring `normalize()` / `posToCell()` is a fast way to
|
||||
prove one-icon-per-cell holds for edge cases (offscreen drops, tiny
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue