docs: vendor the documentation site into the monorepo

Fold the standalone 3x-ui-docs project (Next.js 16 + Fumadocs, deployed to
docs.sanaei.dev) into docs/ so the panel and its documentation share a single
source of truth, the way sing-box keeps its docs in-tree. The old repo becomes
redundant and can be retired.

- Import the full site under docs/ (app, components, content, lib, public,
  scripts, config). The self-contained pnpm project sits alongside the existing
  engineering notes with no filename collisions.
- Re-point "Edit on GitHub" links from MHSanaei/3x-ui-docs to this repo's
  docs/content/docs path (docs/lib/shared.ts, docs/app/.../page.tsx).
- Add docs-ci.yml and docs-deploy.yml under .github/workflows/, scoped to
  docs/** and run with working-directory: docs, since GitHub only runs
  workflows from the repo-root .github/. deploy-static.yml's GitHub Pages
  publish (CNAME docs.sanaei.dev) carries over unchanged.

Follow-up (outside this commit): attach the docs.sanaei.dev custom domain to
this repository's Pages (or set the Vercel project's root directory to docs),
confirm the site is live from the monorepo, then delete MHSanaei/3x-ui-docs.
This commit is contained in:
MHSanaei
2026-07-07 23:07:14 +02:00
parent 2c49dbf54e
commit 9b91f0f42e
283 changed files with 44179 additions and 0 deletions
@@ -0,0 +1,87 @@
'use client';
import { useState } from 'react';
import {
buildScriptCommand,
buildDockerRun,
buildDockerCompose,
type InstallMethod,
type InstallOptions,
} from '@/lib/xray/install';
import { ToolFrame } from './tool-frame';
import { TextField, SelectField, CheckboxField } from './shared/fields';
import { OutputBlock } from './shared/output-block';
export function InstallCommandBuilder() {
const [method, setMethod] = useState<InstallMethod>('script');
const [version, setVersion] = useState('');
const [enableFail2ban, setEnableFail2ban] = useState(true);
const [panelPort, setPanelPort] = useState('');
const [webBasePath, setWebBasePath] = useState('');
const options: InstallOptions = {
method,
version,
enableFail2ban,
panelPort,
webBasePath,
};
return (
<ToolFrame
title="Install command builder"
description="Build the exact install command for your setup. It is assembled in your browser."
>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
<SelectField
label="Method"
value={method}
onChange={(v) => setMethod(v as InstallMethod)}
options={['script', 'docker']}
/>
<TextField
label="Version"
value={version}
onChange={setVersion}
placeholder="latest"
hint="blank = latest stable · a tag like v3.4.0 · or dev-latest for the rolling dev build"
/>
{method === 'docker' ? (
<>
<TextField
label="Panel port"
value={panelPort}
onChange={setPanelPort}
placeholder="2053"
/>
<TextField
label="Web base path"
value={webBasePath}
onChange={setWebBasePath}
placeholder="/panel"
/>
</>
) : null}
</div>
<div className="mt-3">
<CheckboxField
label="Enable Fail2ban"
checked={enableFail2ban}
onChange={setEnableFail2ban}
/>
</div>
<div className="mt-4 grid grid-cols-1 gap-4">
{method === 'script' ? (
<OutputBlock label="Run on your server" value={buildScriptCommand(options)} />
) : (
<>
<OutputBlock label="docker run" value={buildDockerRun(options)} />
<OutputBlock label="docker-compose.yml" value={buildDockerCompose(options)} />
</>
)}
</div>
</ToolFrame>
);
}