Skip to content

Customize the UI

Learn how to customize the Pika Framework user interface, configure features, and extend functionality using designated customization areas that are protected from framework updates.

By the end of this guide, you will:

  • Configure project names and branding
  • Customize site-wide features
  • Configure home page experience
  • Add custom message tag renderers
  • Implement custom authentication
  • Understand protected customization areas
  • Manage sync configuration
  • A running Pika installation
  • Access to project configuration files
  • Understanding of SvelteKit and TypeScript (for advanced customization)
  • Familiarity with AWS CDK (for infrastructure changes)

Pika Framework provides designated areas where you can add custom code without worrying about framework updates overwriting your changes. These areas are protected from sync operations.

Step 1: Configure Project Names and Branding

Section titled “Step 1: Configure Project Names and Branding”

All customization starts with configuring your project identity.

Location: pika-config.ts (root directory)

This file is the single source of truth for project names and is protected from framework updates.

export const pikaConfig: PikaConfig = {
pika: {
projNameL: 'mycompany', // All lowercase
projNameKebabCase: 'mycompany', // Kebab case
projNameTitleCase: 'MyCompany', // Title case
projNameCamel: 'mycompany', // Camel case
projNameHuman: 'My Company' // Human readable
},
pikaChat: {
projNameL: 'mycompanychat', // All lowercase
projNameKebabCase: 'mycompany-chat', // Kebab case
projNameTitleCase: 'MyCompanyChat', // Title case
projNameCamel: 'myCompanyChat', // Camel case
projNameHuman: 'My Company Chat' // Human readable
}
};

Why This Matters:

  • All AWS resources use these names
  • Stack definitions automatically import these values
  • Ensures consistent naming across your infrastructure

Configure the home page title, welcome message, and chat app link visibility.

Location: pika-config.ts (root directory)

export const pikaConfig: PikaConfig = {
// ... project names configuration
siteFeatures: {
homePage: {
// Custom title
homePageTitle: 'Welcome to My Company Chat',
// Custom welcome message
welcomeMessage: 'Get started by selecting a chat app below or asking me anything!',
// Configure which users see links to which chat apps
linksToChatApps: {
userChatAppRules: [
// External users see only external chat apps
{
userTypes: ['external-user'],
chatAppUserTypes: ['external-user']
},
// Internal users see all chat apps
{
userTypes: ['internal-user'],
chatAppUserTypes: ['internal-user', 'external-user']
}
]
}
}
}
};

Configuration Options:

OptionDescriptionRequired
homePageTitleCustom title for home pageNo
welcomeMessageCustom welcome messageNo
linksToChatAppsRules for showing chat app linksNo

Control which users see which chat apps on the home page:

  1. System checks user's user type
  2. Finds matching rules in userChatAppRules
  3. Shows chat apps whose user types match chatAppUserTypes
  4. If no rules match, no chat app links appear

Configure features that affect the entire application.

Location: pika-config.ts (root directory)

siteFeatures: {
// Show AI reasoning traces
traces: {
featureId: 'traces',
enabled: true,
userTypes: ['internal-user'],
detailedTraces: {
enabled: true,
userTypes: ['internal-user'],
userRoles: ['pika:content-admin']
}
},
// Verify and improve response quality
verifyResponse: {
featureId: 'verifyResponse',
enabled: true,
autoRepromptThreshold: 'C', // Auto-improve responses graded C or lower
userTypes: ['internal-user', 'external-user']
},
// User memory for context
userMemory: {
featureId: 'userMemory',
enabled: true,
strategy: 'semantic',
conversationMemoryStrategy: 'preferences'
}
}
siteFeatures: {
// Enable logout
logout: {
featureId: 'logout',
enabled: true,
userTypes: ['internal-user', 'external-user']
},
// Enable file upload
fileUpload: {
featureId: 'fileUpload',
enabled: true,
mimeTypesAllowed: [
'image/*',
'application/pdf',
'text/plain',
'.docx',
'.xlsx'
]
},
// Chat suggestions
suggestions: {
featureId: 'suggestions',
enabled: true,
suggestions: [], // Chat apps define their own
maxToShow: 5,
randomize: false
},
// Input field label
promptInputFieldLabel: {
featureId: 'promptInputFieldLabel',
enabled: true,
promptInputFieldLabel: 'Ready to chat'
},
// UI customization
uiCustomization: {
featureId: 'uiCustomization',
enabled: true,
showUserRegionInLeftNav: false,
showChatHistoryInStandaloneMode: true
},
// Disclaimer notice
chatDisclaimerNotice: {
featureId: 'chatDisclaimerNotice',
enabled: true,
notice: 'This AI-powered chat is here to help, but it may not always be accurate. For urgent issues, please contact support.'
}
}
siteFeatures: {
// Site admin interface
siteAdmin: {
websiteEnabled: true
// Users need 'pika:site-admin' role
},
// Content admin access
contentAdmin: {
enabled: true
// Users need 'pika:content-admin' role
},
// Entity-based access
entity: {
enabled: true,
attributeName: 'accountId',
searchPlaceholderText: 'Search for an account...',
displayNameSingular: 'Account',
displayNamePlural: 'Accounts'
}
}

Create custom renderers for XML tags in LLM responses.

Location: apps/pika-chat/src/lib/client/features/chat/message-segments/custom-components/

CustomDataTable.svelte
<script lang="ts">
export let data: { headers: string[]; rows: string[][] };
</script>
<div class="custom-table">
<table>
<thead>
<tr>
{#each data.headers as header}
<th>{header}</th>
{/each}
</tr>
</thead>
<tbody>
{#each data.rows as row}
<tr>
{#each row as cell}
<td>{cell}</td>
{/each}
</tr>
{/each}
</tbody>
</table>
</div>
<style>
.custom-table {
overflow-x: auto;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
padding: 0.5rem;
border: 1px solid #ddd;
text-align: left;
}
th {
background-color: #f5f5f5;
font-weight: bold;
}
</style>
custom-renderers.ts
import CustomDataTable from './CustomDataTable.svelte';
export const customRenderers: Record<string, Component<any>> = {
'data-table': CustomDataTable
};
<data-table>
{
"headers": ["Name", "Age", "City"],
"rows": [
["John", "30", "NYC"],
["Jane", "25", "LA"]
]
}
</data-table>

Configure custom authentication flows for your SSO or auth provider.

Location: apps/pika-chat/src/lib/server/auth-provider/

import { AuthProvider } from 'pika-shared/types/chatbot/chatbot-types';
import type { AuthenticatedUser } from 'pika-shared/types/chatbot/chatbot-types';
export default class CustomAuthProvider extends AuthProvider<YourAuthData, YourCustomData> {
async getUser(event: RequestEvent): Promise<AuthenticatedUser | undefined> {
// Your authentication logic
const token = event.cookies.get('auth_token');
if (!token) return undefined;
const userData = await validateToken(token);
if (!userData) return undefined;
return {
userId: userData.id,
firstName: userData.firstName,
lastName: userData.lastName,
email: userData.email,
userType: userData.isEmployee ? 'internal-user' : 'external-user',
roles: this.assignRoles(userData),
customData: {
accountId: userData.accountId,
permissions: userData.permissions
}
};
}
private assignRoles(userData: any): string[] {
const roles: string[] = [];
if (userData.isAdmin) {
roles.push('pika:site-admin');
}
if (userData.isSupport) {
roles.push('pika:content-admin');
}
return roles;
}
}

Create new web applications within your Pika project.

Location: apps/custom/

Terminal window
# Create new SvelteKit app
cd apps/custom
npm create svelte@latest my-admin-panel
# Install dependencies
cd my-admin-panel
npm install

Use Cases:

  • Admin dashboards
  • Customer portals
  • Internal tools
  • Separate applications for different user types

Create new backend services and API endpoints.

Location: services/custom/

Use Cases:

  • Payment processing services
  • Email notification services
  • Data analytics services
  • Third-party integrations

These areas are never overwritten by framework updates:

  1. Project Configuration - pika-config.ts
  2. Custom Message Tag Renderers - apps/pika-chat/src/lib/client/features/chat/message-segments/custom-components/
  3. Authentication - apps/pika-chat/src/lib/server/auth-provider/
  4. Custom Web Applications - apps/custom/
  5. Custom Services - services/custom/
  6. Stack Definition Files (by default):
    • apps/pika-chat/infra/bin/pika-chat.ts
    • services/pika/bin/pika.ts

Control which files are protected from framework updates.

Location: .pika-sync.json (root directory)

{
"userProtectedAreas": [
"my-custom-config.ts",
"apps/my-custom-app/"
],
"userUnprotectedAreas": [
"apps/pika-chat/infra/bin/pika-chat.ts",
"services/pika/bin/pika.ts"
]
}

Configuration:

  • userProtectedAreas - Additional files you want to protect
  • userUnprotectedAreas - Default protected files you want to allow updates for

Features follow this precedence order:

  1. Site Level (in pika-config.ts)
  2. Chat App Override (in chat app definition)
  3. Admin Override (via Site Admin interface)

Rules:

  • Site-level settings are the baseline
  • Chat apps can make features more restrictive
  • Admin overrides completely replace chat app settings
  • No level can enable site-disabled features

Before customizing anything else, update project names in pika-config.ts. This ensures consistent naming across all AWS resources.

Always place custom code in designated customization areas. Files outside these areas may be overwritten during framework updates.

Use the appropriate area for your custom code:

TypeLocation
Project namespika-config.ts
UI componentsCustom Components
Auth logicCustom Authentication
New appsCustom Web Applications
Backend servicesCustom Services
InfrastructureStack Definition Files

Initialize git and commit customizations regularly:

Terminal window
git init
git add .
git commit -m "Initial commit with customizations"

After running pika sync, always test customizations to ensure they still work correctly.

Keep documentation of customizations, especially for complex changes to stack definitions or custom services.

When you run pika sync:

  1. Framework files get latest changes
  2. All files in protected areas are preserved
  3. Your userProtectedAreas merge with defaults
  4. Files in userUnprotectedAreas can be updated

This ensures customizations are preserved while receiving framework improvements.

// Update project names
pikaConfig.pikaChat.projNameHuman = 'Acme Corp Assistant';
// Configure home page
siteFeatures.homePage = {
homePageTitle: 'Acme Corp AI Assistant',
welcomeMessage: 'Welcome! How can I help you today?'
};
// Add custom CSS in app.css for brand colors
// Enable entity feature
siteFeatures.entity = {
enabled: true,
attributeName: 'companyId',
displayNameSingular: 'Company',
displayNamePlural: 'Companies'
};
// Enable site admin for access control
siteFeatures.siteAdmin = {
websiteEnabled: true
};
// Configure access rules per tenant in Site Admin interface
// Restrict to internal users
siteFeatures.logout = {
enabled: true,
userTypes: ['internal-user']
};
// Enable all admin features
siteFeatures.contentAdmin = { enabled: true };
siteFeatures.siteAdmin = { websiteEnabled: true };
siteFeatures.traces = {
enabled: true,
userTypes: ['internal-user']
};