mirror of
https://github.com/luxfi/docs.git
synced 2026-09-24 00:25:32 +00:00
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:
@@ -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;
|
||||
@@ -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"]}});
|
||||
@@ -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"), });
|
||||
@@ -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,10 +4,14 @@ node_modules/
|
||||
|
||||
# Build outputs
|
||||
.next/
|
||||
.docs/
|
||||
out/
|
||||
dist/
|
||||
.source/
|
||||
|
||||
# Turbo
|
||||
.turbo/
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.local
|
||||
|
||||
+5
-4
@@ -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
|
||||
|
||||
@@ -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>;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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%);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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
|
||||
```
|
||||
@@ -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"]}
|
||||
@@ -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}'
|
||||
```
|
||||
@@ -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.
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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>
|
||||
</>
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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>;
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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(),
|
||||
],
|
||||
});
|
||||
@@ -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"]
|
||||
}
|
||||
@@ -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>;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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%);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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 |
|
||||
@@ -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
|
||||
```
|
||||
@@ -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
|
||||
```
|
||||
@@ -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
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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>
|
||||
</>
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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>;
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import tailwindcss from '@tailwindcss/postcss';
|
||||
|
||||
export default {
|
||||
plugins: [tailwindcss],
|
||||
};
|
||||
@@ -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(),
|
||||
],
|
||||
});
|
||||
@@ -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"]
|
||||
}
|
||||
@@ -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>;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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%);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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"]}
|
||||
@@ -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
|
||||
```
|
||||
@@ -0,0 +1 @@
|
||||
{"pages":["---Getting Started---","installation","quickstart","---Commands---","commands","---Guides---","guides","---Reference---","configuration","api"]}
|
||||
@@ -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
|
||||
```
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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>
|
||||
</>
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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>;
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import tailwindcss from '@tailwindcss/postcss';
|
||||
|
||||
export default {
|
||||
plugins: [tailwindcss],
|
||||
};
|
||||
@@ -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
Reference in New Issue
Block a user