Post-swap hardening after a full BS4-removed-class sweep of the codebase:
- LocationAutocomplete passed `root: 'form-group'` to react-places-autocomplete;
BS5 removed `.form-group` (it gave the bottom margin) -> use `mb-3`.
- Drop the unused `popper.js@1` dependency (react-bootstrap bundles
@popperjs/core@2). No source imports it.
Sweep otherwise clean: no other BS4-only utility/component classes remain in JSX
or SCSS. Full-app build boots clean.
Completes the Bootstrap 4->5 migration now that every jQuery/BS4 widget is React
(navbar, carousel, dropdowns) — plus the feedback toggle here (Feedback.js:
global `$('#feedback-form').toggle()` -> React state).
- Load Bootstrap 5 CSS from the `bootstrap` npm package in client/index.js
(imported first so app + component styles and react-bootstrap override it).
- Remove the `alexwine:bootstrap-4` meteor package (BS4 CSS + jQuery + BS4 JS).
jQuery for jquery-validation still comes from the npm `jquery` dep.
- Utility renames to BS5: ml-auto->ms-auto, float-right->float-end,
btn-block->w-100, data-toggle->data-bs-toggle (FromNow tooltip).
- forms.scss `.form-label` is no longer a shim (BS5 ships it); comment updated.
Full-app build boots clean; server suite 36 passing. Needs a visual staging pass
across all pages (BS4->5 shifts grid gutters/typography); forms should improve
since react-bootstrap v2 already emitted BS5 markup.
Second (last) jQuery/BS4 JS blocker to the BS5 CSS swap. Replaces the
`bootstrap-carousel-swipe` jQuery plugin + `$(...).carousel()` init with
react-bootstrap's <Carousel> (native swipe, no jQuery) for both home carousels.
- Preserves the progressive `.lazy` background mechanism (blur -> full image on
slide-in): the old `slide.bs.carousel` handler becomes <Carousel onSlide>,
which marks the incoming index in component state.
- Keeps all per-slide class hooks (carousel-item-N, carousel-snd-item-N).
- CSS ports in Index-custom.scss for react-bootstrap's BS5 markup: indicators
render as <button> (not <li>), and prev/next labels use .visually-hidden
(BS4 had .sr-only) -> add a shim so labels stay hidden on current BS4 CSS.
- Drops the now-unused bootstrap-carousel-swipe dependency.
Full-app build boots clean. Needs a visual staging check of the home page.
react-progress-bar.js (unmaintained wrapper) rendered the progress line
through findDOMNode. Reimplemented LoadingBar with progressbar.js directly
(the wrapper's own underlying dep) via a ref + useEffect — same thin line
(strokeWidth 2, #5A7636), no findDOMNode. Promoted progressbar.js to a
direct dependency and removed react-progress-bar.js. Verified progressbar.js
draws its SVG in-browser; findDOMNode gone from /fires and home; REST smoke
byte-identical.
react-share 2.0 shipped function components with defaultProps (CreatedButton,
Icon) -> React-19-blocking warnings on fire-detail pages. v5 is React-18-safe
and drops them. Removed the GooglePlusShareButton/Icon (Google+ is dead;
removed from react-share in v4+); the other 6 buttons (Facebook, Twitter,
Telegram, WhatsApp, Reddit, Email) are API-compatible. Browser-verified 6
buttons render, no defaultProps warnings. REST smoke byte-identical.
Removes the Router/Switch/Route/Link/LinkContainer legacy-context
warnings. Keeps the shared history singleton (used outside React by
NotificationsObserver + Utils/location) via unstable_HistoryRouter, and
bridges v6 hooks back to v4-shaped history/match/location props with a
new withRouterCompat HOC so the ~20 class pages stay untouched.
- <Switch> -> <Routes>, component= -> element=
- Authenticated/Public -> guard components (children or <Navigate replace>)
- LocationListener -> useLocation + useEffect function
- regex route /fire/:type(active|archive|alert)/:id -> /fire/:type/:id
- history.listen callback is ({ location }) in history v5
Browser-verified: SPA nav, /subscriptions->/login auth redirect,
deep-link /fire/archive/:id (params), browser back/forward. REST smoke
byte-identical.
Removes the largest batch of React-19-blocking warnings: the 0.31
components (Grid, FormGroup, ControlLabel, Navbar.Header/Brand, Checkbox,
SafeAnchor) all leaned on legacy context / defaultProps.
29 files converted: Grid->Container, FormGroup/ControlLabel/FormControl/
HelpBlock -> Form.Group/Label/Control/Text, Checkbox -> Form.Check (label
as prop), bsStyle->variant (default->secondary), bsSize->size,
pull-right->float-end. Custom Col.js now re-exports v2's Col; custom
NavItem.js rewritten self-contained (no SafeAnchor/createChainedFunction);
Navigation.js drops react-bootstrap Navbar (raw markup anyway).
CSS stays on Bootstrap 4 (alexwine:bootstrap-4) for now: the BS4->5 jump
is entangled with the jQuery carousel/swipe + navbar-collapse and is
tracked as separate debt in UPGRADE.md. Only .form-label needed a shim
(forms.scss). Browser-verified home carousel+navbar, signup form + terms
checkbox, login form; REST smoke byte-identical.
react-helmet 5 is unmaintained and breaks under React 18 StrictMode.
Same <Helmet> API in the 15 pages; HelmetProvider wraps <App/> in the
client entry. Browser-verified: per-page titles, meta description and
hreflang alternates all inject. REST smoke byte-identical.
None of them is imported anywhere: reactstrap 5.0.0-alpha.3 was never
adopted (react-bootstrap covers the UI), react-leaflet-sidebarv2 and
react-addons-pure-render-mixin were never used, and react-router-hash-link
only survived as a commented-out import in Index.js.
Drop-in for our usage: email.js only does createTransport(MAIL_URL) and reads
transport.options.auth.user (production-only from() branch) — both verified
identical in v6 (createTransport from a URL still populates options.auth.user).
Actual sending goes through ostrio:mailer (MailTime 2.5), v6-compatible. Mail
server inits clean ('I'm the mail server'); REST smoke byte-identical (12/12).
flowkey:raven (Sentry legacy SDK) is dead on Meteor 3 and, with the old
sentry.comunes.org DSN unreachable, spammed the boot log with 502s on every
exception. Replaced by the modern SDKs (8.x) behind the same ravenLogger.log()
facade so the 6 call sites are unchanged. Empty DSN -> plain console logger
(same behavior as before).
End-to-end verified against a real backend: GlitchTip deployed on aaron
(Sentry-compatible, fits in ~1.5GB vs Sentry's 16GB), fronted at
sentry.comunes.org. A test exception sent from the dev server appeared in
GlitchTip within seconds. REST smoke byte-identical (12/12).
chimp 0.51.1 (Selenium 2 / cucumber e2e runner) was the last dependency
pulling native fibers@1.x, which cannot compile on Node 22 and failed the
clean Docker image build (node-gyp: no prebuilt, no python). Not imported
anywhere. Also add python-is-python3 to the builder stage so node-gyp can
find python for any other native dep. Boot + REST smoke green.
The 1.x native binding was built for another Node ABI and failed to load
(accounts-password silently used the pure-JS fallback) and 1.x does not
compile on Node 22, which would break the Docker image build. 5.1.1 ships
prebuilt Node-22 binaries and loads natively. Boot + REST smoke green.
react/react-dom ^18.3.1 (--legacy-peer-deps for the pinned ancient react-*
libs, which still work on 18 via legacy context but gate React 19). Client
entry uses createRoot. Browser-verified on / and /fires; REST smoke
byte-identical (12/12).
fixtures: drop @cleverbeagle/seeder (sync Mongo, unmaintained) for a small
idempotent async seeder (same dev accounts). sitemaps: drop dead
gadicohen:sitemaps for a WebApp.connectHandlers /sitemap.xml with the same
static page list (the per-fire section was already disabled). Verified on
dev boot: 6 users ensured, sitemap serving; REST smoke byte-identical.
The push/email notification processing now lives in the tcef-notifications
service (fases 1a-1c). Removed from the web:
- imports/startup/server/notificationsObserver.js (observe Notifications -> processNotif)
- imports/modules/server/notificationsProcess.js (node-gcm push + notif emails)
- the 'Process pending notif' SyncedCron job in cron.js
- node-gcm dependency (dead Google API since jun-2024)
subsUnion.js is KEPT: it feeds the subs-public-union SiteSettings that the REST
API (status/subs-public-union) serves to the Flutter app; it is not part of the
notifications pipeline.
DEPLOY ORDERING (see UPGRADE.md): production must not run this build until the
tcef-notifications service is emitting in prod — otherwise notifications stop.
REST smoke test green (byte-identical).