Skip to content

Comments

feat(ui): add configurable headline and subtitle via env vars#1347

Open
frank-bee wants to merge 1 commit intokagent-dev:mainfrom
frank-bee:feat/configurable-ui-text
Open

feat(ui): add configurable headline and subtitle via env vars#1347
frank-bee wants to merge 1 commit intokagent-dev:mainfrom
frank-bee:feat/configurable-ui-text

Conversation

@frank-bee
Copy link

Summary

  • Add NEXT_PUBLIC_HEADLINE env var to customize the chat greeting text (defaults to "Start a conversation")
  • Add NEXT_PUBLIC_SUBTITLE env var to display an optional tagline below the "Agents" heading on the landing page
  • Add force-dynamic export to layout.tsx to ensure env vars are read at runtime, not baked in at build time
  • Convert [chatId]/page.tsx from client component to server component for proper env var access

When env vars are not set, everything works exactly as before — zero impact on default deployments.

Environment Variables

Variable Component Default Description
NEXT_PUBLIC_HEADLINE UI "Start a conversation" Chat greeting text shown before the first message
NEXT_PUBLIC_SUBTITLE UI (none) Optional tagline below "Agents" on the landing page

Files Changed

  • ui/src/app/page.tsx — read NEXT_PUBLIC_SUBTITLE, pass to AgentList
  • ui/src/components/AgentList.tsx — accept and render optional subtitle prop
  • ui/src/components/chat/ChatInterface.tsx — accept optional headline prop
  • ui/src/app/agents/[namespace]/[name]/chat/page.tsx — read and pass headline
  • ui/src/app/agents/[namespace]/[name]/chat/[chatId]/page.tsx — convert to server component, read and pass headline
  • ui/src/app/layout.tsx — add force-dynamic for runtime env var support

Test plan

  • Set NEXT_PUBLIC_HEADLINE="Ask your AI assistant", verify it appears in the chat view
  • Set NEXT_PUBLIC_SUBTITLE="Internal AI Platform", verify it appears on the landing page
  • Unset both env vars, verify default behavior is unchanged
  • Run make -C ui build

Closes #1345
Related: #1335

Copilot AI review requested due to automatic review settings February 20, 2026 19:16
@frank-bee frank-bee requested a review from peterj as a code owner February 20, 2026 19:16
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for customizing the UI text via runtime environment variables, allowing deployments to personalize the chat greeting and landing page subtitle without code changes. The implementation reads NEXT_PUBLIC_HEADLINE and NEXT_PUBLIC_SUBTITLE from environment variables and passes them as optional props to the respective components.

Changes:

  • Added optional headline prop to ChatInterface component for customizable chat greeting text
  • Added optional subtitle prop to AgentList component for landing page tagline
  • Converted [chatId]/page.tsx from client to server component to properly access environment variables
  • Added force-dynamic export to root layout for runtime environment variable support

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
ui/src/components/chat/ChatInterface.tsx Added optional headline prop with fallback to "Start a conversation"
ui/src/components/AgentList.tsx Added optional subtitle prop displayed below "Agents" heading
ui/src/app/page.tsx Read NEXT_PUBLIC_SUBTITLE env var and pass to AgentList
ui/src/app/layout.tsx Added force-dynamic export for runtime env var access
ui/src/app/agents/[namespace]/[name]/chat/page.tsx Read NEXT_PUBLIC_HEADLINE env var and pass to ChatInterface
ui/src/app/agents/[namespace]/[name]/chat/[chatId]/page.tsx Converted to async server component, read and pass NEXT_PUBLIC_HEADLINE

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 5 to 8
export default function ChatAgentPage({ params }: { params: Promise<{ name: string, namespace: string }> }) {
const { name, namespace } = use(params);
return <ChatInterface selectedAgentName={name} selectedNamespace={namespace} />;
const headline = process.env.NEXT_PUBLIC_HEADLINE;
return <ChatInterface selectedAgentName={name} selectedNamespace={namespace} headline={headline} />;
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This page component should be converted to an async server component for consistency with the sibling [chatId]/page.tsx file. The current implementation uses the use() hook which is meant for client components, while the environment variable access pattern suggests server-side rendering is intended.

Convert the function to async and use await params instead of use(params):

export default async function ChatAgentPage({ params }: { params: Promise<{ name: string, namespace: string }> }) {
  const { name, namespace } = await params;
  const headline = process.env.NEXT_PUBLIC_HEADLINE;
  return <ChatInterface selectedAgentName={name} selectedNamespace={namespace} headline={headline} />;
}

Also remove the now-unused use import from 'react'.

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already done in this PR — both chat/page.tsx and chat/[chatId]/page.tsx are converted to async server components with await params, and the use import is removed.

Comment on lines +17 to +18
export const dynamic = "force-dynamic";

Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting dynamic = "force-dynamic" in the root layout disables static optimization for the entire application, which may have performance implications. Consider setting this only on the specific pages that need runtime environment variable access instead of globally.

For example, you could add export const dynamic = "force-dynamic" to:

  • ui/src/app/page.tsx (for NEXT_PUBLIC_SUBTITLE)
  • ui/src/app/agents/[namespace]/[name]/chat/page.tsx (for NEXT_PUBLIC_HEADLINE)
  • ui/src/app/agents/[namespace]/[name]/chat/[chatId]/page.tsx (for NEXT_PUBLIC_HEADLINE)

This would allow other pages that don't use these env vars to benefit from static optimization. Note that NEXT_PUBLIC_* env vars are typically available at build time, but if you need them to be configurable at runtime without rebuilding, the current approach or the per-page approach is correct.

Suggested change
export const dynamic = "force-dynamic";

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentional. The env vars need to be read at container runtime (not build time) since this is deployed as a Docker image with configurable env vars. force-dynamic is required for that.

Additionally, the sibling PR #1346 (read-only mode) also reads NEXT_PUBLIC_READ_ONLY in the root layout, so force-dynamic needs to be here regardless. Scoping per-page would add boilerplate for negligible gain on a K8s dashboard app.

Add support for customizing the chat headline and landing page subtitle
through runtime environment variables, enabling enterprise deployments
to personalize the UI without forking.

- NEXT_PUBLIC_HEADLINE: replaces "Start a conversation" chat greeting
- NEXT_PUBLIC_SUBTITLE: optional tagline below "Agents" on landing page
- Add force-dynamic to layout.tsx for runtime env var support
- Convert [chatId]/page.tsx to server component for env var access

When env vars are not set, everything works exactly as before.

Closes kagent-dev#1345

Signed-off-by: Frank Bernhardt <Frank.Bernhardt@quantum-machines.co>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Configurable UI headline and subtitle via environment variables

1 participant