Availability
Portal UI plugins extend the AI Portal (end-user facing) with custom pages, forms, and interactive features. Unlike Admin UI plugins which are only visible to administrators, Portal UI plugins are accessible to all authenticated portal users and support group-based visibility filtering.
Overview
Portal UI plugins enable you to:- Add Portal Pages: Register new routes in the portal navigation
- Extend Portal Sidebar: Add sections and links to the portal drawer
- Serve WebComponents: Use any frontend framework (same asset serving as admin UI)
- Handle Portal RPC: Define backend endpoints that receive authenticated user context
- Control Visibility: Restrict portal pages to specific user groups
- Combine with Admin UI: A single plugin can have both admin and portal interfaces
Use Cases
- Support ticket systems for end users
- Custom resource browsers or dashboards
- User feedback and survey forms
- Forum or community features
- Self-service configuration pages
- Data submission and approval workflows
Architecture
Portal UI plugins use a separate security scope from admin UI plugins. This is enforced at every level:Quick Start
1. Project Structure
2. Create Manifest
The manifest declares both admin (ui) and portal (portal) UI sections. The portal section uses PortalUISlot which includes a groups field for visibility filtering.
Expandable
Group-Based Visibility
Thegroups field on portal slots controls which users can see the page:
The filtering happens server-side — the portal UI registry and sidebar menu endpoints only return entries the authenticated user is allowed to see.
3. Implement the Plugin
A portal UI plugin must implement bothUIProvider (for assets and manifest) and PortalUIProvider (for portal RPC):
Expandable
4. Create Portal WebComponent
Portal WebComponents receive aportalPluginAPI object (injected by the portal plugin loader) for making RPC calls:
Expandable
- Admin components receive
this.pluginAPI(routes toHandleRPC) - Portal components receive
this.portalPluginAPI(routes toHandlePortalRPC)
5. Create Admin WebComponent (Optional)
If your plugin also has an admin interface, create a separate WebComponent that usesthis.pluginAPI:
Expandable
PortalUserContext
Every portal RPC call includes aPortalUserContext with the authenticated user’s information:
- Authorization: Check if the user has permission for the requested operation
- Data scoping: Return only data belonging to the calling user
- Audit logging: Record who performed each action
- Group-based features: Enable features based on group membership
Expandable
Manifest Reference
Portal Slots
Theportal section in the manifest is parallel to the ui section:
Expandable
Capabilities and Permissions
Portal UI plugins must declare both hook types and permissions:studio_uiin hooks enables admin UI + asset servingportal_uiin hooks enables portal RPC handling- Both are required for a plugin with portal UI (assets are served via
UIProvider)
Route Path Convention
Portal plugin routes should follow the pattern/portal/plugins/{plugin-name}/{page} to avoid conflicts with built-in portal routes:
API Endpoints
Portal plugin API endpoints are under/common/ (authenticated, no admin required):
Portal RPC Call Flow
Example: Portal Feedback Plugin
A complete working example is available atexamples/plugins/studio/portal-feedback/.
This plugin demonstrates:
- Portal form for users to submit feedback (
HandlePortalRPC) - Admin dashboard to view all submissions (
HandleRPC) - Shared asset serving between admin and portal UIs
- Group-based visibility (set to
[]for all users) waitForAPIAndLoad()pattern for WebComponent API injection timing
Best Practices
Security
- Never trust portal input - Always validate and sanitize data in
HandlePortalRPC - Scope data to users - Use
userCtx.UserIDto ensure users only see their own data - Keep admin operations in HandleRPC - Destructive operations (delete, admin overrides) should stay in the admin-only
HandleRPCmethod - Check groups in RPC handlers - Even though sidebar visibility is filtered, users could call the RPC endpoint directly. Validate group membership in
HandlePortalRPCfor sensitive operations
Performance
- Use KV storage for persistence - In-memory data is lost on plugin restart
- Cache frequently accessed data - Use
sync.Mapor similar for hot data - Keep portal pages lightweight - Portal users expect fast page loads
WebComponent Patterns
- Wait for API injection - Use the
waitForAPIAndLoad()pattern instead of calling the API inconnectedCallback()directly - Handle errors gracefully - Show user-friendly messages, not stack traces
- Use Shadow DOM - Prevents style conflicts with the host application
- Escape user content - Always escape HTML in dynamic content to prevent XSS