Owner: Engineering Team | Last Updated: 2026-01-30 | Status: Current
The WWAI web app uses Redux Toolkit 2.5.0 for state management. The store is configured in lib/store.ts using combineSlices and configureStore. There are 5 slices managing different domains of application state. For the full web app overview, see Web App Overview.
From lib/store.ts:
import type { Action, ThunkAction } from '@reduxjs/toolkit'
import { combineSlices, configureStore } from '@reduxjs/toolkit'
import commonSlice from './store/commonSlice'
import documentsSlice from './store/documentsSlice'
import humanizerSelectionSlice from './store/humanizerSelectionSlice'
import pauseSlice from './store/pauseSlice'
import userReducer from './store/userSlice'
const rootReducer = combineSlices({
user: userReducer,
humanizerSelection: humanizerSelectionSlice,
documents: documentsSlice,
common: commonSlice,
pause: pauseSlice,
})
export type RootState = ReturnType<typeof rootReducer>
export const makeStore = () => {
return configureStore({
reducer: rootReducer,
})
}
export type AppStore = ReturnType<typeof makeStore>
export type AppDispatch = AppStore['dispatch']
export type AppThunk<ThunkReturnType = void> = ThunkAction<
ThunkReturnType,
RootState,
unknown,
Action
>
Important: The store uses makeStore() factory function (not a singleton) for SSR compatibility — each request gets its own store instance to prevent cross-request state pollution.
| Type | Purpose |
|---|---|
RootState |
Full state tree type (inferred from rootReducer) |
AppStore |
Store instance type |
AppDispatch |
Dispatch type (includes thunk dispatch) |
AppThunk |
Thunk action type |
Manages humanizer preference settings (readability, purpose, anti-detection strength). Synced with backend.
From lib/store/humanizerSelectionSlice.ts:
interface HumanizerSelectionState {
readability: HumanizerSelectOptions | null
purpose: HumanizerSelectOptions | null
anti_detection: number // 0, 1, or 2
}
const initialState: HumanizerSelectionState = {
readability: null,
purpose: null,
anti_detection: 2, // Default: Enhanced
}
Async Thunks:
fetchHumanizerSelectionData(token) — GET /api/feature/remember-humanizer-selection/postHumanizerSelectionData({ newData, token }) — POST /api/feature/remember-humanizer-selection/Sync Action:
setHumanizerSelectionData(payload) — Set all three fields at onceManages user profile and session data.
Manages document list, search state, pagination for the documents panel.
Manages shared UI state (modals, alerts, global flags).
Manages subscription pause state and related UI.
The codebase uses direct react-redux hooks (NOT custom typed wrappers):
import { useDispatch } from 'react-redux'
import { useSelector } from 'react-redux'
import { AppDispatch, RootState } from '@/lib/store'
// Dispatch with type
const dispatch = useDispatch<AppDispatch>()
// Select state with type
const selection = useSelector((state: RootState) => state.humanizerSelection)
Note: There are no useAppDispatch or useAppSelector typed hook wrappers. Components import AppDispatch and RootState directly and use the generic react-redux hooks with type parameters.
From Humanizer.tsx:
import { AppDispatch } from '@/lib/store'
import { postHumanizerSelectionData } from '@/lib/store/humanizerSelectionSlice'
const dispatch = useDispatch<AppDispatch>()
const handleSaveMyPreferences = (value: boolean) => {
if (value) {
dispatch(
postHumanizerSelectionData({
newData: {
readability: readabilitySelected,
purpose: purposeSelected,
anti_detection: strength,
},
token: session?.access_token ?? '',
})
).unwrap().then(() => {
toast.success(t('preferencesSaved'))
})
}
}
lib/
├── store.ts # Store config, type exports
├── store/
│ ├── humanizerSelectionSlice.ts # Humanizer preferences
│ ├── userSlice.ts # User profile data
│ ├── documentsSlice.ts # Document management
│ ├── commonSlice.ts # Shared UI state
│ └── pauseSlice.ts # Subscription pause state
└── utils.ts # Shared utilities
| Date | Author | Change |
|---|---|---|
| 2026-01-30 | Admin | Initial creation |
| 2026-01-30 | Docs team | Rewritten with real code: store.ts config, combineSlices setup, type exports, humanizerSelectionSlice with thunks, usage pattern with direct react-redux hooks |
Prev: Web App - Routing | Next: Web App - Component Library | Up: WalterWrites