@hua-labs/hua-ux 0.1.0-alpha.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +839 -0
- package/dist/framework/a11y/components/LiveRegion.d.ts +64 -0
- package/dist/framework/a11y/components/LiveRegion.d.ts.map +1 -0
- package/dist/framework/a11y/components/LiveRegion.js +43 -0
- package/dist/framework/a11y/components/SkipToContent.d.ts +62 -0
- package/dist/framework/a11y/components/SkipToContent.d.ts.map +1 -0
- package/dist/framework/a11y/components/SkipToContent.js +60 -0
- package/dist/framework/a11y/hooks/useFocusManagement.d.ts +60 -0
- package/dist/framework/a11y/hooks/useFocusManagement.d.ts.map +1 -0
- package/dist/framework/a11y/hooks/useFocusManagement.js +71 -0
- package/dist/framework/a11y/hooks/useFocusTrap.d.ts +64 -0
- package/dist/framework/a11y/hooks/useFocusTrap.d.ts.map +1 -0
- package/dist/framework/a11y/hooks/useFocusTrap.js +185 -0
- package/dist/framework/a11y/hooks/useLiveRegion.d.ts +56 -0
- package/dist/framework/a11y/hooks/useLiveRegion.d.ts.map +1 -0
- package/dist/framework/a11y/hooks/useLiveRegion.js +60 -0
- package/dist/framework/a11y/index.d.ts +16 -0
- package/dist/framework/a11y/index.d.ts.map +1 -0
- package/dist/framework/a11y/index.js +11 -0
- package/dist/framework/branding/context.d.ts +52 -0
- package/dist/framework/branding/context.d.ts.map +1 -0
- package/dist/framework/branding/context.js +96 -0
- package/dist/framework/branding/css-vars.d.ts +34 -0
- package/dist/framework/branding/css-vars.d.ts.map +1 -0
- package/dist/framework/branding/css-vars.js +95 -0
- package/dist/framework/branding/tailwind-config.d.ts +38 -0
- package/dist/framework/branding/tailwind-config.d.ts.map +1 -0
- package/dist/framework/branding/tailwind-config.js +66 -0
- package/dist/framework/components/BrandedButton.d.ts +53 -0
- package/dist/framework/components/BrandedButton.d.ts.map +1 -0
- package/dist/framework/components/BrandedButton.js +40 -0
- package/dist/framework/components/BrandedCard.d.ts +52 -0
- package/dist/framework/components/BrandedCard.d.ts.map +1 -0
- package/dist/framework/components/BrandedCard.js +73 -0
- package/dist/framework/components/ErrorBoundary.d.ts +92 -0
- package/dist/framework/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/framework/components/ErrorBoundary.js +121 -0
- package/dist/framework/components/HuaUxLayout.d.ts +29 -0
- package/dist/framework/components/HuaUxLayout.d.ts.map +1 -0
- package/dist/framework/components/HuaUxLayout.js +32 -0
- package/dist/framework/components/HuaUxPage.d.ts +48 -0
- package/dist/framework/components/HuaUxPage.d.ts.map +1 -0
- package/dist/framework/components/HuaUxPage.js +105 -0
- package/dist/framework/components/Providers.d.ts +17 -0
- package/dist/framework/components/Providers.d.ts.map +1 -0
- package/dist/framework/components/Providers.js +72 -0
- package/dist/framework/components/WelcomePage.d.ts +44 -0
- package/dist/framework/components/WelcomePage.d.ts.map +1 -0
- package/dist/framework/components/WelcomePage.js +80 -0
- package/dist/framework/config/index.d.ts +182 -0
- package/dist/framework/config/index.d.ts.map +1 -0
- package/dist/framework/config/index.js +329 -0
- package/dist/framework/config/merge.d.ts +26 -0
- package/dist/framework/config/merge.d.ts.map +1 -0
- package/dist/framework/config/merge.js +160 -0
- package/dist/framework/config/schema.d.ts +25 -0
- package/dist/framework/config/schema.d.ts.map +1 -0
- package/dist/framework/config/schema.js +122 -0
- package/dist/framework/hooks/useMotion.d.ts +45 -0
- package/dist/framework/hooks/useMotion.d.ts.map +1 -0
- package/dist/framework/hooks/useMotion.js +40 -0
- package/dist/framework/index.d.ts +37 -0
- package/dist/framework/index.d.ts.map +1 -0
- package/dist/framework/index.js +42 -0
- package/dist/framework/license/errors.d.ts +15 -0
- package/dist/framework/license/errors.d.ts.map +1 -0
- package/dist/framework/license/errors.js +52 -0
- package/dist/framework/license/index.d.ts +70 -0
- package/dist/framework/license/index.d.ts.map +1 -0
- package/dist/framework/license/index.js +124 -0
- package/dist/framework/license/loader.d.ts +26 -0
- package/dist/framework/license/loader.d.ts.map +1 -0
- package/dist/framework/license/loader.js +137 -0
- package/dist/framework/license/types.d.ts +67 -0
- package/dist/framework/license/types.d.ts.map +1 -0
- package/dist/framework/license/types.js +18 -0
- package/dist/framework/loading/components/SkeletonGroup.d.ts +44 -0
- package/dist/framework/loading/components/SkeletonGroup.d.ts.map +1 -0
- package/dist/framework/loading/components/SkeletonGroup.js +34 -0
- package/dist/framework/loading/components/SuspenseWrapper.d.ts +58 -0
- package/dist/framework/loading/components/SuspenseWrapper.d.ts.map +1 -0
- package/dist/framework/loading/components/SuspenseWrapper.js +40 -0
- package/dist/framework/loading/hoc/withSuspense.d.ts +46 -0
- package/dist/framework/loading/hoc/withSuspense.d.ts.map +1 -0
- package/dist/framework/loading/hoc/withSuspense.js +54 -0
- package/dist/framework/loading/hooks/useDelayedLoading.d.ts +56 -0
- package/dist/framework/loading/hooks/useDelayedLoading.d.ts.map +1 -0
- package/dist/framework/loading/hooks/useDelayedLoading.js +97 -0
- package/dist/framework/loading/hooks/useLoadingState.d.ts +69 -0
- package/dist/framework/loading/hooks/useLoadingState.d.ts.map +1 -0
- package/dist/framework/loading/hooks/useLoadingState.js +59 -0
- package/dist/framework/loading/index.d.ts +16 -0
- package/dist/framework/loading/index.d.ts.map +1 -0
- package/dist/framework/loading/index.js +13 -0
- package/dist/framework/middleware/i18n.d.ts +90 -0
- package/dist/framework/middleware/i18n.d.ts.map +1 -0
- package/dist/framework/middleware/i18n.js +99 -0
- package/dist/framework/plugins/index.d.ts +8 -0
- package/dist/framework/plugins/index.d.ts.map +1 -0
- package/dist/framework/plugins/index.js +6 -0
- package/dist/framework/plugins/registry.d.ts +95 -0
- package/dist/framework/plugins/registry.d.ts.map +1 -0
- package/dist/framework/plugins/registry.js +160 -0
- package/dist/framework/plugins/types.d.ts +97 -0
- package/dist/framework/plugins/types.d.ts.map +1 -0
- package/dist/framework/plugins/types.js +6 -0
- package/dist/framework/seo/geo/examples.d.ts +87 -0
- package/dist/framework/seo/geo/examples.d.ts.map +1 -0
- package/dist/framework/seo/geo/examples.js +295 -0
- package/dist/framework/seo/geo/generateGEOMetadata.d.ts +107 -0
- package/dist/framework/seo/geo/generateGEOMetadata.d.ts.map +1 -0
- package/dist/framework/seo/geo/generateGEOMetadata.js +404 -0
- package/dist/framework/seo/geo/index.d.ts +19 -0
- package/dist/framework/seo/geo/index.d.ts.map +1 -0
- package/dist/framework/seo/geo/index.js +21 -0
- package/dist/framework/seo/geo/presets.d.ts +52 -0
- package/dist/framework/seo/geo/presets.d.ts.map +1 -0
- package/dist/framework/seo/geo/presets.js +47 -0
- package/dist/framework/seo/geo/structuredData.d.ts +187 -0
- package/dist/framework/seo/geo/structuredData.d.ts.map +1 -0
- package/dist/framework/seo/geo/structuredData.js +354 -0
- package/dist/framework/seo/geo/test-utils.d.ts +78 -0
- package/dist/framework/seo/geo/test-utils.d.ts.map +1 -0
- package/dist/framework/seo/geo/test-utils.js +139 -0
- package/dist/framework/seo/geo/types.d.ts +225 -0
- package/dist/framework/seo/geo/types.d.ts.map +1 -0
- package/dist/framework/seo/geo/types.js +51 -0
- package/dist/framework/types/index.d.ts +577 -0
- package/dist/framework/types/index.d.ts.map +1 -0
- package/dist/framework/types/index.js +6 -0
- package/dist/framework/utils/data-fetching.d.ts +45 -0
- package/dist/framework/utils/data-fetching.d.ts.map +1 -0
- package/dist/framework/utils/data-fetching.js +74 -0
- package/dist/framework/utils/file-structure.d.ts +29 -0
- package/dist/framework/utils/file-structure.d.ts.map +1 -0
- package/dist/framework/utils/file-structure.js +72 -0
- package/dist/framework/utils/metadata.d.ts +109 -0
- package/dist/framework/utils/metadata.d.ts.map +1 -0
- package/dist/framework/utils/metadata.js +105 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/presets/index.d.ts +8 -0
- package/dist/presets/index.d.ts.map +1 -0
- package/dist/presets/index.js +7 -0
- package/dist/presets/marketing.d.ts +41 -0
- package/dist/presets/marketing.d.ts.map +1 -0
- package/dist/presets/marketing.js +81 -0
- package/dist/presets/product.d.ts +41 -0
- package/dist/presets/product.d.ts.map +1 -0
- package/dist/presets/product.js +74 -0
- package/package.json +91 -0
- package/src/framework/README.md +329 -0
- package/src/framework/__tests__/branding/css-vars.test.ts +147 -0
- package/src/framework/__tests__/components/ErrorBoundary.test.tsx +146 -0
- package/src/framework/__tests__/config/defineConfig.test.ts +138 -0
- package/src/framework/__tests__/hooks/useMotion.test.ts +105 -0
- package/src/framework/__tests__/seo/geo/generateGEOMetadata.test.ts +207 -0
- package/src/framework/__tests__/seo/geo/structuredData.test.ts +262 -0
- package/src/framework/a11y/components/LiveRegion.tsx +89 -0
- package/src/framework/a11y/components/SkipToContent.tsx +103 -0
- package/src/framework/a11y/hooks/useFocusManagement.ts +125 -0
- package/src/framework/a11y/hooks/useFocusTrap.ts +239 -0
- package/src/framework/a11y/hooks/useLiveRegion.ts +95 -0
- package/src/framework/a11y/index.ts +17 -0
- package/src/framework/branding/context.tsx +135 -0
- package/src/framework/branding/css-vars.ts +110 -0
- package/src/framework/branding/tailwind-config.ts +90 -0
- package/src/framework/components/BrandedButton.tsx +94 -0
- package/src/framework/components/BrandedCard.tsx +87 -0
- package/src/framework/components/ErrorBoundary.tsx +215 -0
- package/src/framework/components/HuaUxLayout.tsx +36 -0
- package/src/framework/components/HuaUxPage.tsx +138 -0
- package/src/framework/components/Providers.tsx +98 -0
- package/src/framework/components/WelcomePage.tsx +207 -0
- package/src/framework/config/index.ts +349 -0
- package/src/framework/config/merge.ts +190 -0
- package/src/framework/config/schema.ts +140 -0
- package/src/framework/hooks/useMotion.ts +57 -0
- package/src/framework/index.ts +122 -0
- package/src/framework/license/errors.ts +63 -0
- package/src/framework/license/index.ts +137 -0
- package/src/framework/license/loader.ts +158 -0
- package/src/framework/license/types.ts +95 -0
- package/src/framework/loading/components/SkeletonGroup.tsx +70 -0
- package/src/framework/loading/components/SuspenseWrapper.tsx +88 -0
- package/src/framework/loading/hoc/withSuspense.tsx +96 -0
- package/src/framework/loading/hooks/useDelayedLoading.ts +127 -0
- package/src/framework/loading/hooks/useLoadingState.ts +103 -0
- package/src/framework/loading/index.ts +19 -0
- package/src/framework/middleware/i18n.ts +161 -0
- package/src/framework/middleware/index.ts +7 -0
- package/src/framework/plugins/index.ts +13 -0
- package/src/framework/plugins/registry.ts +186 -0
- package/src/framework/plugins/types.ts +106 -0
- package/src/framework/seo/geo/examples.tsx +415 -0
- package/src/framework/seo/geo/generateGEOMetadata.ts +441 -0
- package/src/framework/seo/geo/index.ts +61 -0
- package/src/framework/seo/geo/presets.ts +58 -0
- package/src/framework/seo/geo/structuredData.ts +422 -0
- package/src/framework/seo/geo/test-utils.ts +179 -0
- package/src/framework/seo/geo/types.ts +315 -0
- package/src/framework/types/index.ts +623 -0
- package/src/framework/utils/data-fetching.ts +95 -0
- package/src/framework/utils/file-structure.ts +88 -0
- package/src/framework/utils/metadata.ts +152 -0
- package/src/index.ts +31 -0
- package/src/presets/index.ts +8 -0
- package/src/presets/marketing.ts +88 -0
- package/src/presets/product.ts +81 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hua-labs/hua-ux/framework - Plugin Types
|
|
3
|
+
*
|
|
4
|
+
* 플러그인 타입 정의
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { ComponentType } from 'react';
|
|
8
|
+
import type { HuaUxConfig } from '../types';
|
|
9
|
+
import type { LicenseType } from '../license/types';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 플러그인 인터페이스 / Plugin interface
|
|
13
|
+
*/
|
|
14
|
+
export interface HuaUxPlugin {
|
|
15
|
+
/**
|
|
16
|
+
* 플러그인 이름 / Plugin name
|
|
17
|
+
*
|
|
18
|
+
* 고유한 식별자로 사용됩니다.
|
|
19
|
+
* Used as a unique identifier.
|
|
20
|
+
*/
|
|
21
|
+
name: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 플러그인 버전 / Plugin version
|
|
25
|
+
*
|
|
26
|
+
* Semantic versioning 형식 (예: '1.0.0')
|
|
27
|
+
* Semantic versioning format (e.g., '1.0.0')
|
|
28
|
+
*/
|
|
29
|
+
version: string;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 라이선스 타입 / License type
|
|
33
|
+
*
|
|
34
|
+
* 이 플러그인이 필요한 라이선스 타입
|
|
35
|
+
* Required license type for this plugin
|
|
36
|
+
*/
|
|
37
|
+
license: LicenseType;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 플러그인 초기화 / Plugin initialization
|
|
41
|
+
*
|
|
42
|
+
* 플러그인이 등록될 때 호출됩니다.
|
|
43
|
+
* Called when the plugin is registered.
|
|
44
|
+
*
|
|
45
|
+
* @param config - 프레임워크 설정
|
|
46
|
+
*/
|
|
47
|
+
init?(config: HuaUxConfig): void | Promise<void>;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* 컴포넌트 확장 / Component extensions
|
|
51
|
+
*
|
|
52
|
+
* 플러그인이 제공하는 컴포넌트들
|
|
53
|
+
* Components provided by the plugin
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* components: {
|
|
58
|
+
* ParallaxScroll: ParallaxScrollComponent,
|
|
59
|
+
* Motion3D: Motion3DComponent,
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
components?: Record<string, ComponentType<any>>;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 훅 확장 / Hook extensions
|
|
67
|
+
*
|
|
68
|
+
* 플러그인이 제공하는 커스텀 훅들
|
|
69
|
+
* Custom hooks provided by the plugin
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* hooks: {
|
|
74
|
+
* useParallax: useParallaxHook,
|
|
75
|
+
* useMotion3D: useMotion3DHook,
|
|
76
|
+
* }
|
|
77
|
+
* ```
|
|
78
|
+
*/
|
|
79
|
+
hooks?: Record<string, Function>;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* 설정 스키마 확장 / Config schema extension
|
|
83
|
+
*
|
|
84
|
+
* 플러그인이 추가하는 설정 스키마 (향후 Zod 스키마 지원)
|
|
85
|
+
* Additional config schema added by the plugin (future Zod schema support)
|
|
86
|
+
*/
|
|
87
|
+
configSchema?: any; // 향후 ZodSchema로 변경
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* 라이선스 검증 / License validation
|
|
91
|
+
*
|
|
92
|
+
* 플러그인 등록 시 라이선스를 검증하는 함수
|
|
93
|
+
* Function to validate license when plugin is registered
|
|
94
|
+
*
|
|
95
|
+
* @returns 라이선스 유효 여부
|
|
96
|
+
*/
|
|
97
|
+
checkLicense?(): boolean;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* 플러그인 설명 / Plugin description
|
|
101
|
+
*
|
|
102
|
+
* 플러그인의 기능 설명
|
|
103
|
+
* Description of plugin features
|
|
104
|
+
*/
|
|
105
|
+
description?: string;
|
|
106
|
+
}
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hua-labs/hua-ux/framework - GEO Usage Examples
|
|
3
|
+
*
|
|
4
|
+
* Examples of using GEO (Generative Engine Optimization) to make your
|
|
5
|
+
* application discoverable by AI search engines
|
|
6
|
+
*
|
|
7
|
+
* AI 검색 엔진이 애플리케이션을 잘 찾고 추천하도록 GEO 사용 예시
|
|
8
|
+
*
|
|
9
|
+
* These examples demonstrate various use cases including:
|
|
10
|
+
* - Basic GEO configuration
|
|
11
|
+
* - Using presets
|
|
12
|
+
* - Error handling
|
|
13
|
+
* - Dynamic content
|
|
14
|
+
* - Minimal configuration
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import Script from 'next/script';
|
|
18
|
+
import { generateGEOMetadata, renderJSONLD, createAIContext } from './generateGEOMetadata';
|
|
19
|
+
import { generateFAQPageLD, generateHowToLD } from './structuredData';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Example 1: Basic GEO for a software project
|
|
23
|
+
*
|
|
24
|
+
* AI 검색 엔진이 소프트웨어 프로젝트를 정확하게 이해하도록 기본 GEO 메타데이터 생성
|
|
25
|
+
*/
|
|
26
|
+
export function Example1_BasicGEO() {
|
|
27
|
+
const geoMetadata = generateGEOMetadata({
|
|
28
|
+
name: 'hua-ux',
|
|
29
|
+
alternateName: ['@hua-labs/hua-ux', 'hua UX framework'],
|
|
30
|
+
description:
|
|
31
|
+
'Privacy-first UX framework for Next.js with built-in i18n, motion, and accessibility',
|
|
32
|
+
version: '1.0.0',
|
|
33
|
+
applicationCategory: ['UX Framework', 'Developer Tool'],
|
|
34
|
+
programmingLanguage: ['TypeScript', 'React', 'Next.js'],
|
|
35
|
+
applicationType: 'DeveloperApplication',
|
|
36
|
+
url: 'https://hua-labs.dev',
|
|
37
|
+
documentationUrl: 'https://hua-labs.dev/docs/hua-ux',
|
|
38
|
+
codeRepository: 'https://github.com/hua-labs/hua',
|
|
39
|
+
license: 'MIT',
|
|
40
|
+
author: {
|
|
41
|
+
name: 'hua-labs',
|
|
42
|
+
url: 'https://hua-labs.dev',
|
|
43
|
+
},
|
|
44
|
+
features: [
|
|
45
|
+
'Privacy-first architecture (no tracking, no analytics by default)',
|
|
46
|
+
'Built-in internationalization (i18n) with hua-i18n',
|
|
47
|
+
'Smooth motion animations with hua-motion',
|
|
48
|
+
'WCAG 2.1 compliant accessibility features',
|
|
49
|
+
'Automatic error handling with ErrorBoundary',
|
|
50
|
+
'Loading state optimization (300ms flicker prevention)',
|
|
51
|
+
'AI-friendly documentation (Korean/English bilingual)',
|
|
52
|
+
],
|
|
53
|
+
useCases: [
|
|
54
|
+
'Building multilingual Next.js applications',
|
|
55
|
+
'Creating accessible web applications',
|
|
56
|
+
'Rapid prototyping with privacy-first defaults',
|
|
57
|
+
'Enterprise applications requiring WCAG compliance',
|
|
58
|
+
],
|
|
59
|
+
keywords: [
|
|
60
|
+
'nextjs',
|
|
61
|
+
'react',
|
|
62
|
+
'ux framework',
|
|
63
|
+
'i18n',
|
|
64
|
+
'internationalization',
|
|
65
|
+
'accessibility',
|
|
66
|
+
'a11y',
|
|
67
|
+
'wcag',
|
|
68
|
+
'motion',
|
|
69
|
+
'animation',
|
|
70
|
+
'privacy',
|
|
71
|
+
'gdpr',
|
|
72
|
+
'typescript',
|
|
73
|
+
],
|
|
74
|
+
softwareRequirements: ['Next.js 14+', 'React 18+', 'TypeScript 5+'],
|
|
75
|
+
operatingSystem: ['Windows', 'macOS', 'Linux'],
|
|
76
|
+
relatedTo: [
|
|
77
|
+
'Next.js',
|
|
78
|
+
'React',
|
|
79
|
+
'hua-i18n',
|
|
80
|
+
'hua-motion',
|
|
81
|
+
'hua-state',
|
|
82
|
+
'Tailwind CSS',
|
|
83
|
+
],
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<head>
|
|
88
|
+
{/* Meta tags */}
|
|
89
|
+
{geoMetadata.meta.map((meta) => (
|
|
90
|
+
<meta key={meta.name} name={meta.name} content={meta.content} />
|
|
91
|
+
))}
|
|
92
|
+
|
|
93
|
+
{/* Open Graph tags */}
|
|
94
|
+
{geoMetadata.openGraph?.map((og) => (
|
|
95
|
+
<meta key={og.property} property={og.property} content={og.content} />
|
|
96
|
+
))}
|
|
97
|
+
|
|
98
|
+
{/* Twitter Card tags */}
|
|
99
|
+
{geoMetadata.twitter?.map((tw) => (
|
|
100
|
+
<meta key={tw.name} name={tw.name} content={tw.content} />
|
|
101
|
+
))}
|
|
102
|
+
|
|
103
|
+
{/* JSON-LD structured data */}
|
|
104
|
+
{geoMetadata.jsonLd.map((ld, index) => (
|
|
105
|
+
<Script key={index} {...renderJSONLD(ld)} />
|
|
106
|
+
))}
|
|
107
|
+
</head>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Example 2: Next.js App Router metadata
|
|
113
|
+
*
|
|
114
|
+
* Next.js App Router의 generateMetadata()와 함께 사용
|
|
115
|
+
*/
|
|
116
|
+
export async function Example2_NextjsMetadata() {
|
|
117
|
+
const geoMeta = generateGEOMetadata({
|
|
118
|
+
name: 'My App',
|
|
119
|
+
description: 'Built with hua-ux for privacy-first UX',
|
|
120
|
+
features: ['i18n', 'Dark mode', 'Responsive design'],
|
|
121
|
+
keywords: ['nextjs', 'react', 'privacy', 'accessibility'],
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Next.js Metadata 객체로 변환
|
|
125
|
+
return {
|
|
126
|
+
title: 'My App',
|
|
127
|
+
description: geoMeta.meta.find((m) => m.name === 'description')?.content,
|
|
128
|
+
keywords: geoMeta.meta.find((m) => m.name === 'keywords')?.content,
|
|
129
|
+
openGraph: {
|
|
130
|
+
title: geoMeta.openGraph?.find((og) => og.property === 'og:title')?.content,
|
|
131
|
+
description: geoMeta.openGraph?.find((og) => og.property === 'og:description')
|
|
132
|
+
?.content,
|
|
133
|
+
},
|
|
134
|
+
// JSON-LD는 layout.tsx나 page.tsx에서 Script 컴포넌트로 추가
|
|
135
|
+
other: {
|
|
136
|
+
'script:ld+json': JSON.stringify(geoMeta.jsonLd),
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Example 3: FAQ Page with structured data
|
|
143
|
+
*
|
|
144
|
+
* AI가 자주 묻는 질문에 답변할 수 있도록 FAQ 구조화된 데이터 추가
|
|
145
|
+
*/
|
|
146
|
+
export function Example3_FAQPage() {
|
|
147
|
+
const faqLd = generateFAQPageLD([
|
|
148
|
+
{
|
|
149
|
+
question: 'What is hua-ux?',
|
|
150
|
+
answer:
|
|
151
|
+
'hua-ux is a privacy-first UX framework for Next.js applications. It provides built-in internationalization (i18n), motion animations, accessibility features (WCAG 2.1 compliant), automatic error handling, and loading state optimization.',
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
question: 'How do I install hua-ux?',
|
|
155
|
+
answer:
|
|
156
|
+
'You can create a new hua-ux project using the CLI: npx create-hua-ux my-app. Or install it in an existing Next.js project: pnpm add @hua-labs/hua-ux',
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
question: 'Is hua-ux free to use?',
|
|
160
|
+
answer:
|
|
161
|
+
'Yes, hua-ux is open-source and available under the MIT license. You can use it freely in both personal and commercial projects.',
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
question: 'What makes hua-ux privacy-first?',
|
|
165
|
+
answer:
|
|
166
|
+
'hua-ux has no tracking, no analytics, and no data collection by default. It respects user privacy and follows GDPR/CCPA principles. You have full control over what data your application collects.',
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
question: 'Does hua-ux support TypeScript?',
|
|
170
|
+
answer:
|
|
171
|
+
'Yes, hua-ux is written in TypeScript and provides full type safety. All components, hooks, and utilities come with TypeScript definitions.',
|
|
172
|
+
},
|
|
173
|
+
]);
|
|
174
|
+
|
|
175
|
+
return (
|
|
176
|
+
<head>
|
|
177
|
+
<Script {...renderJSONLD(faqLd)} />
|
|
178
|
+
</head>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Example 4: HowTo Guide with structured data
|
|
184
|
+
*
|
|
185
|
+
* AI가 튜토리얼을 이해하고 추천할 수 있도록 HowTo 구조화된 데이터 추가
|
|
186
|
+
*/
|
|
187
|
+
export function Example4_HowToGuide() {
|
|
188
|
+
const howToLd = generateHowToLD({
|
|
189
|
+
name: 'How to add internationalization (i18n) to your Next.js app with hua-ux',
|
|
190
|
+
description:
|
|
191
|
+
'Step-by-step guide to implementing multilingual support in your Next.js application using hua-ux',
|
|
192
|
+
totalTime: 'PT10M', // 10 minutes
|
|
193
|
+
steps: [
|
|
194
|
+
{
|
|
195
|
+
name: 'Create a new hua-ux project',
|
|
196
|
+
text: 'Run the CLI command: npx create-hua-ux my-app. This creates a new Next.js project with hua-ux pre-configured.',
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: 'Configure supported locales',
|
|
200
|
+
text: 'Edit hua.config.ts and add your locales to the i18n.locales array. For example: locales: ["en", "ko", "ja"]',
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
name: 'Create translation files',
|
|
204
|
+
text: 'Add JSON translation files in the messages/ directory. Create one file per locale: messages/en.json, messages/ko.json, etc.',
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
name: 'Use translations in components',
|
|
208
|
+
text: 'Import useI18n hook and use the t() function to translate text: const { t } = useI18n(); return <h1>{t("welcome")}</h1>',
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
name: 'Add language switcher',
|
|
212
|
+
text: 'Use the LocaleSwitcher component to let users change languages: <LocaleSwitcher />',
|
|
213
|
+
},
|
|
214
|
+
],
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
return (
|
|
218
|
+
<head>
|
|
219
|
+
<Script {...renderJSONLD(howToLd)} />
|
|
220
|
+
</head>
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Example 5: AI Context for Chatbots
|
|
226
|
+
*
|
|
227
|
+
* ChatGPT, Claude 같은 AI 챗봇이 맥락을 이해하기 쉬운 설명 생성
|
|
228
|
+
*/
|
|
229
|
+
export function Example5_AIContext() {
|
|
230
|
+
const context = createAIContext({
|
|
231
|
+
name: 'hua-ux',
|
|
232
|
+
description: 'Privacy-first UX framework for Next.js',
|
|
233
|
+
features: [
|
|
234
|
+
'Internationalization (i18n)',
|
|
235
|
+
'Motion animations',
|
|
236
|
+
'WCAG 2.1 accessibility',
|
|
237
|
+
'Error boundaries',
|
|
238
|
+
'Loading state optimization',
|
|
239
|
+
],
|
|
240
|
+
useCases: [
|
|
241
|
+
'Multilingual web applications',
|
|
242
|
+
'Accessible enterprise applications',
|
|
243
|
+
'Privacy-compliant consumer apps',
|
|
244
|
+
],
|
|
245
|
+
programmingLanguage: ['TypeScript', 'React', 'Next.js'],
|
|
246
|
+
softwareRequirements: ['Next.js 14+', 'React 18+'],
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// Returns:
|
|
250
|
+
// "hua-ux is a Privacy-first UX framework for Next.js. Key features include:
|
|
251
|
+
// Internationalization (i18n), Motion animations, WCAG 2.1 accessibility, Error
|
|
252
|
+
// boundaries, Loading state optimization. Common use cases: Multilingual web
|
|
253
|
+
// applications, Accessible enterprise applications, Privacy-compliant consumer
|
|
254
|
+
// apps. Built with: TypeScript, React, Next.js. Requires: Next.js 14+, React 18+."
|
|
255
|
+
|
|
256
|
+
return (
|
|
257
|
+
<head>
|
|
258
|
+
<meta name="ai:context" content={context} />
|
|
259
|
+
</head>
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Example 6: Complete landing page with full GEO
|
|
265
|
+
*
|
|
266
|
+
* 모든 GEO 기능을 사용한 완전한 랜딩 페이지 예시
|
|
267
|
+
*/
|
|
268
|
+
export function Example6_CompleteLandingPage() {
|
|
269
|
+
// Software metadata
|
|
270
|
+
const geoMeta = generateGEOMetadata({
|
|
271
|
+
name: 'hua-ux',
|
|
272
|
+
description: 'Privacy-first UX framework for Next.js',
|
|
273
|
+
version: '1.0.0',
|
|
274
|
+
applicationCategory: 'UX Framework',
|
|
275
|
+
programmingLanguage: 'TypeScript',
|
|
276
|
+
features: ['i18n', 'Motion', 'Accessibility', 'Error handling', 'Loading optimization'],
|
|
277
|
+
keywords: ['nextjs', 'react', 'ux', 'i18n', 'accessibility', 'privacy'],
|
|
278
|
+
codeRepository: 'https://github.com/hua-labs/hua',
|
|
279
|
+
license: 'MIT',
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
// FAQ structured data
|
|
283
|
+
const faqLd = generateFAQPageLD([
|
|
284
|
+
{ question: 'What is hua-ux?', answer: 'Privacy-first UX framework for Next.js' },
|
|
285
|
+
{ question: 'How to install?', answer: 'npx create-hua-ux my-app' },
|
|
286
|
+
]);
|
|
287
|
+
|
|
288
|
+
// HowTo guide
|
|
289
|
+
const howToLd = generateHowToLD({
|
|
290
|
+
name: 'Getting started with hua-ux',
|
|
291
|
+
steps: [
|
|
292
|
+
{ name: 'Install', text: 'npx create-hua-ux my-app' },
|
|
293
|
+
{ name: 'Configure', text: 'Edit hua.config.ts' },
|
|
294
|
+
{ name: 'Build', text: 'pnpm dev' },
|
|
295
|
+
],
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
// AI context
|
|
299
|
+
const aiContext = createAIContext({
|
|
300
|
+
name: 'hua-ux',
|
|
301
|
+
description: 'Privacy-first UX framework',
|
|
302
|
+
features: ['i18n', 'Motion', 'Accessibility'],
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
return (
|
|
306
|
+
<html>
|
|
307
|
+
<head>
|
|
308
|
+
{/* Basic metadata */}
|
|
309
|
+
{geoMeta.meta.map((meta) => (
|
|
310
|
+
<meta key={meta.name} name={meta.name} content={meta.content} />
|
|
311
|
+
))}
|
|
312
|
+
|
|
313
|
+
{/* Open Graph */}
|
|
314
|
+
{geoMeta.openGraph?.map((og) => (
|
|
315
|
+
<meta key={og.property} property={og.property} content={og.content} />
|
|
316
|
+
))}
|
|
317
|
+
|
|
318
|
+
{/* Twitter Card */}
|
|
319
|
+
{geoMeta.twitter?.map((tw) => (
|
|
320
|
+
<meta key={tw.name} name={tw.name} content={tw.content} />
|
|
321
|
+
))}
|
|
322
|
+
|
|
323
|
+
{/* AI context */}
|
|
324
|
+
<meta name="ai:context" content={aiContext} />
|
|
325
|
+
|
|
326
|
+
{/* Structured data */}
|
|
327
|
+
<Script {...renderJSONLD(geoMeta.jsonLd[0])} />
|
|
328
|
+
<Script {...renderJSONLD(faqLd)} />
|
|
329
|
+
<Script {...renderJSONLD(howToLd)} />
|
|
330
|
+
</head>
|
|
331
|
+
<body>{/* Your content */}</body>
|
|
332
|
+
</html>
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Example 7: Minimal Configuration
|
|
338
|
+
*
|
|
339
|
+
* 최소한의 설정으로 GEO 메타데이터 생성
|
|
340
|
+
* Shows minimum required fields
|
|
341
|
+
*/
|
|
342
|
+
export function Example7_MinimalConfig() {
|
|
343
|
+
const geoMeta = generateGEOMetadata({
|
|
344
|
+
name: 'My App',
|
|
345
|
+
description: 'A simple app',
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
return (
|
|
349
|
+
<>
|
|
350
|
+
<Script {...renderJSONLD(geoMeta.jsonLd[0])} />
|
|
351
|
+
<main>
|
|
352
|
+
<h1>Minimal GEO Configuration</h1>
|
|
353
|
+
<p>Only name and description are required.</p>
|
|
354
|
+
</main>
|
|
355
|
+
</>
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Example 8: Error Handling
|
|
361
|
+
*
|
|
362
|
+
* 에러 처리 예제
|
|
363
|
+
* Shows how to handle validation errors
|
|
364
|
+
*/
|
|
365
|
+
export function Example8_ErrorHandling() {
|
|
366
|
+
try {
|
|
367
|
+
const geoMeta = generateGEOMetadata({
|
|
368
|
+
name: '', // Invalid!
|
|
369
|
+
description: 'Test',
|
|
370
|
+
});
|
|
371
|
+
return <div>Success</div>;
|
|
372
|
+
} catch (error) {
|
|
373
|
+
console.error('GEO metadata generation failed:', error);
|
|
374
|
+
return (
|
|
375
|
+
<div>
|
|
376
|
+
<h1>Error</h1>
|
|
377
|
+
<p>{(error as Error).message}</p>
|
|
378
|
+
</div>
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Example 9: Dynamic Content
|
|
385
|
+
*
|
|
386
|
+
* 동적 콘텐츠를 사용한 GEO 메타데이터 생성
|
|
387
|
+
* Shows how to use dynamic data
|
|
388
|
+
*/
|
|
389
|
+
export function Example9_DynamicContent({
|
|
390
|
+
title,
|
|
391
|
+
features,
|
|
392
|
+
}: {
|
|
393
|
+
title: string;
|
|
394
|
+
features: string[];
|
|
395
|
+
}) {
|
|
396
|
+
const geoMeta = generateGEOMetadata({
|
|
397
|
+
name: title,
|
|
398
|
+
description: `App with ${features.length} features`,
|
|
399
|
+
features,
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
return (
|
|
403
|
+
<>
|
|
404
|
+
<Script {...renderJSONLD(geoMeta.jsonLd[0])} />
|
|
405
|
+
<main>
|
|
406
|
+
<h1>{title}</h1>
|
|
407
|
+
<ul>
|
|
408
|
+
{features.map((feature, i) => (
|
|
409
|
+
<li key={i}>{feature}</li>
|
|
410
|
+
))}
|
|
411
|
+
</ul>
|
|
412
|
+
</main>
|
|
413
|
+
</>
|
|
414
|
+
);
|
|
415
|
+
}
|