Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions docs/en/DEPLOY_OPTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -1505,6 +1505,38 @@ const envs: Record<string, Partial<StackInput>> = {
}
```

## Branding Customization

You can customize the logo and title displayed on the landing page by creating a branding configuration file.

### Configuration

1. Create `packages/cdk/branding.json` with your custom settings:

```json
{
"logoPath": "your-logo.svg",
"title": "Your Custom Title"
}
```

2. Place your custom SVG logo file in `packages/web/src/assets/`:

```
packages/web/src/assets/your-logo.svg
```

### Parameters

- `logoPath` (optional): Filename of the SVG logo in `packages/web/src/assets/`
- `title` (optional): Custom title text to display

### Notes

- If `branding.json` doesn't exist, default AWS logo and title are used
- Only SVG format is supported for custom logos
- The logo will be displayed at 80x80 pixels (size-20 class)

## Security-Related Settings

### Disable Self-Signup
Expand Down
32 changes: 32 additions & 0 deletions docs/ja/DEPLOY_OPTION.md
Original file line number Diff line number Diff line change
Expand Up @@ -1512,6 +1512,38 @@ const envs: Record<string, Partial<StackInput>> = {
}
```

## ブランディングカスタマイズ

ランディングページに表示されるロゴとタイトルをカスタマイズできます。

### 設定方法

1. `packages/cdk/branding.json` にカスタム設定を作成:

```json
{
"logoPath": "your-logo.svg",
"title": "カスタムタイトル"
}
```

2. カスタムSVGロゴファイルを `packages/web/src/assets/` に配置:

```
packages/web/src/assets/your-logo.svg
```

### パラメータ

- `logoPath` (オプション): `packages/web/src/assets/` 内のSVGロゴファイル名
- `title` (オプション): 表示するカスタムタイトルテキスト

### 注意事項

- `branding.json` が存在しない場合、デフォルトのAWSロゴとタイトルが使用されます
- カスタムロゴはSVG形式のみサポートされています
- ロゴは80x80ピクセル(size-20クラス)で表示されます

## セキュリティ関連設定

### セルフサインアップを無効化する
Expand Down
22 changes: 22 additions & 0 deletions packages/cdk/branding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import * as fs from 'fs';
import * as path from 'path';

// Branding configuration interface
interface BrandingConfig {
logoPath?: string;
title?: string;
}

// Load branding configuration from JSON file
export const loadBrandingConfig = (): BrandingConfig => {
const brandingPath = path.join(__dirname, 'branding.json');
try {
if (fs.existsSync(brandingPath)) {
const brandingData = fs.readFileSync(brandingPath, 'utf8');
return JSON.parse(brandingData);
}
} catch (error) {
console.warn('Failed to load branding.json, using defaults:', error);
}
return {};
};
6 changes: 6 additions & 0 deletions packages/cdk/lib/construct/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ export interface WebProps {
readonly agentCoreAgentBuilderRuntime?: AgentCoreConfiguration;
readonly agentCoreExternalRuntimes: AgentCoreConfiguration[];
readonly agentCoreRegion?: string;
readonly brandingConfig?: {
logoPath?: string;
title?: string;
};
}

export class Web extends Construct {
Expand Down Expand Up @@ -307,6 +311,8 @@ export class Web extends Construct {
VITE_APP_AGENT_CORE_EXTERNAL_RUNTIMES: JSON.stringify(
props.agentCoreExternalRuntimes
),
VITE_APP_BRANDING_LOGO_PATH: props.brandingConfig?.logoPath ?? '',
VITE_APP_BRANDING_TITLE: props.brandingConfig?.title ?? '',
},
});
// Enhance computing resources
Expand Down
2 changes: 2 additions & 0 deletions packages/cdk/lib/generative-ai-use-cases-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ export class GenerativeAiUseCasesStack extends Stack {
webBucket: props.webBucket,
cognitoUserPoolProxyEndpoint: props.cognitoUserPoolProxyEndpoint,
cognitoIdentityPoolProxyEndpoint: props.cognitoIdentityPoolProxyEndpoint,
// Branding
brandingConfig: params.brandingConfig,
});

// RAG
Expand Down
7 changes: 7 additions & 0 deletions packages/cdk/lib/stack-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,13 @@ export const processedStackInputSchema = baseStackInputSchema.extend({
),
// Processed agentCoreRegion (null -> modelRegion)
agentCoreRegion: z.string(),
// Branding configuration
brandingConfig: z
.object({
logoPath: z.string().optional(),
title: z.string().optional(),
})
.optional(),
});

export type StackInput = z.infer<typeof stackInputSchema>;
Expand Down
3 changes: 3 additions & 0 deletions packages/cdk/parameter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ProcessedStackInput,
} from './lib/stack-input';
import { ModelConfiguration } from 'generative-ai-use-cases';
import { loadBrandingConfig } from './branding';

// Get parameters from CDK Context
const getContext = (app: cdk.App): StackInput => {
Expand Down Expand Up @@ -77,5 +78,7 @@ export const getParams = (app: cdk.App): ProcessedStackInput => {
),
// Process agentCoreRegion: null -> modelRegion
agentCoreRegion: params.agentCoreRegion || params.modelRegion,
// Load branding configuration
brandingConfig: loadBrandingConfig(),
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -19017,6 +19017,8 @@ exports[`GenerativeAiUseCases matches the snapshot (closed network mode) 6`] = `
],
],
},
"VITE_APP_BRANDING_LOGO_PATH": "",
"VITE_APP_BRANDING_TITLE": "",
"VITE_APP_COGNITO_IDENTITY_POOL_PROXY_ENDPOINT": {
"Fn::Join": [
"",
Expand Down Expand Up @@ -39957,6 +39959,8 @@ exports[`GenerativeAiUseCases matches the snapshot 6`] = `
],
],
},
"VITE_APP_BRANDING_LOGO_PATH": "",
"VITE_APP_BRANDING_TITLE": "",
"VITE_APP_COGNITO_IDENTITY_POOL_PROXY_ENDPOINT": "",
"VITE_APP_COGNITO_USER_POOL_PROXY_ENDPOINT": "",
"VITE_APP_ENDPOINT_NAMES": "[]",
Expand Down
22 changes: 22 additions & 0 deletions packages/web/src/hooks/useBranding.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useMemo } from 'react';

interface BrandingConfig {
logoPath: string;
title: string;
}

const useBranding = (): BrandingConfig => {
const brandingConfig = useMemo(() => {
const logoPath = import.meta.env.VITE_APP_BRANDING_LOGO_PATH;
const title = import.meta.env.VITE_APP_BRANDING_TITLE;

return {
logoPath: logoPath || '',
title: title || '',
};
}, []);

return brandingConfig;
};

export default useBranding;
25 changes: 22 additions & 3 deletions packages/web/src/pages/LandingPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import CardDemo from '../components/CardDemo';
import Button from '../components/Button';
Expand All @@ -23,6 +23,7 @@ import {
} from 'react-icons/pi';
import AwsIcon from '../assets/aws.svg?react';
import useInterUseCases from '../hooks/useInterUseCases';

import {
AgentPageQueryParams,
ChatPageQueryParams,
Expand Down Expand Up @@ -51,6 +52,8 @@ const agentCoreEnabled: boolean =
import.meta.env.VITE_APP_AGENT_CORE_ENABLED === 'true';
const inlineAgents: boolean = import.meta.env.VITE_APP_INLINE_AGENTS === 'true';
const mcpEnabled: boolean = import.meta.env.VITE_APP_MCP_ENABLED === 'true';
const logoPath: string = import.meta.env.VITE_APP_BRANDING_LOGO_PATH || '';
const brandingTitle: string = import.meta.env.VITE_APP_BRANDING_TITLE || '';
const {
imageGenModelIds,
videoGenModelIds,
Expand All @@ -66,6 +69,22 @@ const LandingPage: React.FC = () => {
const { setIsShow, init } = useInterUseCases();
const { t } = useTranslation();

const displayLogo = useMemo(() => {
if (logoPath) {
const logoUrl = new URL(`../assets/${logoPath}`, import.meta.url).href;
return (
<img
src={logoUrl}
alt={brandingTitle || 'Logo'}
className="mr-5 size-20"
/>
);
}
return <AwsIcon className="mr-5 size-20" />;
}, []);

const displayTitle = brandingTitle || t('landing.title');

const demoChat = () => {
const params: ChatPageQueryParams = {
content: t('landing.demo.chat.content'),
Expand Down Expand Up @@ -282,8 +301,8 @@ const LandingPage: React.FC = () => {
return (
<div className="pb-24">
<div className="bg-aws-squid-ink flex flex-col items-center justify-center px-3 py-5 text-xl font-semibold text-white lg:flex-row">
<AwsIcon className="mr-5 size-20" />
{t('landing.title')}
{displayLogo}
{displayTitle}
</div>

<div className="mx-3 mb-6 mt-5 flex flex-col items-center justify-center text-xs lg:flex-row">
Expand Down
2 changes: 2 additions & 0 deletions packages/web/src/vite-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ interface ImportMetaEnv {
readonly VITE_APP_AGENT_CORE_AGENT_BUILDER_ENABLED: string;
readonly VITE_APP_AGENT_CORE_AGENT_BUILDER_RUNTIME: string;
readonly VITE_APP_AGENT_CORE_EXTERNAL_RUNTIMES: string;
readonly VITE_APP_BRANDING_LOGO_PATH: string;
readonly VITE_APP_BRANDING_TITLE: string;
readonly VITE_APP_MCP_SERVERS_CONFIG: string;
}

Expand Down
7 changes: 7 additions & 0 deletions setup-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,10 @@ export VITE_APP_AGENT_CORE_AGENT_BUILDER_ENABLED=$(extract_value "$stack_output"
export VITE_APP_AGENT_CORE_AGENT_BUILDER_RUNTIME=$(extract_value "$stack_output" AgentCoreAgentBuilderRuntime)
export VITE_APP_AGENT_CORE_EXTERNAL_RUNTIMES=$(extract_value "$stack_output" AgentCoreExternalRuntimes)
export VITE_APP_MCP_SERVERS_CONFIG=$(extract_value "$stack_output" McpServersConfig)
if [ -f "packages/cdk/branding.json" ]; then
export VITE_APP_BRANDING_LOGO_PATH=$(cat packages/cdk/branding.json | jq -r '.logoPath // ""')
export VITE_APP_BRANDING_TITLE=$(cat packages/cdk/branding.json | jq -r '.title // ""')
else
export VITE_APP_BRANDING_LOGO_PATH=""
export VITE_APP_BRANDING_TITLE=""
fi