mirror of
https://github.com/iflytek/skillhub.git
synced 2026-10-09 03:17:52 +00:00
Quick Start
This commit is contained in:
parent
bd83f91648
commit
bbd416ceca
7 changed files with 469 additions and 11 deletions
|
|
@ -8,6 +8,40 @@ description: ClawHub CLI 协议兼容层
|
|||
|
||||
SkillHub 提供 ClawHub CLI 协议兼容层,现有工具可无缝迁移。
|
||||
|
||||
## 配置 ClawHub CLI
|
||||
|
||||
要让 ClawHub CLI 连接到你的 SkillHub 实例,需要配置以下环境变量:
|
||||
|
||||
### 环境变量配置
|
||||
|
||||
**Linux/macOS (bash/zsh):**
|
||||
```bash
|
||||
# ~/.bashrc 或 ~/.zshrc
|
||||
export CLAWHUB_SITE=https://skill.xfyun.cn
|
||||
export CLAWHUB_REGISTRY=https://skill.xfyun.cn
|
||||
```
|
||||
|
||||
**Windows (PowerShell):**
|
||||
```powershell
|
||||
# 永久设置(当前用户)
|
||||
[Environment]::SetEnvironmentVariable('CLAWHUB_SITE', 'https://skill.xfyun.cn', 'User')
|
||||
[Environment]::SetEnvironmentVariable('CLAWHUB_REGISTRY', 'https://skill.xfyun.cn', 'User')
|
||||
|
||||
# 或者临时设置(当前会话)
|
||||
$env:CLAWHUB_SITE = 'https://skill.xfyun.cn'
|
||||
$env:CLAWHUB_REGISTRY = 'https://skill.xfyun.cn'
|
||||
```
|
||||
|
||||
### 使用 CLI 标志(单次命令)
|
||||
|
||||
```bash
|
||||
clawhub --site https://skill.xfyun.cn --registry https://skill.xfyun.cn install <skill>
|
||||
```
|
||||
|
||||
### 前端一键复制
|
||||
|
||||
SkillHub 网页端的技能详情页会自动显示带有正确环境变量的安装命令,直接复制即可使用。
|
||||
|
||||
## Well-known 发现
|
||||
|
||||
```http
|
||||
|
|
|
|||
|
|
@ -8,6 +8,40 @@ description: ClawHub CLI protocol compatibility layer
|
|||
|
||||
SkillHub provides a ClawHub CLI protocol compatibility layer for seamless migration of existing tools.
|
||||
|
||||
## Configuring ClawHub CLI
|
||||
|
||||
To connect ClawHub CLI to your SkillHub instance, configure the following environment variables:
|
||||
|
||||
### Environment Variable Configuration
|
||||
|
||||
**Linux/macOS (bash/zsh):**
|
||||
```bash
|
||||
# ~/.bashrc or ~/.zshrc
|
||||
export CLAWHUB_SITE=https://skill.xfyun.cn
|
||||
export CLAWHUB_REGISTRY=https://skill.xfyun.cn
|
||||
```
|
||||
|
||||
**Windows (PowerShell):**
|
||||
```powershell
|
||||
# Permanent setting (current user)
|
||||
[Environment]::SetEnvironmentVariable('CLAWHUB_SITE', 'https://skill.xfyun.cn', 'User')
|
||||
[Environment]::SetEnvironmentVariable('CLAWHUB_REGISTRY', 'https://skill.xfyun.cn', 'User')
|
||||
|
||||
# Or temporary setting (current session)
|
||||
$env:CLAWHUB_SITE = 'https://skill.xfyun.cn'
|
||||
$env:CLAWHUB_REGISTRY = 'https://skill.xfyun.cn'
|
||||
```
|
||||
|
||||
### Using CLI Flags (Single Command)
|
||||
|
||||
```bash
|
||||
clawhub --site https://skill.xfyun.cn --registry https://skill.xfyun.cn install <skill>
|
||||
```
|
||||
|
||||
### One-click Copy from Web UI
|
||||
|
||||
The SkillHub skill detail page automatically displays install commands with the correct environment variables pre-configured. Simply copy and use.
|
||||
|
||||
## Well-known Discovery
|
||||
|
||||
```http
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useState } from 'react'
|
||||
import { useState, useMemo } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Check, Copy } from 'lucide-react'
|
||||
import { Button } from '@/shared/ui/button'
|
||||
|
|
@ -9,12 +9,32 @@ interface InstallCommandProps {
|
|||
version?: string
|
||||
}
|
||||
|
||||
function getAppBaseUrl(): string {
|
||||
if (typeof window === 'undefined') {
|
||||
return ''
|
||||
}
|
||||
const runtimeConfig = window.__SKILLHUB_RUNTIME_CONFIG__
|
||||
if (runtimeConfig?.appBaseUrl) {
|
||||
return runtimeConfig.appBaseUrl
|
||||
}
|
||||
return `${window.location.protocol}//${window.location.host}`
|
||||
}
|
||||
|
||||
export function InstallCommand({ namespace, slug, version }: InstallCommandProps) {
|
||||
const { t } = useTranslation()
|
||||
const [copied, setCopied] = useState(false)
|
||||
const command = version
|
||||
? `clawhub install ${namespace}/${slug}@${version}`
|
||||
: `clawhub install ${namespace}/${slug}`
|
||||
|
||||
const baseUrl = useMemo(() => getAppBaseUrl(), [])
|
||||
|
||||
const cleanNamespace = namespace.startsWith('@') ? namespace.slice(1) : namespace
|
||||
const command = useMemo(() => {
|
||||
const installCmd = `clawhub install ${slug} `
|
||||
// 如果是默认的 clawhub.ai 不需要环境变量,否则显示完整配置
|
||||
if (baseUrl && !baseUrl.includes('clawhub.ai') && !baseUrl.includes('localhost') && !baseUrl.includes('127.0.0.1')) {
|
||||
return `CLAWHUB_SITE=${baseUrl} CLAWHUB_REGISTRY=${baseUrl} ${installCmd}`
|
||||
}
|
||||
return installCmd
|
||||
}, [cleanNamespace, slug, version, baseUrl])
|
||||
|
||||
const handleCopy = async () => {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -69,7 +69,29 @@
|
|||
"footerLicense": "© 2026 SkillHub. Apache License 2.0.",
|
||||
"footerDocs": "Docs",
|
||||
"footerGithub": "GitHub",
|
||||
"footerCommunity": "Community"
|
||||
"footerCommunity": "Community",
|
||||
"quickStart": {
|
||||
"title": "Quick Start",
|
||||
"subtitle": "快速开始",
|
||||
"description": "Get started with SkillHub in just a few simple steps",
|
||||
"tip": "💡 Tip: Visit the skill detail page for one-click install commands with environment variables",
|
||||
"steps": {
|
||||
"configureEnv": {
|
||||
"title": "1. Configure Environment Variables",
|
||||
"description": "Configure ClawHub CLI to connect to SkillHub"
|
||||
},
|
||||
"installSkills": {
|
||||
"title": "2. Install Skills",
|
||||
"description": "Search and install the skills you need",
|
||||
"code": "# Search skills\nclawhub search <keyword>\n\n# Install skill\nclawhub install <skill>"
|
||||
},
|
||||
"publishSkills": {
|
||||
"title": "3. Publish Skills",
|
||||
"description": "Share your skills with the team",
|
||||
"code": "# Publish skill\nclawhub publish\n\n# Or use web interface\n# Click \"Publish Skill\""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"home": {
|
||||
"subtitle": "Modern Skill Registry",
|
||||
|
|
@ -80,7 +102,29 @@
|
|||
"popularDescription": "Most popular skills in the community",
|
||||
"latestTitle": "Latest Releases",
|
||||
"latestDescription": "Freshly published skills",
|
||||
"viewAll": "View All →"
|
||||
"viewAll": "View All →",
|
||||
"quickStart": {
|
||||
"title": "Quick Start",
|
||||
"subtitle": "快速开始",
|
||||
"description": "Get started with SkillHub in just a few simple steps",
|
||||
"tip": "💡 Tip: Visit the skill detail page for one-click install commands with environment variables",
|
||||
"steps": {
|
||||
"configureEnv": {
|
||||
"title": "1. Configure Environment Variables",
|
||||
"description": "Configure ClawHub CLI to connect to SkillHub"
|
||||
},
|
||||
"installSkills": {
|
||||
"title": "2. Install Skills",
|
||||
"description": "Search and install the skills you need",
|
||||
"code": "# Search skills\nclawhub search <keyword>\n\n# Install skill\nclawhub install <skill>"
|
||||
},
|
||||
"publishSkills": {
|
||||
"title": "3. Publish Skills",
|
||||
"description": "Share your skills with the team",
|
||||
"code": "# Publish skill\nclawhub publish\n\n# Or use web interface\n# Click \"Publish Skill\""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"search": {
|
||||
"title": "Search Skills",
|
||||
|
|
|
|||
|
|
@ -69,7 +69,29 @@
|
|||
"footerLicense": "© 2026 SkillHub。Apache License 2.0。",
|
||||
"footerDocs": "文档",
|
||||
"footerGithub": "GitHub",
|
||||
"footerCommunity": "社区"
|
||||
"footerCommunity": "社区",
|
||||
"quickStart": {
|
||||
"title": "快速开始",
|
||||
"subtitle": "Quick Start",
|
||||
"description": "只需几个简单步骤,即可开始使用 SkillHub",
|
||||
"tip": "💡 提示:访问技能详情页可获取带环境变量的一键复制安装命令",
|
||||
"steps": {
|
||||
"configureEnv": {
|
||||
"title": "1. 配置环境变量",
|
||||
"description": "设置 ClawHub CLI 连接到 SkillHub"
|
||||
},
|
||||
"installSkills": {
|
||||
"title": "2. 安装技能",
|
||||
"description": "搜索并安装你需要的技能",
|
||||
"code": "# 搜索技能\nclawhub search <keyword>\n\n# 安装技能\nclawhub install <skill>"
|
||||
},
|
||||
"publishSkills": {
|
||||
"title": "3. 发布技能",
|
||||
"description": "分享你的技能给团队使用",
|
||||
"code": "# 发布技能\nclawhub publish\n\n# 或使用网页界面\n# 点击\"发布技能\""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"home": {
|
||||
"subtitle": "现代化的技能注册中心",
|
||||
|
|
@ -80,7 +102,29 @@
|
|||
"popularDescription": "社区最受欢迎的技能",
|
||||
"latestTitle": "最新发布",
|
||||
"latestDescription": "刚刚发布的新技能",
|
||||
"viewAll": "查看全部 →"
|
||||
"viewAll": "查看全部 →",
|
||||
"quickStart": {
|
||||
"title": "快速开始",
|
||||
"subtitle": "Quick Start",
|
||||
"description": "只需几个简单步骤,即可开始使用 SkillHub",
|
||||
"tip": "💡 提示:访问技能详情页可获取带环境变量的一键复制安装命令",
|
||||
"steps": {
|
||||
"configureEnv": {
|
||||
"title": "1. 配置环境变量",
|
||||
"description": "设置 ClawHub CLI 连接到 SkillHub"
|
||||
},
|
||||
"installSkills": {
|
||||
"title": "2. 安装技能",
|
||||
"description": "搜索并安装你需要的技能",
|
||||
"code": "# 搜索技能\nclawhub search <keyword>\n\n# 安装技能\nclawhub install <skill>"
|
||||
},
|
||||
"publishSkills": {
|
||||
"title": "3. 发布技能",
|
||||
"description": "分享你的技能给团队使用",
|
||||
"code": "# 发布技能\nclawhub publish\n\n# 或使用网页界面\n# 点击\"发布技能\""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"search": {
|
||||
"title": "搜索技能",
|
||||
|
|
|
|||
|
|
@ -5,6 +5,144 @@ import { SkillCard } from '@/features/skill/skill-card'
|
|||
import { SkeletonList } from '@/shared/components/skeleton-loader'
|
||||
import { useSearchSkills } from '@/shared/hooks/use-skill-queries'
|
||||
import { Button } from '@/shared/ui/button'
|
||||
import { Check, Copy, Terminal, Settings, PackageOpen } from 'lucide-react'
|
||||
import { useState, useMemo } from 'react'
|
||||
|
||||
function getAppBaseUrl(): string {
|
||||
if (typeof window === 'undefined') {
|
||||
return 'https://skill.xfyun.cn'
|
||||
}
|
||||
const runtimeConfig = window.__SKILLHUB_RUNTIME_CONFIG__
|
||||
if (runtimeConfig?.appBaseUrl) {
|
||||
return runtimeConfig.appBaseUrl
|
||||
}
|
||||
return `${window.location.protocol}//${window.location.host}`
|
||||
}
|
||||
|
||||
function CopyButton({ text }: { text: string }) {
|
||||
const { t } = useTranslation()
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
const handleCopy = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text)
|
||||
setCopied(true)
|
||||
window.setTimeout(() => setCopied(false), 2000)
|
||||
} catch (err) {
|
||||
console.error('Failed to copy:', err)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={handleCopy}
|
||||
title={copied ? t('copyButton.copied') || 'Copied' : t('copyButton.copy') || 'Copy'}
|
||||
aria-label={copied ? t('copyButton.copied') || 'Copied' : t('copyButton.copy') || 'Copy'}
|
||||
className="h-8 w-8"
|
||||
>
|
||||
{copied ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
function CodeBlock({ code }: { code: string }) {
|
||||
return (
|
||||
<div className="relative group">
|
||||
<div className="flex items-center justify-between px-4 py-2 bg-slate-900 border-b border-slate-700 rounded-t-lg">
|
||||
<span className="text-xs text-slate-400 font-mono">bash</span>
|
||||
<CopyButton text={code} />
|
||||
</div>
|
||||
<pre className="p-4 bg-slate-950 rounded-b-lg overflow-x-auto">
|
||||
<code className="font-mono text-sm text-slate-200">{code}</code>
|
||||
</pre>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function QuickStartSection() {
|
||||
const { t } = useTranslation()
|
||||
const baseUrl = useMemo(() => getAppBaseUrl(), [])
|
||||
|
||||
const steps = [
|
||||
{
|
||||
icon: <Settings className="h-6 w-6" />,
|
||||
title: t('home.quickStart.steps.configureEnv.title'),
|
||||
description: t('home.quickStart.steps.configureEnv.description'),
|
||||
code: `# Linux/macOS
|
||||
export CLAWHUB_SITE=${baseUrl}
|
||||
export CLAWHUB_REGISTRY=${baseUrl}
|
||||
|
||||
# Windows PowerShell
|
||||
$env:CLAWHUB_SITE = '${baseUrl}'
|
||||
$env:CLAWHUB_REGISTRY = '${baseUrl}'`,
|
||||
},
|
||||
{
|
||||
icon: <Terminal className="h-6 w-6" />,
|
||||
title: t('home.quickStart.steps.installSkills.title'),
|
||||
description: t('home.quickStart.steps.installSkills.description'),
|
||||
code: t('home.quickStart.steps.installSkills.code'),
|
||||
},
|
||||
{
|
||||
icon: <PackageOpen className="h-6 w-6" />,
|
||||
title: t('home.quickStart.steps.publishSkills.title'),
|
||||
description: t('home.quickStart.steps.publishSkills.description'),
|
||||
code: t('home.quickStart.steps.publishSkills.code'),
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<section className="space-y-8 py-12">
|
||||
<div className="text-center space-y-4">
|
||||
<h2 className="text-3xl md:text-4xl font-bold font-heading text-foreground">
|
||||
{t('home.quickStart.title')}
|
||||
<span className="block text-lg font-normal text-muted-foreground mt-2">
|
||||
{t('home.quickStart.subtitle')}
|
||||
</span>
|
||||
</h2>
|
||||
<p className="text-muted-foreground max-w-2xl mx-auto">
|
||||
{t('home.quickStart.description')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-1 gap-6 max-w-4xl mx-auto">
|
||||
{steps.map((step, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
className="relative p-6 rounded-2xl bg-card border border-border hover:border-cyan-500/50 transition-all duration-300"
|
||||
>
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="flex-shrink-0 p-3 rounded-xl bg-cyan-500/10 text-cyan-400">
|
||||
{step.icon}
|
||||
</div>
|
||||
<div className="flex-1 space-y-4">
|
||||
<div>
|
||||
<h3 className="text-xl font-bold text-foreground">
|
||||
{step.title}
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{step.description}
|
||||
</p>
|
||||
</div>
|
||||
<CodeBlock code={step.code} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="text-center pt-4">
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-yellow-500/10 border border-yellow-500/30">
|
||||
<span className="text-sm text-yellow-300">
|
||||
{t('home.quickStart.tip')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
export function HomePage() {
|
||||
const { t } = useTranslation()
|
||||
|
|
@ -59,7 +197,7 @@ export function HomePage() {
|
|||
</div>
|
||||
|
||||
{/* Popular Downloads Section */}
|
||||
<section className="space-y-6 animate-fade-up delay-3">
|
||||
<section className="space-y-6 animate-fade-up">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h2 className="text-3xl font-bold font-heading text-foreground mb-2">{t('home.popularTitle')}</h2>
|
||||
|
|
@ -89,7 +227,7 @@ export function HomePage() {
|
|||
</section>
|
||||
|
||||
{/* Latest Releases Section */}
|
||||
<section className="space-y-6 animate-fade-up delay-4">
|
||||
<section className="space-y-6 animate-fade-up">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h2 className="text-3xl font-bold font-heading text-foreground mb-2">{t('home.latestTitle')}</h2>
|
||||
|
|
@ -117,6 +255,9 @@ export function HomePage() {
|
|||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
{/* Quick Start Section */}
|
||||
<QuickStartSection />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,145 @@ import { useAuth } from '@/features/auth/use-auth'
|
|||
import { LanguageSwitcher } from '@/shared/components/language-switcher'
|
||||
import { UserMenu } from '@/shared/components/user-menu'
|
||||
import { Button } from '@/shared/ui/button'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { Check, Copy, Terminal, Settings, PackageOpen } from 'lucide-react'
|
||||
import { useEffect, useRef, useState, useMemo } from 'react'
|
||||
|
||||
function getAppBaseUrl(): string {
|
||||
if (typeof window === 'undefined') {
|
||||
return 'https://skill.xfyun.cn'
|
||||
}
|
||||
const runtimeConfig = window.__SKILLHUB_RUNTIME_CONFIG__
|
||||
if (runtimeConfig?.appBaseUrl) {
|
||||
return runtimeConfig.appBaseUrl
|
||||
}
|
||||
return `${window.location.protocol}//${window.location.host}`
|
||||
}
|
||||
|
||||
function CopyButton({ text }: { text: string }) {
|
||||
const { t } = useTranslation()
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
const handleCopy = async () => {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text)
|
||||
setCopied(true)
|
||||
window.setTimeout(() => setCopied(false), 2000)
|
||||
} catch (err) {
|
||||
console.error('Failed to copy:', err)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={handleCopy}
|
||||
title={copied ? (t('copyButton.copied') || 'Copied') : (t('copyButton.copy') || 'Copy')}
|
||||
aria-label={copied ? (t('copyButton.copied') || 'Copied') : (t('copyButton.copy') || 'Copy')}
|
||||
className="h-8 w-8"
|
||||
>
|
||||
{copied ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
function CodeBlock({ code }: { code: string }) {
|
||||
return (
|
||||
<div className="relative group">
|
||||
<div className="flex items-center justify-between px-4 py-2 bg-slate-900 border-b border-slate-700 rounded-t-lg">
|
||||
<span className="text-xs text-slate-400 font-mono">bash</span>
|
||||
<CopyButton text={code} />
|
||||
</div>
|
||||
<pre className="p-4 bg-slate-950 rounded-b-lg overflow-x-auto">
|
||||
<code className="font-mono text-sm text-slate-200">{code}</code>
|
||||
</pre>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function QuickStartSection() {
|
||||
const { t } = useTranslation()
|
||||
const baseUrl = useMemo(() => getAppBaseUrl(), [])
|
||||
|
||||
const steps = [
|
||||
{
|
||||
icon: <Settings className="h-6 w-6" />,
|
||||
title: t('landing.quickStart.steps.configureEnv.title'),
|
||||
description: t('landing.quickStart.steps.configureEnv.description'),
|
||||
code: `# Linux/macOS
|
||||
export CLAWHUB_SITE=${baseUrl}
|
||||
export CLAWHUB_REGISTRY=${baseUrl}
|
||||
|
||||
# Windows PowerShell
|
||||
$env:CLAWHUB_SITE = '${baseUrl}'
|
||||
$env:CLAWHUB_REGISTRY = '${baseUrl}'`,
|
||||
},
|
||||
{
|
||||
icon: <Terminal className="h-6 w-6" />,
|
||||
title: t('landing.quickStart.steps.installSkills.title'),
|
||||
description: t('landing.quickStart.steps.installSkills.description'),
|
||||
code: t('landing.quickStart.steps.installSkills.code'),
|
||||
},
|
||||
{
|
||||
icon: <PackageOpen className="h-6 w-6" />,
|
||||
title: t('landing.quickStart.steps.publishSkills.title'),
|
||||
description: t('landing.quickStart.steps.publishSkills.description'),
|
||||
code: t('landing.quickStart.steps.publishSkills.code'),
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<section className="py-20 space-y-8">
|
||||
<div className="text-center space-y-4 animate-fade-up">
|
||||
<h2 className="text-4xl md:text-5xl font-bold text-slate-100">
|
||||
{t('landing.quickStart.title')}
|
||||
<span className="block text-lg font-normal text-slate-400 mt-2">
|
||||
{t('landing.quickStart.subtitle')}
|
||||
</span>
|
||||
</h2>
|
||||
<p className="text-lg text-slate-400 max-w-2xl mx-auto">
|
||||
{t('landing.quickStart.description')}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-1 gap-6 max-w-4xl mx-auto">
|
||||
{steps.map((step, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
className="relative p-6 rounded-2xl bg-slate-800/40 backdrop-blur-sm border border-slate-700/50 hover:border-cyan-500/50 transition-all duration-300 animate-fade-up"
|
||||
style={{ animationDelay: (idx * 0.1) + 's' }}
|
||||
>
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="flex-shrink-0 p-3 rounded-xl bg-cyan-500/10 text-cyan-400">
|
||||
{step.icon}
|
||||
</div>
|
||||
<div className="flex-1 space-y-4">
|
||||
<div>
|
||||
<h3 className="text-xl font-bold text-slate-100">
|
||||
{step.title}
|
||||
</h3>
|
||||
<p className="text-sm text-slate-400">
|
||||
{step.description}
|
||||
</p>
|
||||
</div>
|
||||
<CodeBlock code={step.code} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="text-center pt-4 animate-fade-up">
|
||||
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-yellow-500/10 border border-yellow-500/30">
|
||||
<span className="text-sm text-yellow-300">
|
||||
{t('landing.quickStart.tip')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
export function LandingPage() {
|
||||
const { t } = useTranslation()
|
||||
|
|
@ -278,6 +416,9 @@ export function LandingPage() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* Quick Start Section */}
|
||||
<QuickStartSection />
|
||||
|
||||
</div>
|
||||
|
||||
<div className="relative z-10 border-t border-slate-800/50 backdrop-blur-sm">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue