feat(ui): configurable headline and subtitle via env vars (fixes #1345)#1396
feat(ui): configurable headline and subtitle via env vars (fixes #1345)#1396fl-sean03 wants to merge 4 commits intokagent-dev:mainfrom
Conversation
Add NEXT_PUBLIC_HEADLINE env var to customize the chat greeting (default: "Start a conversation") and NEXT_PUBLIC_SUBTITLE env var for an optional tagline below the "Agents" heading on the landing page. - ChatInterface accepts optional `headline` prop - AgentList accepts optional `subtitle` prop - Server/page components read process.env and pass as props - Zero impact on default deployments (env vars are optional) Fixes kagent-dev#1345 Signed-off-by: Sean <sean@opspawn.com> Signed-off-by: fl-sean03 <jmhbh@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR adds support for customizable UI text through environment variables NEXT_PUBLIC_HEADLINE (for chat greeting) and NEXT_PUBLIC_SUBTITLE (for landing page tagline). However, the implementation does not fully achieve the stated goal of runtime configuration, as Next.js inlines NEXT_PUBLIC_* variables at build time by default.
Changes:
- Added optional
headlineandsubtitleprops toChatInterfaceandAgentListcomponents respectively - Updated page components to read environment variables and pass them as props
- Default values are preserved when env vars are not set
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 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 with conditional rendering |
ui/src/app/page.tsx |
Reads NEXT_PUBLIC_SUBTITLE env var and passes to AgentList |
ui/src/app/agents/page.tsx |
Reads NEXT_PUBLIC_SUBTITLE env var and passes to AgentList |
ui/src/app/agents/[namespace]/[name]/chat/page.tsx |
Reads NEXT_PUBLIC_HEADLINE env var and passes to ChatInterface |
ui/src/app/agents/[namespace]/[name]/chat/[chatId]/page.tsx |
Reads NEXT_PUBLIC_HEADLINE env var in client component |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -1,5 +1,6 @@ | |||
| import AgentList from "@/components/AgentList"; | |||
|
|
|||
There was a problem hiding this comment.
NEXT_PUBLIC_ environment variables are inlined at build time by default in Next.js. To ensure the subtitle can be changed at runtime without rebuilding (as described in the issue #1345), you need to add export const dynamic = "force-dynamic"; before the component function. This forces the page to be dynamically rendered, allowing the env var to be read at runtime from the deployment environment.
| export const dynamic = "force-dynamic"; |
| @@ -1,4 +1,5 @@ | |||
| import AgentList from "@/components/AgentList"; | |||
There was a problem hiding this comment.
NEXT_PUBLIC_ environment variables are inlined at build time by default in Next.js. To ensure the subtitle can be changed at runtime without rebuilding (as described in the issue #1345), you need to add export const dynamic = "force-dynamic"; before the component function. This forces the page to be dynamically rendered, allowing the env var to be read at runtime from the deployment environment.
| import AgentList from "@/components/AgentList"; | |
| import AgentList from "@/components/AgentList"; | |
| export const dynamic = "force-dynamic"; |
| export default function ChatAgentPage({ params }: { params: Promise<{ name: string, namespace: string }> }) { | ||
| const { name, namespace } = use(params); | ||
| return <ChatInterface selectedAgentName={name} selectedNamespace={namespace} />; | ||
| } No newline at end of file | ||
| const headline = process.env.NEXT_PUBLIC_HEADLINE; | ||
| return <ChatInterface selectedAgentName={name} selectedNamespace={namespace} headline={headline} />; |
There was a problem hiding this comment.
NEXT_PUBLIC_ environment variables are inlined at build time by default in Next.js. To ensure the headline can be changed at runtime without rebuilding (as described in the issue #1345), you need to add export const dynamic = "force-dynamic"; before the component function. This forces the page to be dynamically rendered, allowing the env var to be read at runtime from the deployment environment.
| selectedNamespace={namespace} | ||
| sessionId={chatId} | ||
| headline={process.env.NEXT_PUBLIC_HEADLINE} | ||
| />; |
There was a problem hiding this comment.
This is a client component (marked with "use client"), but it's trying to read a NEXT_PUBLIC_ environment variable. While NEXT_PUBLIC_ vars are available in client components, they are always inlined at build time and cannot be changed at runtime. Since the issue #1345 requires runtime configuration, this page should either: (1) be converted to a server component by removing "use client" and adding export const dynamic = "force-dynamic";, or (2) receive the headline value from a parent server component via props.
Ensures NEXT_PUBLIC_* env vars are read at runtime on each request, not baked in at build time. This is required for runtime-configurable Next.js deployments as described in issue kagent-dev#1345. Signed-off-by: Sean <sean@opspawn.com> Signed-off-by: fl-sean03 <jmhbh@users.noreply.github.com>
|
Added
This ensures the env vars are read at runtime (on each request), not baked in at build time. As the issue description specifies, this is the correct pattern for runtime-configurable Next.js env vars. Skipped |
|
Addressed Copilot feedback in 5f3c694: converted |
The [chatId]/page.tsx was a "use client" component, which means NEXT_PUBLIC_ env vars are inlined at build time and cannot be changed at runtime. Convert to an async server component with force-dynamic to match the other pages, ensuring the headline env var is read at request time. Signed-off-by: Sean <sean@opspawn.com> Signed-off-by: fl-sean03 <jmhbh@users.noreply.github.com>
5f3c694 to
78af4eb
Compare
Summary
NEXT_PUBLIC_HEADLINEenv var to customize the chat greeting (default: "Start a conversation")NEXT_PUBLIC_SUBTITLEenv var for an optional tagline below the "Agents" heading on the landing pageChatInterfaceaccepts optionalheadlineprop, falling back to the default textAgentListaccepts optionalsubtitleprop, rendered only when providedprocess.envand pass values as propsChanges
ui/src/components/chat/ChatInterface.tsxheadlineprop to interface; use it in the empty-state greetingui/src/components/AgentList.tsxAgentListPropsinterface with optionalsubtitle; render subtitle below heading when providedui/src/app/agents/[namespace]/[name]/chat/page.tsxNEXT_PUBLIC_HEADLINEand pass as propui/src/app/agents/[namespace]/[name]/chat/[chatId]/page.tsxNEXT_PUBLIC_HEADLINEand pass as propui/src/app/page.tsxNEXT_PUBLIC_SUBTITLEand pass as propui/src/app/agents/page.tsxNEXT_PUBLIC_SUBTITLEand pass as propTest plan
npm run build— compiles successfullynpm run lint— no lint errorsnpm run test— all 107 tests passNEXT_PUBLIC_HEADLINE="Hello there"and verify chat greeting changesNEXT_PUBLIC_SUBTITLE="Your AI assistants"and verify subtitle appears on landing pageFixes #1345