Skip to content

Epic Stack catch-up 5/7: Server index.ts / drop server-build / Express 5 #28

Description

@cursor

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 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.

Upstream

Reference files (current Epic Stack):

Do this

Branch off origin/dev. PR into dev.

  1. Entry

    • Replace index.js with index.ts matching upstream: load dotenv, source-map-support, mocks if MOCKS=true, then always import('./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
  2. 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)
  3. 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)
  4. 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
  5. 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)
  6. 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)
  • vite.config.ts (SSR input + keep localtunnel/sentry)
  • .gitignore, .prettierignore, eslint.config.js / eslintIgnore as needed
  • Tests that import server boot

Do not

  • Do not bump vite 6→7, vitest 3→4, @sentry/* 9→10, prisma beyond patch/minor
  • Do not switch to react-router-auto-routes
  • Do not edit dashboard+ route files
  • Do not remove extra UI dependencies
  • Do not base on PR P/patn dev stack updater #21

Acceptance

  • No server-build / build-server.ts in the repo or Dockerfile
  • node index.ts is the dev and prod entry (with MOCKS=true for mocked dev)
  • Express 5; rate limiter uses ipKeyGenerator
  • Localtunnel allowedHosts still works
  • npm run build, typecheck, test -- --run pass; Playwright on the PR is green
  • PR targets dev

Staging smoke (human) — required

Staging must boot. Check:

  • HTTPS / no trailing-slash issues
  • /resources/healthcheck
  • Login, notes, dashboard
  • Static /assets and favicons
  • Rate limit does not lock you out while clicking around

PR target: dev (never main). Implement only this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions