diff --git a/docs/en/Community-Articles/2026-06-08-getting-started-with-the-abp-react-template/Post.md b/docs/en/Community-Articles/2026-06-08-getting-started-with-the-abp-react-template/Post.md
index a63ce8c77c..af05fd0c0e 100644
--- a/docs/en/Community-Articles/2026-06-08-getting-started-with-the-abp-react-template/Post.md
+++ b/docs/en/Community-Articles/2026-06-08-getting-started-with-the-abp-react-template/Post.md
@@ -1,6 +1,6 @@
ABP has supported multiple UI approaches for a long time, but many teams building line-of-business apps have been waiting for a first-class React option that feels native to the framework instead of bolted on. That is exactly what the ABP React template brings.
-If you are already using ABP for application services, modules, authentication, multi-tenancy, and code generation, the React template gives you a modern frontend stack without forcing you to hand-wire the same infrastructure in every project. You get React + TypeScript, a sensible project structure, generated API clients, authentication, localization, permission-aware UI, and a prebuilt admin experience that matches how ABP applications are typically built.
+If you are already using ABP for application services, modules, authentication, multi-tenancy, and code generation, the React template gives you a modern frontend stack without forcing you to hand-wire the same infrastructure in every project. You get React + TypeScript, a sensible project structure, typed Axios API modules, authentication, localization, permission-aware UI, and a prebuilt admin experience that matches how ABP applications are typically built.
This article explains what the ABP React template is, how it is structured, what you get out of the box, where it fits well, and what to watch for before adopting it.
@@ -158,33 +158,33 @@ In many projects, teams secure the backend correctly but forget to make the fron
The ABP React template reduces that mismatch.
-## API integration without hand-written client boilerplate
+## API integration with typed Axios modules
-One of the most useful parts of the template is the generated API client approach.
+The main React application organizes its application-specific backend calls in typed modules under `src/lib/api/`. These modules define the DTO interfaces and call the backend through a shared Axios instance that centralizes authentication, tenant and language headers, and common 401/403 handling.
-ABP can generate frontend API clients from OpenAPI definitions, so your React app consumes backend endpoints using generated contracts instead of duplicated DTO definitions or hand-written fetch code.
+The Web React template does not generate these modules from OpenAPI. When a backend contract changes, update the matching DTOs and functions under `src/lib/api/`, update their callers, and run the TypeScript build to catch mismatches.
### Why this is a big deal
-Without generated clients, frontend/backend integration often drifts over time:
+Keeping the API calls in typed modules gives the application one place to maintain each backend integration:
-- DTOs change but frontend types do not
-- query strings are built inconsistently
-- error handling varies by developer
-- service layers become repetitive
+- components do not build request URLs themselves
+- DTOs and request functions stay together
+- authentication and tenant headers use the shared Axios client
+- TanStack Query remains focused on fetching, caching, and invalidation
-With the ABP React template, Axios is already set up and typically used together with TanStack Query. That gives you a cleaner pattern for data fetching, caching, invalidation, and loading states.
+With the ABP React template, Axios is already set up and typically used together with TanStack Query. That gives you a clean pattern for data fetching, caching, invalidation, and loading states.
A simplified example looks like this:
```tsx
import { useQuery } from '@tanstack/react-query';
-import { identityUserControllerGetList } from '@/client';
+import { getUsers } from '@/lib/api/identity';
export function UsersPage() {
const query = useQuery({
queryKey: ['users'],
- queryFn: () => identityUserControllerGetList({ maxResultCount: 10, skipCount: 0 }),
+ queryFn: () => getUsers({ maxResultCount: 10, skipCount: 0 }),
});
if (query.isLoading) return
Loading...
;
@@ -192,7 +192,7 @@ export function UsersPage() {
return (
- {query.data.items.map((user) => (
+ {query.data?.items.map((user) => (
- {user.userName}
))}
@@ -200,7 +200,7 @@ export function UsersPage() {
}
```
-The exact generated function names may vary based on your solution, but the pattern is the point: use generated contracts, wrap them with TanStack Query, and keep components focused on UI.
+The available modules vary based on the features selected for the solution. Keep application-specific backend calls in `src/lib/api/`, wrap them with TanStack Query, and keep components focused on UI.
## UI system and customization model
@@ -406,7 +406,7 @@ Use it when:
- you are starting a new ABP project with a modern template
- you want React + TypeScript with ABP conventions already wired in
- you need authentication, permissions, localization, and multi-tenancy from day one
-- you want generated API clients instead of duplicated DTOs
+- you want typed API modules with a shared Axios client
- you prefer source-owned UI components
- your app is admin-heavy, form-heavy, or module-heavy
@@ -470,7 +470,7 @@ A plain React starter gives you flexibility, but also leaves many critical conce
Compared to a generic starter, ABP gives you tighter integration for:
- auth and authorization
-- generated API clients
+- typed API modules
- localization
- tenant-aware applications
- modular backend alignment
@@ -483,7 +483,7 @@ That makes it less minimal than a blank React scaffold, but much more useful for
The ABP React template is not interesting because it says React on the label. It is interesting because it brings React into ABP's application model in a way that feels intentional.
-You get a modern frontend stack, source-owned customization, generated client integration, and the ABP features many teams actually need in production: permissions, localization, multi-tenancy, and admin tooling.
+You get a modern frontend stack, source-owned customization, typed API integration, and the ABP features many teams actually need in production: permissions, localization, multi-tenancy, and admin tooling.
If your team already values ABP on the backend and wants React on the frontend, this template is one of the fastest ways to get to a serious foundation without spending the first sprint rebuilding plumbing.
@@ -491,6 +491,6 @@ If your team already values ABP on the backend and wants React on the frontend,
- The ABP React template is available in ABP's modern template system, not classic templates.
- It uses a practical stack: React, TypeScript, Vite, TanStack Router/Query, shadcn/ui, Tailwind, Zod, and Axios.
-- Key strengths are generated API clients, OIDC auth, permission-aware UI, localization, and multi-tenancy.
+- Key strengths are typed API modules, OIDC auth, permission-aware UI, localization, and multi-tenancy.
- The frontend is source-owned, which gives you flexibility but also requires discipline.
-- It is a strong choice for ABP-based business apps, especially admin-heavy and SaaS-style applications.
\ No newline at end of file
+- It is a strong choice for ABP-based business apps, especially admin-heavy and SaaS-style applications.
diff --git a/docs/en/framework/ui/react/environment-variables.md b/docs/en/framework/ui/react/environment-variables.md
index 2b84b0c4d0..21a4a451bf 100644
--- a/docs/en/framework/ui/react/environment-variables.md
+++ b/docs/en/framework/ui/react/environment-variables.md
@@ -62,7 +62,7 @@ The template loads `/dynamic-env.json` first and then tries `/getEnvConfig` for
| `oAuthConfig.clientId` | OpenIddict client ID. The main React app uses `_App`. |
| `oAuthConfig.scope` | OAuth scopes requested by the SPA. |
| `apis.default.url` | Backend API base URL. In microservice solutions, this normally points to the Web Gateway. |
-| `apis.default.rootNamespace` | Root namespace used by generated API code and module-specific clients. |
+| `apis.default.rootNamespace` | Root namespace populated by the solution template. The current React applications do not read this value. |
| `adminConsoleUrl` | Origin of the Admin Console app. The React template uses it to open `/admin-console`. |
The `DynamicEnv` type also includes fields such as `production`, `oAuthConfig.requireHttps`, `oAuthConfig.responseType`, `oAuthConfig.strictDiscoveryDocumentValidation`, and `oAuthConfig.skipIssuerCheck`. The template's OIDC setup always uses the Authorization Code flow by setting `responseType` to `code`.
diff --git a/docs/en/framework/ui/react/http-requests.md b/docs/en/framework/ui/react/http-requests.md
index ceacd6d328..70bbdd4c25 100644
--- a/docs/en/framework/ui/react/http-requests.md
+++ b/docs/en/framework/ui/react/http-requests.md
@@ -57,7 +57,7 @@ Use this instance for application API modules instead of creating new Axios clie
Before each request, the template:
- Sets `baseURL` from runtime configuration.
-- Adds `Authorization: Bearer ` from the OIDC user.
+- Gets the OIDC access token through `ensureAccessToken`, silently renewing a missing or expired token when a refresh token is available, and adds any returned token as `Authorization: Bearer `.
- Adds `__tenant` when the user has selected a tenant.
- Adds `Accept-Language` from i18next.
- Keeps default AJAX headers such as `X-Requested-With`.
@@ -66,9 +66,9 @@ Before each request, the template:
api.interceptors.request.use(async (config) => {
config.baseURL = getApiBaseUrl()
- const user = await userManager.getUser()
- if (user?.access_token) {
- config.headers.Authorization = `Bearer ${user.access_token}`
+ const accessToken = await ensureAccessToken()
+ if (accessToken) {
+ config.headers.Authorization = `Bearer ${accessToken}`
}
const tenantId = sessionStorage.getItem('abp_tenant_id')
@@ -89,8 +89,8 @@ api.interceptors.request.use(async (config) => {
The response interceptor handles common authorization failures:
-- `401 Unauthorized`: redirects to login unless `skipAuthRedirect` is set.
-- `403 Forbidden`: redirects to `/403` unless `skip403Redirect` is set.
+- `401 Unauthorized`: unless `skipAuthRedirect` is set, tries to refresh the access token and retries the request once. If the token cannot be refreshed, it redirects to login. With `skipAuthRedirect`, the original error is rejected to the caller.
+- `403 Forbidden`: redirects non-mutating requests to `/403` unless `skip403Redirect` is set. Mutation errors are rejected so TanStack Query or the caller can handle them.
- Other errors are rejected so the caller can handle them.
```ts
@@ -99,12 +99,17 @@ api.interceptors.response.use(
async (error) => {
const status = error.response?.status
- if (status === 401 && !error.config?.skipAuthRedirect) {
- await userManager.signinRedirect()
- return Promise.reject(new Error('Unauthorized - redirecting to login'))
+ const config = error.config
+
+ if (status === 401 && !config?.skipAuthRedirect) {
+ return handleUnauthorizedResponse(error)
}
- if (status === 403 && !error.config?.skip403Redirect) {
+ if (
+ status === 403 &&
+ !config?.skip403Redirect &&
+ !isMutatingRequest(config?.method)
+ ) {
window.location.href = '/403'
return Promise.reject(new Error('Forbidden'))
}
@@ -134,11 +139,20 @@ export interface BookDto {
price: number
}
-export async function getBooks(): Promise> {
+export interface PagedAndSortedResultRequestDto {
+ maxResultCount?: number
+ skipCount?: number
+ sorting?: string
+}
+
+export async function getBooks(
+ params: PagedAndSortedResultRequestDto = {}
+): Promise> {
const { data } = await api.get>('/app/book', {
params: {
- maxResultCount: 10,
- skipCount: 0,
+ maxResultCount: params.maxResultCount ?? 10,
+ skipCount: params.skipCount ?? 0,
+ sorting: params.sorting,
},
})
return data
@@ -202,11 +216,17 @@ const productsQuery = useQuery({
})
```
-## Keeping API Modules in Sync
+## Keeping the Main React SPA's API Modules in Sync
+
+The main developer-owned React SPA lives under `react/` in layered and single-layer solutions, and under `apps/react/` in microservice solutions. Its application-specific typed API modules are maintained under `src/lib/api/`.
+
+These instructions apply to the main developer-owned React SPA. They do not describe the React Public Web app, the Admin Console, React Native clients, or API calls implemented inside Low-Code packages.
+
+`abp generate-proxy` has no React target. Its `-t js` generator produces jQuery proxy scripts for MVC / Razor Pages applications, must be run from a directory containing a top-level `.csproj` file, and writes scripts that use `abp.ajax` and `$` to `wwwroot/client-proxies/-proxy.js` by default. It does not generate the TypeScript / Axios modules used by the React application.
-`abp generate-proxy` has no React target. Its `-t js` generator produces jQuery proxy scripts for MVC / Razor Pages applications, and it must run in a folder that contains a Web project file, so it does not apply to the React application. Update the modules under `src/lib/api/` yourself when a backend contract changes:
+Update the modules under `src/lib/api/` yourself when a backend contract changes:
-1. Start the backend and check the new contract on its Swagger UI or `/api/abp/api-definition?includeTypes=true`.
+1. Start the backend that owns the application service and check the new contract on its Swagger UI or `/api/abp/api-definition?includeTypes=true`. In a microservice solution, use the owning service's entry in the Web Gateway Swagger UI, or call that service's `/api/abp/api-definition?includeTypes=true` endpoint directly. By default, the generated Web Gateway routes `/api/abp/*` to the Administration service, so its gateway URL does not expose the API-definition models of the other services.
2. Update the DTO interfaces and function signatures in the matching module.
3. Update the callers and run `npm run build` so TypeScript reports the mismatches.
diff --git a/docs/en/solution-templates/microservice/mobile-applications.md b/docs/en/solution-templates/microservice/mobile-applications.md
index 153b883c1c..175fd165cb 100644
--- a/docs/en/solution-templates/microservice/mobile-applications.md
+++ b/docs/en/solution-templates/microservice/mobile-applications.md
@@ -37,7 +37,7 @@ The generated React Native app is configured in `Environment.ts` with:
* the `MobileGateway` base URL
* the `ReactNative` client id and scopes
-At runtime, the mobile client uses the password grant to exchange credentials for access and refresh tokens at the `AuthServer` `/connect/token` endpoint, then sends bearer tokens to backend APIs through the `MobileGateway`. Account-related operations such as registration, password reset, profile picture management, and logout use the generated API client under `src/api`.
+At runtime, the mobile client uses the password grant to exchange credentials for access and refresh tokens at the `AuthServer` `/connect/token` endpoint, then sends bearer tokens to backend APIs through the `MobileGateway`. Account-related operations such as registration, password reset, and profile picture management use the template-provided API client under `src/api`.
## Built-in Capabilities