20. Architecture Overview & Patterns¶
High-level structure of the SPEX Frontend and the core patterns used across features.
Stack - React 17, React Router v5, Redux with redux-saga, Material‑UI v4, styled-components. - Axios client with auth + cancellation wrappers.
Providers & Store
- App providers and theme: src/components/App/index.jsx:10-36
- Store + saga middleware: src/redux/index.js:1-28
- Root reducers/sagas assembly: src/redux/modules/index.js:1-20,22-35,37-53
Module Pattern (slice + sagas + selectors)
- Each feature exports a slice created via createSlice
with:
- reducers
: synchronous reducers and common helpers startFetching/stopFetching
.
- sagas
: generator map keyed by actions.*
for side effects.
- selectors
: memoized selectors via createSelector
.
- Example (jobs): src/redux/modules/jobs/index.js:1-36,98-136,240-556
- Root assembly collects slice.sagas
and runs them in rootSaga
.
HTTP Client & Auth
- Backend client factory with auth token + response interceptor:
- src/middleware/backendClient.js:1-28,58-120
- Base URL from REACT_APP_BACKEND_URL_ROOT
.
- Unauth handling wired in App: configureBackendClient(() => logout())
- src/components/App/index.jsx:12-20
Routing
- Public /login
; private area wrapped by PrivateRoute
→ PrivateRoutes
under Layout
.
- Definitions: src/routes/index.jsx:1-18
, src/routes/PrivateRoutes.jsx:1-62
- Path constants: src/models/PathNames.js:1-12
Theming & Global Styles
- Theme factory + GlobalStyle: src/themes/index.js:1-60
- Providers order: StylesProvider → MuiThemeProvider → styled ThemeProvider.
- App wiring: src/components/App/index.jsx:18-36
Shared UI & Utilities
- Shared components under src/shared/components/*
(tables, forms, view controls, etc.).
- Utilities: src/shared/utils/*
(storage, formatters, etc.).
Error/Cancel Strategy
- Begin/end of requests via startFetching/stopFetching
to toggle isFetching
.
- Failures normalized by requestFail
reducers across modules.
- Cancellation tokens wrapped around axios calls: wrapHttpWithCancellation
.
Notes - Keep features isolated; export actions/selectors from their slice. - Prefer selectors in components; avoid reaching into state shape directly.