feat(site): add standalone marketing website
This commit is contained in:
1 parent
4b0e4c4a8d
commit
9f07be50af
13 files changed
+3666
No files matched your search
@@ -0,0 +1,2 @@
|
||||
ignore-workspace=true
|
||||
lockfile-dir=.
|
||||
@@ -0,0 +1,63 @@
|
||||
# Prompt Optimizer 官网
|
||||
|
||||
本目录是 `always200.com` 对应的独立官网工程。
|
||||
|
||||
它与产品站、文档站彻底分离:
|
||||
|
||||
- `always200.com`:官网(当前目录)
|
||||
- `docs.always200.com`:文档站(`mkdocs/`)
|
||||
- `prompt.always200.com`:产品站(根项目)
|
||||
|
||||
## 目录职责
|
||||
|
||||
- 技术栈:独立 Vite 静态站
|
||||
- 部署目标:独立 Vercel 项目
|
||||
- Vercel Root Directory:`site/`
|
||||
- 官网不复用根项目的业务代码、UI 组件和构建链路
|
||||
- 官网保留自己的 `package.json`、`pnpm-lock.yaml`、`vercel.json`
|
||||
|
||||
## 本地运行
|
||||
|
||||
在 `site/` 目录内执行:
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
启动后访问终端输出的地址,默认通常是:
|
||||
|
||||
- `http://127.0.0.1:5173/`
|
||||
|
||||
如果端口被占用,Vite 会自动切换到其他端口。
|
||||
|
||||
## 语言切换
|
||||
|
||||
- 默认支持中文与英文两种官网文案
|
||||
- 首次访问会根据浏览器语言自动选择中文或英文
|
||||
- 用户手动切换语言后,会记住选择,后续访问优先使用上次手动选择
|
||||
- 当前官网采用单页静态渲染,不额外引入前端 i18n 框架
|
||||
|
||||
## 本地构建与静态预览
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
python -m http.server 8011 -d dist
|
||||
```
|
||||
|
||||
访问:
|
||||
|
||||
- `http://127.0.0.1:8011/`
|
||||
|
||||
## 路由说明
|
||||
|
||||
- `/`:官网首页
|
||||
- `/docs`:跳转到 `https://docs.always200.com/`
|
||||
- `/docs/:path*`:跳转到 `https://docs.always200.com/:path*`
|
||||
|
||||
## 部署
|
||||
|
||||
- 独立 Vercel 项目
|
||||
- Root Directory:`site/`
|
||||
- 正式域名:`always200.com`
|
||||
- `www.always200.com` 建议在 Vercel Dashboard 中跳转到 `always200.com`
|
||||
@@ -0,0 +1,27 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Prompt Optimizer | 提示词优化,不该只靠感觉</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Prompt Optimizer 把提示词优化、真实测试、结果评估和建议应用放进同一个工作台。"
|
||||
/>
|
||||
<link rel="canonical" href="https://always200.com/" />
|
||||
<link rel="icon" type="image/png" href="/images/favicon.png" />
|
||||
<meta property="og:title" content="Prompt Optimizer" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="把提示词优化、真实测试、结果评估和建议应用放进同一个工作台。"
|
||||
/>
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://always200.com/" />
|
||||
<meta property="og:image" content="https://always200.com/images/og-cover.png" />
|
||||
<meta name="theme-color" content="#fcfbff" />
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "prompt-optimizer-site",
|
||||
"private": true,
|
||||
"version": "0.1.0",
|
||||
"packageManager": "pnpm@10.6.1",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"devDependencies": {
|
||||
"vite": "^7.1.7"
|
||||
}
|
||||
}
|
||||
Generated
+673
@@ -0,0 +1,673 @@
|
||||
lockfileVersion: '9.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
importers:
|
||||
|
||||
.:
|
||||
devDependencies:
|
||||
vite:
|
||||
specifier: ^7.1.7
|
||||
version: 7.3.1(@types/node@22.19.15)(jiti@2.6.1)(yaml@2.8.2)
|
||||
|
||||
packages:
|
||||
|
||||
'@esbuild/aix-ppc64@0.27.4':
|
||||
resolution: {integrity: sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [aix]
|
||||
|
||||
'@esbuild/android-arm64@0.27.4':
|
||||
resolution: {integrity: sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.27.4':
|
||||
resolution: {integrity: sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.27.4':
|
||||
resolution: {integrity: sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/darwin-arm64@0.27.4':
|
||||
resolution: {integrity: sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.27.4':
|
||||
resolution: {integrity: sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.27.4':
|
||||
resolution: {integrity: sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.27.4':
|
||||
resolution: {integrity: sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/linux-arm64@0.27.4':
|
||||
resolution: {integrity: sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.27.4':
|
||||
resolution: {integrity: sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.27.4':
|
||||
resolution: {integrity: sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.27.4':
|
||||
resolution: {integrity: sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.27.4':
|
||||
resolution: {integrity: sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.27.4':
|
||||
resolution: {integrity: sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.27.4':
|
||||
resolution: {integrity: sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.27.4':
|
||||
resolution: {integrity: sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.27.4':
|
||||
resolution: {integrity: sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/netbsd-arm64@0.27.4':
|
||||
resolution: {integrity: sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.27.4':
|
||||
resolution: {integrity: sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/openbsd-arm64@0.27.4':
|
||||
resolution: {integrity: sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.27.4':
|
||||
resolution: {integrity: sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openharmony-arm64@0.27.4':
|
||||
resolution: {integrity: sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@esbuild/sunos-x64@0.27.4':
|
||||
resolution: {integrity: sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/win32-arm64@0.27.4':
|
||||
resolution: {integrity: sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.27.4':
|
||||
resolution: {integrity: sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.27.4':
|
||||
resolution: {integrity: sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.59.0':
|
||||
resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@rollup/rollup-android-arm64@4.59.0':
|
||||
resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@rollup/rollup-darwin-arm64@4.59.0':
|
||||
resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@rollup/rollup-darwin-x64@4.59.0':
|
||||
resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@rollup/rollup-freebsd-arm64@4.59.0':
|
||||
resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@rollup/rollup-freebsd-x64@4.59.0':
|
||||
resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.59.0':
|
||||
resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.59.0':
|
||||
resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.59.0':
|
||||
resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-loong64-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-loong64-musl@4.59.0':
|
||||
resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-musl@4.59.0':
|
||||
resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-musl@4.59.0':
|
||||
resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.59.0':
|
||||
resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-openbsd-x64@4.59.0':
|
||||
resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@rollup/rollup-openharmony-arm64@4.59.0':
|
||||
resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.59.0':
|
||||
resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-ia32-msvc@4.59.0':
|
||||
resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-x64-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-x64-msvc@4.59.0':
|
||||
resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@types/estree@1.0.8':
|
||||
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
|
||||
|
||||
'@types/node@22.19.15':
|
||||
resolution: {integrity: sha512-F0R/h2+dsy5wJAUe3tAU6oqa2qbWY5TpNfL/RGmo1y38hiyO1w3x2jPtt76wmuaJI4DQnOBu21cNXQ2STIUUWg==}
|
||||
|
||||
esbuild@0.27.4:
|
||||
resolution: {integrity: sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
fdir@6.5.0:
|
||||
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
peerDependencies:
|
||||
picomatch: ^3 || ^4
|
||||
peerDependenciesMeta:
|
||||
picomatch:
|
||||
optional: true
|
||||
|
||||
fsevents@2.3.3:
|
||||
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||
os: [darwin]
|
||||
|
||||
jiti@2.6.1:
|
||||
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
|
||||
hasBin: true
|
||||
|
||||
nanoid@3.3.11:
|
||||
resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
hasBin: true
|
||||
|
||||
picocolors@1.1.1:
|
||||
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
|
||||
|
||||
picomatch@4.0.3:
|
||||
resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
postcss@8.5.8:
|
||||
resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==}
|
||||
engines: {node: ^10 || ^12 || >=14}
|
||||
|
||||
rollup@4.59.0:
|
||||
resolution: {integrity: sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
|
||||
source-map-js@1.2.1:
|
||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
tinyglobby@0.2.15:
|
||||
resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
undici-types@6.21.0:
|
||||
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
|
||||
|
||||
vite@7.3.1:
|
||||
resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==}
|
||||
engines: {node: ^20.19.0 || >=22.12.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@types/node': ^20.19.0 || >=22.12.0
|
||||
jiti: '>=1.21.0'
|
||||
less: ^4.0.0
|
||||
lightningcss: ^1.21.0
|
||||
sass: ^1.70.0
|
||||
sass-embedded: ^1.70.0
|
||||
stylus: '>=0.54.8'
|
||||
sugarss: ^5.0.0
|
||||
terser: ^5.16.0
|
||||
tsx: ^4.8.1
|
||||
yaml: ^2.4.2
|
||||
peerDependenciesMeta:
|
||||
'@types/node':
|
||||
optional: true
|
||||
jiti:
|
||||
optional: true
|
||||
less:
|
||||
optional: true
|
||||
lightningcss:
|
||||
optional: true
|
||||
sass:
|
||||
optional: true
|
||||
sass-embedded:
|
||||
optional: true
|
||||
stylus:
|
||||
optional: true
|
||||
sugarss:
|
||||
optional: true
|
||||
terser:
|
||||
optional: true
|
||||
tsx:
|
||||
optional: true
|
||||
yaml:
|
||||
optional: true
|
||||
|
||||
yaml@2.8.2:
|
||||
resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==}
|
||||
engines: {node: '>= 14.6'}
|
||||
hasBin: true
|
||||
|
||||
snapshots:
|
||||
|
||||
'@esbuild/aix-ppc64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-arm64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-arm64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openharmony-arm64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.27.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-android-arm64@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-darwin-arm64@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-darwin-x64@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-freebsd-arm64@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-freebsd-x64@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-loong64-gnu@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-loong64-musl@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-ppc64-gnu@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-ppc64-musl@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-riscv64-musl@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-openbsd-x64@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-openharmony-arm64@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-ia32-msvc@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-x64-gnu@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-x64-msvc@4.59.0':
|
||||
optional: true
|
||||
|
||||
'@types/estree@1.0.8': {}
|
||||
|
||||
'@types/node@22.19.15':
|
||||
dependencies:
|
||||
undici-types: 6.21.0
|
||||
optional: true
|
||||
|
||||
esbuild@0.27.4:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.27.4
|
||||
'@esbuild/android-arm': 0.27.4
|
||||
'@esbuild/android-arm64': 0.27.4
|
||||
'@esbuild/android-x64': 0.27.4
|
||||
'@esbuild/darwin-arm64': 0.27.4
|
||||
'@esbuild/darwin-x64': 0.27.4
|
||||
'@esbuild/freebsd-arm64': 0.27.4
|
||||
'@esbuild/freebsd-x64': 0.27.4
|
||||
'@esbuild/linux-arm': 0.27.4
|
||||
'@esbuild/linux-arm64': 0.27.4
|
||||
'@esbuild/linux-ia32': 0.27.4
|
||||
'@esbuild/linux-loong64': 0.27.4
|
||||
'@esbuild/linux-mips64el': 0.27.4
|
||||
'@esbuild/linux-ppc64': 0.27.4
|
||||
'@esbuild/linux-riscv64': 0.27.4
|
||||
'@esbuild/linux-s390x': 0.27.4
|
||||
'@esbuild/linux-x64': 0.27.4
|
||||
'@esbuild/netbsd-arm64': 0.27.4
|
||||
'@esbuild/netbsd-x64': 0.27.4
|
||||
'@esbuild/openbsd-arm64': 0.27.4
|
||||
'@esbuild/openbsd-x64': 0.27.4
|
||||
'@esbuild/openharmony-arm64': 0.27.4
|
||||
'@esbuild/sunos-x64': 0.27.4
|
||||
'@esbuild/win32-arm64': 0.27.4
|
||||
'@esbuild/win32-ia32': 0.27.4
|
||||
'@esbuild/win32-x64': 0.27.4
|
||||
|
||||
fdir@6.5.0(picomatch@4.0.3):
|
||||
optionalDependencies:
|
||||
picomatch: 4.0.3
|
||||
|
||||
fsevents@2.3.3:
|
||||
optional: true
|
||||
|
||||
jiti@2.6.1:
|
||||
optional: true
|
||||
|
||||
nanoid@3.3.11: {}
|
||||
|
||||
picocolors@1.1.1: {}
|
||||
|
||||
picomatch@4.0.3: {}
|
||||
|
||||
postcss@8.5.8:
|
||||
dependencies:
|
||||
nanoid: 3.3.11
|
||||
picocolors: 1.1.1
|
||||
source-map-js: 1.2.1
|
||||
|
||||
rollup@4.59.0:
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
optionalDependencies:
|
||||
'@rollup/rollup-android-arm-eabi': 4.59.0
|
||||
'@rollup/rollup-android-arm64': 4.59.0
|
||||
'@rollup/rollup-darwin-arm64': 4.59.0
|
||||
'@rollup/rollup-darwin-x64': 4.59.0
|
||||
'@rollup/rollup-freebsd-arm64': 4.59.0
|
||||
'@rollup/rollup-freebsd-x64': 4.59.0
|
||||
'@rollup/rollup-linux-arm-gnueabihf': 4.59.0
|
||||
'@rollup/rollup-linux-arm-musleabihf': 4.59.0
|
||||
'@rollup/rollup-linux-arm64-gnu': 4.59.0
|
||||
'@rollup/rollup-linux-arm64-musl': 4.59.0
|
||||
'@rollup/rollup-linux-loong64-gnu': 4.59.0
|
||||
'@rollup/rollup-linux-loong64-musl': 4.59.0
|
||||
'@rollup/rollup-linux-ppc64-gnu': 4.59.0
|
||||
'@rollup/rollup-linux-ppc64-musl': 4.59.0
|
||||
'@rollup/rollup-linux-riscv64-gnu': 4.59.0
|
||||
'@rollup/rollup-linux-riscv64-musl': 4.59.0
|
||||
'@rollup/rollup-linux-s390x-gnu': 4.59.0
|
||||
'@rollup/rollup-linux-x64-gnu': 4.59.0
|
||||
'@rollup/rollup-linux-x64-musl': 4.59.0
|
||||
'@rollup/rollup-openbsd-x64': 4.59.0
|
||||
'@rollup/rollup-openharmony-arm64': 4.59.0
|
||||
'@rollup/rollup-win32-arm64-msvc': 4.59.0
|
||||
'@rollup/rollup-win32-ia32-msvc': 4.59.0
|
||||
'@rollup/rollup-win32-x64-gnu': 4.59.0
|
||||
'@rollup/rollup-win32-x64-msvc': 4.59.0
|
||||
fsevents: 2.3.3
|
||||
|
||||
source-map-js@1.2.1: {}
|
||||
|
||||
tinyglobby@0.2.15:
|
||||
dependencies:
|
||||
fdir: 6.5.0(picomatch@4.0.3)
|
||||
picomatch: 4.0.3
|
||||
|
||||
undici-types@6.21.0:
|
||||
optional: true
|
||||
|
||||
vite@7.3.1(@types/node@22.19.15)(jiti@2.6.1)(yaml@2.8.2):
|
||||
dependencies:
|
||||
esbuild: 0.27.4
|
||||
fdir: 6.5.0(picomatch@4.0.3)
|
||||
picomatch: 4.0.3
|
||||
postcss: 8.5.8
|
||||
rollup: 4.59.0
|
||||
tinyglobby: 0.2.15
|
||||
optionalDependencies:
|
||||
'@types/node': 22.19.15
|
||||
fsevents: 2.3.3
|
||||
jiti: 2.6.1
|
||||
yaml: 2.8.2
|
||||
|
||||
yaml@2.8.2:
|
||||
optional: true
|
||||
@@ -0,0 +1 @@
|
||||
packages: []
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 320 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 174 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 320 KiB |
@@ -0,0 +1,815 @@
|
||||
import './styles.css'
|
||||
|
||||
const STORAGE_KEY = 'prompt-optimizer-site-locale'
|
||||
const THEME_STORAGE_KEY = 'prompt-optimizer-site-theme'
|
||||
const SUPPORTED_LOCALES = ['zh-CN', 'en']
|
||||
const THEME_MODES = ['system', 'dark', 'light']
|
||||
|
||||
const translations = {
|
||||
'zh-CN': {
|
||||
htmlLang: 'zh-CN',
|
||||
title: 'Prompt Optimizer | 提示词优化,应该基于真实结果',
|
||||
description: '在一个工作台里完成提示词优化、真实测试、结果评估与建议应用。',
|
||||
brandAriaLabel: 'Prompt Optimizer 官网首页',
|
||||
nav: {
|
||||
product: '产品',
|
||||
docs: '文档',
|
||||
github: 'GitHub',
|
||||
githubLabel: '开源仓库',
|
||||
themeAria: '切换主题模式',
|
||||
themeLabels: {
|
||||
system: '自动',
|
||||
dark: '深',
|
||||
light: '浅'
|
||||
},
|
||||
locale: 'EN',
|
||||
localeAria: '切换到英文',
|
||||
menuAria: '切换导航菜单'
|
||||
},
|
||||
hero: {
|
||||
eyebrow: '开源提示词工作台',
|
||||
titleTop: '提示词优化',
|
||||
titleMid: '应该基于',
|
||||
titleBottom: '真实结果',
|
||||
lead: '在一个工作台里完成优化、测试、评估,让建议回到当前提示词。',
|
||||
primary: '打开产品',
|
||||
secondary: '查看文档',
|
||||
stats: [
|
||||
{ value: '4 步闭环', label: '从测试到应用' },
|
||||
{ value: '多工作区', label: '单条、变量、上下文' },
|
||||
{ value: '结果证据', label: '改动基于输出' }
|
||||
],
|
||||
visualLabel: '结果闭环',
|
||||
visualTitle: '左改右测,结论回流',
|
||||
visualSummary: '左侧改提示词,右侧看结果,再把结论带回工作区。',
|
||||
visualTags: ['左侧工作区', '右侧测试', '单结果评估'],
|
||||
screenshotBadge: '工作台预览',
|
||||
screenshotAlt: 'Prompt Optimizer 工作台截图'
|
||||
},
|
||||
value: {
|
||||
kicker: '为什么不同',
|
||||
title: '不是改字工具,而是结果驱动的工作台',
|
||||
lead: '先看真实输出,再决定提示词到底要不要改。',
|
||||
manifestoLabel: '结果优先',
|
||||
manifestoTitle: '先看结果,再决定修改',
|
||||
manifestoBody: '它把分析、评估、对比和应用建议收进同一条可回溯的工作流。',
|
||||
principles: [
|
||||
{
|
||||
index: '01',
|
||||
title: '改动必须回应输出',
|
||||
body: '不是润色文本,而是修正结果偏差。',
|
||||
tags: ['分析', '评估', '应用']
|
||||
},
|
||||
{
|
||||
index: '02',
|
||||
title: '任务边界要清楚',
|
||||
body: '分析、评估、对比各自独立建模。'
|
||||
},
|
||||
{
|
||||
index: '03',
|
||||
title: '结论要能继续迭代',
|
||||
body: '输出结论最终要回到当前工作区。'
|
||||
}
|
||||
]
|
||||
},
|
||||
workflow: {
|
||||
kicker: '工作方式',
|
||||
title: '用一次闭环,把改动落回真实结果',
|
||||
lead: '左侧设计提示词,右侧验证结果,再把结论收回来。',
|
||||
steps: [
|
||||
{
|
||||
label: '工作区',
|
||||
title: '设计层',
|
||||
body: '在左侧持续改写当前可编辑提示词。'
|
||||
},
|
||||
{
|
||||
label: '测试',
|
||||
title: '执行层',
|
||||
body: '在右侧用真实输入和模型配置跑结果。'
|
||||
},
|
||||
{
|
||||
label: '回流',
|
||||
title: '决策层',
|
||||
body: '把结果收敛成可继续应用的改动建议。'
|
||||
}
|
||||
]
|
||||
},
|
||||
scenario: {
|
||||
kicker: '工作区覆盖',
|
||||
title: '适配不同的提示词结构',
|
||||
lead: '单条提示词、变量模板和上下文链路,都能放进同一套验证流程。',
|
||||
columns: {
|
||||
type: '结构类型',
|
||||
fit: '适用内容',
|
||||
capability: '关键能力'
|
||||
},
|
||||
cards: [
|
||||
{
|
||||
label: '单条提示词',
|
||||
title: 'system / user 单提示词',
|
||||
body: '适合优化角色、规则与输出格式。',
|
||||
tags: ['system', 'user', '聚焦分析']
|
||||
},
|
||||
{
|
||||
label: '变量模板',
|
||||
title: '变量模板',
|
||||
body: '把主题、语气和角色收进模板后再验证。',
|
||||
tags: ['占位变量', '真实输入', '模板复用']
|
||||
},
|
||||
{
|
||||
label: '上下文链路',
|
||||
title: '多消息上下文',
|
||||
body: '当 system、user 与上下文共同影响结果时仍可分析。',
|
||||
tags: ['system + user', '上下文', '多消息']
|
||||
}
|
||||
]
|
||||
},
|
||||
access: {
|
||||
kicker: '开放与入口',
|
||||
title: '开源可信,也能立刻开始',
|
||||
lead: '看清它的开放能力,再选最顺手的入口。',
|
||||
proof: {
|
||||
label: 'GitHub 仓库',
|
||||
title: 'linshenkx/prompt-optimizer',
|
||||
body: '同一套产品能力覆盖 Web、桌面版、自托管、Docker 和 MCP。',
|
||||
facts: ['AGPL-3.0', 'Web / Desktop / Extension', 'Docker / MCP'],
|
||||
primary: '查看 GitHub',
|
||||
secondary: '下载 Release'
|
||||
},
|
||||
entries: [
|
||||
{
|
||||
title: '在线产品',
|
||||
body: '直接进入工作台开始优化。',
|
||||
href: 'https://prompt.always200.com'
|
||||
},
|
||||
{
|
||||
title: '下载桌面版',
|
||||
body: '从 Releases 获取安装包。',
|
||||
href: 'https://github.com/linshenkx/prompt-optimizer/releases'
|
||||
},
|
||||
{
|
||||
title: 'Chrome 插件',
|
||||
body: '从 Chrome Web Store 安装入口。',
|
||||
href: 'https://chromewebstore.google.com/detail/prompt-optimizer/cakkkhboolfnadechdlgdcnjammejlna'
|
||||
},
|
||||
{
|
||||
title: 'Docker / MCP',
|
||||
body: '适合自托管和外部集成。',
|
||||
href: 'https://docs.always200.com/deployment/docker-basic/'
|
||||
}
|
||||
]
|
||||
},
|
||||
footer: {
|
||||
title: 'Prompt Optimizer',
|
||||
body: '让提示词优化回到真实结果。',
|
||||
product: '产品',
|
||||
docs: '文档',
|
||||
github: 'GitHub'
|
||||
}
|
||||
},
|
||||
en: {
|
||||
htmlLang: 'en',
|
||||
title: 'Prompt Optimizer | Prompt optimization should follow real outputs',
|
||||
description: 'One workspace for prompt iteration, real testing, result evaluation, and applying improvements.',
|
||||
brandAriaLabel: 'Prompt Optimizer website home',
|
||||
nav: {
|
||||
product: 'Product',
|
||||
docs: 'Docs',
|
||||
github: 'GitHub',
|
||||
githubLabel: 'Open-source repository',
|
||||
themeAria: 'Switch theme mode',
|
||||
themeLabels: {
|
||||
system: 'Auto',
|
||||
dark: 'Dark',
|
||||
light: 'Light'
|
||||
},
|
||||
locale: '中文',
|
||||
localeAria: 'Switch to Chinese',
|
||||
menuAria: 'Toggle navigation menu'
|
||||
},
|
||||
hero: {
|
||||
eyebrow: 'Open-source prompt workspace',
|
||||
titleTop: 'Prompt optimization',
|
||||
titleMid: 'should follow',
|
||||
titleBottom: 'real outputs',
|
||||
lead: 'Iterate, test, evaluate, and return changes in one workspace.',
|
||||
primary: 'Open Product',
|
||||
secondary: 'Read Docs',
|
||||
stats: [
|
||||
{ value: '4-Step', label: 'From test to apply' },
|
||||
{ value: 'Multi-Workspace', label: 'Single, variable, context' },
|
||||
{ value: 'Evidence-Based', label: 'Edits follow outputs' }
|
||||
],
|
||||
visualLabel: 'Closed Loop',
|
||||
visualTitle: 'Edit left, test right',
|
||||
visualSummary: 'Refine the prompt, inspect the result, then send the conclusion back.',
|
||||
visualTags: ['Editable workspace', 'Real test run', 'Result evaluation'],
|
||||
screenshotBadge: 'Workspace preview',
|
||||
screenshotAlt: 'Prompt Optimizer workspace screenshot'
|
||||
},
|
||||
value: {
|
||||
kicker: 'Why it is different',
|
||||
title: 'Not a rewrite toy, but an output-driven workspace',
|
||||
lead: 'See the output first, then decide whether the prompt should change.',
|
||||
manifestoLabel: 'Result First',
|
||||
manifestoTitle: 'Look at the result before the rewrite',
|
||||
manifestoBody: 'It keeps analysis, evaluation, compare, and apply actions inside one traceable loop.',
|
||||
principles: [
|
||||
{
|
||||
index: '01',
|
||||
title: 'Edits must answer the output',
|
||||
body: 'The goal is not prettier wording, but better execution.',
|
||||
tags: ['Analysis', 'Evaluation', 'Apply']
|
||||
},
|
||||
{
|
||||
index: '02',
|
||||
title: 'Action boundaries stay clear',
|
||||
body: 'Analysis, evaluation, and compare are modeled separately.'
|
||||
},
|
||||
{
|
||||
index: '03',
|
||||
title: 'Findings should keep iterating',
|
||||
body: 'Every conclusion should flow back into the editable workspace.'
|
||||
}
|
||||
]
|
||||
},
|
||||
workflow: {
|
||||
kicker: 'How it works',
|
||||
title: 'Close the loop from edit to real result',
|
||||
lead: 'Design on the left, validate on the right, then fold the conclusion back.',
|
||||
steps: [
|
||||
{
|
||||
label: 'Workspace',
|
||||
title: 'Design layer',
|
||||
body: 'Keep refining the editable prompt in the left workspace.'
|
||||
},
|
||||
{
|
||||
label: 'Run',
|
||||
title: 'Execution layer',
|
||||
body: 'Use real inputs and model settings on the right.'
|
||||
},
|
||||
{
|
||||
label: 'Return',
|
||||
title: 'Decision layer',
|
||||
body: 'Turn results into changes that can be applied back.'
|
||||
}
|
||||
]
|
||||
},
|
||||
scenario: {
|
||||
kicker: 'Workspace coverage',
|
||||
title: 'Handle more than a single prompt string',
|
||||
lead: 'Single prompts, variable templates, and context chains all fit into the same validation loop.',
|
||||
columns: {
|
||||
type: 'Structure',
|
||||
fit: 'Best for',
|
||||
capability: 'Key capability'
|
||||
},
|
||||
cards: [
|
||||
{
|
||||
label: 'Single prompt',
|
||||
title: 'System / user single prompt',
|
||||
body: 'Best for roles, rules, and output instructions.',
|
||||
tags: ['system', 'user', 'focused analysis']
|
||||
},
|
||||
{
|
||||
label: 'Variables',
|
||||
title: 'Variable templates',
|
||||
body: 'Validate reusable templates with real values.',
|
||||
tags: ['variables', 'real input', 'reuse']
|
||||
},
|
||||
{
|
||||
label: 'Context chain',
|
||||
title: 'Multi-message context',
|
||||
body: 'Useful when system, user, and context all affect the result.',
|
||||
tags: ['system + user', 'context', 'multi-message']
|
||||
}
|
||||
]
|
||||
},
|
||||
access: {
|
||||
kicker: 'Open and access',
|
||||
title: 'Open-source credibility with immediate entry points',
|
||||
lead: 'Check the open surface first, then choose the path that fits you.',
|
||||
proof: {
|
||||
label: 'GitHub repository',
|
||||
title: 'linshenkx/prompt-optimizer',
|
||||
body: 'The same product surface spans web, desktop, self-hosting, Docker, and MCP.',
|
||||
facts: ['AGPL-3.0', 'Web / Desktop / Extension', 'Docker / MCP'],
|
||||
primary: 'View on GitHub',
|
||||
secondary: 'Download Releases'
|
||||
},
|
||||
entries: [
|
||||
{
|
||||
title: 'Web App',
|
||||
body: 'Open the workspace and start optimizing.',
|
||||
href: 'https://prompt.always200.com'
|
||||
},
|
||||
{
|
||||
title: 'Desktop Downloads',
|
||||
body: 'Get installers and archives from Releases.',
|
||||
href: 'https://github.com/linshenkx/prompt-optimizer/releases'
|
||||
},
|
||||
{
|
||||
title: 'Chrome Extension',
|
||||
body: 'Install it from the Chrome Web Store.',
|
||||
href: 'https://chromewebstore.google.com/detail/prompt-optimizer/cakkkhboolfnadechdlgdcnjammejlna'
|
||||
},
|
||||
{
|
||||
title: 'Docker / MCP',
|
||||
body: 'Best for self-hosting and integrations.',
|
||||
href: 'https://docs.always200.com/deployment/docker-basic/'
|
||||
}
|
||||
]
|
||||
},
|
||||
footer: {
|
||||
title: 'Prompt Optimizer',
|
||||
body: 'Bring prompt optimization back to real outputs.',
|
||||
product: 'Product',
|
||||
docs: 'Docs',
|
||||
github: 'GitHub'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeLocale(locale) {
|
||||
if (!locale) return 'zh-CN'
|
||||
if (locale.startsWith('zh')) return 'zh-CN'
|
||||
return 'en'
|
||||
}
|
||||
|
||||
function getInitialLocale() {
|
||||
const storedLocale = window.localStorage.getItem(STORAGE_KEY)
|
||||
if (storedLocale && SUPPORTED_LOCALES.includes(storedLocale)) {
|
||||
return storedLocale
|
||||
}
|
||||
|
||||
const browserLocale = normalizeLocale(navigator.language || navigator.languages?.[0] || 'zh-CN')
|
||||
return SUPPORTED_LOCALES.includes(browserLocale) ? browserLocale : 'zh-CN'
|
||||
}
|
||||
|
||||
function normalizeThemeMode(themeMode) {
|
||||
if (THEME_MODES.includes(themeMode)) return themeMode
|
||||
return 'system'
|
||||
}
|
||||
|
||||
function getInitialThemeMode() {
|
||||
return normalizeThemeMode(window.localStorage.getItem(THEME_STORAGE_KEY) || 'system')
|
||||
}
|
||||
|
||||
function resolveTheme(themeMode) {
|
||||
if (themeMode === 'light' || themeMode === 'dark') return themeMode
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
||||
}
|
||||
|
||||
function getNextThemeMode(themeMode) {
|
||||
if (themeMode === 'system') return 'dark'
|
||||
if (themeMode === 'dark') return 'light'
|
||||
return 'system'
|
||||
}
|
||||
|
||||
function renderLocaleButton(copy) {
|
||||
return `
|
||||
<button class="locale-switch" type="button" data-locale-toggle="true" aria-label="${copy.nav.localeAria}">
|
||||
${copy.nav.locale}
|
||||
</button>
|
||||
`
|
||||
}
|
||||
|
||||
function renderThemeButton(copy, themeMode) {
|
||||
return `
|
||||
<button class="theme-switch" type="button" data-theme-toggle="true" aria-label="${copy.nav.themeAria}" title="${copy.nav.themeAria}">
|
||||
<span class="theme-switch__icon" aria-hidden="true">${renderThemeIcon(themeMode)}</span>
|
||||
<span class="theme-switch__label">${copy.nav.themeLabels[themeMode]}</span>
|
||||
</button>
|
||||
`
|
||||
}
|
||||
|
||||
function renderThemeIcon(themeMode) {
|
||||
if (themeMode === 'dark') {
|
||||
return `
|
||||
<svg viewBox="0 0 24 24" role="img" focusable="false">
|
||||
<path d="M21 12.79A9 9 0 0 1 11.21 3a7.5 7.5 0 1 0 9.79 9.79Z" fill="currentColor" />
|
||||
</svg>
|
||||
`
|
||||
}
|
||||
|
||||
if (themeMode === 'light') {
|
||||
return `
|
||||
<svg viewBox="0 0 24 24" role="img" focusable="false">
|
||||
<circle cx="12" cy="12" r="4.2" fill="currentColor" />
|
||||
<path d="M12 1.5v3M12 19.5v3M4.57 4.57l2.12 2.12M17.31 17.31l2.12 2.12M1.5 12h3M19.5 12h3M4.57 19.43l2.12-2.12M17.31 6.69l2.12-2.12" fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.8" />
|
||||
</svg>
|
||||
`
|
||||
}
|
||||
|
||||
return `
|
||||
<svg viewBox="0 0 24 24" role="img" focusable="false">
|
||||
<rect x="4" y="5" width="16" height="11" rx="2.2" fill="none" stroke="currentColor" stroke-width="1.8" />
|
||||
<path d="M8 19h8" fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.8" />
|
||||
<path d="M10 16.5h4" fill="none" stroke="currentColor" stroke-linecap="round" stroke-width="1.8" />
|
||||
</svg>
|
||||
`
|
||||
}
|
||||
|
||||
function renderGithubPill(copy) {
|
||||
return `
|
||||
<a class="github-pill" href="https://github.com/linshenkx/prompt-optimizer" target="_blank" rel="noopener" aria-label="${copy.nav.githubLabel}">
|
||||
<span class="github-pill__icon" aria-hidden="true">
|
||||
<svg viewBox="0 0 24 24" role="img" focusable="false">
|
||||
<path d="M12 1.5a10.5 10.5 0 0 0-3.32 20.47c.52.1.7-.23.7-.5v-1.95c-2.86.62-3.46-1.21-3.46-1.21-.47-1.18-1.14-1.5-1.14-1.5-.93-.64.07-.63.07-.63 1.03.07 1.57 1.06 1.57 1.06.91 1.56 2.4 1.1 2.98.84.09-.66.36-1.1.65-1.35-2.28-.26-4.67-1.14-4.67-5.08 0-1.12.4-2.04 1.05-2.76-.1-.26-.46-1.31.1-2.73 0 0 .86-.28 2.82 1.05a9.8 9.8 0 0 1 5.13 0c1.96-1.33 2.82-1.05 2.82-1.05.56 1.42.2 2.47.1 2.73.66.72 1.05 1.64 1.05 2.76 0 3.95-2.39 4.82-4.67 5.08.37.32.7.95.7 1.92v2.84c0 .28.18.61.7.5A10.5 10.5 0 0 0 12 1.5Z" fill="currentColor"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="github-pill__text">${copy.nav.github}</span>
|
||||
<img
|
||||
class="github-pill__badge"
|
||||
src="https://img.shields.io/github/stars/linshenkx/prompt-optimizer?style=flat&label=stars&color=2563eb&labelColor=f8fbff&logo=github&logoColor=0f172a"
|
||||
alt="GitHub stars"
|
||||
/>
|
||||
</a>
|
||||
`
|
||||
}
|
||||
|
||||
function renderNav(copy, themeMode) {
|
||||
return `
|
||||
<a href="https://prompt.always200.com" target="_blank" rel="noopener">${copy.nav.product}</a>
|
||||
<a href="https://docs.always200.com" target="_blank" rel="noopener">${copy.nav.docs}</a>
|
||||
${renderGithubPill(copy)}
|
||||
${renderThemeButton(copy, themeMode)}
|
||||
${renderLocaleButton(copy)}
|
||||
`
|
||||
}
|
||||
|
||||
function renderStats(stats) {
|
||||
return stats
|
||||
.map(
|
||||
(item) => `
|
||||
<article class="hero-stat">
|
||||
<strong>${item.value}</strong>
|
||||
<span>${item.label}</span>
|
||||
</article>
|
||||
`
|
||||
)
|
||||
.join('')
|
||||
}
|
||||
|
||||
function renderPills(items, className = '') {
|
||||
return items.map((item) => `<span class="${className}">${item}</span>`).join('')
|
||||
}
|
||||
|
||||
function renderApp(locale, themeMode) {
|
||||
const copy = translations[locale]
|
||||
const resolvedTheme = resolveTheme(themeMode)
|
||||
|
||||
document.documentElement.lang = copy.htmlLang
|
||||
document.documentElement.dataset.locale = locale
|
||||
document.documentElement.dataset.theme = resolvedTheme
|
||||
document.documentElement.dataset.themeMode = themeMode
|
||||
document.title = copy.title
|
||||
|
||||
const descriptionMeta = document.querySelector('meta[name="description"]')
|
||||
const ogDescriptionMeta = document.querySelector('meta[property="og:description"]')
|
||||
const ogTitleMeta = document.querySelector('meta[property="og:title"]')
|
||||
const themeColorMeta = document.querySelector('meta[name="theme-color"]')
|
||||
|
||||
if (descriptionMeta) descriptionMeta.setAttribute('content', copy.description)
|
||||
if (ogDescriptionMeta) ogDescriptionMeta.setAttribute('content', copy.description)
|
||||
if (ogTitleMeta) ogTitleMeta.setAttribute('content', copy.title)
|
||||
if (themeColorMeta) themeColorMeta.setAttribute('content', resolvedTheme === 'dark' ? '#081120' : '#f8fbfe')
|
||||
|
||||
document.querySelector('#app').innerHTML = `
|
||||
<div class="site-shell">
|
||||
<div class="site-background" aria-hidden="true">
|
||||
<div class="site-glow site-glow--left"></div>
|
||||
<div class="site-glow site-glow--right"></div>
|
||||
<div class="site-grid"></div>
|
||||
</div>
|
||||
|
||||
<header class="site-header">
|
||||
<a class="site-brand" href="/" aria-label="${copy.brandAriaLabel}">
|
||||
<img src="/images/logo.png" alt="" class="site-brand__logo" />
|
||||
<span class="site-brand__text">Prompt Optimizer</span>
|
||||
</a>
|
||||
<button class="site-menu-button" type="button" aria-expanded="false" aria-controls="site-nav" aria-label="${copy.nav.menuAria}">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</button>
|
||||
<nav class="site-nav" id="site-nav" aria-label="Primary">
|
||||
${renderNav(copy, themeMode)}
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section class="hero">
|
||||
<div class="hero-copy" data-reveal style="--reveal-delay: 20ms">
|
||||
<div class="eyebrow">
|
||||
<img src="/images/logo.png" alt="" />
|
||||
<span>${copy.hero.eyebrow}</span>
|
||||
</div>
|
||||
<h1 class="hero-title">
|
||||
<span class="hero-title__line hero-title__line--top">${copy.hero.titleTop}</span>
|
||||
<span class="hero-title__line hero-title__line--mid">${copy.hero.titleMid}</span>
|
||||
<span class="hero-title__line hero-title__line--bottom">${copy.hero.titleBottom}</span>
|
||||
</h1>
|
||||
<p class="hero-lead">${copy.hero.lead}</p>
|
||||
<div class="hero-actions">
|
||||
<a class="button button--primary" href="https://prompt.always200.com" target="_blank" rel="noopener">${copy.hero.primary}</a>
|
||||
<a class="button" href="https://docs.always200.com" target="_blank" rel="noopener">${copy.hero.secondary}</a>
|
||||
</div>
|
||||
<div class="hero-proof">
|
||||
${renderStats(copy.hero.stats)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hero-visual" data-reveal style="--reveal-delay: 120ms">
|
||||
<div class="hero-visual__meta">
|
||||
<span class="signal-label">${copy.hero.visualLabel}</span>
|
||||
<p>${copy.hero.visualTitle}</p>
|
||||
</div>
|
||||
<div class="hero-shot">
|
||||
<div class="hero-shot__badge">${copy.hero.screenshotBadge}</div>
|
||||
<img src="/images/demo/knowledge-graph-extractor.png" alt="${copy.hero.screenshotAlt}" />
|
||||
</div>
|
||||
<div class="hero-caption">
|
||||
<strong>${copy.hero.visualSummary}</strong>
|
||||
<div class="hero-caption__tags">
|
||||
${renderPills(copy.hero.visualTags)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section section--value">
|
||||
<div class="value-layout">
|
||||
<div class="section-head value-head" data-reveal>
|
||||
<p class="section-kicker">${copy.value.kicker}</p>
|
||||
<h2>${copy.value.title}</h2>
|
||||
<p class="section-lead">${copy.value.lead}</p>
|
||||
<div class="value-manifesto">
|
||||
<span class="value-manifesto__label">${copy.value.manifestoLabel}</span>
|
||||
<h3>${copy.value.manifestoTitle}</h3>
|
||||
<p>${copy.value.manifestoBody}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="value-principles">
|
||||
${copy.value.principles
|
||||
.map(
|
||||
(principle, index) => `
|
||||
<article class="value-principle" data-reveal style="--reveal-delay: ${80 + index * 70}ms">
|
||||
<span class="value-principle__index">${principle.index}</span>
|
||||
<div class="value-principle__body">
|
||||
<h3>${principle.title}</h3>
|
||||
<p>${principle.body}</p>
|
||||
${
|
||||
principle.tags
|
||||
? `
|
||||
<div class="value-principle__tags">
|
||||
${renderPills(principle.tags)}
|
||||
</div>
|
||||
`
|
||||
: ''
|
||||
}
|
||||
</div>
|
||||
</article>
|
||||
`
|
||||
)
|
||||
.join('')}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section section--workflow" data-reveal>
|
||||
<div class="section-head section-head--center workflow-head">
|
||||
<p class="section-kicker">${copy.workflow.kicker}</p>
|
||||
<h2>${copy.workflow.title}</h2>
|
||||
<p class="section-lead">${copy.workflow.lead}</p>
|
||||
</div>
|
||||
<div class="workflow-line">
|
||||
${copy.workflow.steps
|
||||
.map(
|
||||
(step, index) => `
|
||||
<article class="workflow-node workflow-node--${index + 1}" data-reveal style="--reveal-delay: ${100 + index * 90}ms">
|
||||
<div class="workflow-node__marker">
|
||||
<span class="workflow-index">0${index + 1}</span>
|
||||
</div>
|
||||
<div class="workflow-node__body">
|
||||
<span class="workflow-card__label">${step.label}</span>
|
||||
<h3>${step.title}</h3>
|
||||
<p>${step.body}</p>
|
||||
</div>
|
||||
</article>
|
||||
`
|
||||
)
|
||||
.join('')}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section section--scenario">
|
||||
<div class="scenario-layout">
|
||||
<div class="section-head scenario-head" data-reveal>
|
||||
<p class="section-kicker">${copy.scenario.kicker}</p>
|
||||
<h2>${copy.scenario.title}</h2>
|
||||
<p class="section-lead">${copy.scenario.lead}</p>
|
||||
</div>
|
||||
<div class="scenario-matrix" data-reveal style="--reveal-delay: 100ms">
|
||||
<div class="scenario-matrix__head">
|
||||
<span>${copy.scenario.columns.type}</span>
|
||||
<span>${copy.scenario.columns.fit}</span>
|
||||
<span>${copy.scenario.columns.capability}</span>
|
||||
</div>
|
||||
${copy.scenario.cards
|
||||
.map(
|
||||
(card, index) => `
|
||||
<article class="scenario-row scenario-row--${index + 1}" data-reveal style="--reveal-delay: ${120 + index * 80}ms">
|
||||
<div class="scenario-row__meta">
|
||||
<span class="scenario-row__index">0${index + 1}</span>
|
||||
<span class="scenario-card__label">${card.label}</span>
|
||||
</div>
|
||||
<div class="scenario-row__body">
|
||||
<h3>${card.title}</h3>
|
||||
<p>${card.body}</p>
|
||||
</div>
|
||||
<div class="scenario-row__tags">
|
||||
${renderPills(card.tags)}
|
||||
</div>
|
||||
</article>
|
||||
`
|
||||
)
|
||||
.join('')}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section section--access">
|
||||
<div class="section-head" data-reveal>
|
||||
<p class="section-kicker">${copy.access.kicker}</p>
|
||||
<h2>${copy.access.title}</h2>
|
||||
<p class="section-lead">${copy.access.lead}</p>
|
||||
</div>
|
||||
<article class="proof-strip" data-reveal style="--reveal-delay: 80ms">
|
||||
<div class="proof-strip__main">
|
||||
<div class="proof-strip__top">
|
||||
<div class="proof-strip__title">
|
||||
<span class="proof-strip__label">${copy.access.proof.label}</span>
|
||||
<strong>${copy.access.proof.title}</strong>
|
||||
</div>
|
||||
<img
|
||||
class="proof-strip__stars"
|
||||
src="https://img.shields.io/github/stars/linshenkx/prompt-optimizer?style=for-the-badge&label=stars&color=2d6cff&labelColor=0b1633"
|
||||
alt="GitHub stars"
|
||||
/>
|
||||
</div>
|
||||
<p>${copy.access.proof.body}</p>
|
||||
<div class="proof-strip__facts">
|
||||
${renderPills(copy.access.proof.facts)}
|
||||
</div>
|
||||
</div>
|
||||
<div class="proof-strip__actions">
|
||||
<a class="button button--primary" href="https://github.com/linshenkx/prompt-optimizer" target="_blank" rel="noopener">${copy.access.proof.primary}</a>
|
||||
<a class="button button--light" href="https://github.com/linshenkx/prompt-optimizer/releases" target="_blank" rel="noopener">${copy.access.proof.secondary}</a>
|
||||
</div>
|
||||
</article>
|
||||
<div class="entry-shelf">
|
||||
${copy.access.entries
|
||||
.map(
|
||||
(entry, index) => `
|
||||
<a class="entry-card entry-card--${index + 1}" data-reveal style="--reveal-delay: ${120 + index * 70}ms" href="${entry.href}" target="_blank" rel="noopener">
|
||||
<strong>${entry.title}</strong>
|
||||
<span>${entry.body}</span>
|
||||
</a>
|
||||
`
|
||||
)
|
||||
.join('')}
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer class="site-footer">
|
||||
<div class="site-footer__copy">
|
||||
<strong>${copy.footer.title}</strong>
|
||||
<p>${copy.footer.body}</p>
|
||||
</div>
|
||||
<div class="site-footer__links">
|
||||
<a href="https://prompt.always200.com" target="_blank" rel="noopener">${copy.footer.product}</a>
|
||||
<a href="https://docs.always200.com" target="_blank" rel="noopener">${copy.footer.docs}</a>
|
||||
<a href="https://github.com/linshenkx/prompt-optimizer" target="_blank" rel="noopener">${copy.footer.github}</a>
|
||||
${renderThemeButton(copy, themeMode)}
|
||||
${renderLocaleButton(copy)}
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
`
|
||||
|
||||
bindInteractions(locale, themeMode)
|
||||
bindRevealAnimations()
|
||||
bindMotionEffects()
|
||||
}
|
||||
|
||||
function bindInteractions(locale, themeMode) {
|
||||
const menuButton = document.querySelector('.site-menu-button')
|
||||
const nav = document.querySelector('.site-nav')
|
||||
|
||||
if (menuButton && nav) {
|
||||
menuButton.addEventListener('click', () => {
|
||||
const expanded = menuButton.getAttribute('aria-expanded') === 'true'
|
||||
menuButton.setAttribute('aria-expanded', String(!expanded))
|
||||
nav.classList.toggle('site-nav--open', !expanded)
|
||||
})
|
||||
}
|
||||
|
||||
document.querySelectorAll('[data-locale-toggle="true"]').forEach((button) => {
|
||||
button.addEventListener('click', () => {
|
||||
const nextLocale = locale === 'zh-CN' ? 'en' : 'zh-CN'
|
||||
window.localStorage.setItem(STORAGE_KEY, nextLocale)
|
||||
currentLocale = nextLocale
|
||||
renderApp(currentLocale, currentThemeMode)
|
||||
})
|
||||
})
|
||||
|
||||
document.querySelectorAll('[data-theme-toggle="true"]').forEach((button) => {
|
||||
button.addEventListener('click', () => {
|
||||
const nextThemeMode = getNextThemeMode(themeMode)
|
||||
window.localStorage.setItem(THEME_STORAGE_KEY, nextThemeMode)
|
||||
currentThemeMode = nextThemeMode
|
||||
renderApp(currentLocale, currentThemeMode)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function bindRevealAnimations() {
|
||||
const revealTargets = document.querySelectorAll('[data-reveal]')
|
||||
|
||||
if (!revealTargets.length) return
|
||||
|
||||
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
||||
|
||||
if (prefersReducedMotion) {
|
||||
revealTargets.forEach((node) => node.classList.add('is-visible'))
|
||||
return
|
||||
}
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
revealTargets.forEach((node) => node.classList.add('is-visible'))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function bindMotionEffects() {
|
||||
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
||||
const prefersFinePointer = window.matchMedia('(pointer: fine)').matches
|
||||
|
||||
if (prefersReducedMotion || !prefersFinePointer) return
|
||||
|
||||
const clamp = (value, min, max) => Math.min(max, Math.max(min, value))
|
||||
|
||||
const bindPointerSurface = (selector, prefix, maxTilt = 6, maxShift = 16) => {
|
||||
const element = document.querySelector(selector)
|
||||
if (!element) return
|
||||
|
||||
const reset = () => {
|
||||
element.style.setProperty(`--${prefix}-pointer-x`, '50%')
|
||||
element.style.setProperty(`--${prefix}-pointer-y`, '50%')
|
||||
element.style.setProperty(`--${prefix}-tilt-x`, '0deg')
|
||||
element.style.setProperty(`--${prefix}-tilt-y`, '0deg')
|
||||
element.style.setProperty(`--${prefix}-shift-x`, '0px')
|
||||
element.style.setProperty(`--${prefix}-shift-y`, '0px')
|
||||
}
|
||||
|
||||
const update = (event) => {
|
||||
const rect = element.getBoundingClientRect()
|
||||
const px = clamp(((event.clientX - rect.left) / rect.width) * 100, 0, 100)
|
||||
const py = clamp(((event.clientY - rect.top) / rect.height) * 100, 0, 100)
|
||||
const nx = clamp((px - 50) / 50, -1, 1)
|
||||
const ny = clamp((py - 50) / 50, -1, 1)
|
||||
|
||||
element.style.setProperty(`--${prefix}-pointer-x`, `${px.toFixed(2)}%`)
|
||||
element.style.setProperty(`--${prefix}-pointer-y`, `${py.toFixed(2)}%`)
|
||||
element.style.setProperty(`--${prefix}-tilt-x`, `${(-ny * maxTilt).toFixed(2)}deg`)
|
||||
element.style.setProperty(`--${prefix}-tilt-y`, `${(nx * maxTilt).toFixed(2)}deg`)
|
||||
element.style.setProperty(`--${prefix}-shift-x`, `${(nx * maxShift).toFixed(2)}px`)
|
||||
element.style.setProperty(`--${prefix}-shift-y`, `${(ny * maxShift).toFixed(2)}px`)
|
||||
}
|
||||
|
||||
reset()
|
||||
element.addEventListener('pointermove', update)
|
||||
element.addEventListener('pointerleave', reset)
|
||||
}
|
||||
|
||||
bindPointerSurface('.hero', 'hero', 5.5, 18)
|
||||
bindPointerSurface('.proof-strip', 'proof', 3.5, 10)
|
||||
}
|
||||
|
||||
let currentLocale = getInitialLocale()
|
||||
let currentThemeMode = getInitialThemeMode()
|
||||
|
||||
const colorSchemeMedia = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
|
||||
if (typeof colorSchemeMedia.addEventListener === 'function') {
|
||||
colorSchemeMedia.addEventListener('change', () => {
|
||||
if (currentThemeMode === 'system') {
|
||||
renderApp(currentLocale, currentThemeMode)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
renderApp(currentLocale, currentThemeMode)
|
||||
+2052
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"buildCommand": "pnpm build",
|
||||
"outputDirectory": "dist",
|
||||
"redirects": [
|
||||
{
|
||||
"source": "/docs",
|
||||
"destination": "https://docs.always200.com/",
|
||||
"permanent": true
|
||||
},
|
||||
{
|
||||
"source": "/docs/:path*",
|
||||
"destination": "https://docs.always200.com/:path*",
|
||||
"permanent": true
|
||||
}
|
||||
],
|
||||
"github": {
|
||||
"silent": true
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user