Extend App UI SDK API Reference
Overview
If you scaffolded your project using the official Extend App UI templates, this package is already included. You don't need to install it manually.
The @accelbyte/sdk-extend-app-ui package is the official Extend App UI SDK for building Extend App UIs, which are micro-frontends embedded inside the AccelByte Gaming Services (AGS) Admin Portal. It provides:
- A React context that handles authentication and permission checking.
- A Vite dev plugin that proxies requests to the AGS backend.
- TypeScript types for the module contract between the host (Admin Portal) and your app.
For the full TypeScript source and type definitions beyond what is documented here, see the @accelbyte/sdk-extend-app-ui package on npm.
Key terms
For shared terms (Namespace, IAM permissions, AGS Shared Cloud, AGS Private Cloud, App UI name), see Extend App UI key terms.
-
Micro-frontends: small, self-contained web applications embedded inside a larger portal. Extend App UIs are micro-frontends that run inside the AGS Admin Portal as native-feeling pages.
-
CORS: a browser security policy that blocks web pages from making direct API requests to a different domain than the one serving them. The
devProxyPluginworks around this during local development by routing requests through the local dev server.
AppUIModule
AppUIModule is the entry point contract your app must export. The Admin Portal calls mount(container, context) when the user opens your App UI, and calls the cleanup function it returns when the user navigates away.
Minimal example:
// module.tsx
import { type AppUIModule } from '@accelbyte/sdk-extend-app-ui'
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
export const module: AppUIModule = {
mount(container) {
const root = createRoot(container)
root.render(
<StrictMode>
<div>Hello world!</div>
</StrictMode>
)
return () => root.unmount()
}
}
Full example (with AGS SDK and permission checking):
To make AGS API calls or check permissions, wrap your app with AppUIContextProvider and QueryClientProvider. The SDK uses React Query internally, so a QueryClient is required.
// module.tsx
import { AppUIContextProvider, CrudType, useAppUIContext, type AppUIModule } from '@accelbyte/sdk-extend-app-ui'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
const client = new QueryClient({ defaultOptions: { queries: { retry: false, refetchOnWindowFocus: false } } })
export const module: AppUIModule = {
mount(container, hostContext) {
const root = createRoot(container)
root.render(
<StrictMode>
<QueryClientProvider client={client}>
<AppUIContextProvider sdkConfig={hostContext.sdkConfig} isCurrentUserHasPermission={hostContext.isCurrentUserHasPermission}>
<Component />
</AppUIContextProvider>
</QueryClientProvider>
</StrictMode>
)
return () => root.unmount()
}
}
// eslint-disable-next-line react-refresh/only-export-components
const Component = () => {
const { isCurrentUserHasPermission } = useAppUIContext()
return (
<div>
<div>Hello world!</div>
<div hidden={!isCurrentUserHasPermission({ action: CrudType.READ, resource: 'ADMIN:NONEXISTENTRESOURCE' })}>Hello world!</div>
</div>
)
}
HostContext
HostContext is the object the Admin Portal passes as the second argument to your mount() function. It gives your App UI everything it needs to make authenticated AGS API calls and check the current user's permissions.
interface HostContext {
/** Core SDK configuration passed from the Admin Portal. Pass this to AppUIContextProvider. */
sdkConfig: SdkConfigOptions
/** The base path the Admin Portal uses to route requests for this App UI. */
basePath: string
/** Returns true if the current portal user has the given permission. */
isCurrentUserHasPermission: (permission: CrudRolePermission) => boolean
}
Pass hostContext.sdkConfig and hostContext.isCurrentUserHasPermission directly to AppUIContextProvider — the full example in AppUIModule shows this pattern.
AppUIContextProvider
AppUIContextProvider is a React context provider that initializes the AccelByte SDK and manages authentication and permission state for your App UI. Wrap your application root with this component.
interface AppUIContextProviderProps {
sdkConfig: SdkConfigOptions
/**
* Provided by the host in production. Omit in development —
* the provider will fall back to its own PermissionGuard.
*/
isCurrentUserHasPermission?: (permission: CrudRolePermission) => boolean
children: ReactNode
}
The provider detects the environment via NODE_ENV and switches behavior accordingly.
| Aspect | Development | Production |
|---|---|---|
| Auth | Exchanges OAuth2 authorization code, refreshes tokens automatically | Skipped. Admin Portal manages auth. |
| Permissions | Fetches current user and all roles from IAM, sets a permission checker | Uses isCurrentUserHasPermission passed by the Admin Portal |
Usage example:
import { AppUIContextProvider } from '@accelbyte/sdk-extend-app-ui'
function App() {
return (
<AppUIContextProvider sdkConfig={sdkConfig}>
<YourAppContent />
</AppUIContextProvider>
)
}
useAppUIContext
useAppUIContext is a React hook that gives child components access to the initialized SDK instance and permission utilities provided by AppUIContextProvider.
interface AppUIContextValue {
/** Initialized AccelByteSDK instance. Use this to call AGS APIs. */
sdk: AccelByteSDK
/** True while user data or roles are loading. */
isLoading: boolean
/** Returns true if the current user has the given permission. */
isCurrentUserHasPermission: (permission: CrudRolePermission) => boolean
}
Usage example:
Use isCurrentUserHasPermission to conditionally show UI elements based on the current user's access level. Pass a CrudRolePermission object with an action from CrudType and the permission resource string your Extend service requires.
import { useAppUIContext, CrudType } from '@accelbyte/sdk-extend-app-ui'
function TournamentListHeader() {
const { isCurrentUserHasPermission } = useAppUIContext()
return (
<p hidden={!isCurrentUserHasPermission({ action: CrudType.READ, resource: 'ADMIN:RANDOMRESOURCE' })}>
This header is only visible to users with READ access on ADMIN:RANDOMRESOURCE
</p>
)
}
CrudType is an enum with these values: CREATE, READ, UPDATE, DELETE. Replace ADMIN:RANDOMRESOURCE with the permission resource string for your service. See Permission Fundamentals for how resource strings are structured.
devProxyPlugin
devProxyPlugin is a Vite plugin that proxies API requests to the AGS backend during local development, avoiding CORS errors. Add it to your vite.config.ts.
function devProxyPlugin(options: {
/** AGS backend base URL. Must match the baseURL registered in your IAM OAuth client. */
baseUrl: string
/** OAuth2 redirect URI. Must match the redirect URI registered in your IAM OAuth client. */
redirectURI: string
}): Plugin
Both baseUrl and redirectURI must match the values registered in your IAM OAuth client. This is already taken care of by Extend Helper CLI with the setup-env command.
All requests to /proxy/* are forwarded to the AGS backend. Point your SDK's baseURL to /proxy in development:
const sdkConfig = {
baseURL: import.meta.env.DEV ? '/proxy' : 'https://your-ags-instance.accelbyte.io'
// ...
}
The plugin also handles Shared Cloud subdomain routing. In Shared Cloud, each namespace is served from its own subdomain (for example, spaceshooter-game.prod.gamingservices.accelbyte.io). AGS validates the Referer header of incoming requests to confirm they originate from the correct subdomain — a check that fails during local development because your requests come from localhost. To work around this, the plugin reads the access_token cookie, extracts the current namespace from it, and sets the Referer header on each proxied request to match the expected subdomain URL.
Types
For the complete TypeScript interface definitions of all exported types, see the @accelbyte/sdk-extend-app-ui package on npm.
| Type | Description |
|---|---|
SdkConfigOptions | Core config passed to AccelByte.SDK() |
HostContext | Object passed from the host to mount(): sdkConfig, basePath, isCurrentUserHasPermission |
AppUIModule | Contract your app module must implement: mount(container, context): () => void |
CrudRolePermission | Permission descriptor used with isCurrentUserHasPermission |
CrudType | Enum for CRUD actions with string values: CREATE, READ, UPDATE, DELETE |
Next steps
- Troubleshoot Extend App UI to diagnose and fix common App UI issues.