You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Parent: search for issue titled “Epic Stack catch-up: tracking”. Do this only after packages 1 and 4 are on dev (RR bump + LiteFS/cache/fallthrough). Package 2–3 are nice-to-have first.
Goal
Match Epic Stack’s server boot: TypeScript entry, no server-build / other/build-server.ts, Vite SSR server/app.ts, Express 5 path matching, rate-limit IPv6 helper.
This is medium-high risk. Do not also do Vite 7, Sentry 10, or the routing migration.
Replace index.js with index.ts matching upstream: load dotenv, source-map-support, mocks if MOCKS=true, then alwaysimport('./server/index.ts') (no server-build branch)
Update package.json scripts: dev, dev:no-mocks, start, start:mocks should run node index.ts (keep this site’s dev:scan / localtunnel scripts)
Remove build:remix / build:server split if upstream is just react-router build. Remove other/build-server.ts. Drop server-build from .gitignore / .prettierignore / Dockerfile copy if present
eslintIgnore can drop /server-build
server/app.ts
Split the React Router createRequestHandler into server/app.ts as upstream does
Vite config: for SSR builds, rollupOptions.input = './server/app.ts'
Dev: appType: 'custom', ssrLoadModule('./server/app.ts')after security/rate-limit middleware (see #1076)
Express 5
Bump express to 5.x and @types/express to 5.x (Epic Stack ^5.2.1 / ^5.0.6)
Bump express-rate-limit to 8.x and use ipKeyGenerator in keyGenerator (keep fly-client-ip first)
Convert wildcard paths to what Express 5 / path-to-regexp needs (Epic Stack uses regexes). Do not guess /:path(*) unless that is what current Express 5 in this PR actually requires — match upstream server/index.ts
Add /dashboard to strongPaths (this site’s admin UI)
Dockerfile
Stop copying server-build
Keep Sentry build secrets this site already uses if still needed
Keep LiteFS copy / CMD ["litefs", "mount"]
Do not change Fly app name or region
Vite
Keep localtunnel allowedHosts
Keep Sentry plugin wiring from package 2 if already merged; do not regress hidden sourcemaps
Do not add react-router-devtools here unless it is required to compile (it is not)
engines.node: "^22.18.0"
Files allowed
index.js (delete) / index.ts (add)
server/index.ts, server/app.ts (new), server/dev-server.js (delete if unused)
other/build-server.ts (delete)
other/Dockerfile
package.json, package-lock.json (express, express-rate-limit, @types/express, and whatever those require — not vite/vitest/sentry major)
Parent issue: #23
Parent: search for issue titled “Epic Stack catch-up: tracking”. Do this only after packages 1 and 4 are on
dev(RR bump + LiteFS/cache/fallthrough). Package 2–3 are nice-to-have first.Goal
Match Epic Stack’s server boot: TypeScript entry, no
server-build/other/build-server.ts, Vite SSRserver/app.ts, Express 5 path matching, rate-limit IPv6 helper.This is medium-high risk. Do not also do Vite 7, Sentry 10, or the routing migration.
Upstream
server/index.tsand simplify processes epicweb-dev/epic-stack#1066 / epicweb-dev/epic-stack@bac7bd4 — migrate toserver/index.ts, deletebuild-serverapp.get('*')→app.get(/.*/)(or regex Epic Stack uses);/img/*→/^\/img\/.*/;app.all('*', ...)goes away because the RR handler isserver/app.tsipKeyGeneratorfromexpress-rate-limit(Epic Stackserver/index.ts)"node": "^22.18.0"(keep Node 22; this is a range, not a jump to 24)Reference files (current Epic Stack):
build.rollupOptions.inputfor SSR)Do this
Branch off
origin/dev. PR intodev.Entry
index.jswithindex.tsmatching upstream: load dotenv, source-map-support, mocks ifMOCKS=true, then alwaysimport('./server/index.ts')(noserver-buildbranch)package.jsonscripts:dev,dev:no-mocks,start,start:mocksshould runnode index.ts(keep this site’sdev:scan/localtunnelscripts)build:remix/build:serversplit if upstream is justreact-router build. Removeother/build-server.ts. Dropserver-buildfrom.gitignore/.prettierignore/ Dockerfile copy if presenteslintIgnorecan drop/server-buildserver/app.tscreateRequestHandlerintoserver/app.tsas upstream doesrollupOptions.input='./server/app.ts'appType: 'custom',ssrLoadModule('./server/app.ts')after security/rate-limit middleware (see #1076)Express 5
expressto 5.x and@types/expressto 5.x (Epic Stack^5.2.1/^5.0.6)express-rate-limitto 8.x and useipKeyGeneratorinkeyGenerator(keepfly-client-ipfirst)/:path(*)unless that is what current Express 5 in this PR actually requires — match upstreamserver/index.ts/dashboardtostrongPaths(this site’s admin UI)Dockerfile
server-buildCMD ["litefs", "mount"]Vite
allowedHostsengines.node:"^22.18.0"Files allowed
index.js(delete) /index.ts(add)server/index.ts,server/app.ts(new),server/dev-server.js(delete if unused)other/build-server.ts(delete)other/Dockerfilepackage.json,package-lock.json(express, express-rate-limit, @types/express, and whatever those require — not vite/vitest/sentry major)vite.config.ts(SSR input + keep localtunnel/sentry).gitignore,.prettierignore,eslint.config.js/eslintIgnoreas neededDo not
vite6→7,vitest3→4,@sentry/*9→10,prismabeyond patch/minorreact-router-auto-routesdashboard+route filesAcceptance
server-build/build-server.tsin the repo or Dockerfilenode index.tsis the dev and prod entry (withMOCKS=truefor mocked dev)ipKeyGeneratorallowedHostsstill worksnpm run build,typecheck,test -- --runpass; Playwright on the PR is greendevStaging smoke (human) — required
Staging must boot. Check:
/resources/healthcheck/assetsand faviconsPR target:
dev(nevermain). Implement only this issue.