Implementation:Langgenius Dify Web App Context
| Knowledge Sources | |
|---|---|
| Domains | Frontend, Web App, Access Control, Sharing |
| Last Updated | 2026-02-12 07:00 GMT |
Overview
A Zustand store and provider component that manages shared web application state including share codes, app information, access modes, and embedded context for publicly shared Dify applications.
Description
The WebAppStoreProvider and its associated useWebAppStore Zustand store manage all client-side state for Dify's publicly shared web applications (the end-user facing side). The store holds the share code (extracted from the URL), app information (AppData), chat configuration (ChatConfig), access mode (AccessMode), app metadata, a flag for whether the user can access the app, and embedded user/conversation IDs for iframe integration scenarios.
The WebAppStoreProvider component handles initialization logic on mount. It extracts the share code from either a redirect_url query parameter or the current pathname, processes embedded system variables from URL parameters (user ID and conversation ID) asynchronously with cancellation support, and fetches the web app's access mode via useGetWebAppAccessModeByCode. While the global system features or access mode are loading, it displays a loading spinner.
The share code extraction has two strategies: it first checks for a redirect_url query parameter (used after authentication redirects) and falls back to parsing the last segment of the current pathname. The special path segment webapp-signin is excluded from share code detection. The embedded user ID and conversation ID are extracted asynchronously through getProcessedSystemVariablesFromUrlParams, which supports decryption of URL parameters for secure iframe embedding.
Usage
Wrap any shared web app page with WebAppStoreProvider to initialize the share code, access mode, and embedded context. Consume the store in child components via useWebAppStore with a selector function to read or update specific fields. This provider is intended for the public-facing web app routes, not the console application.
Code Reference
Source Location
- Repository: Langgenius_Dify
- File: web/context/web-app-context.tsx
- Lines: 1-127
Signature
type WebAppStore = {
shareCode: string | null
updateShareCode: (shareCode: string | null) => void
appInfo: AppData | null
updateAppInfo: (appInfo: AppData | null) => void
appParams: ChatConfig | null
updateAppParams: (appParams: ChatConfig | null) => void
webAppAccessMode: AccessMode
updateWebAppAccessMode: (accessMode: AccessMode) => void
appMeta: AppMeta | null
updateWebAppMeta: (appMeta: AppMeta | null) => void
userCanAccessApp: boolean
updateUserCanAccessApp: (canAccess: boolean) => void
embeddedUserId: string | null
updateEmbeddedUserId: (userId: string | null) => void
embeddedConversationId: string | null
updateEmbeddedConversationId: (conversationId: string | null) => void
}
export const useWebAppStore: UseBoundStore<StoreApi<WebAppStore>>
const WebAppStoreProvider: FC<PropsWithChildren>
Import
import WebAppStoreProvider, { useWebAppStore } from '@/context/web-app-context'
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| children | PropsWithChildren |
Yes | Child components rendered after share code and access mode are resolved |
Outputs
| Name | Type | Description |
|---|---|---|
| shareCode | null | The share code extracted from the URL, used to identify the shared app |
| updateShareCode | null) => void | Updates the share code in the store |
| appInfo | null | The fetched application data for the shared web app |
| updateAppInfo | null) => void | Sets the app information in the store |
| appParams | null | Chat configuration parameters for the web app |
| updateAppParams | null) => void | Updates the chat configuration |
| webAppAccessMode | AccessMode |
The access control mode for the web app (e.g., SPECIFIC_GROUPS_MEMBERS) |
| updateWebAppAccessMode | (accessMode: AccessMode) => void |
Updates the access mode |
| appMeta | null | Metadata about the shared application |
| updateWebAppMeta | null) => void | Updates the app metadata |
| userCanAccessApp | boolean |
Whether the current user has permission to access the shared app |
| updateUserCanAccessApp | (canAccess: boolean) => void |
Updates the user access flag |
| embeddedUserId | null | User ID extracted from URL params for embedded/iframe scenarios |
| updateEmbeddedUserId | null) => void | Updates the embedded user ID |
| embeddedConversationId | null | Conversation ID extracted from URL params for embedded/iframe scenarios |
| updateEmbeddedConversationId | null) => void | Updates the embedded conversation ID |
Usage Examples
import WebAppStoreProvider from '@/context/web-app-context'
function SharedAppLayout({ children }) {
return (
<WebAppStoreProvider>
{children}
</WebAppStoreProvider>
)
}
Reading App Info in a Component
import { useWebAppStore } from '@/context/web-app-context'
function AppHeader() {
const appInfo = useWebAppStore(state => state.appInfo)
const shareCode = useWebAppStore(state => state.shareCode)
if (!appInfo) return null
return (
<header>
<h1>{appInfo.site.title}</h1>
<p>Share code: {shareCode}</p>
</header>
)
}
Updating Chat Configuration
import { useWebAppStore } from '@/context/web-app-context'
function ChatInitializer({ config }) {
const updateAppParams = useWebAppStore(state => state.updateAppParams)
useEffect(() => {
updateAppParams(config)
}, [config, updateAppParams])
return null
}
Checking Access Control
import { useWebAppStore } from '@/context/web-app-context'
function AccessGate({ children }) {
const userCanAccessApp = useWebAppStore(state => state.userCanAccessApp)
const webAppAccessMode = useWebAppStore(state => state.webAppAccessMode)
if (!userCanAccessApp) {
return <AccessDeniedPage accessMode={webAppAccessMode} />
}
return <>{children}</>
}