Configuring a Portal App
Learn how to set up a standalone chat portal that can be embedded in websites or used as a standalone application.
Overview
A portal app is a lightweight chat interface that connects to your AgentPress API. The portal app serves as the recommended template for creating embedded chat widgets or standalone chat applications.
Basic Setup
1. Routes Configuration
Configure your app in src/routes.tsx with the AgentPressProvider:
import { EAppType } from "@agentpress/lib/types";
import { AgentPressProvider, Chat } from "@agentpress/ui/core";
import { toolsUI } from "@repo/custom/ui";
import { Toaster } from "@agentpress/ui/ui";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { createRootRoute, createRoute, Outlet } from "@tanstack/react-router";
const config = {
apiHost: import.meta.env.VITE_API_HOST || "http://localhost:3001",
toolsUI,
isGuest: true,
voiceTranscription: true,
appType: EAppType.PORTAL,
};
const rootRoute = createRootRoute({
component: () => (
<AgentPressProvider config={config}>
<Outlet />
<ReactQueryDevtools />
<Toaster />
</AgentPressProvider>
),
});
// Add your chat and login routes
const indexRoute = createRoute({
getParentRoute: () => rootRoute,
path: "/",
component: ChatPage,
});
const loginRoute = createRoute({
getParentRoute: () => rootRoute,
path: "/login",
component: LoginPage,
});
export const routeTree = rootRoute.addChildren([indexRoute, loginRoute]);Note: Unlike console apps, portal apps typically don’t use beforeLoad auth guards, so you don’t need to call setAgentPressConfig() separately. The AgentPressProvider handles the configuration internally.
The AgentPressProvider handles all necessary setup including:
- React Query client for data fetching
- Theme provider for light/dark mode
- Task WebSocket management via Zustand
- Tooltip provider
- Error boundary for graceful error handling
2. Main Application
In your main.tsx, set up routing:
import { StrictMode } from "react";
import ReactDOM from "react-dom/client";
import { RouterProvider, createRouter } from "@tanstack/react-router";
import { routeTree } from "./routes";
const router = createRouter({ routeTree });
const rootElement = document.getElementById("root")!;
const root = ReactDOM.createRoot(rootElement);
root.render(
<StrictMode>
<RouterProvider router={router} />
</StrictMode>
);Configuration Options
Core Configuration
The config prop passed to AgentPressProvider accepts these options:
apiHost(required) - URL of your AgentPress API servertoolsUI(required) - Custom tool UI components from your custom packageappType(required) -EAppType.PORTALorEAppType.CONSOLEisGuest(optional) - Allow guest access without authenticationvoiceTranscription(optional) - Enable voice-to-text functionality (default: true)
Environment Variables
Set up your environment variables:
# .env
VITE_API_HOST=https://your-api-domain.comChat Component Configuration
URL Parameters
The chat component supports various URL parameters for customization:
const chatSearchSchema = z.object({
agentId: z.string().optional().default(""),
disableThreadList: z.boolean().optional().default(false),
hideUsername: z.boolean().optional().default(false),
hideAgents: z.boolean().optional().default(false),
disableUpload: z.boolean().optional().default(false),
sidebarOpen: z.boolean().optional().default(true),
hideNewThread: z.boolean().optional().default(false),
disableFeedback: z.boolean().optional().default(false),
initialUserMessage: z.string().optional().default(""),
authToken: z.string().optional().default(""),
threadId: z.string().optional().default(""),
});Chat Component Usage
<Chat
defaultAgentId={agentId}
disableThreadList={disableThreadList}
hideUsername={hideUsername}
hideAgents={hideAgents}
disableUpload={disableUpload}
hideNewThread={hideNewThread}
sidebarOpen={sidebarOpen}
disableFeedback={disableFeedback}
initialUserMessage={initialUserMessage}
initialThreadId={threadId}
/>Embedding Options
URL Parameters for Embedding
Customize the chat interface using URL parameters:
https://your-portal.com/?agentId=agent-123&disableThreadList=true&hideUsername=trueCommon parameters:
agentId- Specific agent to usedisableThreadList- Hide the conversation history sidebarhideUsername- Don’t display usernameshideAgents- Hide agent selection dropdowndisableUpload- Disable file upload functionalityhideNewThread- Hide new conversation buttoninitialUserMessage- Pre-populate the input fieldauthToken- Authenticate with a specific token
iFrame Embedding
Embed the portal in any website:
<iframe
src="https://your-portal.com/?disableThreadList=true&hideUsername=true&hideSettings=true"
className="w-[700px] max-w-full max-h-[900px] h-full overflow-hidden m-4 border-2 border-secondary rounded-2xl"
allow="microphone; clipboard-read; clipboard-write; camera; geolocation; fullscreen;"
sandbox="allow-same-origin allow-scripts allow-popups allow-forms allow-downloads allow-modals allow-presentation allow-storage-access-by-user-activation"
frameborder="0">
</iframe>iFrame Security and Permissions
Allow Attributes:
microphone- Enable voice input functionalityclipboard-read; clipboard-write- Allow copy/paste operationscamera- Enable camera access for file uploadsgeolocation- Allow location-based featuresfullscreen- Enable fullscreen mode
Sandbox Attributes:
allow-same-origin- Allow access to same-origin resourcesallow-scripts- Enable JavaScript executionallow-popups- Allow popup windows (for file downloads)allow-forms- Enable form submissionsallow-downloads- Allow file downloadsallow-modals- Enable modal dialogsallow-presentation- Allow presentation APIallow-storage-access-by-user-activation- Enable storage access
Authentication
Guest Mode
Enable guest access without login in your config:
<AgentPressProvider
config={{
isGuest: true,
// ... other options
}}
>
{/* ... */}
</AgentPressProvider>Token-Based Authentication
Pass authentication tokens via URL:
https://your-portal.com/?authToken=your-jwt-tokenThe portal will automatically attempt login with the provided token.
Deployment
Build for Production
# From portal app directory
bun run buildEnvironment Configuration
Set production environment variables:
# Production .env
VITE_API_HOST=https://api.yourcompany.comStatic Hosting
The built portal is officially supported on AWS:
- AWS S3 + CloudFront (officially supported via Terraform)
Customization
Custom Tool UIs
Import and configure your custom tool UIs in the provider config:
import { toolsUI } from "@repo/custom/ui";
<AgentPressProvider
config={{
toolsUI,
// ... other options
}}
>
{/* ... */}
</AgentPressProvider>Header Customization
Customize or hide the header:
{!disableThreadList && (
<header className="h-16 w-full flex items-center justify-center border-b">
<AgentPressLogo />
<AgentPressLogoLabel />
</header>
)}Best Practices
Security
- Validate auth tokens on the server side
- Set CORS policies appropriately on your API
- Limit guest access if handling sensitive data
Performance
- Enable compression for static assets
- Use CDN for global distribution
- Optimize images and assets
- Monitor bundle size with build tools
User Experience
- Set appropriate defaults for your use case
- Test on mobile devices for responsive design
- Provide loading states for better UX
- Handle network errors gracefully
Troubleshooting
Connection Issues
Portal can’t connect to API:
- Check
VITE_API_HOSTenvironment variable - Verify API server is running and accessible
- Check CORS configuration on API server
Authentication failures:
- Verify auth tokens are valid
- Check token expiration
- Ensure API authentication endpoints are working
Your portal app is now ready to provide a seamless chat experience for your users!