Frontend Codebase Review
1. Structure
The Good:
- Domain-Driven Directory Structure: The
app/ folder logically separates concerns (api, components, navigation, screens, stores, etc.).
- Screen Segregation: Dividing
screens/ into researcher, user, and shared successfully implements modular access control patterns matching your backend roles.
Bad Smells & Areas for Improvement:
- Duplicate Components Folders: There is both
frontend/components/ and frontend/app/components/. This creates ambiguity about where new components belong. They should be merged into a single source of truth.
- Unused Expo Router: The
package.json contains "expo-router": "^6.0.21", but the application clearly uses @react-navigation/native (in RootNavigator.tsx). According to your strict rules ("No Expo Router"), this dependency is dead weight and should be uninstalled to reduce bundle size and confusion.
- Missing Path Aliases (
@/): The swipelab.md rule strictly mandates using the @/ alias, yet imports rely on relative paths (e.g., ../../api/apiEndpoints in LoginScreen.tsx). The tsconfig.json should be updated to enforce this, and all relative imports should be refactored.
- Circular Dependency Workarounds: In
apiFetch.ts and authStore.ts, there are dynamic inline imports like const { useAuthStore } = require("../stores/authStore");. This is a classic symptom of circular dependencies and should be refactored into a dependency-injection pattern or by extracting shared logic into a neutral utility file.
2. Design
The Good:
- Responsive Awareness: The
LoginScreen.tsx incorporates useResponsive() to conditionally apply web-specific layouts (webCard, webScreenContainer), which is a good practice for cross-platform React Native apps.
Bad Smells & Areas for Improvement:
- Hardcoded Styling (Magic Colors): Colors are hardcoded across components (e.g.,
#4B7BE5, #2E8B57, #fff in LoginScreen.tsx). There is no apparent usage of a centralized design system or theme provider. This makes implementing dark mode or rebranding very difficult.
- Inline Styles: In
App.tsx and other root files, inline styles (e.g., style={{ flex: 1, justifyContent: "center", alignItems: "center" }}) are being used instead of StyleSheet.create. This impacts readability and React Native rendering performance.
- Missing Global Error Boundaries: The root
App.tsx lacks an <ErrorBoundary /> wrapper. This violates the project rule: "Handle API failures gracefully with appropriate UI feedback (e.g., toasts, error boundaries). Avoid silent failures..."
3. Security Threats & Bad Practices
- Web Token Storage (XSS Vulnerability): In
authStore.ts and apiFetch.ts, JWT tokens (including refresh tokens) are stored in localStorage when Platform.OS === 'web'. localStorage is highly vulnerable to Cross-Site Scripting (XSS) attacks. For production web environments, refresh tokens should ideally be handled via HttpOnly cookies.
- Missing Global Toast/Error UI for API Failures: While
apiFetch.ts gracefully intercepts 401s and handles token refreshes, other API failures (like 500s or network drops) are not funneled into a centralized UI feedback system (like a Toast notification). This leads to silent failures or requires every single component to reinvent error handling.
- Logout Race Conditions: The
logout function in authStore.ts checks !state.token && !state.role but relies on require("../api/apiFetch") to make the invalidation call, which might fail or be slow. The cleanup process is generally fine but mixing SecureStore async actions with synchronous React state updates can sometimes cause brief UI tearing.
Recommendations for Next Steps:
- Consolidate
frontend/components/ and frontend/app/components/.
- Remove
expo-router from package.json.
- Configure
tsconfig.json and refactor imports to use the @/ alias.
- Implement a centralized Theme/Design token system to eliminate hardcoded hex colors.
- Resolve circular dependencies to remove inline
require() calls.
- Add a global Error Boundary and a Toast notification provider at the
App.tsx level.
Frontend Codebase Review
1. Structure
The Good:
app/folder logically separates concerns (api,components,navigation,screens,stores, etc.).screens/intoresearcher,user, andsharedsuccessfully implements modular access control patterns matching your backend roles.Bad Smells & Areas for Improvement:
frontend/components/andfrontend/app/components/. This creates ambiguity about where new components belong. They should be merged into a single source of truth.package.jsoncontains"expo-router": "^6.0.21", but the application clearly uses@react-navigation/native(inRootNavigator.tsx). According to your strict rules ("No Expo Router"), this dependency is dead weight and should be uninstalled to reduce bundle size and confusion.@/): Theswipelab.mdrule strictly mandates using the@/alias, yet imports rely on relative paths (e.g.,../../api/apiEndpointsinLoginScreen.tsx). Thetsconfig.jsonshould be updated to enforce this, and all relative imports should be refactored.apiFetch.tsandauthStore.ts, there are dynamic inline imports likeconst { useAuthStore } = require("../stores/authStore");. This is a classic symptom of circular dependencies and should be refactored into a dependency-injection pattern or by extracting shared logic into a neutral utility file.2. Design
The Good:
LoginScreen.tsxincorporatesuseResponsive()to conditionally apply web-specific layouts (webCard,webScreenContainer), which is a good practice for cross-platform React Native apps.Bad Smells & Areas for Improvement:
#4B7BE5,#2E8B57,#fffinLoginScreen.tsx). There is no apparent usage of a centralized design system or theme provider. This makes implementing dark mode or rebranding very difficult.App.tsxand other root files, inline styles (e.g.,style={{ flex: 1, justifyContent: "center", alignItems: "center" }}) are being used instead ofStyleSheet.create. This impacts readability and React Native rendering performance.App.tsxlacks an<ErrorBoundary />wrapper. This violates the project rule: "Handle API failures gracefully with appropriate UI feedback (e.g., toasts, error boundaries). Avoid silent failures..."3. Security Threats & Bad Practices
authStore.tsandapiFetch.ts, JWT tokens (including refresh tokens) are stored inlocalStoragewhenPlatform.OS === 'web'.localStorageis highly vulnerable to Cross-Site Scripting (XSS) attacks. For production web environments, refresh tokens should ideally be handled viaHttpOnlycookies.apiFetch.tsgracefully intercepts 401s and handles token refreshes, other API failures (like 500s or network drops) are not funneled into a centralized UI feedback system (like a Toast notification). This leads to silent failures or requires every single component to reinvent error handling.logoutfunction inauthStore.tschecks!state.token && !state.rolebut relies onrequire("../api/apiFetch")to make the invalidation call, which might fail or be slow. The cleanup process is generally fine but mixingSecureStoreasync actions with synchronous React state updates can sometimes cause brief UI tearing.Recommendations for Next Steps:
frontend/components/andfrontend/app/components/.expo-routerfrompackage.json.tsconfig.jsonand refactor imports to use the@/alias.require()calls.App.tsxlevel.