Restructure to Turbo monorepo with 13 documentation apps

Single-app → multi-app monorepo architecture:
- apps/docs/ — Main Lux docs (replaces root-level app)
- apps/bootnode-docs/ — Bootnode service
- apps/bridge-docs/ — Bridge service
- apps/cli-docs/ — CLI tool
- apps/explorer-docs/ — Block explorer
- apps/hsm-docs/ — Hardware security module
- apps/indexer-docs/ — Blockchain indexer
- apps/kms-docs/ — Key management service
- apps/mpc-docs/ — Multi-party computation
- apps/netrunner-docs/ — Network testing
- apps/sdk-docs/ — SDK documentation
- apps/wallet-docs/ — Wallet service

New: pnpm-workspace.yaml, turbo.json, per-app configs
Updated: Dockerfile (filter build), .gitignore (.turbo/, .docs/)
Root package.json stripped to workspace orchestrator
This commit is contained in:
2026-03-14 16:26:20 -07:00
parent c339b011c7
commit 8446558013
436 changed files with 17017 additions and 1343 deletions
-12
View File
@@ -1,12 +0,0 @@
// @ts-nocheck
import { browser } from '@hanzo/docs-mdx/runtime/browser';
import type * as Config from '../source.config';
const create = browser<typeof Config, import("@hanzo/docs-mdx/runtime/types").InternalTypeConfig & {
DocData: {
}
}>();
const browserCollections = {
docs: create.doc("docs", {"index.mdx": () => import("../content/docs/index.mdx?collection=docs"), "build/contracts.mdx": () => import("../content/docs/build/contracts.mdx?collection=docs"), "build/index.mdx": () => import("../content/docs/build/index.mdx?collection=docs"), "build/sdks.mdx": () => import("../content/docs/build/sdks.mdx?collection=docs"), "build/subnets.mdx": () => import("../content/docs/build/subnets.mdx?collection=docs"), "build/tutorials.mdx": () => import("../content/docs/build/tutorials.mdx?collection=docs"), "learn/architecture.mdx": () => import("../content/docs/learn/architecture.mdx?collection=docs"), "learn/consensus.mdx": () => import("../content/docs/learn/consensus.mdx?collection=docs"), "learn/index.mdx": () => import("../content/docs/learn/index.mdx?collection=docs"), "learn/post-quantum.mdx": () => import("../content/docs/learn/post-quantum.mdx?collection=docs"), "learn/tokenomics.mdx": () => import("../content/docs/learn/tokenomics.mdx?collection=docs"), "nodes/archive.mdx": () => import("../content/docs/nodes/archive.mdx?collection=docs"), "nodes/full-node.mdx": () => import("../content/docs/nodes/full-node.mdx?collection=docs"), "nodes/index.mdx": () => import("../content/docs/nodes/index.mdx?collection=docs"), "nodes/validator.mdx": () => import("../content/docs/nodes/validator.mdx?collection=docs"), "reference/health.mdx": () => import("../content/docs/reference/health.mdx?collection=docs"), "reference/index.mdx": () => import("../content/docs/reference/index.mdx?collection=docs"), "reference/info.mdx": () => import("../content/docs/reference/info.mdx?collection=docs"), "reference/json-rpc.mdx": () => import("../content/docs/reference/json-rpc.mdx?collection=docs"), "reference/platform.mdx": () => import("../content/docs/reference/platform.mdx?collection=docs"), "reference/sdk-go.mdx": () => import("../content/docs/reference/sdk-go.mdx?collection=docs"), "reference/sdk-js.mdx": () => import("../content/docs/reference/sdk-js.mdx?collection=docs"), }),
};
export default browserCollections;
-8
View File
@@ -1,8 +0,0 @@
// @ts-nocheck
import { dynamic } from '@hanzo/docs-mdx/runtime/dynamic';
import * as Config from '../source.config';
const create = await dynamic<typeof Config, import("@hanzo/docs-mdx/runtime/types").InternalTypeConfig & {
DocData: {
}
}>(Config, {"configPath":"source.config.ts","environment":"next","outDir":".docs"}, {"doc":{"passthroughs":["extractedReferences"]}});
-37
View File
@@ -1,37 +0,0 @@
// @ts-nocheck
import { frontmatter as __fd_glob_26 } from "../content/docs/reference/sdk-js.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_25 } from "../content/docs/reference/sdk-go.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_24 } from "../content/docs/reference/platform.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_23 } from "../content/docs/reference/json-rpc.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_22 } from "../content/docs/reference/info.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_21 } from "../content/docs/reference/index.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_20 } from "../content/docs/reference/health.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_19 } from "../content/docs/nodes/validator.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_18 } from "../content/docs/nodes/index.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_17 } from "../content/docs/nodes/full-node.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_16 } from "../content/docs/nodes/archive.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_15 } from "../content/docs/learn/tokenomics.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_14 } from "../content/docs/learn/post-quantum.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_13 } from "../content/docs/learn/index.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_12 } from "../content/docs/learn/consensus.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_11 } from "../content/docs/learn/architecture.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_10 } from "../content/docs/build/tutorials.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_9 } from "../content/docs/build/subnets.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_8 } from "../content/docs/build/sdks.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_7 } from "../content/docs/build/index.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_6 } from "../content/docs/build/contracts.mdx?collection=docs&only=frontmatter"
import { frontmatter as __fd_glob_5 } from "../content/docs/index.mdx?collection=docs&only=frontmatter"
import { default as __fd_glob_4 } from "../content/docs/reference/meta.json?collection=docs"
import { default as __fd_glob_3 } from "../content/docs/nodes/meta.json?collection=docs"
import { default as __fd_glob_2 } from "../content/docs/learn/meta.json?collection=docs"
import { default as __fd_glob_1 } from "../content/docs/build/meta.json?collection=docs"
import { default as __fd_glob_0 } from "../content/docs/meta.json?collection=docs"
import { server } from '@hanzo/docs-mdx/runtime/server';
import type * as Config from '../source.config';
const create = server<typeof Config, import("@hanzo/docs-mdx/runtime/types").InternalTypeConfig & {
DocData: {
}
}>({"doc":{"passthroughs":["extractedReferences"]}});
export const docs = await create.docsLazy("docs", "content/docs", {"meta.json": __fd_glob_0, "build/meta.json": __fd_glob_1, "learn/meta.json": __fd_glob_2, "nodes/meta.json": __fd_glob_3, "reference/meta.json": __fd_glob_4, }, {"index.mdx": __fd_glob_5, "build/contracts.mdx": __fd_glob_6, "build/index.mdx": __fd_glob_7, "build/sdks.mdx": __fd_glob_8, "build/subnets.mdx": __fd_glob_9, "build/tutorials.mdx": __fd_glob_10, "learn/architecture.mdx": __fd_glob_11, "learn/consensus.mdx": __fd_glob_12, "learn/index.mdx": __fd_glob_13, "learn/post-quantum.mdx": __fd_glob_14, "learn/tokenomics.mdx": __fd_glob_15, "nodes/archive.mdx": __fd_glob_16, "nodes/full-node.mdx": __fd_glob_17, "nodes/index.mdx": __fd_glob_18, "nodes/validator.mdx": __fd_glob_19, "reference/health.mdx": __fd_glob_20, "reference/index.mdx": __fd_glob_21, "reference/info.mdx": __fd_glob_22, "reference/json-rpc.mdx": __fd_glob_23, "reference/platform.mdx": __fd_glob_24, "reference/sdk-go.mdx": __fd_glob_25, "reference/sdk-js.mdx": __fd_glob_26, }, {"index.mdx": () => import("../content/docs/index.mdx?collection=docs"), "build/contracts.mdx": () => import("../content/docs/build/contracts.mdx?collection=docs"), "build/index.mdx": () => import("../content/docs/build/index.mdx?collection=docs"), "build/sdks.mdx": () => import("../content/docs/build/sdks.mdx?collection=docs"), "build/subnets.mdx": () => import("../content/docs/build/subnets.mdx?collection=docs"), "build/tutorials.mdx": () => import("../content/docs/build/tutorials.mdx?collection=docs"), "learn/architecture.mdx": () => import("../content/docs/learn/architecture.mdx?collection=docs"), "learn/consensus.mdx": () => import("../content/docs/learn/consensus.mdx?collection=docs"), "learn/index.mdx": () => import("../content/docs/learn/index.mdx?collection=docs"), "learn/post-quantum.mdx": () => import("../content/docs/learn/post-quantum.mdx?collection=docs"), "learn/tokenomics.mdx": () => import("../content/docs/learn/tokenomics.mdx?collection=docs"), "nodes/archive.mdx": () => import("../content/docs/nodes/archive.mdx?collection=docs"), "nodes/full-node.mdx": () => import("../content/docs/nodes/full-node.mdx?collection=docs"), "nodes/index.mdx": () => import("../content/docs/nodes/index.mdx?collection=docs"), "nodes/validator.mdx": () => import("../content/docs/nodes/validator.mdx?collection=docs"), "reference/health.mdx": () => import("../content/docs/reference/health.mdx?collection=docs"), "reference/index.mdx": () => import("../content/docs/reference/index.mdx?collection=docs"), "reference/info.mdx": () => import("../content/docs/reference/info.mdx?collection=docs"), "reference/json-rpc.mdx": () => import("../content/docs/reference/json-rpc.mdx?collection=docs"), "reference/platform.mdx": () => import("../content/docs/reference/platform.mdx?collection=docs"), "reference/sdk-go.mdx": () => import("../content/docs/reference/sdk-go.mdx?collection=docs"), "reference/sdk-js.mdx": () => import("../content/docs/reference/sdk-js.mdx?collection=docs"), });
-28
View File
@@ -1,28 +0,0 @@
// source.config.ts
import { defineConfig, defineDocs } from "@hanzo/docs/mdx/config";
var docs = defineDocs({
docs: {
async: true
},
meta: {}
});
var source_config_default = defineConfig({
mdxOptions: async () => {
const { rehypeCodeDefaultOptions } = await import("@hanzo/docs/core/mdx-plugins/rehype-code");
return {
rehypeCodeOptions: {
langs: ["ts", "js", "html", "tsx", "mdx", "go", "rust", "bash", "json", "yaml", "toml"],
inline: "tailing-curly-colon",
themes: {
light: "github-light",
dark: "github-dark"
},
transformers: [...rehypeCodeDefaultOptions.transformers ?? []]
}
};
}
});
export {
source_config_default as default,
docs
};
+4
View File
@@ -4,10 +4,14 @@ node_modules/
# Build outputs
.next/
.docs/
out/
dist/
.source/
# Turbo
.turbo/
# Environment
.env
.env.local
+5 -4
View File
@@ -1,12 +1,13 @@
FROM node:22-alpine AS build
WORKDIR /app
RUN corepack enable pnpm
COPY package.json pnpm-lock.yaml ./
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json ./
COPY apps/docs/package.json apps/docs/package.json
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build
COPY apps/docs apps/docs
RUN pnpm --filter docs build
FROM nginx:alpine
COPY --from=build /app/out /usr/share/nginx/html
COPY --from=build /app/apps/docs/out /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 3000
+8
View File
@@ -0,0 +1,8 @@
import type { ReactNode } from 'react';
import { HomeLayout } from '@hanzo/docs-base-ui/layouts/home';
import { baseOptions } from '@/lib/layout.shared';
import { linkItems } from '@/lib/layout.shared';
export default function Layout({ children }: { children: ReactNode }) {
return <HomeLayout {...baseOptions()} links={linkItems}>{children}</HomeLayout>;
}
+42
View File
@@ -0,0 +1,42 @@
import Link from 'next/link';
export default function HomePage() {
return (
<main className="flex flex-1 flex-col items-center justify-center text-center px-4 py-16">
<div className="max-w-3xl mx-auto">
<div className="inline-flex items-center gap-2 rounded-full border border-fd-border px-4 py-1.5 text-sm text-fd-muted-foreground mb-6">
RPC · WebSockets · NFT API · Token API
</div>
<h1 className="text-5xl md:text-7xl font-bold mb-6 bg-gradient-to-r from-blue-400 to-indigo-400 bg-clip-text text-transparent">
Lux Cloud
</h1>
<p className="text-lg text-fd-muted-foreground mb-8 max-w-2xl mx-auto">
Enterprise blockchain infrastructure APIs. Multi-chain RPC proxy,
real-time WebSockets, token and NFT APIs, and webhook notifications.
</p>
<div className="rounded-lg border border-fd-border bg-fd-card p-4 mb-8 max-w-md mx-auto font-mono text-sm">
<span className="text-fd-muted-foreground">$</span>{' '}curl https://api.lux.cloud/v1/health
</div>
<div className="flex gap-4 justify-center mb-16">
<Link href="/docs" className="rounded-lg bg-fd-primary text-fd-primary-foreground px-6 py-3 font-medium hover:bg-fd-primary/90 transition-colors">Get Started</Link>
<Link href="/docs/api" className="rounded-lg border border-fd-border px-6 py-3 font-medium hover:bg-fd-accent transition-colors">API Reference</Link>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 text-left">
{[
{ name: 'Multi-Chain RPC', desc: 'JSON-RPC proxy with load balancing for all Lux chains' },
{ name: 'WebSockets', desc: 'Real-time blockchain event subscriptions' },
{ name: 'Token API', desc: 'ERC-20/721/1155 balances, metadata, and transfers' },
{ name: 'NFT API', desc: 'NFT collections, ownership, and media' },
{ name: 'Webhooks', desc: 'Event-driven notifications for on-chain activity' },
{ name: 'White-Label', desc: 'Deploy as Lux Cloud, Hanzo Web3, or custom brand' },
].map((c) => (
<div key={c.name} className="rounded-lg border border-fd-border bg-fd-card p-5 hover:border-fd-ring transition-colors">
<h3 className="font-semibold mb-1">{c.name}</h3>
<p className="text-sm text-fd-muted-foreground">{c.desc}</p>
</div>
))}
</div>
</div>
</main>
);
}
@@ -0,0 +1,96 @@
import type { Metadata } from 'next';
import { type ComponentProps, type FC, type ReactNode } from 'react';
import { Callout } from '@hanzo/docs-base-ui/components/callout';
import { TypeTable } from '@hanzo/docs-base-ui/components/type-table';
import { createMetadata } from '@/lib/metadata';
import { source } from '@/lib/source';
import { Card, Cards } from '@hanzo/docs-base-ui/components/card';
import Link from '@hanzo/docs-core/link';
import { findSiblings } from '@hanzo/docs-core/page-tree';
import { DocsBody, DocsPage, PageLastUpdate } from '@hanzo/docs-base-ui/layouts/docs/page';
import { notFound } from 'next/navigation';
import { getMDXComponents } from '@/mdx-components';
interface DocsPageProps {
params: Promise<{ slug?: string[] }>;
}
export const revalidate = false;
export default async function Page(props: DocsPageProps) {
const params = await props.params;
const page = source.getPage(params.slug);
if (!page) notFound();
const { body: Mdx, toc, lastModified } = await page.data.load();
return (
<DocsPage
toc={toc}
tableOfContent={{
style: 'clerk',
}}
>
<h1 className="text-[1.75em] font-semibold">{page.data.title}</h1>
<p className="text-lg text-fd-muted-foreground mb-6">{page.data.description}</p>
<div className="prose flex-1 text-fd-foreground/90">
<Mdx
components={getMDXComponents({
a: (props) => <Link {...props} />,
blockquote: Callout as unknown as FC<ComponentProps<'blockquote'>>,
TypeTable,
DocsCategory: ({ url }) => {
return <DocsCategory url={url ?? page.url} />;
},
})}
/>
{page.data.index ? <DocsCategory url={page.url} /> : null}
</div>
{lastModified && <PageLastUpdate date={lastModified} />}
</DocsPage>
);
}
function DocsCategory({ url }: { url: string }) {
return (
<Cards>
{findSiblings(source.getPageTree(), url).map((item) => {
if (item.type === 'separator') return;
if (item.type === 'folder') {
if (!item.index) return;
item = item.index;
}
return (
<Card key={item.url} title={item.name} href={item.url}>
{item.description}
</Card>
);
})}
</Cards>
);
}
export async function generateMetadata(props: DocsPageProps): Promise<Metadata> {
const { slug = [] } = await props.params;
const page = source.getPage(slug);
if (!page)
return createMetadata({
title: 'Not Found',
});
const description = page.data.description ?? 'Lux Cloud Documentation';
return createMetadata({
title: page.data.title,
description,
openGraph: {
url: `/docs/${page.slugs.join('/')}`,
},
});
}
export function generateStaticParams() {
return source.generateParams();
}
+43
View File
@@ -0,0 +1,43 @@
import { DocsLayout } from '@hanzo/docs/ui/layouts/docs';
import { baseOptions, linkItems, logo } from '@/lib/layout.shared';
import { source } from '@/lib/source';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
const base = baseOptions();
return (
<DocsLayout
{...base}
tree={source.getPageTree()}
links={linkItems.filter((item) => item.type === 'icon')}
nav={{
...base.nav,
title: (
<>
{logo}
<span className="font-medium max-md:hidden">Lux Cloud</span>
</>
),
}}
sidebar={{
tabs: {
transform(option, node) {
if (!node.icon) return option;
return {
...option,
icon: (
<div className="[&_svg]:size-full rounded-lg size-full text-brand max-md:bg-brand/10 max-md:border max-md:p-1.5">
{node.icon}
</div>
),
};
},
},
}}
>
{children}
</DocsLayout>
);
}
+38
View File
@@ -0,0 +1,38 @@
@import 'tailwindcss';
@import '@hanzo/docs-base-ui/css/neutral.css';
@import '@hanzo/docs-base-ui/css/preset.css';
@plugin 'tailwindcss-animate';
@theme {
--spacing-page: 1436px;
--color-brand: hsl(220, 84%, 50%);
--color-brand-foreground: white;
}
@theme inline {
--default-mono-font-family: var(--font-mono);
}
html { scrollbar-gutter: stable; }
html:has(body[data-scroll-locked]) { scrollbar-gutter: auto; }
body { background-color: var(--color-fd-background); }
:root {
color-scheme: dark;
--color-fd-background: hsl(0, 0%, 2%);
--color-fd-foreground: hsl(0, 0%, 96%);
--color-fd-muted: hsl(0, 0%, 10%);
--color-fd-muted-foreground: hsla(0, 0%, 70%, 0.85);
--color-fd-popover: hsl(0, 0%, 4%);
--color-fd-popover-foreground: hsl(0, 0%, 90%);
--color-fd-card: hsl(0, 0%, 4%);
--color-fd-card-foreground: hsl(0, 0%, 96%);
--color-fd-border: hsla(0, 0%, 40%, 0.2);
--color-fd-primary: hsl(0, 0%, 96%);
--color-fd-primary-foreground: hsl(0, 0%, 8%);
--color-fd-secondary: hsl(0, 0%, 12%);
--color-fd-secondary-foreground: hsl(0, 0%, 92%);
--color-fd-accent: hsla(0, 0%, 40%, 0.3);
--color-fd-accent-foreground: hsl(0, 0%, 92%);
--color-fd-ring: hsl(0, 0%, 55%);
}
+19
View File
@@ -0,0 +1,19 @@
'use client';
import { ThemeProvider } from 'next-themes';
import type { ReactNode } from 'react';
export function Body({ children }: { children: ReactNode }) {
return (
<body className="antialiased">
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
{children}
</ThemeProvider>
</body>
);
}
+43
View File
@@ -0,0 +1,43 @@
import './global.css';
import type { Viewport } from 'next';
import { baseUrl, createMetadata } from '@/lib/metadata';
import { Body } from '@/app/layout.client';
import { Provider } from './provider';
import type { ReactNode } from 'react';
import { Geist, Geist_Mono } from 'next/font/google';
import { TreeContextProvider } from '@hanzo/docs/ui/contexts/tree';
import { source } from '@/lib/source';
import { NextProvider } from '@hanzo/docs/core/framework/next';
export const metadata = createMetadata({
title: {
template: '%s | Lux Cloud',
default: 'Lux Cloud - Blockchain Infrastructure Platform',
},
description: 'Enterprise blockchain infrastructure APIs. Multi-chain RPC, WebSockets, NFT API, token API, and more.',
metadataBase: baseUrl,
});
const geist = Geist({ variable: '--font-sans', subsets: ['latin'] });
const mono = Geist_Mono({ variable: '--font-mono', subsets: ['latin'] });
export const viewport: Viewport = {
themeColor: [
{ media: '(prefers-color-scheme: dark)', color: '#0A0A0A' },
{ media: '(prefers-color-scheme: light)', color: '#0A0A0A' },
],
};
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en" className={`${geist.variable} ${mono.variable}`} suppressHydrationWarning>
<Body>
<NextProvider>
<TreeContextProvider tree={source.getPageTree()}>
<Provider>{children}</Provider>
</TreeContextProvider>
</NextProvider>
</Body>
</html>
);
}
+15
View File
@@ -0,0 +1,15 @@
'use client';
import { RootProvider } from '@hanzo/docs/ui/provider/base';
import type { ReactNode } from 'react';
import { TooltipProvider } from '@radix-ui/react-tooltip';
export function Provider({ children }: { children: ReactNode }) {
return (
<RootProvider theme={{ defaultTheme: 'dark', enableSystem: false }}>
<TooltipProvider>
{children}
</TooltipProvider>
</RootProvider>
);
}
+19
View File
@@ -0,0 +1,19 @@
---
title: API Reference
description: REST API endpoints
icon: FileCode
---
## Authentication
All requests require an API key via Bearer token.
## Endpoints
| Method | Path | Description |
|--------|------|-------------|
| POST | `/v1/rpc/{chain}` | JSON-RPC proxy |
| GET | `/v1/tokens/balances` | Token balances |
| GET | `/v1/nft/owner` | NFT ownership |
| POST | `/v1/webhooks` | Create webhook |
| GET | `/v1/health` | Health check |
@@ -0,0 +1,15 @@
---
title: Configuration
description: Environment variables
icon: Settings
---
## Environment Variables
| Variable | Description |
|----------|-------------|
| `API_KEY_SALT` | Salt for API key hashing |
| `DATABASE_URL` | PostgreSQL connection |
| `REDIS_URL` | Redis for WebSocket state |
| `RPC_ENDPOINTS` | Upstream node endpoints |
| `NEXT_PUBLIC_BRAND` | Brand (lux/hanzo/zoo/bootnode) |
@@ -0,0 +1,13 @@
---
title: Deployment
description: Deploy Lux Cloud infrastructure
icon: Server
---
## Architecture
```
Traefik LB → API Gateway → RPC Proxy → Lux Nodes
→ Token Indexer → PostgreSQL
→ WebSocket Hub → Redis
```
+33
View File
@@ -0,0 +1,33 @@
---
title: Lux Cloud
description: Enterprise blockchain infrastructure platform
index: true
icon: Cloud
---
Lux Cloud provides unified APIs for interacting with blockchain networks. Deploy as lux.cloud, web3.hanzo.ai, or your own brand.
## APIs
| API | Description |
|-----|-------------|
| **RPC** | Multi-chain JSON-RPC proxy with load balancing |
| **WebSockets** | Real-time blockchain subscriptions |
| **Token API** | ERC-20/721/1155 balances and metadata |
| **NFT API** | Collections, ownership, media |
| **Webhooks** | Event-driven notifications |
| **Transfers** | Transaction history and analytics |
## Supported Chains
| Chain | Chain ID | RPC Endpoint |
|-------|----------|-------------|
| Lux C-Chain | 96369 | `https://api.lux.cloud/v1/rpc/lux` |
| Zoo | 200200 | `https://api.lux.cloud/v1/rpc/zoo` |
| Hanzo | 36963 | `https://api.lux.cloud/v1/rpc/hanzo` |
| SPC | 36911 | `https://api.lux.cloud/v1/rpc/spc` |
| Pars | 494949 | `https://api.lux.cloud/v1/rpc/pars` |
## White-Label
Lux Cloud supports white-label deployment for different brands. Set `NEXT_PUBLIC_BRAND` to customize.
@@ -0,0 +1,18 @@
---
title: Installation
description: Deploy Lux Cloud
icon: Download
---
## Docker
```bash
docker pull ghcr.io/luxfi/cloud:latest
docker compose up -d
```
## Kubernetes
```bash
helm install cloud luxfi/cloud --namespace cloud
```
@@ -0,0 +1 @@
{"pages":["---Getting Started---","installation","quickstart","---APIs---","rpc","websockets","tokens","nft","webhooks","---Operations---","deployment","configuration","---Branding---","white-label","---API Reference---","api"]}
+17
View File
@@ -0,0 +1,17 @@
---
title: NFT API
description: NFT collections, ownership, and media
icon: Image
---
## Get NFTs
```bash
curl https://api.lux.cloud/v1/nft/owner?address=0x...
```
## Collection Data
```bash
curl https://api.lux.cloud/v1/nft/collection?contract=0x...
```
@@ -0,0 +1,14 @@
---
title: Quick Start
description: Your first API call
icon: Zap
---
## Get Block Number
```bash
curl -X POST https://api.lux.cloud/v1/rpc/lux \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
```
+17
View File
@@ -0,0 +1,17 @@
---
title: RPC API
description: Multi-chain JSON-RPC proxy
icon: Server
---
## Endpoints
All chains are accessible via:
```
https://api.lux.cloud/v1/rpc/{chain}
```
## Load Balancing
Requests are distributed across healthy nodes with automatic failover.
@@ -0,0 +1,19 @@
---
title: Token API
description: ERC-20/721/1155 balances and metadata
icon: Coins
---
## Get Balances
```bash
curl https://api.lux.cloud/v1/tokens/balances?address=0x...
```
## Supported Standards
| Standard | Features |
|----------|----------|
| ERC-20 | Balance, transfers, metadata |
| ERC-721 | Ownership, metadata, media |
| ERC-1155 | Multi-token balances |
@@ -0,0 +1,12 @@
---
title: Webhooks
description: Event-driven notifications
icon: Bell
---
## Create Webhook
```bash
curl -X POST https://api.lux.cloud/v1/webhooks \
-d '{"url": "https://example.com/hook", "events": ["transfer"]}'
```
@@ -0,0 +1,17 @@
---
title: WebSockets
description: Real-time blockchain subscriptions
icon: Radio
---
## Connect
```javascript
const ws = new WebSocket('wss://api.lux.cloud/v1/ws/lux');
ws.send(JSON.stringify({
jsonrpc: '2.0',
method: 'eth_subscribe',
params: ['newHeads'],
id: 1
}));
```
@@ -0,0 +1,16 @@
---
title: White-Label
description: Deploy under your own brand
icon: Palette
---
## Brands
| Brand | Domain | Config |
|-------|--------|--------|
| Lux Cloud | lux.cloud | Default |
| Hanzo Web3 | web3.hanzo.ai | `NEXT_PUBLIC_BRAND=hanzo` |
| Zoo Labs | web3.zoo.ngo | `NEXT_PUBLIC_BRAND=zoo` |
| Bootnode | bootno.de | `NEXT_PUBLIC_BRAND=bootnode` |
Brand is auto-detected from domain or set via environment variable.
+6
View File
@@ -0,0 +1,6 @@
import { cx } from 'class-variance-authority';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: Parameters<typeof cx>) {
return twMerge(cx(inputs));
}
+40
View File
@@ -0,0 +1,40 @@
import { BookOpenIcon, CloudIcon } from 'lucide-react';
import type { BaseLayoutProps, LinkItemType } from '@hanzo/docs/ui/layouts/shared';
export const linkItems: LinkItemType[] = [
{
icon: <BookOpenIcon />,
text: 'Documentation',
url: '/docs',
active: 'nested-url',
},
{
type: 'icon',
url: 'https://github.com/luxfi',
label: 'github',
text: 'Github',
icon: (
<svg role="img" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
</svg>
),
external: true,
},
];
export const logo = (
<CloudIcon className="size-5" />
);
export function baseOptions(): BaseLayoutProps {
return {
nav: {
title: (
<>
{logo}
<span className="font-medium">Lux Cloud</span>
</>
),
},
};
}
+26
View File
@@ -0,0 +1,26 @@
import type { Metadata } from 'next';
export const baseUrl = new URL(
process.env.NEXT_PUBLIC_SITE_URL ?? 'https://lux.cloud',
);
export function createMetadata(override: Metadata): Metadata {
return {
...override,
openGraph: {
title: override.title ?? undefined,
description: override.description ?? undefined,
url: baseUrl,
siteName: 'Lux Cloud Docs',
type: 'website',
...override.openGraph,
},
twitter: {
card: 'summary_large_image',
site: '@luxnetwork',
creator: '@luxnetwork',
...override.twitter,
},
metadataBase: baseUrl,
};
}
+16
View File
@@ -0,0 +1,16 @@
import {
type InferMetaType,
type InferPageType,
loader,
} from '@hanzo/docs/core/source';
import { docs } from '@hanzo/mdx:collections/server';
import { lucideIconsPlugin } from '@hanzo/docs/core/source/lucide-icons';
export const source = loader({
source: docs.toSource(),
baseUrl: '/docs',
plugins: [lucideIconsPlugin()],
});
export type Page = InferPageType<typeof source>;
export type Meta = InferMetaType<typeof source>;
+24
View File
@@ -0,0 +1,24 @@
import type { MDXComponents } from 'mdx/types';
import defaultMdxComponents from '@hanzo/docs-base-ui/mdx';
import { Tab, Tabs } from '@hanzo/docs-base-ui/components/tabs';
import { Callout } from '@hanzo/docs-base-ui/components/callout';
import { Step, Steps } from '@hanzo/docs-base-ui/components/steps';
import { File, Folder, Files } from '@hanzo/docs-base-ui/components/files';
import { Accordion, Accordions } from '@hanzo/docs-base-ui/components/accordion';
export function getMDXComponents(components?: MDXComponents): MDXComponents {
return {
...defaultMdxComponents,
Tab,
Tabs,
Callout,
Step,
Steps,
File,
Folder,
Files,
Accordion,
Accordions,
...components,
};
}
+40
View File
@@ -0,0 +1,40 @@
import { resolve } from 'path';
import createBundleAnalyzer from '@next/bundle-analyzer';
import { createMDX } from '@hanzo/docs/mdx/next';
import type { NextConfig } from 'next';
const withAnalyzer = createBundleAnalyzer({
enabled: process.env.ANALYZE === 'true',
});
const config: NextConfig = {
output: 'export',
reactStrictMode: true,
typescript: {
ignoreBuildErrors: true,
},
webpack: (config) => {
config.resolve.alias = {
...config.resolve.alias,
'@hanzo/mdx:collections/server': resolve(__dirname, './docs/server.ts'),
'@hanzo/mdx:collections/browser': resolve(__dirname, './docs/browser.ts'),
'@hanzo/mdx:collections/dynamic': resolve(__dirname, './docs/dynamic.ts'),
};
return config;
},
logging: {
fetches: {
fullUrl: true,
},
},
serverExternalPackages: [
'shiki',
],
images: {
unoptimized: true,
},
};
const withMDX = createMDX();
export default withAnalyzer(withMDX(config as any) as NextConfig);
+47
View File
@@ -0,0 +1,47 @@
{
"name": "bootnode-docs",
"version": "0.1.0",
"private": true,
"scripts": {
"build": "docs-mdx && next build --webpack",
"types:check": "docs-mdx && tsc --noEmit",
"clean": "rimraf .next",
"dev": "next dev --port 3020 --webpack",
"lint": "docs-mdx && eslint .",
"start": "next start"
},
"dependencies": {
"@hanzo/mdx-runtime": "^1.6.1",
"@hanzo/docs": "^16.4.1",
"@hanzo/docs-core": "^16.5.3",
"@hanzo/docs-mdx": "^14.2.8",
"@hanzo/docs-base-ui": "^16.5.3",
"@hanzo/docs-ui": "^16.5.3",
"@radix-ui/react-tooltip": "^1.2.8",
"@shikijs/rehype": "^3.21.0",
"@shikijs/transformers": "^3.21.0",
"class-variance-authority": "^0.7.1",
"lucide-react": "^0.562.0",
"next": "^16.0.10",
"next-themes": "^0.4.6",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"shiki": "^3.21.0",
"tailwind-merge": "^3.4.0",
"zod": "^4.3.5"
},
"devDependencies": {
"@hanzo/docs-cli": "^1.2.5",
"@next/bundle-analyzer": "16.1.1",
"@next/env": "16.1.1",
"@next/eslint-plugin-next": "16.1.1",
"@tailwindcss/postcss": "^4.1.18",
"@types/node": "^24.10.2",
"@types/react": "^19.2.8",
"@types/react-dom": "^19.2.3",
"postcss": "^8.5.6",
"tailwindcss": "^4.1.18",
"tailwindcss-animate": "^1.0.7",
"typescript": "^5.9.3"
}
}
+65
View File
@@ -0,0 +1,65 @@
import {
applyMdxPreset,
defineConfig,
defineDocs,
frontmatterSchema,
metaSchema,
} from '@hanzo/docs-mdx/config';
import { z } from 'zod';
import lastModified from '@hanzo/docs-mdx/plugins/last-modified';
export const docs = defineDocs({
docs: {
schema: frontmatterSchema.extend({
index: z.boolean().default(false),
}),
postprocess: {
includeProcessedMarkdown: true,
extractLinkReferences: true,
},
async: true,
async mdxOptions(environment) {
const { rehypeCodeDefaultOptions } = await import('@hanzo/docs-core/mdx-plugins/rehype-code');
const { remarkStructureDefaultOptions } =
await import('@hanzo/docs-core/mdx-plugins/remark-structure');
const { remarkSteps } = await import('@hanzo/docs-core/mdx-plugins/remark-steps');
return applyMdxPreset({
remarkStructureOptions: {
types: [...remarkStructureDefaultOptions.types, 'code'],
},
rehypeCodeOptions: {
langs: ['ts', 'js', 'rust', 'python', 'go', 'bash', 'json', 'yaml', 'toml', 'shell', 'typescript', 'javascript', 'markdown', 'solidity'],
inline: 'tailing-curly-colon',
themes: {
light: 'github-light',
dark: 'github-dark',
},
transformers: [
...(rehypeCodeDefaultOptions.transformers ?? []),
],
},
remarkCodeTabOptions: {
parseMdx: true,
},
remarkNpmOptions: {
persist: {
id: 'package-manager',
},
},
remarkPlugins: [remarkSteps],
})(environment);
},
},
meta: {
schema: metaSchema.extend({
description: z.string().optional(),
}),
},
});
export default defineConfig({
plugins: [
lastModified(),
],
});
+21
View File
@@ -0,0 +1,21 @@
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true,
"plugins": [{ "name": "next" }],
"paths": { "@/*": ["./*"] },
"target": "ES2017"
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", ".next/dev/types/**/*.ts"],
"exclude": ["node_modules"]
}
+8
View File
@@ -0,0 +1,8 @@
import type { ReactNode } from 'react';
import { HomeLayout } from '@hanzo/docs-base-ui/layouts/home';
import { baseOptions } from '@/lib/layout.shared';
import { linkItems } from '@/lib/layout.shared';
export default function Layout({ children }: { children: ReactNode }) {
return <HomeLayout {...baseOptions()} links={linkItems}>{children}</HomeLayout>;
}
+42
View File
@@ -0,0 +1,42 @@
import Link from 'next/link';
export default function HomePage() {
return (
<main className="flex flex-1 flex-col items-center justify-center text-center px-4 py-16">
<div className="max-w-3xl mx-auto">
<div className="inline-flex items-center gap-2 rounded-full border border-fd-border px-4 py-1.5 text-sm text-fd-muted-foreground mb-6">
Cross-Chain · MPC-Secured · Multi-Network
</div>
<h1 className="text-5xl md:text-7xl font-bold mb-6 bg-gradient-to-r from-purple-400 to-pink-400 bg-clip-text text-transparent">
Lux Bridge
</h1>
<p className="text-lg text-fd-muted-foreground mb-8 max-w-2xl mx-auto">
Cross-chain bridge with MPC-secured transfers.
Move assets between Lux subnets, Ethereum, Bitcoin, and more.
</p>
<div className="rounded-lg border border-fd-border bg-fd-card p-4 mb-8 max-w-md mx-auto font-mono text-sm">
<span className="text-fd-muted-foreground">$</span>{' '}npm install @luxfi/bridge
</div>
<div className="flex gap-4 justify-center mb-16">
<Link href="/docs" className="rounded-lg bg-fd-primary text-fd-primary-foreground px-6 py-3 font-medium hover:bg-fd-primary/90 transition-colors">Get Started</Link>
<Link href="/docs/api" className="rounded-lg border border-fd-border px-6 py-3 font-medium hover:bg-fd-accent transition-colors">API Reference</Link>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 text-left">
{[
{ name: 'Cross-Chain Transfers', desc: 'Bridge assets between any supported chain' },
{ name: 'MPC Security', desc: 'Threshold ECDSA signing with HSM attestation' },
{ name: 'Relay Network', desc: 'Decentralized relay with consensus verification' },
{ name: 'Multi-Chain', desc: 'Lux subnets, Ethereum, Bitcoin, and more' },
{ name: 'Bridge UI', desc: 'Production-ready Next.js frontend' },
{ name: 'Bridge API', desc: 'REST API for programmatic transfers' },
].map((c) => (
<div key={c.name} className="rounded-lg border border-fd-border bg-fd-card p-5 hover:border-fd-ring transition-colors">
<h3 className="font-semibold mb-1">{c.name}</h3>
<p className="text-sm text-fd-muted-foreground">{c.desc}</p>
</div>
))}
</div>
</div>
</main>
);
}
@@ -0,0 +1,96 @@
import type { Metadata } from 'next';
import { type ComponentProps, type FC, type ReactNode } from 'react';
import { Callout } from '@hanzo/docs-base-ui/components/callout';
import { TypeTable } from '@hanzo/docs-base-ui/components/type-table';
import { createMetadata } from '@/lib/metadata';
import { source } from '@/lib/source';
import { Card, Cards } from '@hanzo/docs-base-ui/components/card';
import Link from '@hanzo/docs-core/link';
import { findSiblings } from '@hanzo/docs-core/page-tree';
import { DocsBody, DocsPage, PageLastUpdate } from '@hanzo/docs-base-ui/layouts/docs/page';
import { notFound } from 'next/navigation';
import { getMDXComponents } from '@/mdx-components';
interface DocsPageProps {
params: Promise<{ slug?: string[] }>;
}
export const revalidate = false;
export default async function Page(props: DocsPageProps) {
const params = await props.params;
const page = source.getPage(params.slug);
if (!page) notFound();
const { body: Mdx, toc, lastModified } = await page.data.load();
return (
<DocsPage
toc={toc}
tableOfContent={{
style: 'clerk',
}}
>
<h1 className="text-[1.75em] font-semibold">{page.data.title}</h1>
<p className="text-lg text-fd-muted-foreground mb-6">{page.data.description}</p>
<div className="prose flex-1 text-fd-foreground/90">
<Mdx
components={getMDXComponents({
a: (props) => <Link {...props} />,
blockquote: Callout as unknown as FC<ComponentProps<'blockquote'>>,
TypeTable,
DocsCategory: ({ url }) => {
return <DocsCategory url={url ?? page.url} />;
},
})}
/>
{page.data.index ? <DocsCategory url={page.url} /> : null}
</div>
{lastModified && <PageLastUpdate date={lastModified} />}
</DocsPage>
);
}
function DocsCategory({ url }: { url: string }) {
return (
<Cards>
{findSiblings(source.getPageTree(), url).map((item) => {
if (item.type === 'separator') return;
if (item.type === 'folder') {
if (!item.index) return;
item = item.index;
}
return (
<Card key={item.url} title={item.name} href={item.url}>
{item.description}
</Card>
);
})}
</Cards>
);
}
export async function generateMetadata(props: DocsPageProps): Promise<Metadata> {
const { slug = [] } = await props.params;
const page = source.getPage(slug);
if (!page)
return createMetadata({
title: 'Not Found',
});
const description = page.data.description ?? 'Lux Bridge Documentation';
return createMetadata({
title: page.data.title,
description,
openGraph: {
url: `/docs/${page.slugs.join('/')}`,
},
});
}
export function generateStaticParams() {
return source.generateParams();
}
+43
View File
@@ -0,0 +1,43 @@
import { DocsLayout } from '@hanzo/docs/ui/layouts/docs';
import { baseOptions, linkItems, logo } from '@/lib/layout.shared';
import { source } from '@/lib/source';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
const base = baseOptions();
return (
<DocsLayout
{...base}
tree={source.getPageTree()}
links={linkItems.filter((item) => item.type === 'icon')}
nav={{
...base.nav,
title: (
<>
{logo}
<span className="font-medium max-md:hidden">Lux Bridge</span>
</>
),
}}
sidebar={{
tabs: {
transform(option, node) {
if (!node.icon) return option;
return {
...option,
icon: (
<div className="[&_svg]:size-full rounded-lg size-full text-brand max-md:bg-brand/10 max-md:border max-md:p-1.5">
{node.icon}
</div>
),
};
},
},
}}
>
{children}
</DocsLayout>
);
}
+38
View File
@@ -0,0 +1,38 @@
@import 'tailwindcss';
@import '@hanzo/docs-base-ui/css/neutral.css';
@import '@hanzo/docs-base-ui/css/preset.css';
@plugin 'tailwindcss-animate';
@theme {
--spacing-page: 1436px;
--color-brand: hsl(280, 84%, 45%);
--color-brand-foreground: white;
}
@theme inline {
--default-mono-font-family: var(--font-mono);
}
html { scrollbar-gutter: stable; }
html:has(body[data-scroll-locked]) { scrollbar-gutter: auto; }
body { background-color: var(--color-fd-background); }
:root {
color-scheme: dark;
--color-fd-background: hsl(0, 0%, 2%);
--color-fd-foreground: hsl(0, 0%, 96%);
--color-fd-muted: hsl(0, 0%, 10%);
--color-fd-muted-foreground: hsla(0, 0%, 70%, 0.85);
--color-fd-popover: hsl(0, 0%, 4%);
--color-fd-popover-foreground: hsl(0, 0%, 90%);
--color-fd-card: hsl(0, 0%, 4%);
--color-fd-card-foreground: hsl(0, 0%, 96%);
--color-fd-border: hsla(0, 0%, 40%, 0.2);
--color-fd-primary: hsl(0, 0%, 96%);
--color-fd-primary-foreground: hsl(0, 0%, 8%);
--color-fd-secondary: hsl(0, 0%, 12%);
--color-fd-secondary-foreground: hsl(0, 0%, 92%);
--color-fd-accent: hsla(0, 0%, 40%, 0.3);
--color-fd-accent-foreground: hsl(0, 0%, 92%);
--color-fd-ring: hsl(0, 0%, 55%);
}
+19
View File
@@ -0,0 +1,19 @@
'use client';
import { ThemeProvider } from 'next-themes';
import type { ReactNode } from 'react';
export function Body({ children }: { children: ReactNode }) {
return (
<body className="antialiased">
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
{children}
</ThemeProvider>
</body>
);
}
+43
View File
@@ -0,0 +1,43 @@
import './global.css';
import type { Viewport } from 'next';
import { baseUrl, createMetadata } from '@/lib/metadata';
import { Body } from '@/app/layout.client';
import { Provider } from './provider';
import type { ReactNode } from 'react';
import { Geist, Geist_Mono } from 'next/font/google';
import { TreeContextProvider } from '@hanzo/docs/ui/contexts/tree';
import { source } from '@/lib/source';
import { NextProvider } from '@hanzo/docs/core/framework/next';
export const metadata = createMetadata({
title: {
template: '%s | Lux Bridge',
default: 'Lux Bridge - Cross-chain bridge with MPC-secured transfers',
},
description: 'Cross-chain bridge with MPC-secured transfers',
metadataBase: baseUrl,
});
const geist = Geist({ variable: '--font-sans', subsets: ['latin'] });
const mono = Geist_Mono({ variable: '--font-mono', subsets: ['latin'] });
export const viewport: Viewport = {
themeColor: [
{ media: '(prefers-color-scheme: dark)', color: '#0A0A0A' },
{ media: '(prefers-color-scheme: light)', color: '#0A0A0A' },
],
};
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en" className={`${geist.variable} ${mono.variable}`} suppressHydrationWarning>
<Body>
<NextProvider>
<TreeContextProvider tree={source.getPageTree()}>
<Provider>{children}</Provider>
</TreeContextProvider>
</NextProvider>
</Body>
</html>
);
}
+15
View File
@@ -0,0 +1,15 @@
'use client';
import { RootProvider } from '@hanzo/docs/ui/provider/base';
import type { ReactNode } from 'react';
import { TooltipProvider } from '@radix-ui/react-tooltip';
export function Provider({ children }: { children: ReactNode }) {
return (
<RootProvider theme={{ defaultTheme: 'dark', enableSystem: false }}>
<TooltipProvider>
{children}
</TooltipProvider>
</RootProvider>
);
}
+14
View File
@@ -0,0 +1,14 @@
---
title: API Reference
description: Bridge REST API
icon: FileCode
---
## Endpoints
| Method | Path | Description |
|--------|------|-------------|
| POST | `/v1/transfer` | Initiate transfer |
| GET | `/v1/transfer/:id` | Get transfer status |
| GET | `/v1/transfers` | List transfers |
| GET | `/v1/chains` | Supported chains |
@@ -0,0 +1,14 @@
---
title: Architecture
description: Bridge design and MPC integration
icon: GitBranch
---
## Components
| Component | Description |
|-----------|-------------|
| Bridge UI | Next.js frontend |
| Bridge API | Node.js server |
| MPC Nodes | Threshold signers |
| Relay | Cross-chain message passing |
+13
View File
@@ -0,0 +1,13 @@
---
title: Supported Chains
description: Chains and asset support
icon: Link
---
## Chain Matrix
| Source | Destination | Assets |
|--------|-------------|--------|
| Lux C | Zoo/Hanzo/SPC/Pars | LUX, tokens |
| Ethereum | Lux C | ETH, USDC, USDT |
| Bitcoin | Lux C | BTC (wrapped) |
@@ -0,0 +1,13 @@
---
title: Configuration
description: Environment variables and settings
icon: Settings
---
## Environment Variables
| Variable | Description |
|----------|-------------|
| `MPC_URL` | MPC API endpoint |
| `BRIDGE_DB_URL` | PostgreSQL connection |
| `SUPPORTED_CHAINS` | Comma-separated chain IDs |
@@ -0,0 +1,22 @@
---
title: Deployment
description: Deploy the bridge on Kubernetes
icon: Server
---
## K8s
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: bridge-ui
spec:
template:
spec:
containers:
- name: bridge-ui
image: ghcr.io/luxfi/bridge-ui:latest
ports:
- containerPort: 3000
```
+26
View File
@@ -0,0 +1,26 @@
---
title: Lux Bridge
description: Cross-chain bridge with MPC-secured transfers
index: true
icon: ArrowLeftRight
---
Move assets between Lux subnets, Ethereum, Bitcoin, and other chains using MPC threshold signatures.
## Flow
```
User ──► Bridge UI ──► Bridge API ──► MPC Nodes ──► Destination Chain
│
HSM Attestation
```
## Supported Chains
| Chain | Type | Assets |
|-------|------|--------|
| Lux C-Chain | EVM | LUX, WLUX, tokens |
| Zoo | Subnet EVM | ZOO, tokens |
| Hanzo | Subnet EVM | HANZO, tokens |
| Ethereum | EVM | ETH, ERC-20 |
| Bitcoin | UTXO | BTC |
@@ -0,0 +1,18 @@
---
title: Installation
description: Set up the Lux Bridge
icon: Download
---
## Bridge UI
```bash
git clone https://github.com/luxfi/bridge
cd bridge/ui && npm install && npm run dev
```
## Bridge API
```bash
cd bridge/server && npm install && npm start
```
+1
View File
@@ -0,0 +1 @@
{"pages":["---Getting Started---","installation","quickstart","---Architecture---","architecture","chains","---Operations---","deployment","configuration","---API Reference---","api","---Security---","security"]}
@@ -0,0 +1,11 @@
---
title: Quick Start
description: Your first cross-chain transfer
icon: Zap
---
1. Open [bridge.lux.network](https://bridge.lux.network)
2. Connect your wallet
3. Select source and destination chains
4. Enter amount and confirm
5. MPC nodes sign the transfer
@@ -0,0 +1,12 @@
---
title: Security
description: MPC security model
icon: ShieldAlert
---
## Security Model
- **MPC threshold** — t-of-n nodes must agree
- **HSM attestation** — Hardware-bound signatures
- **Intent verification** — Server-side co-sign
- **Audit logging** — All operations logged
+6
View File
@@ -0,0 +1,6 @@
import { cx } from 'class-variance-authority';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: Parameters<typeof cx>) {
return twMerge(cx(inputs));
}
+40
View File
@@ -0,0 +1,40 @@
import { BookOpenIcon, ArrowLeftRightIcon as ProjectIcon } from 'lucide-react';
import type { BaseLayoutProps, LinkItemType } from '@hanzo/docs/ui/layouts/shared';
export const linkItems: LinkItemType[] = [
{
icon: <BookOpenIcon />,
text: 'Documentation',
url: '/docs',
active: 'nested-url',
},
{
type: 'icon',
url: 'https://github.com/luxfi/bridge',
label: 'github',
text: 'Github',
icon: (
<svg role="img" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
</svg>
),
external: true,
},
];
export const logo = (
<ProjectIcon className="size-5" />
);
export function baseOptions(): BaseLayoutProps {
return {
nav: {
title: (
<>
{logo}
<span className="font-medium">Lux Bridge</span>
</>
),
},
};
}
+26
View File
@@ -0,0 +1,26 @@
import type { Metadata } from 'next';
export const baseUrl = new URL(
process.env.NEXT_PUBLIC_SITE_URL ?? 'https://bridge.lux.network',
);
export function createMetadata(override: Metadata): Metadata {
return {
...override,
openGraph: {
title: override.title ?? undefined,
description: override.description ?? undefined,
url: baseUrl,
siteName: 'Lux Bridge Docs',
type: 'website',
...override.openGraph,
},
twitter: {
card: 'summary_large_image',
site: '@luxnetwork',
creator: '@luxnetwork',
...override.twitter,
},
metadataBase: baseUrl,
};
}
+16
View File
@@ -0,0 +1,16 @@
import {
type InferMetaType,
type InferPageType,
loader,
} from '@hanzo/docs/core/source';
import { docs } from '@hanzo/mdx:collections/server';
import { lucideIconsPlugin } from '@hanzo/docs/core/source/lucide-icons';
export const source = loader({
source: docs.toSource(),
baseUrl: '/docs',
plugins: [lucideIconsPlugin()],
});
export type Page = InferPageType<typeof source>;
export type Meta = InferMetaType<typeof source>;
+24
View File
@@ -0,0 +1,24 @@
import type { MDXComponents } from 'mdx/types';
import defaultMdxComponents from '@hanzo/docs-base-ui/mdx';
import { Tab, Tabs } from '@hanzo/docs-base-ui/components/tabs';
import { Callout } from '@hanzo/docs-base-ui/components/callout';
import { Step, Steps } from '@hanzo/docs-base-ui/components/steps';
import { File, Folder, Files } from '@hanzo/docs-base-ui/components/files';
import { Accordion, Accordions } from '@hanzo/docs-base-ui/components/accordion';
export function getMDXComponents(components?: MDXComponents): MDXComponents {
return {
...defaultMdxComponents,
Tab,
Tabs,
Callout,
Step,
Steps,
File,
Folder,
Files,
Accordion,
Accordions,
...components,
};
}
+28
View File
@@ -0,0 +1,28 @@
import { resolve } from 'path';
import createBundleAnalyzer from '@next/bundle-analyzer';
import { createMDX } from '@hanzo/docs/mdx/next';
import type { NextConfig } from 'next';
const withAnalyzer = createBundleAnalyzer({
enabled: process.env.ANALYZE === 'true',
});
const config: NextConfig = {
output: 'export',
reactStrictMode: true,
typescript: { ignoreBuildErrors: true },
webpack: (config) => {
config.resolve.alias = {
...config.resolve.alias,
'@hanzo/mdx:collections/server': resolve(__dirname, './docs/server.ts'),
'@hanzo/mdx:collections/browser': resolve(__dirname, './docs/browser.ts'),
'@hanzo/mdx:collections/dynamic': resolve(__dirname, './docs/dynamic.ts'),
};
return config;
},
serverExternalPackages: ['shiki'],
images: { unoptimized: true },
};
const withMDX = createMDX();
export default withAnalyzer(withMDX(config as any) as NextConfig);
+47
View File
@@ -0,0 +1,47 @@
{
"name": "bridge-docs",
"version": "0.1.0",
"private": true,
"scripts": {
"build": "docs-mdx && next build --webpack",
"types:check": "docs-mdx && tsc --noEmit",
"clean": "rimraf .next",
"dev": "next dev --port 3018 --webpack",
"lint": "docs-mdx && eslint .",
"start": "next start"
},
"dependencies": {
"@hanzo/mdx-runtime": "^1.6.1",
"@hanzo/docs": "^16.4.1",
"@hanzo/docs-core": "^16.5.3",
"@hanzo/docs-mdx": "^14.2.8",
"@hanzo/docs-base-ui": "^16.5.3",
"@hanzo/docs-ui": "^16.5.3",
"@radix-ui/react-tooltip": "^1.2.8",
"@shikijs/rehype": "^3.21.0",
"@shikijs/transformers": "^3.21.0",
"class-variance-authority": "^0.7.1",
"lucide-react": "^0.562.0",
"next": "^16.0.10",
"next-themes": "^0.4.6",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"shiki": "^3.21.0",
"tailwind-merge": "^3.4.0",
"zod": "^4.3.5"
},
"devDependencies": {
"@hanzo/docs-cli": "^1.2.5",
"@next/bundle-analyzer": "16.1.1",
"@next/env": "16.1.1",
"@next/eslint-plugin-next": "16.1.1",
"@tailwindcss/postcss": "^4.1.18",
"@types/node": "^24.10.2",
"@types/react": "^19.2.8",
"@types/react-dom": "^19.2.3",
"postcss": "^8.5.6",
"tailwindcss": "^4.1.18",
"tailwindcss-animate": "^1.0.7",
"typescript": "^5.9.3"
}
}
+5
View File
@@ -0,0 +1,5 @@
import tailwindcss from '@tailwindcss/postcss';
export default {
plugins: [tailwindcss],
};
+65
View File
@@ -0,0 +1,65 @@
import {
applyMdxPreset,
defineConfig,
defineDocs,
frontmatterSchema,
metaSchema,
} from '@hanzo/docs-mdx/config';
import { z } from 'zod';
import lastModified from '@hanzo/docs-mdx/plugins/last-modified';
export const docs = defineDocs({
docs: {
schema: frontmatterSchema.extend({
index: z.boolean().default(false),
}),
postprocess: {
includeProcessedMarkdown: true,
extractLinkReferences: true,
},
async: true,
async mdxOptions(environment) {
const { rehypeCodeDefaultOptions } = await import('@hanzo/docs-core/mdx-plugins/rehype-code');
const { remarkStructureDefaultOptions } =
await import('@hanzo/docs-core/mdx-plugins/remark-structure');
const { remarkSteps } = await import('@hanzo/docs-core/mdx-plugins/remark-steps');
return applyMdxPreset({
remarkStructureOptions: {
types: [...remarkStructureDefaultOptions.types, 'code'],
},
rehypeCodeOptions: {
langs: ['ts', 'js', 'rust', 'python', 'go', 'bash', 'json', 'yaml', 'toml', 'shell', 'typescript', 'javascript', 'markdown', 'solidity'],
inline: 'tailing-curly-colon',
themes: {
light: 'github-light',
dark: 'github-dark',
},
transformers: [
...(rehypeCodeDefaultOptions.transformers ?? []),
],
},
remarkCodeTabOptions: {
parseMdx: true,
},
remarkNpmOptions: {
persist: {
id: 'package-manager',
},
},
remarkPlugins: [remarkSteps],
})(environment);
},
},
meta: {
schema: metaSchema.extend({
description: z.string().optional(),
}),
},
});
export default defineConfig({
plugins: [
lastModified(),
],
});
+21
View File
@@ -0,0 +1,21 @@
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true,
"plugins": [{ "name": "next" }],
"paths": { "@/*": ["./*"] },
"target": "ES2017"
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", ".next/dev/types/**/*.ts"],
"exclude": ["node_modules"]
}
+8
View File
@@ -0,0 +1,8 @@
import type { ReactNode } from 'react';
import { HomeLayout } from '@hanzo/docs-base-ui/layouts/home';
import { baseOptions } from '@/lib/layout.shared';
import { linkItems } from '@/lib/layout.shared';
export default function Layout({ children }: { children: ReactNode }) {
return <HomeLayout {...baseOptions()} links={linkItems}>{children}</HomeLayout>;
}
+42
View File
@@ -0,0 +1,42 @@
import Link from 'next/link';
export default function HomePage() {
return (
<main className="flex flex-1 flex-col items-center justify-center text-center px-4 py-16">
<div className="max-w-3xl mx-auto">
<div className="inline-flex items-center gap-2 rounded-full border border-fd-border px-4 py-1.5 text-sm text-fd-muted-foreground mb-6">
Networks · Subnets · Wallets · Validators
</div>
<h1 className="text-5xl md:text-7xl font-bold mb-6 bg-gradient-to-r from-blue-400 to-cyan-400 bg-clip-text text-transparent">
Lux CLI
</h1>
<p className="text-lg text-fd-muted-foreground mb-8 max-w-2xl mx-auto">
Command-line interface for Lux Network operations.
Deploy subnets, manage validators, and interact with chains.
</p>
<div className="rounded-lg border border-fd-border bg-fd-card p-4 mb-8 max-w-md mx-auto font-mono text-sm">
<span className="text-fd-muted-foreground">$</span>{' '}curl -sSL https://cli.lux.network/install | sh
</div>
<div className="flex gap-4 justify-center mb-16">
<Link href="/docs" className="rounded-lg bg-fd-primary text-fd-primary-foreground px-6 py-3 font-medium hover:bg-fd-primary/90 transition-colors">Get Started</Link>
<Link href="/docs/commands" className="rounded-lg border border-fd-border px-6 py-3 font-medium hover:bg-fd-accent transition-colors">Commands</Link>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 text-left">
{[
{ name: 'Network Management', desc: 'Start, stop, and monitor local and remote networks' },
{ name: 'Subnet Deployment', desc: 'Create and deploy subnets with custom VMs' },
{ name: 'Wallet Operations', desc: 'Create wallets, transfer assets, check balances' },
{ name: 'Validator Control', desc: 'Add validators, manage delegation, stake LUX' },
{ name: 'Chain Configuration', desc: 'Deploy EVM chains with custom genesis' },
{ name: 'Health Monitoring', desc: 'Node health checks and network diagnostics' },
].map((c) => (
<div key={c.name} className="rounded-lg border border-fd-border bg-fd-card p-5 hover:border-fd-ring transition-colors">
<h3 className="font-semibold mb-1">{c.name}</h3>
<p className="text-sm text-fd-muted-foreground">{c.desc}</p>
</div>
))}
</div>
</div>
</main>
);
}
@@ -0,0 +1,96 @@
import type { Metadata } from 'next';
import { type ComponentProps, type FC, type ReactNode } from 'react';
import { Callout } from '@hanzo/docs-base-ui/components/callout';
import { TypeTable } from '@hanzo/docs-base-ui/components/type-table';
import { createMetadata } from '@/lib/metadata';
import { source } from '@/lib/source';
import { Card, Cards } from '@hanzo/docs-base-ui/components/card';
import Link from '@hanzo/docs-core/link';
import { findSiblings } from '@hanzo/docs-core/page-tree';
import { DocsBody, DocsPage, PageLastUpdate } from '@hanzo/docs-base-ui/layouts/docs/page';
import { notFound } from 'next/navigation';
import { getMDXComponents } from '@/mdx-components';
interface DocsPageProps {
params: Promise<{ slug?: string[] }>;
}
export const revalidate = false;
export default async function Page(props: DocsPageProps) {
const params = await props.params;
const page = source.getPage(params.slug);
if (!page) notFound();
const { body: Mdx, toc, lastModified } = await page.data.load();
return (
<DocsPage
toc={toc}
tableOfContent={{
style: 'clerk',
}}
>
<h1 className="text-[1.75em] font-semibold">{page.data.title}</h1>
<p className="text-lg text-fd-muted-foreground mb-6">{page.data.description}</p>
<div className="prose flex-1 text-fd-foreground/90">
<Mdx
components={getMDXComponents({
a: (props) => <Link {...props} />,
blockquote: Callout as unknown as FC<ComponentProps<'blockquote'>>,
TypeTable,
DocsCategory: ({ url }) => {
return <DocsCategory url={url ?? page.url} />;
},
})}
/>
{page.data.index ? <DocsCategory url={page.url} /> : null}
</div>
{lastModified && <PageLastUpdate date={lastModified} />}
</DocsPage>
);
}
function DocsCategory({ url }: { url: string }) {
return (
<Cards>
{findSiblings(source.getPageTree(), url).map((item) => {
if (item.type === 'separator') return;
if (item.type === 'folder') {
if (!item.index) return;
item = item.index;
}
return (
<Card key={item.url} title={item.name} href={item.url}>
{item.description}
</Card>
);
})}
</Cards>
);
}
export async function generateMetadata(props: DocsPageProps): Promise<Metadata> {
const { slug = [] } = await props.params;
const page = source.getPage(slug);
if (!page)
return createMetadata({
title: 'Not Found',
});
const description = page.data.description ?? 'Lux CLI Documentation';
return createMetadata({
title: page.data.title,
description,
openGraph: {
url: `/docs/${page.slugs.join('/')}`,
},
});
}
export function generateStaticParams() {
return source.generateParams();
}
+43
View File
@@ -0,0 +1,43 @@
import { DocsLayout } from '@hanzo/docs/ui/layouts/docs';
import { baseOptions, linkItems, logo } from '@/lib/layout.shared';
import { source } from '@/lib/source';
import type { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
const base = baseOptions();
return (
<DocsLayout
{...base}
tree={source.getPageTree()}
links={linkItems.filter((item) => item.type === 'icon')}
nav={{
...base.nav,
title: (
<>
{logo}
<span className="font-medium max-md:hidden">Lux CLI</span>
</>
),
}}
sidebar={{
tabs: {
transform(option, node) {
if (!node.icon) return option;
return {
...option,
icon: (
<div className="[&_svg]:size-full rounded-lg size-full text-brand max-md:bg-brand/10 max-md:border max-md:p-1.5">
{node.icon}
</div>
),
};
},
},
}}
>
{children}
</DocsLayout>
);
}
+38
View File
@@ -0,0 +1,38 @@
@import 'tailwindcss';
@import '@hanzo/docs-base-ui/css/neutral.css';
@import '@hanzo/docs-base-ui/css/preset.css';
@plugin 'tailwindcss-animate';
@theme {
--spacing-page: 1436px;
--color-brand: hsl(210, 84%, 45%);
--color-brand-foreground: white;
}
@theme inline {
--default-mono-font-family: var(--font-mono);
}
html { scrollbar-gutter: stable; }
html:has(body[data-scroll-locked]) { scrollbar-gutter: auto; }
body { background-color: var(--color-fd-background); }
:root {
color-scheme: dark;
--color-fd-background: hsl(0, 0%, 2%);
--color-fd-foreground: hsl(0, 0%, 96%);
--color-fd-muted: hsl(0, 0%, 10%);
--color-fd-muted-foreground: hsla(0, 0%, 70%, 0.85);
--color-fd-popover: hsl(0, 0%, 4%);
--color-fd-popover-foreground: hsl(0, 0%, 90%);
--color-fd-card: hsl(0, 0%, 4%);
--color-fd-card-foreground: hsl(0, 0%, 96%);
--color-fd-border: hsla(0, 0%, 40%, 0.2);
--color-fd-primary: hsl(0, 0%, 96%);
--color-fd-primary-foreground: hsl(0, 0%, 8%);
--color-fd-secondary: hsl(0, 0%, 12%);
--color-fd-secondary-foreground: hsl(0, 0%, 92%);
--color-fd-accent: hsla(0, 0%, 40%, 0.3);
--color-fd-accent-foreground: hsl(0, 0%, 92%);
--color-fd-ring: hsl(0, 0%, 55%);
}
+19
View File
@@ -0,0 +1,19 @@
'use client';
import { ThemeProvider } from 'next-themes';
import type { ReactNode } from 'react';
export function Body({ children }: { children: ReactNode }) {
return (
<body className="antialiased">
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
{children}
</ThemeProvider>
</body>
);
}
+43
View File
@@ -0,0 +1,43 @@
import './global.css';
import type { Viewport } from 'next';
import { baseUrl, createMetadata } from '@/lib/metadata';
import { Body } from '@/app/layout.client';
import { Provider } from './provider';
import type { ReactNode } from 'react';
import { Geist, Geist_Mono } from 'next/font/google';
import { TreeContextProvider } from '@hanzo/docs/ui/contexts/tree';
import { source } from '@/lib/source';
import { NextProvider } from '@hanzo/docs/core/framework/next';
export const metadata = createMetadata({
title: {
template: '%s | Lux CLI',
default: 'Lux CLI - Command-line interface for Lux Network operations',
},
description: 'Command-line interface for Lux Network operations',
metadataBase: baseUrl,
});
const geist = Geist({ variable: '--font-sans', subsets: ['latin'] });
const mono = Geist_Mono({ variable: '--font-mono', subsets: ['latin'] });
export const viewport: Viewport = {
themeColor: [
{ media: '(prefers-color-scheme: dark)', color: '#0A0A0A' },
{ media: '(prefers-color-scheme: light)', color: '#0A0A0A' },
],
};
export default function RootLayout({ children }: { children: ReactNode }) {
return (
<html lang="en" className={`${geist.variable} ${mono.variable}`} suppressHydrationWarning>
<Body>
<NextProvider>
<TreeContextProvider tree={source.getPageTree()}>
<Provider>{children}</Provider>
</TreeContextProvider>
</NextProvider>
</Body>
</html>
);
}
+15
View File
@@ -0,0 +1,15 @@
'use client';
import { RootProvider } from '@hanzo/docs/ui/provider/base';
import type { ReactNode } from 'react';
import { TooltipProvider } from '@radix-ui/react-tooltip';
export function Provider({ children }: { children: ReactNode }) {
return (
<RootProvider theme={{ defaultTheme: 'dark', enableSystem: false }}>
<TooltipProvider>
{children}
</TooltipProvider>
</RootProvider>
);
}
+16
View File
@@ -0,0 +1,16 @@
---
title: API Reference
description: Programmatic CLI usage
icon: FileCode
---
The CLI can be used programmatically via the Go SDK:
```go
import "github.com/luxfi/cli/pkg/network"
net, _ := network.Start(network.Config{
NumNodes: 5,
})
defer net.Stop()
```
@@ -0,0 +1,8 @@
---
title: Commands
description: CLI command reference
index: true
icon: Terminal
---
All available CLI commands organized by category.
@@ -0,0 +1,13 @@
---
title: lux key
description: Manage keys and addresses
---
## Usage
```bash
lux key create <name>
lux key list
lux key export <name>
lux key delete <name>
```
@@ -0,0 +1 @@
{"pages":["network","subnet","key","wallet","node"]}
@@ -0,0 +1,13 @@
---
title: lux network
description: Manage local and remote networks
---
## Usage
```bash
lux network start [--num-nodes 5]
lux network stop
lux network status
lux network clean
```
@@ -0,0 +1,12 @@
---
title: lux node
description: Validator operations and health
---
## Usage
```bash
lux node whitelist --subnet <id>
lux node validate --subnet <id> --stake <n>
lux node health
```
@@ -0,0 +1,13 @@
---
title: lux subnet
description: Create and deploy subnets
---
## Usage
```bash
lux subnet create <name> --evm
lux subnet deploy <name> --local|--testnet|--mainnet
lux subnet join <name>
lux subnet export <name>
```
@@ -0,0 +1,12 @@
---
title: lux wallet
description: Transfer assets and check balances
---
## Usage
```bash
lux wallet transfer --to <addr> --amount <n>
lux wallet balance
lux wallet fund --chain <name>
```
@@ -0,0 +1,25 @@
---
title: Configuration
description: CLI configuration options
icon: Settings
---
## Config File
The CLI reads from `~/.lux/config.json`:
```json
{
"network": "mainnet",
"node_url": "https://api.lux.network",
"key_name": "default"
}
```
## Environment Variables
| Variable | Description |
|----------|-------------|
| `LUX_NETWORK` | Network to connect to |
| `LUX_KEY_NAME` | Default key name |
| `LUX_PRIVATE_KEY` | Private key (hex) |
@@ -0,0 +1,23 @@
---
title: Custom VM
description: Build and deploy a custom virtual machine
icon: Cpu
---
## Build
```bash
go build -o myvm ./cmd/myvm
```
## Register
```bash
lux subnet create mychain --custom --vm-path ./myvm
```
## Deploy
```bash
lux subnet deploy mychain --local
```
@@ -0,0 +1,27 @@
---
title: Deploy a Subnet
description: Create and deploy a subnet EVM chain
icon: Layers
---
## Create
```bash
lux subnet create mychain --evm
```
Follow the prompts to configure gas, fees, and genesis allocations.
## Deploy Locally
```bash
lux subnet deploy mychain --local
```
## Deploy to Testnet
```bash
lux subnet deploy mychain --testnet
```
Requires funded keys on the P-Chain.
@@ -0,0 +1,8 @@
---
title: Guides
description: Step-by-step tutorials
index: true
icon: BookOpen
---
Practical guides for common Lux CLI workflows.
@@ -0,0 +1,25 @@
---
title: Local Network
description: Set up a local 5-node Lux network
icon: Server
---
## Start a Local Network
```bash
lux network start --num-nodes 5
```
This starts a 5-node Lux network on your machine with all standard chains (P, X, C).
## Verify
```bash
lux network status
```
## Stop
```bash
lux network stop
```
@@ -0,0 +1 @@
{"pages":["local-network","deploy-subnet","custom-vm"]}
+24
View File
@@ -0,0 +1,24 @@
---
title: Lux CLI
description: Command-line interface for Lux Network operations
index: true
icon: Terminal
---
The Lux CLI provides tools for network management, subnet deployment, wallet operations, and validator control.
## Quick Install
```bash
curl -sSL https://cli.lux.network/install | sh
```
## Commands
| Command | Description |
|---------|-------------|
| `lux network` | Start, stop, and manage local networks |
| `lux subnet` | Create and deploy subnets |
| `lux key` | Manage keys and addresses |
| `lux wallet` | Transfer assets and check balances |
| `lux node` | Validator operations and health |
@@ -0,0 +1,29 @@
---
title: Installation
description: Install the Lux CLI
icon: Download
---
## Script Install
```bash
curl -sSL https://cli.lux.network/install | sh
```
## Go Install
```bash
go install github.com/luxfi/cli@latest
```
## Homebrew
```bash
brew install luxfi/tap/lux
```
## Verify
```bash
lux --version
```
+1
View File
@@ -0,0 +1 @@
{"pages":["---Getting Started---","installation","quickstart","---Commands---","commands","---Guides---","guides","---Reference---","configuration","api"]}
+29
View File
@@ -0,0 +1,29 @@
---
title: Quick Start
description: Deploy your first subnet in minutes
icon: Zap
---
## Create a Local Network
```bash
lux network start
```
## Create a Subnet
```bash
lux subnet create mysubnet --evm
```
## Deploy the Subnet
```bash
lux subnet deploy mysubnet --local
```
## Send a Transaction
```bash
lux wallet transfer --to 0x... --amount 1 --chain mysubnet
```
+6
View File
@@ -0,0 +1,6 @@
import { cx } from 'class-variance-authority';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: Parameters<typeof cx>) {
return twMerge(cx(inputs));
}
+40
View File
@@ -0,0 +1,40 @@
import { BookOpenIcon, TerminalIcon as ProjectIcon } from 'lucide-react';
import type { BaseLayoutProps, LinkItemType } from '@hanzo/docs/ui/layouts/shared';
export const linkItems: LinkItemType[] = [
{
icon: <BookOpenIcon />,
text: 'Documentation',
url: '/docs',
active: 'nested-url',
},
{
type: 'icon',
url: 'https://github.com/luxfi/cli',
label: 'github',
text: 'Github',
icon: (
<svg role="img" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" />
</svg>
),
external: true,
},
];
export const logo = (
<ProjectIcon className="size-5" />
);
export function baseOptions(): BaseLayoutProps {
return {
nav: {
title: (
<>
{logo}
<span className="font-medium">Lux CLI</span>
</>
),
},
};
}
+26
View File
@@ -0,0 +1,26 @@
import type { Metadata } from 'next';
export const baseUrl = new URL(
process.env.NEXT_PUBLIC_SITE_URL ?? 'https://cli.lux.network',
);
export function createMetadata(override: Metadata): Metadata {
return {
...override,
openGraph: {
title: override.title ?? undefined,
description: override.description ?? undefined,
url: baseUrl,
siteName: 'Lux CLI Docs',
type: 'website',
...override.openGraph,
},
twitter: {
card: 'summary_large_image',
site: '@luxnetwork',
creator: '@luxnetwork',
...override.twitter,
},
metadataBase: baseUrl,
};
}
+16
View File
@@ -0,0 +1,16 @@
import {
type InferMetaType,
type InferPageType,
loader,
} from '@hanzo/docs/core/source';
import { docs } from '@hanzo/mdx:collections/server';
import { lucideIconsPlugin } from '@hanzo/docs/core/source/lucide-icons';
export const source = loader({
source: docs.toSource(),
baseUrl: '/docs',
plugins: [lucideIconsPlugin()],
});
export type Page = InferPageType<typeof source>;
export type Meta = InferMetaType<typeof source>;
+24
View File
@@ -0,0 +1,24 @@
import type { MDXComponents } from 'mdx/types';
import defaultMdxComponents from '@hanzo/docs-base-ui/mdx';
import { Tab, Tabs } from '@hanzo/docs-base-ui/components/tabs';
import { Callout } from '@hanzo/docs-base-ui/components/callout';
import { Step, Steps } from '@hanzo/docs-base-ui/components/steps';
import { File, Folder, Files } from '@hanzo/docs-base-ui/components/files';
import { Accordion, Accordions } from '@hanzo/docs-base-ui/components/accordion';
export function getMDXComponents(components?: MDXComponents): MDXComponents {
return {
...defaultMdxComponents,
Tab,
Tabs,
Callout,
Step,
Steps,
File,
Folder,
Files,
Accordion,
Accordions,
...components,
};
}
+28
View File
@@ -0,0 +1,28 @@
import { resolve } from 'path';
import createBundleAnalyzer from '@next/bundle-analyzer';
import { createMDX } from '@hanzo/docs/mdx/next';
import type { NextConfig } from 'next';
const withAnalyzer = createBundleAnalyzer({
enabled: process.env.ANALYZE === 'true',
});
const config: NextConfig = {
output: 'export',
reactStrictMode: true,
typescript: { ignoreBuildErrors: true },
webpack: (config) => {
config.resolve.alias = {
...config.resolve.alias,
'@hanzo/mdx:collections/server': resolve(__dirname, './docs/server.ts'),
'@hanzo/mdx:collections/browser': resolve(__dirname, './docs/browser.ts'),
'@hanzo/mdx:collections/dynamic': resolve(__dirname, './docs/dynamic.ts'),
};
return config;
},
serverExternalPackages: ['shiki'],
images: { unoptimized: true },
};
const withMDX = createMDX();
export default withAnalyzer(withMDX(config as any) as NextConfig);
+47
View File
@@ -0,0 +1,47 @@
{
"name": "cli-docs",
"version": "0.1.0",
"private": true,
"scripts": {
"build": "docs-mdx && next build --webpack",
"types:check": "docs-mdx && tsc --noEmit",
"clean": "rimraf .next",
"dev": "next dev --port 3015 --webpack",
"lint": "docs-mdx && eslint .",
"start": "next start"
},
"dependencies": {
"@hanzo/mdx-runtime": "^1.6.1",
"@hanzo/docs": "^16.4.1",
"@hanzo/docs-core": "^16.5.3",
"@hanzo/docs-mdx": "^14.2.8",
"@hanzo/docs-base-ui": "^16.5.3",
"@hanzo/docs-ui": "^16.5.3",
"@radix-ui/react-tooltip": "^1.2.8",
"@shikijs/rehype": "^3.21.0",
"@shikijs/transformers": "^3.21.0",
"class-variance-authority": "^0.7.1",
"lucide-react": "^0.562.0",
"next": "^16.0.10",
"next-themes": "^0.4.6",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"shiki": "^3.21.0",
"tailwind-merge": "^3.4.0",
"zod": "^4.3.5"
},
"devDependencies": {
"@hanzo/docs-cli": "^1.2.5",
"@next/bundle-analyzer": "16.1.1",
"@next/env": "16.1.1",
"@next/eslint-plugin-next": "16.1.1",
"@tailwindcss/postcss": "^4.1.18",
"@types/node": "^24.10.2",
"@types/react": "^19.2.8",
"@types/react-dom": "^19.2.3",
"postcss": "^8.5.6",
"tailwindcss": "^4.1.18",
"tailwindcss-animate": "^1.0.7",
"typescript": "^5.9.3"
}
}
+5
View File
@@ -0,0 +1,5 @@
import tailwindcss from '@tailwindcss/postcss';
export default {
plugins: [tailwindcss],
};
+65
View File
@@ -0,0 +1,65 @@
import {
applyMdxPreset,
defineConfig,
defineDocs,
frontmatterSchema,
metaSchema,
} from '@hanzo/docs-mdx/config';
import { z } from 'zod';
import lastModified from '@hanzo/docs-mdx/plugins/last-modified';
export const docs = defineDocs({
docs: {
schema: frontmatterSchema.extend({
index: z.boolean().default(false),
}),
postprocess: {
includeProcessedMarkdown: true,
extractLinkReferences: true,
},
async: true,
async mdxOptions(environment) {
const { rehypeCodeDefaultOptions } = await import('@hanzo/docs-core/mdx-plugins/rehype-code');
const { remarkStructureDefaultOptions } =
await import('@hanzo/docs-core/mdx-plugins/remark-structure');
const { remarkSteps } = await import('@hanzo/docs-core/mdx-plugins/remark-steps');
return applyMdxPreset({
remarkStructureOptions: {
types: [...remarkStructureDefaultOptions.types, 'code'],
},
rehypeCodeOptions: {
langs: ['ts', 'js', 'rust', 'python', 'go', 'bash', 'json', 'yaml', 'toml', 'shell', 'typescript', 'javascript', 'markdown', 'solidity'],
inline: 'tailing-curly-colon',
themes: {
light: 'github-light',
dark: 'github-dark',
},
transformers: [
...(rehypeCodeDefaultOptions.transformers ?? []),
],
},
remarkCodeTabOptions: {
parseMdx: true,
},
remarkNpmOptions: {
persist: {
id: 'package-manager',
},
},
remarkPlugins: [remarkSteps],
})(environment);
},
},
meta: {
schema: metaSchema.extend({
description: z.string().optional(),
}),
},
});
export default defineConfig({
plugins: [
lastModified(),
],
});

Some files were not shown because too many files have changed in this diff Show More