Closes the migration. Every line of vanilla JS/CSS/HTML that used to
render the user-facing app is gone. The React bundle in public/app/
is the entire client.
Deleted (everything was 100% covered by ported React equivalents):
• public/index.html (vanilla shell — auth screen + tab loader)
• public/js/ (~30 vanilla modules: app.js, auth.js,
admin.js, calculators.js, peGuide.js,
bedside/*, learningHub.js, encounters.js,
etc. — all replaced by client/src/pages/*
and client/src/data/*)
• public/components/ (18 lazy-loaded HTML fragments — not
loaded by any React route)
• public/css/styles.css (vanilla design system — superseded by
Tailwind + shadcn classes throughout
the React tree)
• public/e2e-harness.html (vanilla-only Playwright bootstrapper)
• e2e/tests/bedside-smoke.spec.js
• e2e/tests/top-calculators.spec.js
(the two e2e specs that exercised
/e2e-harness.html and the vanilla
calculators directly — replaced by
calculators-react.spec.js +
bedside-react.spec.js + the 136
vitest parity tests in
shared/clinical/*.test.ts)
Moved (still needed by the backend):
• public/js/pediatricScheduleData.js → src/data/pediatric-schedule-data.js
Required by src/routes/wellVisit.ts at runtime; should never have been
in public/ anyway since it carries server-side schedule + growth +
BMI reference tables and was being served as a 2120-line public JS
blob to every browser. Not in public/ means it's not exposed to
anonymous web requests anymore.
server.ts
• Removed the dead getTemplatedIndex() / INDEX_PATH machinery that
used to BUILD_ID-stamp /js/* and /css/* references in the vanilla
HTML. Vite's hashed asset URLs already do that job for the React
bundle.
• express.static cache header: removed the /components/ branch
(folder no longer exists) and changed /js/ + /css/ from 1-hour
to 1-day immutable cache — safe because Vite hashes the
filenames on every build.
Backend tsc + client tsc + vite build all green. 136/136 vitest
parity tests still pass against the captured calc-vectors.json.
Initial bundle unchanged at 343.97 kB / 106.59 kB gz.
Instead of shipping placeholder pages, added a new backend endpoint
so the React client can render the real AAP/CDC tables without
duplicating the 2000-line pediatricScheduleData module in the client
bundle:
GET /api/schedule-data (authed)
Returns { visitAges, periodicity, catchUpSchedule, vaccineFullNames }
— everything the vaccine table and catch-up views need from the
server-side pediatricScheduleData require(). VACCINE_FULL_NAMES
(which was inlined in public/js/wellVisit.js) now lives in the
route file so it's single-sourced.
client/src/pages/VaxSchedule.tsx
useQuery → /api/schedule-data. Renders the full vaccine × visit-age
grid with sticky header + sticky first column for long scrolling.
Each filled cell shows the dose number or bullet, with the original
note text on hover.
client/src/pages/Catchup.tsx
Card-per-vaccine layout with min-age / min-interval tables and
catch-up notes. Matches the vanilla layout.
Layout: vaccine + catch-up links now available in the sidebar.
Typecheck green both sides. Vite build 382 kB / 112 kB gzipped.
sickVisit.ts — /api/sick-visit/note
wellVisit.ts — /api/well-visit/{shadess,note}
peGuide.ts — /api/generate-pe-narrative (with typed PeStep)
milestones.ts — /api/{milestones-data, generate-milestone-narrative, generate-milestone-summary}
chartReview.ts — /api/generate-chart-review (typed VisitEntry etc.)
All five follow the established pattern. Added a handful of inline
interfaces (PeStep, MilestoneItem, VisitEntry) where the existing code
was juggling anonymous object shapes — these will migrate into
shared/types.ts during Day 5 if reused elsewhere.
14 of 29 routes converted. Progress: 14/54 backend files.
tsc --noEmit green.