Summary
The frontend carries two HTTP clients. axios is used by exactly one module; the other nine api/ modules use fetch via apiFetch. Consolidating removes a dependency and eliminates a divergent auth request path.
Part of #569.
Relevant code
frontend/src/api/axios.ts — the axios instance (baseURL, withCredentials: true)
frontend/src/api/auth.ts — the only consumer
- All other
api/ modules (activities, announcements, appConfig, categories, player, projects, skills, tasks) use apiFetch
Confirmed by grep: axios appears in those two files only.
Proposed fix
Port api/auth.ts to apiFetch and delete api/axios.ts, then drop axios from package.json.
Two differences need care rather than a blind swap:
withCredentials: true — the axios instance sends cookies; apiFetch does not. Establish whether any auth endpoint actually depends on cookie transport, or whether this is vestigial config alongside the JWT-in-header scheme. If it's genuinely needed, apiFetch will need a credentials: 'include' option.
- Token handling —
apiFetch automatically attaches Authorization and refreshes expiring tokens via getValidAccessToken. Some auth calls (login, register, password reset) are deliberately unauthenticated and must not trigger a refresh attempt. apiFetch already supports passing an explicit token as its third argument, but the genuinely token-free calls need a path that skips getValidAccessToken entirely — otherwise logging in could trip handleUnauthorized and clear storage.
Point 2 is the real substance here; get it wrong and login breaks in a way tests may not catch.
Acceptance criteria
Notes
Not a DOM-coupling issue strictly, but it's in the same layer and halves the surface that needs porting — axios works under React Native, so this is about removing redundancy and a second auth path rather than a hard blocker.
The refresh-on-unauthenticated-call trap is the main risk; worth verifying manually against a real login rather than trusting unit tests alone.
Summary
The frontend carries two HTTP clients.
axiosis used by exactly one module; the other nineapi/modules usefetchviaapiFetch. Consolidating removes a dependency and eliminates a divergent auth request path.Part of #569.
Relevant code
frontend/src/api/axios.ts— the axios instance (baseURL,withCredentials: true)frontend/src/api/auth.ts— the only consumerapi/modules (activities,announcements,appConfig,categories,player,projects,skills,tasks) useapiFetchConfirmed by grep:
axiosappears in those two files only.Proposed fix
Port
api/auth.tstoapiFetchand deleteapi/axios.ts, then dropaxiosfrompackage.json.Two differences need care rather than a blind swap:
withCredentials: true— the axios instance sends cookies;apiFetchdoes not. Establish whether any auth endpoint actually depends on cookie transport, or whether this is vestigial config alongside the JWT-in-header scheme. If it's genuinely needed,apiFetchwill need acredentials: 'include'option.apiFetchautomatically attachesAuthorizationand refreshes expiring tokens viagetValidAccessToken. Some auth calls (login, register, password reset) are deliberately unauthenticated and must not trigger a refresh attempt.apiFetchalready supports passing an explicit token as its third argument, but the genuinely token-free calls need a path that skipsgetValidAccessTokenentirely — otherwise logging in could triphandleUnauthorizedand clear storage.Point 2 is the real substance here; get it wrong and login breaks in a way tests may not catch.
Acceptance criteria
api/auth.tsusesapiFetch;api/axios.tsis deleted;axiosremoved frompackage.jsonhandleUnauthorizedon failurewithCredentialswas load-bearing is explicitly determined and documented in the PRNotes
Not a DOM-coupling issue strictly, but it's in the same layer and halves the surface that needs porting —
axiosworks under React Native, so this is about removing redundancy and a second auth path rather than a hard blocker.The refresh-on-unauthenticated-call trap is the main risk; worth verifying manually against a real login rather than trusting unit tests alone.