From dfd93b456ff1fe9d59525609b3ecc14c84bb5e00 Mon Sep 17 00:00:00 2001 From: Max Korp Date: Mon, 4 Aug 2025 17:08:58 -0700 Subject: [PATCH 1/4] Add ?features=false to hide the feature chooser in the left bar. --- .../dojo/src/components/sidebar/sidebar.tsx | 6 ++-- .../dojo/src/contexts/url-params-context.tsx | 28 ++++++++++++++++--- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx b/typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx index 7743e593f..0f324f738 100644 --- a/typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx +++ b/typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx @@ -28,7 +28,7 @@ interface SidebarProps { export function Sidebar({ isMobile, onMobileClose }: SidebarProps) { const router = useRouter(); const pathname = usePathname(); - const { view, pickerDisabled, setView } = useURLParams(); + const { view, pickerDisabled, featureSelectionDisabled, setView } = useURLParams(); const [isDarkTheme, setIsDarkTheme] = useState(false); // Extract the current integration ID from the pathname @@ -98,7 +98,7 @@ export function Sidebar({ isMobile, onMobileClose }: SidebarProps) { }, []); return ( -
{/* Sidebar Header */} @@ -179,7 +179,7 @@ export function Sidebar({ isMobile, onMobileClose }: SidebarProps) { {/* Demo List */}
- {currentIntegration ? ( + {(currentIntegration && !featureSelectionDisabled) ? ( void; setSidebarHidden: (disabled: boolean) => void; + setFeatureSelectionDisabled: (disabled: boolean) => void; setPickerDisabled: (disabled: boolean) => void; setCodeFile: (fileName: string) => void; } @@ -34,12 +36,13 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) { view: (searchParams.get("view") as View) || "preview", sidebarHidden: searchParams.get("sidebar") === "disabled", pickerDisabled: searchParams.get("picker") === "false", + featureSelectionDisabled: searchParams.get("features") === "false", })); // Update URL when state changes const updateURL = (newState: Partial) => { const params = new URLSearchParams(searchParams.toString()); - + // Update view param if (newState.view !== undefined) { if (newState.view === "preview") { @@ -48,7 +51,7 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) { params.set("view", newState.view); } } - + // Update sidebar param if (newState.sidebarHidden !== undefined) { if (newState.sidebarHidden) { @@ -57,7 +60,16 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) { params.delete("sidebar"); } } - + + // Update features param + if (newState.featureSelectionDisabled !== undefined) { + if (newState.featureSelectionDisabled) { + params.set("features", "false"); + } else { + params.delete("features"); + } + } + // Update picker param if (newState.pickerDisabled !== undefined) { if (newState.pickerDisabled) { @@ -77,8 +89,9 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) { view: (searchParams.get("view") as View) || "preview", sidebarHidden: searchParams.get("sidebar") === "disabled", pickerDisabled: searchParams.get("picker") === "false", + featureSelectionDisabled: searchParams.get("features") === "false", }; - + setState(newState); }, [searchParams]); @@ -101,6 +114,12 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) { updateURL({ pickerDisabled }); }; + const setFeatureSelectionDisabled = (featureSelectionDisabled: boolean) => { + const newState = { ...state, featureSelectionDisabled }; + setState(newState); + updateURL({ featureSelectionDisabled }); + }; + const setCodeFile = (fileName: string) => { const newState = { ...state, file: fileName }; setState(newState); @@ -112,6 +131,7 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) { setView, setSidebarHidden, setPickerDisabled, + setFeatureSelectionDisabled, setCodeFile, }; From 76a2572bed6b86cb13ec52a8d4ccd08406691efd Mon Sep 17 00:00:00 2001 From: Max Korp Date: Mon, 4 Aug 2025 17:30:53 -0700 Subject: [PATCH 2/4] Make title configurable --- .../apps/dojo/scripts/run-dojo-everything.js | 1 + .../src/components/layout/main-layout.tsx | 7 +++-- .../dojo/src/components/sidebar/sidebar.tsx | 3 +- typescript-sdk/apps/dojo/src/env.ts | 30 ++++++++++++------- .../apps/dojo/src/utils/domain-config.ts | 14 +++++++++ 5 files changed, 41 insertions(+), 14 deletions(-) create mode 100644 typescript-sdk/apps/dojo/src/utils/domain-config.ts diff --git a/typescript-sdk/apps/dojo/scripts/run-dojo-everything.js b/typescript-sdk/apps/dojo/scripts/run-dojo-everything.js index d93ba15fa..90d76e615 100755 --- a/typescript-sdk/apps/dojo/scripts/run-dojo-everything.js +++ b/typescript-sdk/apps/dojo/scripts/run-dojo-everything.js @@ -126,6 +126,7 @@ const dojo = { LLAMA_INDEX_URL: 'http://localhost:8007', MASTRA_URL: 'http://localhost:8008', PYDANTIC_AI_URL: 'http://localhost:8009', + NEXT_PUBLIC_CUSTOM_DOMAIN_TITLE: 'cpkdojo.local___CopilotKit Feature Viewer', } } diff --git a/typescript-sdk/apps/dojo/src/components/layout/main-layout.tsx b/typescript-sdk/apps/dojo/src/components/layout/main-layout.tsx index 3173ecc10..9706452ce 100644 --- a/typescript-sdk/apps/dojo/src/components/layout/main-layout.tsx +++ b/typescript-sdk/apps/dojo/src/components/layout/main-layout.tsx @@ -7,6 +7,7 @@ import { Menu, X } from "lucide-react"; import { Button } from "@/components/ui/button"; import { useURLParams } from "@/contexts/url-params-context"; +import { getTitleForCurrentDomain } from "@/utils/domain-config"; export function MainLayout({ children }: { children: React.ReactNode }) { const [isMobileSidebarOpen, setIsMobileSidebarOpen] = useState(false); @@ -52,7 +53,7 @@ export function MainLayout({ children }: { children: React.ReactNode }) { > {isMobileSidebarOpen ? : } -

AG-UI Dojo

+

{getTitleForCurrentDomain() || "AG-UI Dojo"}

{/* Spacer for centering */}
@@ -100,8 +101,8 @@ function MaybeSidebar({ isMobile, isMobileSidebarOpen, onMobileClose }: MaybeSid return (
diff --git a/typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx b/typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx index 0f324f738..f6a076e50 100644 --- a/typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx +++ b/typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx @@ -19,6 +19,7 @@ import { menuIntegrations } from "@/menu"; import { Feature } from "@/types/integration"; import { useURLParams } from "@/contexts/url-params-context"; import { View } from "@/types/interface"; +import { getTitleForCurrentDomain } from "@/utils/domain-config"; interface SidebarProps { isMobile?: boolean; @@ -106,7 +107,7 @@ export function Sidebar({ isMobile, onMobileClose }: SidebarProps) {

- AG-UI Interactive Dojo + {getTitleForCurrentDomain() || "AG-UI Interactive Dojo"}

diff --git a/typescript-sdk/apps/dojo/src/env.ts b/typescript-sdk/apps/dojo/src/env.ts index 4ac83b257..df4df2f37 100644 --- a/typescript-sdk/apps/dojo/src/env.ts +++ b/typescript-sdk/apps/dojo/src/env.ts @@ -8,18 +8,28 @@ type envVars = { llamaIndexUrl: string; crewAiUrl: string; pydanticAIUrl: string; + customDomainTitle: Record; } export default function getEnvVars(): envVars { - return { - serverStarterUrl: process.env.SERVER_STARTER_URL || 'http://localhost:8000', - serverStarterAllFeaturesUrl: process.env.SERVER_STARTER_ALL_FEATURES_URL || 'http://localhost:8000', - mastraUrl: process.env.MASTRA_URL || 'http://localhost:4111', - langgraphUrl: process.env.LANGGRAPH_URL || 'http://localhost:2024', - langgraphFastApiUrl: process.env.LANGGRAPH_FAST_API_URL || 'http://localhost:8000', - agnoUrl: process.env.AGNO_URL || 'http://localhost:9001', - llamaIndexUrl: process.env.LLAMA_INDEX_URL || 'http://localhost:9000', - crewAiUrl: process.env.CREW_AI_URL || 'http://localhost:9002', - pydanticAIUrl: process.env.PYDANTIC_AI_URL || 'http://localhost:9000', + const customDomainTitle: Record = {}; + if (process.env.NEXT_PUBLIC_CUSTOM_DOMAIN_TITLE) { + const [domain, title] = process.env.NEXT_PUBLIC_CUSTOM_DOMAIN_TITLE.split('___'); + if (domain && title) { + customDomainTitle[domain] = title; } + } + + return { + serverStarterUrl: process.env.SERVER_STARTER_URL || 'http://localhost:8000', + serverStarterAllFeaturesUrl: process.env.SERVER_STARTER_ALL_FEATURES_URL || 'http://localhost:8000', + mastraUrl: process.env.MASTRA_URL || 'http://localhost:4111', + langgraphUrl: process.env.LANGGRAPH_URL || 'http://localhost:2024', + langgraphFastApiUrl: process.env.LANGGRAPH_FAST_API_URL || 'http://localhost:8000', + agnoUrl: process.env.AGNO_URL || 'http://localhost:9001', + llamaIndexUrl: process.env.LLAMA_INDEX_URL || 'http://localhost:9000', + crewAiUrl: process.env.CREW_AI_URL || 'http://localhost:9002', + pydanticAIUrl: process.env.PYDANTIC_AI_URL || 'http://localhost:9000', + customDomainTitle: customDomainTitle, + } } \ No newline at end of file diff --git a/typescript-sdk/apps/dojo/src/utils/domain-config.ts b/typescript-sdk/apps/dojo/src/utils/domain-config.ts new file mode 100644 index 000000000..e44b7fcf1 --- /dev/null +++ b/typescript-sdk/apps/dojo/src/utils/domain-config.ts @@ -0,0 +1,14 @@ +import getEnvVars from "@/env"; + + +export function getTitleForCurrentDomain(): string | undefined { + const envVars = getEnvVars(); + + // Check if we're in the browser + if (typeof window == "undefined") { + return undefined; + } + + const host = window.location.hostname; + return envVars.customDomainTitle[host] || undefined; +} \ No newline at end of file From 60e342202393b1ea447f2041eabb323dda6ce4a0 Mon Sep 17 00:00:00 2001 From: Max Korp Date: Tue, 5 Aug 2025 10:29:54 -0700 Subject: [PATCH 3/4] add viewSelection=false to hide view selector --- .../dojo/src/components/sidebar/sidebar.tsx | 6 +++++- .../dojo/src/contexts/url-params-context.tsx | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx b/typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx index f6a076e50..acf73ad27 100644 --- a/typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx +++ b/typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx @@ -29,7 +29,7 @@ interface SidebarProps { export function Sidebar({ isMobile, onMobileClose }: SidebarProps) { const router = useRouter(); const pathname = usePathname(); - const { view, pickerDisabled, featureSelectionDisabled, setView } = useURLParams(); + const { view, pickerDisabled, featureSelectionDisabled, setView, viewSelectionDisabled} = useURLParams(); const [isDarkTheme, setIsDarkTheme] = useState(false); // Extract the current integration ID from the pathname @@ -116,6 +116,7 @@ export function Sidebar({ isMobile, onMobileClose }: SidebarProps) {
{/* Controls Section */} + {(!viewSelectionDisabled || !pickerDisabled) && (
{/* Integration picker */} {!pickerDisabled && ( @@ -144,6 +145,7 @@ export function Sidebar({ isMobile, onMobileClose }: SidebarProps) { )} {/* Preview/Code Tabs */} + {!viewSelectionDisabled &&
+ }
+ )} {/* Demo List */}
diff --git a/typescript-sdk/apps/dojo/src/contexts/url-params-context.tsx b/typescript-sdk/apps/dojo/src/contexts/url-params-context.tsx index f0907bb37..70a0c9ba4 100644 --- a/typescript-sdk/apps/dojo/src/contexts/url-params-context.tsx +++ b/typescript-sdk/apps/dojo/src/contexts/url-params-context.tsx @@ -8,6 +8,7 @@ interface URLParamsState { view: View; sidebarHidden: boolean; featureSelectionDisabled: boolean; + viewSelectionDisabled: boolean; pickerDisabled: boolean; file?: string; } @@ -16,6 +17,7 @@ interface URLParamsContextType extends URLParamsState { setView: (view: View) => void; setSidebarHidden: (disabled: boolean) => void; setFeatureSelectionDisabled: (disabled: boolean) => void; + setViewSelectionDisabled: (disabled: boolean) => void; setPickerDisabled: (disabled: boolean) => void; setCodeFile: (fileName: string) => void; } @@ -35,6 +37,7 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) { const [state, setState] = useState(() => ({ view: (searchParams.get("view") as View) || "preview", sidebarHidden: searchParams.get("sidebar") === "disabled", + viewSelectionDisabled: searchParams.get("viewSelection") === "false", pickerDisabled: searchParams.get("picker") === "false", featureSelectionDisabled: searchParams.get("features") === "false", })); @@ -61,6 +64,14 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) { } } + // Update viewSelection param + if (newState.viewSelectionDisabled !== undefined) { + if (newState.viewSelectionDisabled) { + params.set("viewSelection", "false"); + } else { + params.delete("viewSelection"); + } + } // Update features param if (newState.featureSelectionDisabled !== undefined) { if (newState.featureSelectionDisabled) { @@ -90,6 +101,7 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) { sidebarHidden: searchParams.get("sidebar") === "disabled", pickerDisabled: searchParams.get("picker") === "false", featureSelectionDisabled: searchParams.get("features") === "false", + viewSelectionDisabled: searchParams.get("viewSelection") === "false", }; setState(newState); @@ -120,6 +132,12 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) { updateURL({ featureSelectionDisabled }); }; + const setViewSelectionDisabled = (viewSelectionDisabled: boolean) => { + const newState = { ...state, viewSelectionDisabled }; + setState(newState); + updateURL({ viewSelectionDisabled }); + }; + const setCodeFile = (fileName: string) => { const newState = { ...state, file: fileName }; setState(newState); @@ -132,6 +150,7 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) { setSidebarHidden, setPickerDisabled, setFeatureSelectionDisabled, + setViewSelectionDisabled, setCodeFile, }; From 51a58b33626dbdf146456b494021493d26bcb2f3 Mon Sep 17 00:00:00 2001 From: Max Korp Date: Tue, 5 Aug 2025 10:34:34 -0700 Subject: [PATCH 4/4] rename query params for consistency and clarity --- .../dojo/src/components/sidebar/sidebar.tsx | 10 +-- .../dojo/src/contexts/url-params-context.tsx | 84 +++++++++---------- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx b/typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx index acf73ad27..aef8940df 100644 --- a/typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx +++ b/typescript-sdk/apps/dojo/src/components/sidebar/sidebar.tsx @@ -29,7 +29,7 @@ interface SidebarProps { export function Sidebar({ isMobile, onMobileClose }: SidebarProps) { const router = useRouter(); const pathname = usePathname(); - const { view, pickerDisabled, featureSelectionDisabled, setView, viewSelectionDisabled} = useURLParams(); + const { view, frameworkPickerHidden, viewPickerHidden, featurePickerHidden, setView} = useURLParams(); const [isDarkTheme, setIsDarkTheme] = useState(false); // Extract the current integration ID from the pathname @@ -116,10 +116,10 @@ export function Sidebar({ isMobile, onMobileClose }: SidebarProps) {
{/* Controls Section */} - {(!viewSelectionDisabled || !pickerDisabled) && ( + {(!frameworkPickerHidden|| !viewPickerHidden) && (
{/* Integration picker */} - {!pickerDisabled && ( + {!frameworkPickerHidden&& (
@@ -145,7 +145,7 @@ export function Sidebar({ isMobile, onMobileClose }: SidebarProps) { )} {/* Preview/Code Tabs */} - {!viewSelectionDisabled && + {!viewPickerHidden &&
- {(currentIntegration && !featureSelectionDisabled) ? ( + {(currentIntegration && !featurePickerHidden) ? ( void; setSidebarHidden: (disabled: boolean) => void; - setFeatureSelectionDisabled: (disabled: boolean) => void; - setViewSelectionDisabled: (disabled: boolean) => void; - setPickerDisabled: (disabled: boolean) => void; + setFrameworkPickerHidden: (disabled: boolean) => void; + setViewPickerHidden: (disabled: boolean) => void; + setFeaturePickerHidden: (disabled: boolean) => void; setCodeFile: (fileName: string) => void; } @@ -36,10 +36,10 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) { // Initialize state from URL params const [state, setState] = useState(() => ({ view: (searchParams.get("view") as View) || "preview", - sidebarHidden: searchParams.get("sidebar") === "disabled", - viewSelectionDisabled: searchParams.get("viewSelection") === "false", - pickerDisabled: searchParams.get("picker") === "false", - featureSelectionDisabled: searchParams.get("features") === "false", + sidebarHidden: searchParams.get("sidebar") === "false", + frameworkPickerHidden: searchParams.get("frameworkPicker") === "false", + viewPickerHidden: searchParams.get("viewPicker") === "false", + featurePickerHidden: searchParams.get("featurePicker") === "false", })); // Update URL when state changes @@ -58,35 +58,35 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) { // Update sidebar param if (newState.sidebarHidden !== undefined) { if (newState.sidebarHidden) { - params.set("sidebar", "disabled"); + params.set("sidebar", "false"); } else { params.delete("sidebar"); } } - // Update viewSelection param - if (newState.viewSelectionDisabled !== undefined) { - if (newState.viewSelectionDisabled) { - params.set("viewSelection", "false"); + // Update frameworkPicker param + if (newState.frameworkPickerHidden !== undefined) { + if (newState.frameworkPickerHidden) { + params.set("frameworkPicker", "false"); } else { - params.delete("viewSelection"); + params.delete("frameworkPicker"); } } - // Update features param - if (newState.featureSelectionDisabled !== undefined) { - if (newState.featureSelectionDisabled) { - params.set("features", "false"); + + // Update viewPicker param + if (newState.viewPickerHidden !== undefined) { + if (newState.viewPickerHidden) { + params.set("viewPicker", "false"); } else { - params.delete("features"); + params.delete("viewPicker"); } } - - // Update picker param - if (newState.pickerDisabled !== undefined) { - if (newState.pickerDisabled) { - params.set("picker", "false"); + // Update featurePicker param + if (newState.featurePickerHidden !== undefined) { + if (newState.featurePickerHidden) { + params.set("featurePicker", "false"); } else { - params.delete("picker"); + params.delete("features"); } } @@ -99,9 +99,9 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) { const newState: URLParamsState = { view: (searchParams.get("view") as View) || "preview", sidebarHidden: searchParams.get("sidebar") === "disabled", - pickerDisabled: searchParams.get("picker") === "false", - featureSelectionDisabled: searchParams.get("features") === "false", - viewSelectionDisabled: searchParams.get("viewSelection") === "false", + frameworkPickerHidden: searchParams.get("frameworkPicker") === "false", + viewPickerHidden: searchParams.get("viewPicker") === "false", + featurePickerHidden: searchParams.get("featurePicker") === "false", }; setState(newState); @@ -120,22 +120,22 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) { updateURL({ sidebarHidden }); }; - const setPickerDisabled = (pickerDisabled: boolean) => { - const newState = { ...state, pickerDisabled }; + const setFrameworkPickerHidden = (frameworkPickerHidden: boolean) => { + const newState = { ...state, frameworkPickerHidden }; setState(newState); - updateURL({ pickerDisabled }); + updateURL({ frameworkPickerHidden }); }; - const setFeatureSelectionDisabled = (featureSelectionDisabled: boolean) => { - const newState = { ...state, featureSelectionDisabled }; + const setViewPickerHidden = (viewPickerHidden: boolean) => { + const newState = { ...state, viewPickerHidden }; setState(newState); - updateURL({ featureSelectionDisabled }); + updateURL({ viewPickerHidden }); }; - const setViewSelectionDisabled = (viewSelectionDisabled: boolean) => { - const newState = { ...state, viewSelectionDisabled }; + const setFeaturePickerHidden = (featurePickerHidden: boolean) => { + const newState = { ...state, featurePickerHidden }; setState(newState); - updateURL({ viewSelectionDisabled }); + updateURL({ featurePickerHidden }); }; const setCodeFile = (fileName: string) => { @@ -148,9 +148,9 @@ export function URLParamsProvider({ children }: URLParamsProviderProps) { ...state, setView, setSidebarHidden, - setPickerDisabled, - setFeatureSelectionDisabled, - setViewSelectionDisabled, + setFrameworkPickerHidden, + setViewPickerHidden, + setFeaturePickerHidden, setCodeFile, };