fumadocs-deploy
2
总安装量
2
周安装量
#67326
全站排名
安装命令
npx skills add https://github.com/foreveryh/deeptoai-skills --skill fumadocs-deploy
Agent 安装分布
opencode
2
gemini-cli
2
claude-code
2
github-copilot
2
codex
2
kimi-cli
2
Skill 文档
Fumadocs Deploy
Fumadocs æå»ºåé¨ç½²éªè¯å·¥å ·ï¼ç¡®ä¿ææèµæºæ£ç¡®é¨ç½²ã
åç½®æ¡ä»¶
- Fumadocs 项ç®å·²åå§å
- Caddy å·²å®è£ å¹¶é ç½®
- æå»ºè¾åºç®å½ï¼
apps/docs-app/out/
宿´æµç¨
Step 0: é ç½®æ£æ¥ï¼éè¦ï¼ï¼
æ£æ¥ Next.js é ç½®:
# éæå¯¼åºå¿
é¡»ç¦ç¨å¾çä¼å
if ! grep -q "unoptimized: true" next.config.mjs; then
echo "â ç¼ºå° images.unoptimized: true"
echo ""
echo "è¯·å¨ next.config.mjs 䏿·»å ï¼"
echo ""
echo "export default {"
echo " output: 'export',"
echo " images: {"
echo " unoptimized: true,"
echo " },"
echo "}"
exit 1
fi
echo "â
Next.js é
ç½®æ£ç¡®"
æ£æ¥ i18n é ç½®ï¼å¦æä½¿ç¨å¤è¯è¨ï¼:
# æ£æ¥ UI ç¿»è¯æä»¶æ¯å¦å®æ´
for lang in en zh-CN fr; do
if [ ! -f "libs/i18n/locales/$lang.ts" ]; then
echo "â ï¸ ç¼ºå° $lang.ts ç¿»è¯æä»¶"
else
lines=$(wc -l < "libs/i18n/locales/$lang.ts")
echo "â
$lang.ts: $lines è¡"
fi
done
Step 1: æ¸ çç¼å
æ¸ çæå»ºç¼å:
# æ¸
çææç¼å
rm -rf .turbo
rm -rf apps/docs-app/.next
rm -rf apps/docs-app/out
echo "â
ç¼åå·²æ¸
ç"
Step 2: æå»º
è¿è¡æå»ºå½ä»¤:
# æå»º Fumadocs
pnpm build:docs
# æ£æ¥æå»ºç»æ
if [ -d "apps/docs-app/out" ]; then
echo "â
æå»ºæå"
ls -lh apps/docs-app/out/ | head -10
else
echo "â æå»ºå¤±è´¥"
exit 1
fi
éªè¯æå»ºè¾åº:
# æ£æ¥ HTML æä»¶
find apps/docs-app/out -name "*.html" | wc -l
# æ£æ¥å¾ç
find apps/docs-app/out/images -type f 2>/dev/null | wc -l
# æ£æ¥éæèµæº
find apps/docs-app/out/_next -type f 2>/dev/null | wc -l
Step 3: Caddy é ç½®æ£æ¥
å¿ éçè·¯å¾é ç½®:
# /etc/caddy/Caddyfile
yourdomain.com {
# å¿
é¡»å
å«çè·¯å¾
@docs_static path /_next* /docs* /zh-CN/docs* /en/docs* /fr/docs* /images*
root * /path/to/fumadocs/apps/docs-app/out
# éææä»¶æå¡
file_server @docs_static
# SPA fallbackï¼å¦æä½¿ç¨ï¼
@docs_not_static not path /_next* /images*
try_files @docs_not_static {path} /index.html
}
æ£æ¥ Caddy é ç½®:
# éªè¯ Caddyfile è¯æ³
caddy validate --config /etc/caddy/Caddyfile
# æ£æ¥å¿
éè·¯å¾
grep -E "/_next\*|/docs\*|/images\*" /etc/caddy/Caddyfile || echo "â ï¸ ç¼ºå°è·¯å¾é
ç½®"
常è§é ç½®é®é¢:
| é®é¢ | åå | è§£å³æ¹æ¡ |
|---|---|---|
| å¾ç 404 | Caddy æªé
ç½® /images* |
æ·»å @docs_static path /images* |
| é¡µé¢ 404 | è¯è¨è·¯å¾æªå å« | æ·»å /en/docs* /zh-CN/docs* |
| æ ·å¼ä¸¢å¤± | /_next* è·¯å¾æªé
ç½® |
æ·»å @docs_static path /_next* |
Step 4: éè½½ Caddy
# ä¼é
éè½½ï¼ä¸ä¸ææå¡ï¼
sudo systemctl reload caddy
# æä½¿ç¨ Caddy å½ä»¤
caddy reload --config /etc/caddy/Caddyfile
# æ£æ¥ Caddy ç¶æ
sudo systemctl status caddy
Step 5: é¨ç½²éªè¯
éªè¯æ¸ å:
DOMAIN="yourdomain.com"
SLUG="your-article"
echo "=== é¨ç½²éªè¯ ==="
# 1. æµè¯ä¸»é¡µ
curl -s -o /dev/null -w "主页: %{http_code}\n" "https://$DOMAIN/"
# 2. æµè¯æç« 页é¢ï¼åè¯è¨ï¼
curl -s -o /dev/null -w "è±æé¡µé¢: %{http_code}\n" "https://$DOMAIN/en/docs/$SLUG"
curl -s -o /dev/null -w "䏿页é¢: %{http_code}\n" "https://$DOMAIN/zh-CN/docs/$SLUG"
# 3. æµè¯å¾ç
curl -s -o /dev/null -w "å¾ç1: %{http_code}\n" "https://$DOMAIN/images/docs/$SLUG/img01.png"
# 4. æµè¯éæèµæº
curl -s -o /dev/null -w "CSS: %{http_code}\n" "https://$DOMAIN/_next/static/css/$(ls apps/docs-app/out/_next/static/css/ | head -1)"
echo "=== éªè¯å®æ ==="
ææç»æ:
主页: 200
è±æé¡µé¢: 200
䏿页é¢: 200
å¾ç1: 200
CSS: 200
é¨ç½²åæ£æ¥
æ£æ¥ Next.js é ç½®ï¼éè¦ï¼ï¼
éæå¯¼åºå¿ é¡»ç¦ç¨å¾çä¼å:
// next.config.mjs æ next.config.js
export default {
output: 'export',
images: {
unoptimized: true, // â å¿
é¡»ï¼éæå¯¼åºæ¶å¾çä¼å API ä¸å¯ç¨
},
trailingSlash: true,
}
妿æªç¦ç¨ï¼ä¼åºç°:
/_next/image?url=...è¿å 404- å¾çæ æ³å è½½
éªè¯é ç½®:
# æ£æ¥é
ç½®æä»¶
grep "unoptimized: true" next.config.mjs || echo "â ï¸ éè¦æ·»å images.unoptimized: true"
æ£æ¥å¾çå¯è®¿é®æ§
# æ£æ¥ææå¾ç
for img in apps/docs-app/out/images/docs/**/*.png; do
url="https://$DOMAIN${img#apps/docs-app/out}"
status=$(curl -s -o /dev/null -w "%{http_code}" "$url")
if [ "$status" != "200" ]; then
echo "â $url: $status"
fi
done
æ£æ¥é¡µé¢æ¸²æ
# æ£æ¥ HTML å
嫿£ç¡®å
容
curl -s "https://$DOMAIN/en/docs/$SLUG" | grep -q "<title>" && echo "â
æ é¢åå¨"
curl -s "https://$DOMAIN/en/docs/$SLUG" | grep -q "<meta name=\"description\"" && echo "â
æè¿°åå¨"
常è§é®é¢ææ¥
é®é¢ 1: å¾ç 404
è¯æ:
# æ£æ¥å¾çæ¯å¦åå¨
ls -l apps/docs-app/out/images/docs/$SLUG/
# æ£æ¥ Caddy é
ç½®
grep "/images\*" /etc/caddy/Caddyfile
# æ£æ¥æä»¶æé
stat apps/docs-app/out/images/docs/$SLUG/*.png
è§£å³:
- 确认å¾çå·²ä¸è½½å°æ£ç¡®ä½ç½®
- 确认 Caddy é
ç½®å
å«
/images*è·¯å¾ - 确认æä»¶æéå¯è¯»ï¼644ï¼
é®é¢ 2: é¡µé¢ 404
è¯æ:
# æ£æ¥ HTML æä»¶æ¯å¦åå¨
ls -l apps/docs-app/out/en/docs/$SLUG.html
# æ£æ¥ Caddy é
ç½®
grep "/en/docs\*" /etc/caddy/Caddyfile
è§£å³:
- 确认æå»ºæå
- 确认è¯è¨è·¯å¾å·²é ç½®
- éè½½ Caddy
é®é¢ 3: æ ·å¼ä¸¢å¤±
è¯æ:
# æ£æ¥éæèµæº
ls -l apps/docs-app/out/_next/static/css/
# æ£æ¥ Caddy é
ç½®
grep "/_next\*" /etc/caddy/Caddyfile
è§£å³:
- 确认
/_next*è·¯å¾å·²é ç½® - æ¸ çæµè§å¨ç¼å
- éæ°æå»º
ä¸å ¶ä» Skills é å
fumadocs-article-importer (导å
¥æç« )
â
article-translator (ç¿»è¯å
容)
â
mdx-validator (颿£æ¥)
â
pnpm build:docs (æå»º)
â
fumadocs-deploy â ä½ å¨è¿éï¼é¨ç½²éªè¯ï¼
èªå¨åé¨ç½²èæ¬
#!/bin/bash
# deploy-fumadocs.sh
set -e
echo "=== å¼å§é¨ç½² ==="
# 1. æ¸
ç
echo "æ¸
çç¼å..."
rm -rf .turbo apps/docs-app/.next apps/docs-app/out
# 2. æå»º
echo "æå»ºé¡¹ç®..."
pnpm build:docs
# 3. éªè¯æå»º
if [ ! -d "apps/docs-app/out" ]; then
echo "â æå»ºå¤±è´¥"
exit 1
fi
# 4. éè½½ Caddy
echo "éè½½ Caddy..."
sudo systemctl reload caddy
# 5. éªè¯é¨ç½²
echo "éªè¯é¨ç½²..."
sleep 2
DOMAIN="yourdomain.com"
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://$DOMAIN/")
if [ "$STATUS" = "200" ]; then
echo "â
é¨ç½²æåï¼"
else
echo "â é¨ç½²å¤±è´¥: HTTP $STATUS"
exit 1
fi
é 置示ä¾
next.config.js
module.exports = {
output: 'export',
images: {
unoptimized: true, // éæå¯¼åºå¿
é¡»ç¦ç¨å¾çä¼å
},
trailingSlash: true,
}
Caddyfileï¼å®æ´ç¤ºä¾ï¼
docs.example.com {
# æ¥å¿
log {
output file /var/log/caddy/docs-access.log
}
# éææä»¶è·¯å¾
@static path /_next* /docs* /en/docs* /zh-CN/docs* /fr/docs* /images*
root * /var/www/fumadocs/apps/docs-app/out
# éææä»¶æå¡
file_server @static
# å缩
encode gzip zstd
# ç¼å
@cacheable path /_next/static/*
header @cacheable Cache-Control "public, max-age=31536000, immutable"
# å®å
¨å¤´
header {
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
Referrer-Policy "strict-origin-when-cross-origin"
}
}
çæ§åæ¥å¿
# æ¥ç Caddy æ¥å¿
sudo journalctl -u caddy -f
# æ¥çè®¿é®æ¥å¿
tail -f /var/log/caddy/docs-access.log
# æ£æ¥é误
grep "ERROR" /var/log/caddy/docs-access.log