feat(website): 添加项目官网
使用 Astro 框架构建的静态官网
This commit is contained in:
@@ -0,0 +1 @@
|
||||
export default new Map();
|
||||
@@ -0,0 +1 @@
|
||||
export default new Map();
|
||||
Vendored
+199
@@ -0,0 +1,199 @@
|
||||
declare module 'astro:content' {
|
||||
export interface RenderResult {
|
||||
Content: import('astro/runtime/server/index.js').AstroComponentFactory;
|
||||
headings: import('astro').MarkdownHeading[];
|
||||
remarkPluginFrontmatter: Record<string, any>;
|
||||
}
|
||||
interface Render {
|
||||
'.md': Promise<RenderResult>;
|
||||
}
|
||||
|
||||
export interface RenderedContent {
|
||||
html: string;
|
||||
metadata?: {
|
||||
imagePaths: Array<string>;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
declare module 'astro:content' {
|
||||
type Flatten<T> = T extends { [K: string]: infer U } ? U : never;
|
||||
|
||||
export type CollectionKey = keyof AnyEntryMap;
|
||||
export type CollectionEntry<C extends CollectionKey> = Flatten<AnyEntryMap[C]>;
|
||||
|
||||
export type ContentCollectionKey = keyof ContentEntryMap;
|
||||
export type DataCollectionKey = keyof DataEntryMap;
|
||||
|
||||
type AllValuesOf<T> = T extends any ? T[keyof T] : never;
|
||||
type ValidContentEntrySlug<C extends keyof ContentEntryMap> = AllValuesOf<
|
||||
ContentEntryMap[C]
|
||||
>['slug'];
|
||||
|
||||
export type ReferenceDataEntry<
|
||||
C extends CollectionKey,
|
||||
E extends keyof DataEntryMap[C] = string,
|
||||
> = {
|
||||
collection: C;
|
||||
id: E;
|
||||
};
|
||||
export type ReferenceContentEntry<
|
||||
C extends keyof ContentEntryMap,
|
||||
E extends ValidContentEntrySlug<C> | (string & {}) = string,
|
||||
> = {
|
||||
collection: C;
|
||||
slug: E;
|
||||
};
|
||||
export type ReferenceLiveEntry<C extends keyof LiveContentConfig['collections']> = {
|
||||
collection: C;
|
||||
id: string;
|
||||
};
|
||||
|
||||
/** @deprecated Use `getEntry` instead. */
|
||||
export function getEntryBySlug<
|
||||
C extends keyof ContentEntryMap,
|
||||
E extends ValidContentEntrySlug<C> | (string & {}),
|
||||
>(
|
||||
collection: C,
|
||||
// Note that this has to accept a regular string too, for SSR
|
||||
entrySlug: E,
|
||||
): E extends ValidContentEntrySlug<C>
|
||||
? Promise<CollectionEntry<C>>
|
||||
: Promise<CollectionEntry<C> | undefined>;
|
||||
|
||||
/** @deprecated Use `getEntry` instead. */
|
||||
export function getDataEntryById<C extends keyof DataEntryMap, E extends keyof DataEntryMap[C]>(
|
||||
collection: C,
|
||||
entryId: E,
|
||||
): Promise<CollectionEntry<C>>;
|
||||
|
||||
export function getCollection<C extends keyof AnyEntryMap, E extends CollectionEntry<C>>(
|
||||
collection: C,
|
||||
filter?: (entry: CollectionEntry<C>) => entry is E,
|
||||
): Promise<E[]>;
|
||||
export function getCollection<C extends keyof AnyEntryMap>(
|
||||
collection: C,
|
||||
filter?: (entry: CollectionEntry<C>) => unknown,
|
||||
): Promise<CollectionEntry<C>[]>;
|
||||
|
||||
export function getLiveCollection<C extends keyof LiveContentConfig['collections']>(
|
||||
collection: C,
|
||||
filter?: LiveLoaderCollectionFilterType<C>,
|
||||
): Promise<
|
||||
import('astro').LiveDataCollectionResult<LiveLoaderDataType<C>, LiveLoaderErrorType<C>>
|
||||
>;
|
||||
|
||||
export function getEntry<
|
||||
C extends keyof ContentEntryMap,
|
||||
E extends ValidContentEntrySlug<C> | (string & {}),
|
||||
>(
|
||||
entry: ReferenceContentEntry<C, E>,
|
||||
): E extends ValidContentEntrySlug<C>
|
||||
? Promise<CollectionEntry<C>>
|
||||
: Promise<CollectionEntry<C> | undefined>;
|
||||
export function getEntry<
|
||||
C extends keyof DataEntryMap,
|
||||
E extends keyof DataEntryMap[C] | (string & {}),
|
||||
>(
|
||||
entry: ReferenceDataEntry<C, E>,
|
||||
): E extends keyof DataEntryMap[C]
|
||||
? Promise<DataEntryMap[C][E]>
|
||||
: Promise<CollectionEntry<C> | undefined>;
|
||||
export function getEntry<
|
||||
C extends keyof ContentEntryMap,
|
||||
E extends ValidContentEntrySlug<C> | (string & {}),
|
||||
>(
|
||||
collection: C,
|
||||
slug: E,
|
||||
): E extends ValidContentEntrySlug<C>
|
||||
? Promise<CollectionEntry<C>>
|
||||
: Promise<CollectionEntry<C> | undefined>;
|
||||
export function getEntry<
|
||||
C extends keyof DataEntryMap,
|
||||
E extends keyof DataEntryMap[C] | (string & {}),
|
||||
>(
|
||||
collection: C,
|
||||
id: E,
|
||||
): E extends keyof DataEntryMap[C]
|
||||
? string extends keyof DataEntryMap[C]
|
||||
? Promise<DataEntryMap[C][E]> | undefined
|
||||
: Promise<DataEntryMap[C][E]>
|
||||
: Promise<CollectionEntry<C> | undefined>;
|
||||
export function getLiveEntry<C extends keyof LiveContentConfig['collections']>(
|
||||
collection: C,
|
||||
filter: string | LiveLoaderEntryFilterType<C>,
|
||||
): Promise<import('astro').LiveDataEntryResult<LiveLoaderDataType<C>, LiveLoaderErrorType<C>>>;
|
||||
|
||||
/** Resolve an array of entry references from the same collection */
|
||||
export function getEntries<C extends keyof ContentEntryMap>(
|
||||
entries: ReferenceContentEntry<C, ValidContentEntrySlug<C>>[],
|
||||
): Promise<CollectionEntry<C>[]>;
|
||||
export function getEntries<C extends keyof DataEntryMap>(
|
||||
entries: ReferenceDataEntry<C, keyof DataEntryMap[C]>[],
|
||||
): Promise<CollectionEntry<C>[]>;
|
||||
|
||||
export function render<C extends keyof AnyEntryMap>(
|
||||
entry: AnyEntryMap[C][string],
|
||||
): Promise<RenderResult>;
|
||||
|
||||
export function reference<C extends keyof AnyEntryMap>(
|
||||
collection: C,
|
||||
): import('astro/zod').ZodEffects<
|
||||
import('astro/zod').ZodString,
|
||||
C extends keyof ContentEntryMap
|
||||
? ReferenceContentEntry<C, ValidContentEntrySlug<C>>
|
||||
: ReferenceDataEntry<C, keyof DataEntryMap[C]>
|
||||
>;
|
||||
// Allow generic `string` to avoid excessive type errors in the config
|
||||
// if `dev` is not running to update as you edit.
|
||||
// Invalid collection names will be caught at build time.
|
||||
export function reference<C extends string>(
|
||||
collection: C,
|
||||
): import('astro/zod').ZodEffects<import('astro/zod').ZodString, never>;
|
||||
|
||||
type ReturnTypeOrOriginal<T> = T extends (...args: any[]) => infer R ? R : T;
|
||||
type InferEntrySchema<C extends keyof AnyEntryMap> = import('astro/zod').infer<
|
||||
ReturnTypeOrOriginal<Required<ContentConfig['collections'][C]>['schema']>
|
||||
>;
|
||||
|
||||
type ContentEntryMap = {
|
||||
|
||||
};
|
||||
|
||||
type DataEntryMap = {
|
||||
|
||||
};
|
||||
|
||||
type AnyEntryMap = ContentEntryMap & DataEntryMap;
|
||||
|
||||
type ExtractLoaderTypes<T> = T extends import('astro/loaders').LiveLoader<
|
||||
infer TData,
|
||||
infer TEntryFilter,
|
||||
infer TCollectionFilter,
|
||||
infer TError
|
||||
>
|
||||
? { data: TData; entryFilter: TEntryFilter; collectionFilter: TCollectionFilter; error: TError }
|
||||
: { data: never; entryFilter: never; collectionFilter: never; error: never };
|
||||
type ExtractDataType<T> = ExtractLoaderTypes<T>['data'];
|
||||
type ExtractEntryFilterType<T> = ExtractLoaderTypes<T>['entryFilter'];
|
||||
type ExtractCollectionFilterType<T> = ExtractLoaderTypes<T>['collectionFilter'];
|
||||
type ExtractErrorType<T> = ExtractLoaderTypes<T>['error'];
|
||||
|
||||
type LiveLoaderDataType<C extends keyof LiveContentConfig['collections']> =
|
||||
LiveContentConfig['collections'][C]['schema'] extends undefined
|
||||
? ExtractDataType<LiveContentConfig['collections'][C]['loader']>
|
||||
: import('astro/zod').infer<
|
||||
Exclude<LiveContentConfig['collections'][C]['schema'], undefined>
|
||||
>;
|
||||
type LiveLoaderEntryFilterType<C extends keyof LiveContentConfig['collections']> =
|
||||
ExtractEntryFilterType<LiveContentConfig['collections'][C]['loader']>;
|
||||
type LiveLoaderCollectionFilterType<C extends keyof LiveContentConfig['collections']> =
|
||||
ExtractCollectionFilterType<LiveContentConfig['collections'][C]['loader']>;
|
||||
type LiveLoaderErrorType<C extends keyof LiveContentConfig['collections']> = ExtractErrorType<
|
||||
LiveContentConfig['collections'][C]['loader']
|
||||
>;
|
||||
|
||||
export type ContentConfig = typeof import("../src/content.config.mjs");
|
||||
export type LiveContentConfig = never;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
[["Map",1,2],"meta::meta",["Map",3,4,5,6],"astro-version","5.16.5","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"static\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4000,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[],\"responsiveStyles\":false},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true,\"allowedDomains\":[]},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false,\"liveContentCollections\":false,\"csp\":false,\"staticImportMetaEnv\":false,\"chromeDevtoolsWorkspace\":false,\"failOnPrerenderConflict\":false,\"svgo\":false},\"legacy\":{\"collections\":false}}"]
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"_variables": {
|
||||
"lastUpdateCheck": 1765549520905
|
||||
}
|
||||
}
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
/// <reference types="astro/client" />
|
||||
/// <reference path="content.d.ts" />
|
||||
@@ -0,0 +1,9 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
import tailwind from '@astrojs/tailwind';
|
||||
|
||||
export default defineConfig({
|
||||
integrations: [tailwind()],
|
||||
server: {
|
||||
port: 4000,
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "@ai-assistant/website",
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"build": "astro build",
|
||||
"preview": "astro preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^5.0.0",
|
||||
"@astrojs/tailwind": "^6.0.0",
|
||||
"tailwindcss": "^3.4.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none">
|
||||
<rect width="32" height="32" rx="6" fill="#0c4a6e"/>
|
||||
<path d="M8 10h16M8 16h12M8 22h8" stroke="#38bdf8" stroke-width="2" stroke-linecap="round"/>
|
||||
<circle cx="24" cy="22" r="3" fill="#38bdf8"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 279 B |
@@ -0,0 +1,34 @@
|
||||
---
|
||||
interface Props {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const { title } = Astro.props;
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="AI Terminal Assistant - 终端 AI 编程助手" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<title>{title}</title>
|
||||
</head>
|
||||
<body class="bg-gray-950 text-gray-100 antialiased">
|
||||
<slot />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<style is:global>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
||||
|
||||
html {
|
||||
font-family: 'Inter', system-ui, sans-serif;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: rgba(14, 165, 233, 0.3);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,202 @@
|
||||
---
|
||||
import Layout from '../layouts/Layout.astro';
|
||||
|
||||
const features = [
|
||||
{
|
||||
icon: '⚡',
|
||||
title: '流式对话',
|
||||
description: '基于 Claude API 的实时流式响应,让 AI 交互更加自然流畅。',
|
||||
},
|
||||
{
|
||||
icon: '🛠️',
|
||||
title: '丰富工具',
|
||||
description: '内置文件操作、Bash 执行、代码搜索等开发工具,直接在终端中完成编程任务。',
|
||||
},
|
||||
{
|
||||
icon: '📝',
|
||||
title: '智能编辑',
|
||||
description: '支持多种编辑模式:整体替换、Diff 补丁、搜索替换,灵活应对各种场景。',
|
||||
},
|
||||
{
|
||||
icon: '🔍',
|
||||
title: 'LSP 集成',
|
||||
description: '集成语言服务器协议,提供代码诊断、定义跳转等智能编程支持。',
|
||||
},
|
||||
{
|
||||
icon: '💾',
|
||||
title: 'Checkpoint',
|
||||
description: 'Shadow Git 检查点系统,随时保存和恢复工作状态,操作更安全。',
|
||||
},
|
||||
{
|
||||
icon: '🔌',
|
||||
title: 'MCP 支持',
|
||||
description: '支持 Model Context Protocol,轻松扩展 AI 能力边界。',
|
||||
},
|
||||
];
|
||||
---
|
||||
|
||||
<Layout title="AI Terminal Assistant - 终端 AI 编程助手">
|
||||
<!-- Navigation -->
|
||||
<nav class="fixed top-0 left-0 right-0 z-50 border-b border-gray-800 bg-gray-950/80 backdrop-blur-sm">
|
||||
<div class="mx-auto flex max-w-6xl items-center justify-between px-6 py-4">
|
||||
<a href="/" class="text-xl font-bold text-white">
|
||||
<span class="text-primary-400">AI</span> Terminal Assistant
|
||||
</a>
|
||||
<div class="flex items-center gap-6">
|
||||
<a href="#features" class="text-sm text-gray-400 transition hover:text-white">功能</a>
|
||||
<a href="#quickstart" class="text-sm text-gray-400 transition hover:text-white">快速开始</a>
|
||||
<a
|
||||
href="https://github.com"
|
||||
target="_blank"
|
||||
class="rounded-lg bg-gray-800 px-4 py-2 text-sm font-medium text-white transition hover:bg-gray-700"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Hero Section -->
|
||||
<section class="relative flex min-h-screen items-center justify-center overflow-hidden px-6 pt-20">
|
||||
<!-- Background gradient -->
|
||||
<div class="absolute inset-0 bg-gradient-to-b from-primary-900/20 via-transparent to-transparent"></div>
|
||||
<div class="absolute top-1/4 left-1/2 h-96 w-96 -translate-x-1/2 rounded-full bg-primary-500/10 blur-3xl"></div>
|
||||
|
||||
<div class="relative z-10 mx-auto max-w-4xl text-center">
|
||||
<h1 class="mb-6 text-5xl font-bold leading-tight text-white md:text-6xl">
|
||||
终端中的
|
||||
<span class="bg-gradient-to-r from-primary-400 to-cyan-400 bg-clip-text text-transparent">
|
||||
AI 编程助手
|
||||
</span>
|
||||
</h1>
|
||||
<p class="mx-auto mb-10 max-w-2xl text-lg text-gray-400">
|
||||
基于 Claude API 构建的终端 AI 助手。支持文件操作、代码搜索、智能编辑,
|
||||
让 AI 成为你的编程伙伴。
|
||||
</p>
|
||||
|
||||
<!-- Terminal Demo -->
|
||||
<div class="mx-auto mb-10 max-w-2xl overflow-hidden rounded-xl border border-gray-800 bg-gray-900 shadow-2xl">
|
||||
<div class="flex items-center gap-2 border-b border-gray-800 bg-gray-900 px-4 py-3">
|
||||
<div class="h-3 w-3 rounded-full bg-red-500"></div>
|
||||
<div class="h-3 w-3 rounded-full bg-yellow-500"></div>
|
||||
<div class="h-3 w-3 rounded-full bg-green-500"></div>
|
||||
<span class="ml-2 text-sm text-gray-500">terminal</span>
|
||||
</div>
|
||||
<div class="p-6 text-left font-mono text-sm">
|
||||
<p class="text-gray-500">$ ai-assistant serve --port 3000</p>
|
||||
<p class="mt-2 text-green-400">✓ Server started on http://localhost:3000</p>
|
||||
<p class="mt-4 text-gray-500">$ ai-assistant attach</p>
|
||||
<p class="mt-2 text-primary-400">AI Assistant ready. How can I help?</p>
|
||||
<p class="mt-4 text-white">
|
||||
<span class="text-gray-500">></span> 帮我找出这个项目中所有的 TODO 注释
|
||||
</p>
|
||||
<p class="mt-2 text-gray-300">正在搜索代码库中的 TODO 注释...</p>
|
||||
<span class="inline-block h-4 w-2 animate-pulse bg-primary-400"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- CTA Buttons -->
|
||||
<div class="flex flex-wrap items-center justify-center gap-4">
|
||||
<a
|
||||
href="#quickstart"
|
||||
class="rounded-xl bg-primary-500 px-8 py-3 font-medium text-white shadow-lg shadow-primary-500/25 transition hover:bg-primary-600"
|
||||
>
|
||||
快速开始
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com"
|
||||
target="_blank"
|
||||
class="rounded-xl border border-gray-700 bg-gray-900 px-8 py-3 font-medium text-white transition hover:border-gray-600 hover:bg-gray-800"
|
||||
>
|
||||
查看源码
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Features Section -->
|
||||
<section id="features" class="px-6 py-24">
|
||||
<div class="mx-auto max-w-6xl">
|
||||
<h2 class="mb-4 text-center text-3xl font-bold text-white">核心功能</h2>
|
||||
<p class="mx-auto mb-16 max-w-2xl text-center text-gray-400">
|
||||
专为开发者设计,让 AI 真正融入你的开发工作流
|
||||
</p>
|
||||
|
||||
<div class="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||
{
|
||||
features.map((feature) => (
|
||||
<div class="group rounded-2xl border border-gray-800 bg-gray-900/50 p-6 transition hover:border-gray-700 hover:bg-gray-900">
|
||||
<div class="mb-4 text-4xl">{feature.icon}</div>
|
||||
<h3 class="mb-2 text-lg font-semibold text-white">{feature.title}</h3>
|
||||
<p class="text-sm leading-relaxed text-gray-400">{feature.description}</p>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Quick Start Section -->
|
||||
<section id="quickstart" class="px-6 py-24">
|
||||
<div class="mx-auto max-w-3xl">
|
||||
<h2 class="mb-4 text-center text-3xl font-bold text-white">快速开始</h2>
|
||||
<p class="mx-auto mb-12 max-w-xl text-center text-gray-400">只需几步即可开始使用</p>
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Step 1 -->
|
||||
<div class="rounded-xl border border-gray-800 bg-gray-900 p-6">
|
||||
<div class="mb-3 flex items-center gap-3">
|
||||
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-primary-500/20 text-sm font-bold text-primary-400">
|
||||
1
|
||||
</span>
|
||||
<h3 class="font-semibold text-white">克隆项目</h3>
|
||||
</div>
|
||||
<pre class="overflow-x-auto rounded-lg bg-gray-950 p-4 font-mono text-sm text-gray-300"><code>git clone https://github.com/your-repo/ai-terminal-assistant.git
|
||||
cd ai-terminal-assistant</code></pre>
|
||||
</div>
|
||||
|
||||
<!-- Step 2 -->
|
||||
<div class="rounded-xl border border-gray-800 bg-gray-900 p-6">
|
||||
<div class="mb-3 flex items-center gap-3">
|
||||
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-primary-500/20 text-sm font-bold text-primary-400">
|
||||
2
|
||||
</span>
|
||||
<h3 class="font-semibold text-white">安装依赖</h3>
|
||||
</div>
|
||||
<pre class="overflow-x-auto rounded-lg bg-gray-950 p-4 font-mono text-sm text-gray-300"><code>pnpm install</code></pre>
|
||||
</div>
|
||||
|
||||
<!-- Step 3 -->
|
||||
<div class="rounded-xl border border-gray-800 bg-gray-900 p-6">
|
||||
<div class="mb-3 flex items-center gap-3">
|
||||
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-primary-500/20 text-sm font-bold text-primary-400">
|
||||
3
|
||||
</span>
|
||||
<h3 class="font-semibold text-white">配置 API Key</h3>
|
||||
</div>
|
||||
<pre class="overflow-x-auto rounded-lg bg-gray-950 p-4 font-mono text-sm text-gray-300"><code>echo "ANTHROPIC_API_KEY=your-api-key" > .env</code></pre>
|
||||
</div>
|
||||
|
||||
<!-- Step 4 -->
|
||||
<div class="rounded-xl border border-gray-800 bg-gray-900 p-6">
|
||||
<div class="mb-3 flex items-center gap-3">
|
||||
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-primary-500/20 text-sm font-bold text-primary-400">
|
||||
4
|
||||
</span>
|
||||
<h3 class="font-semibold text-white">启动服务</h3>
|
||||
</div>
|
||||
<pre class="overflow-x-auto rounded-lg bg-gray-950 p-4 font-mono text-sm text-gray-300"><code>pnpm server:dev</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="border-t border-gray-800 px-6 py-12">
|
||||
<div class="mx-auto max-w-6xl text-center">
|
||||
<p class="text-sm text-gray-500">
|
||||
AI Terminal Assistant · Built with Claude API
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</Layout>
|
||||
@@ -0,0 +1,23 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
export default {
|
||||
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
primary: {
|
||||
50: '#f0f9ff',
|
||||
100: '#e0f2fe',
|
||||
200: '#bae6fd',
|
||||
300: '#7dd3fc',
|
||||
400: '#38bdf8',
|
||||
500: '#0ea5e9',
|
||||
600: '#0284c7',
|
||||
700: '#0369a1',
|
||||
800: '#075985',
|
||||
900: '#0c4a6e',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+1591
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user