Max/docs theme rework (#6593)
* Rawer landing page - Angular, clean docs styling inspired by Oxide - zero all border-radius globally (kill rounded corners) - sharp code blocks with subtle border - callouts: left-border accent instead of rounded pill - clean table grid lines, sharp search box and MUI buttons - tighter heading letter-spacing (-0.02em) - flat left-border sidebar active item instead of background blob * Add JetBrains Mono for headings/sidebar, push Oxide styling further - import JetBrains Mono via Google Fonts - apply mono font to headings, sidebar, nav bar, search, table headers - darken background (#181C1E), muted body text, h2 bottom border - subtle background tint on active sidebar item - inline code: background-only (no border), monospace table headers - fix active sidebar item font size (scope separator label rule) * Rework docs landing page: hero, ASCII cards, SDKs, get started - add hero section with subtitle covering all doc areas - replace PNG vector illustrations with ASCII art in primary green - add SDKs section with Rust and TypeScript links - add get started section: What is the Mixnet, Send a message, Run a node - add footer links to GitHub and Matrix - fix nav dropdown font (button + ul selectors) - add landing card hover style * Self-host JetBrains Mono, refine landing page - replace Google Fonts import with local @font-face (woff2) - add font files + OFL license to public/fonts/ - remove redundant "Nym Docs" hero heading (already in nav) - drop quick-links pills section - fix SDK box borders (negative margin collapse) - rewrite footer as simple link row (GitHub, Matrix, nym.com) * Light mode styling, dark-mode diagram invert, click-to-expand images - add full light mode CSS: pale grey bg, darker green links, mono fonts - invert diagram images in dark mode with mix-blend-mode: lighten - add click-to-expand overlay for content images - revert mermaid diagrams back to original PNGs * Fix Lychee config for fonts * Make light mode green darker * Animate landing page ASCII art, remove architecture diagram - Network: animated packet traversal through gw_e → M1/M2/M3 → gw_ex with diagonal cross-connections showing mixing paths - Developers: typewriter effect with blinking cursor - Operators: looping progress bar with continuously incrementing packet count - APIs: staged line-by-line response reveal - Remove architecture overview PNG from network/architecture.mdx * Small copy change to SDK headers * Fix links
This commit is contained in:
@@ -1,120 +1,504 @@
|
||||
import React from "react";
|
||||
import { Box, Grid, Typography } from "@mui/material";
|
||||
import useMediaQuery from "@mui/material/useMediaQuery";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
|
||||
import Image from "next/image";
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import Link from "next/link";
|
||||
|
||||
import networkDocs from "../public/images/landing/Vector1.png";
|
||||
import developerDocs from "../public/images/landing/Vector2.png";
|
||||
import sdkDocs from "../public/images/landing/Vector3.png";
|
||||
import operatorGuide from "../public/images/landing/Vector4.png";
|
||||
export const LandingPage = () => {
|
||||
const theme = useTheme();
|
||||
const isTablet = useMediaQuery(theme.breakpoints.up("md"));
|
||||
const isDesktop = useMediaQuery(theme.breakpoints.up("xl"));
|
||||
const asciiStyle: React.CSSProperties = {
|
||||
fontFamily: "var(--font-mono)",
|
||||
fontSize: "0.72rem",
|
||||
lineHeight: 1.4,
|
||||
color: "var(--colorPrimary)",
|
||||
opacity: 0.7,
|
||||
whiteSpace: "pre",
|
||||
margin: 0,
|
||||
};
|
||||
|
||||
const squares = [
|
||||
{
|
||||
text: "Network Docs",
|
||||
description: "Architecture, crypto systems, and how the Mixnet works",
|
||||
href: "/network",
|
||||
icon: developerDocs,
|
||||
},
|
||||
{
|
||||
text: "Operator Guides",
|
||||
description:
|
||||
"Guides and maintenance: if you want to run a node, start here",
|
||||
// ── Animation components ──
|
||||
|
||||
href: "/operators/introduction",
|
||||
icon: operatorGuide,
|
||||
},
|
||||
{
|
||||
text: "Developer Portal",
|
||||
description: "Conceptual overview, clients, tools and SDKs",
|
||||
const randomRow = () => Math.floor(Math.random() * 3);
|
||||
const randomPath = () => [randomRow(), randomRow(), randomRow()];
|
||||
|
||||
href: "/developers",
|
||||
icon: sdkDocs,
|
||||
},
|
||||
{
|
||||
text: "APIs",
|
||||
description: "Interactive API specs for Nym infrastructure",
|
||||
const NetworkAnimation = () => {
|
||||
// Packets traverse 5 stages: gw_e(0) → M1(1) → M2(2) → M3(3) → gw_ex(4)
|
||||
// stage -1 = not yet mounted (SSR-safe, renders all ○)
|
||||
const [packets, setPackets] = useState([
|
||||
{ path: randomPath(), stage: -1 },
|
||||
{ path: randomPath(), stage: -1 },
|
||||
]);
|
||||
useEffect(() => {
|
||||
// kick off with staggered positions
|
||||
setPackets([
|
||||
{ path: randomPath(), stage: 0 },
|
||||
{ path: randomPath(), stage: 3 },
|
||||
]);
|
||||
|
||||
href: "/apis/introduction",
|
||||
icon: networkDocs,
|
||||
},
|
||||
];
|
||||
const id = setInterval(() => {
|
||||
setPackets((prev) =>
|
||||
prev.map((p) => {
|
||||
const next = (p.stage + 1) % 5;
|
||||
return { stage: next, path: next === 0 ? randomPath() : p.path };
|
||||
})
|
||||
);
|
||||
}, 300);
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
|
||||
const shortenDescription = (description: string) => {
|
||||
return description.slice(0, 18) + "...";
|
||||
const gwNode = (stage: number) => {
|
||||
const active = packets.some((p) => p.stage === stage);
|
||||
return (
|
||||
<span
|
||||
style={
|
||||
active ? { color: "var(--colorPrimary)", opacity: 1 } : undefined
|
||||
}
|
||||
>
|
||||
{active ? "\u25CF" : "\u25CB"}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const mixNode = (col: number, row: number) => {
|
||||
const active = packets.some(
|
||||
(p) => p.stage === col + 1 && p.path[col] === row
|
||||
);
|
||||
const filled = active;
|
||||
return (
|
||||
<span
|
||||
style={
|
||||
active ? { color: "var(--colorPrimary)", opacity: 1 } : undefined
|
||||
}
|
||||
>
|
||||
{filled ? "\u25CF" : "\u25CB"}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box margin={"0 auto"} textAlign="center">
|
||||
{/*<Typography variant="h2" mb={6}>
|
||||
Nym Docs
|
||||
</Typography>
|
||||
|
||||
<Typography mb={10}>
|
||||
Nym is a privacy platform. It provides strong network-level privacy
|
||||
against sophisticated end-to-end attackers, and anonymous access control
|
||||
using blinded, re-randomizable, decentralized credentials. Our goal is
|
||||
to allow developers to build new applications, or upgrade existing apps,
|
||||
with privacy features unavailable in other systems.
|
||||
</Typography>*/}
|
||||
<Grid container border={"1px solid #2E3538"}>
|
||||
{squares.map((square, index) => (
|
||||
<Grid
|
||||
item
|
||||
key={index}
|
||||
xs={12}
|
||||
sm={6}
|
||||
padding={{ xs: 3, xl: 4 }}
|
||||
sx={{
|
||||
borderBottom: {
|
||||
xs: index < 3 ? "1px solid #2E3538" : "none",
|
||||
sm: index === 0 || index === 1 ? "1px solid #2E3538" : "none",
|
||||
},
|
||||
borderRight: {
|
||||
xs: "none",
|
||||
sm: index === 0 || index === 2 ? "1px solid #2E3538" : "none",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Link href={square.href}>
|
||||
<Box
|
||||
display={"flex"}
|
||||
gap={{ xs: 3, xl: 4 }}
|
||||
height={"100%"}
|
||||
flexDirection="column"
|
||||
alignItems="center"
|
||||
>
|
||||
<Typography variant="h5" sx={{ fontWeight: 600 }}>
|
||||
{square.text}
|
||||
</Typography>
|
||||
|
||||
<Typography
|
||||
variant="body1"
|
||||
textAlign="center"
|
||||
sx={{
|
||||
color: "#909195",
|
||||
}}
|
||||
>
|
||||
{square.description}
|
||||
</Typography>
|
||||
|
||||
<Image
|
||||
src={square.icon}
|
||||
alt={square.text}
|
||||
width={isDesktop ? 180 : isTablet ? 140 : 180}
|
||||
height={isDesktop ? 134 : isTablet ? 90 : 134}
|
||||
/>
|
||||
</Box>
|
||||
</Link>
|
||||
</Grid>
|
||||
))}
|
||||
</Grid>
|
||||
</Box>
|
||||
<pre style={{ ...asciiStyle, marginTop: "1.2rem" }}>
|
||||
{"gw_e M1 M2 M3 gw_ex\n"}
|
||||
{" "}
|
||||
{mixNode(0, 0)}
|
||||
{" \u2500\u2500 "}
|
||||
{mixNode(1, 0)}
|
||||
{" \u2500\u2500 "}
|
||||
{mixNode(2, 0)}
|
||||
{"\n"}
|
||||
{" \\ / \\ /\n"}
|
||||
{" "}
|
||||
{gwNode(0)}
|
||||
{" \u2500\u2500 "}
|
||||
{mixNode(0, 1)}
|
||||
{" \u2500\u2500 "}
|
||||
{mixNode(1, 1)}
|
||||
{" \u2500\u2500 "}
|
||||
{mixNode(2, 1)}
|
||||
{" \u2500\u2500 "}
|
||||
{gwNode(4)}
|
||||
{"\n"}
|
||||
{" / \\ / \\\n"}
|
||||
{" "}
|
||||
{mixNode(0, 2)}
|
||||
{" \u2500\u2500 "}
|
||||
{mixNode(1, 2)}
|
||||
{" \u2500\u2500 "}
|
||||
{mixNode(2, 2)}
|
||||
</pre>
|
||||
);
|
||||
};
|
||||
|
||||
const TypewriterAnimation = () => {
|
||||
const text =
|
||||
"let client = MixnetClient::connect_new().await?;\n" +
|
||||
"\n" +
|
||||
"client.send(msg).await;";
|
||||
const [charCount, setCharCount] = useState(0);
|
||||
const [showCursor, setShowCursor] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
const run = () => {
|
||||
setCharCount(0);
|
||||
let i = 0;
|
||||
const type = () => {
|
||||
if (cancelled) return;
|
||||
if (i <= text.length) {
|
||||
setCharCount(i);
|
||||
i++;
|
||||
setTimeout(type, 40);
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
if (!cancelled) run();
|
||||
}, 2000);
|
||||
}
|
||||
};
|
||||
type();
|
||||
};
|
||||
run();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(() => setShowCursor((v) => !v), 530);
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<pre style={{ ...asciiStyle, marginTop: "1.2rem" }}>
|
||||
{text.slice(0, charCount)}
|
||||
<span style={{ opacity: 0.6 }}>{showCursor ? "\u258C" : " "}</span>
|
||||
<span style={{ opacity: 0 }}>{text.slice(charCount)}</span>
|
||||
</pre>
|
||||
);
|
||||
};
|
||||
|
||||
const OperatorsAnimation = () => {
|
||||
const totalBars = 10;
|
||||
const [tick, setTick] = useState(0);
|
||||
const mixRef = useRef(0);
|
||||
const [mixCount, setMixCount] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(() => {
|
||||
setTick((t) => t + 1);
|
||||
mixRef.current += Math.floor(Math.random() * 8) + 5;
|
||||
setMixCount(mixRef.current);
|
||||
}, 80);
|
||||
return () => clearInterval(id);
|
||||
}, []);
|
||||
|
||||
const mixFilled = Math.min(tick % 12, totalBars);
|
||||
const bar = (f: number) =>
|
||||
"\u25A0".repeat(f) + "\u25A1".repeat(totalBars - f);
|
||||
const fmt = (n: number) => n.toLocaleString("en");
|
||||
|
||||
return (
|
||||
<pre style={{ ...asciiStyle, marginTop: "1.2rem" }}>
|
||||
{"> nym-node run\n\n"}
|
||||
{" mixing: "}
|
||||
{bar(mixFilled)}
|
||||
{" "}
|
||||
{fmt(mixCount)}
|
||||
{" pkts"}
|
||||
</pre>
|
||||
);
|
||||
};
|
||||
|
||||
const ApiAnimation = () => {
|
||||
const lines = [
|
||||
"GET /v1/mixnodes/active",
|
||||
"",
|
||||
'{ "count": 498,',
|
||||
' "nodes": [ ... ] }',
|
||||
];
|
||||
const [visibleLines, setVisibleLines] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
const run = () => {
|
||||
setVisibleLines(0);
|
||||
setTimeout(() => {
|
||||
if (cancelled) return;
|
||||
setVisibleLines(1);
|
||||
setTimeout(() => {
|
||||
if (cancelled) return;
|
||||
let i = 2;
|
||||
const reveal = () => {
|
||||
if (cancelled) return;
|
||||
if (i <= lines.length) {
|
||||
setVisibleLines(i);
|
||||
i++;
|
||||
setTimeout(reveal, 300);
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
if (!cancelled) run();
|
||||
}, 2000);
|
||||
}
|
||||
};
|
||||
reveal();
|
||||
}, 800);
|
||||
}, 100);
|
||||
};
|
||||
run();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<pre style={{ ...asciiStyle, marginTop: "1.2rem" }}>
|
||||
{lines.slice(0, visibleLines).map((line, i) => (
|
||||
<React.Fragment key={i}>
|
||||
{i > 0 && "\n"}
|
||||
{line}
|
||||
</React.Fragment>
|
||||
))}
|
||||
<span style={{ opacity: 0 }}>
|
||||
{lines.slice(visibleLines).map((line, i) => (
|
||||
<React.Fragment key={i}>
|
||||
{visibleLines > 0 || i > 0 ? "\n" : ""}
|
||||
{line}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</span>
|
||||
</pre>
|
||||
);
|
||||
};
|
||||
|
||||
// ── Section data ──
|
||||
|
||||
const sections = [
|
||||
{
|
||||
title: "Network",
|
||||
description:
|
||||
"Architecture, cryptographic systems, and how the Mixnet protects your traffic.",
|
||||
href: "/network",
|
||||
animation: "network" as const,
|
||||
},
|
||||
{
|
||||
title: "Developers",
|
||||
description: "SDKs, tutorials, and integration guides for building on Nym.",
|
||||
href: "/developers",
|
||||
animation: "typewriter" as const,
|
||||
},
|
||||
{
|
||||
title: "Operators",
|
||||
description:
|
||||
"Set up and maintain mix nodes, gateways, and network infrastructure.",
|
||||
href: "/operators/introduction",
|
||||
animation: "progress" as const,
|
||||
},
|
||||
{
|
||||
title: "APIs",
|
||||
description: "Interactive specs for querying Nym infrastructure.",
|
||||
href: "/apis/introduction",
|
||||
animation: "api" as const,
|
||||
},
|
||||
];
|
||||
|
||||
const AnimationBlock = ({ type }: { type: string }) => {
|
||||
switch (type) {
|
||||
case "network":
|
||||
return <NetworkAnimation />;
|
||||
case "typewriter":
|
||||
return <TypewriterAnimation />;
|
||||
case "progress":
|
||||
return <OperatorsAnimation />;
|
||||
case "api":
|
||||
return <ApiAnimation />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const sdks = [
|
||||
{
|
||||
name: "Rust",
|
||||
description:
|
||||
"Native SDK with async Mixnet client, streams, and TcpProxy modules.",
|
||||
href: "/developers/rust",
|
||||
},
|
||||
{
|
||||
name: "TypeScript",
|
||||
description:
|
||||
"Browser-based SDK with fetch API replacement and message-based WebSocket transport.",
|
||||
href: "/developers/typescript",
|
||||
},
|
||||
];
|
||||
|
||||
export const LandingPage = () => {
|
||||
return (
|
||||
<div
|
||||
style={{ maxWidth: "64rem", margin: "0 auto", padding: "3rem 1.5rem" }}
|
||||
>
|
||||
{/* ── Section cards ── */}
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(2, 1fr)",
|
||||
border: "1px solid var(--border)",
|
||||
marginBottom: "3.5rem",
|
||||
}}
|
||||
>
|
||||
{sections.map((s, i) => (
|
||||
<Link
|
||||
key={i}
|
||||
href={s.href}
|
||||
style={{ textDecoration: "none", display: "flex" }}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
padding: "1.5rem",
|
||||
borderBottom: i < 2 ? "1px solid var(--border)" : undefined,
|
||||
borderRight:
|
||||
i % 2 === 0 ? "1px solid var(--border)" : undefined,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
flex: 1,
|
||||
transition: "background-color 0.15s",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
className="landing-card"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: "0.5rem",
|
||||
marginBottom: "0.5rem",
|
||||
}}
|
||||
>
|
||||
<h2
|
||||
className="landing-heading"
|
||||
style={{
|
||||
fontFamily: "var(--font-mono)",
|
||||
fontSize: "1.25rem",
|
||||
fontWeight: 600,
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
border: "none",
|
||||
}}
|
||||
>
|
||||
{s.title}
|
||||
</h2>
|
||||
<span
|
||||
style={{ color: "var(--textMuted)", fontSize: "0.9rem" }}
|
||||
>
|
||||
›
|
||||
</span>
|
||||
</div>
|
||||
<p
|
||||
style={{
|
||||
fontSize: "0.88rem",
|
||||
color: "var(--textMuted)",
|
||||
lineHeight: 1.6,
|
||||
margin: 0,
|
||||
}}
|
||||
>
|
||||
{s.description}
|
||||
</p>
|
||||
</div>
|
||||
<AnimationBlock type={s.animation} />
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* ── SDKs ── */}
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr 1fr",
|
||||
gap: "0",
|
||||
marginBottom: "3.5rem",
|
||||
}}
|
||||
>
|
||||
<div style={{ paddingRight: "2rem" }}>
|
||||
<h2
|
||||
className="landing-heading"
|
||||
style={{
|
||||
fontFamily: "var(--font-mono)",
|
||||
fontSize: "1.35rem",
|
||||
fontWeight: 600,
|
||||
marginBottom: "0.5rem",
|
||||
border: "none",
|
||||
padding: 0,
|
||||
}}
|
||||
>
|
||||
SDKs
|
||||
</h2>
|
||||
<p
|
||||
style={{
|
||||
fontSize: "0.88rem",
|
||||
color: "var(--textMuted)",
|
||||
lineHeight: 1.6,
|
||||
}}
|
||||
>
|
||||
Integrate Mixnet privacy into your application with our Rust and
|
||||
TypeScript SDKs.
|
||||
</p>
|
||||
</div>
|
||||
<div style={{ display: "flex", flexDirection: "column", gap: "0" }}>
|
||||
{sdks.map((sdk, i) => (
|
||||
<Link key={i} href={sdk.href} style={{ textDecoration: "none" }}>
|
||||
<div
|
||||
className="landing-card"
|
||||
style={{
|
||||
padding: "1rem 1.2rem",
|
||||
border: "1px solid var(--border)",
|
||||
marginTop: i > 0 ? "-1px" : undefined,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
transition: "background-color 0.15s",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<span
|
||||
className="landing-heading"
|
||||
style={{
|
||||
fontFamily: "var(--font-mono)",
|
||||
fontSize: "1rem",
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
{sdk.name}
|
||||
</span>
|
||||
<p
|
||||
style={{
|
||||
fontSize: "0.8rem",
|
||||
color: "var(--textMuted)",
|
||||
margin: "0.25rem 0 0 0",
|
||||
}}
|
||||
>
|
||||
{sdk.description}
|
||||
</p>
|
||||
</div>
|
||||
<span style={{ color: "var(--textMuted)", fontSize: "1rem" }}>
|
||||
›
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ── Links ── */}
|
||||
<div
|
||||
style={{
|
||||
borderTop: "1px solid var(--border)",
|
||||
paddingTop: "1.5rem",
|
||||
display: "flex",
|
||||
gap: "2rem",
|
||||
fontSize: "0.82rem",
|
||||
fontFamily: "var(--font-mono)",
|
||||
}}
|
||||
>
|
||||
<a
|
||||
href="https://github.com/nymtech"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={{ color: "var(--textMuted)", textDecoration: "none" }}
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
<a
|
||||
href="https://matrix.to/#/#operators:nymtech.chat"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={{ color: "var(--textMuted)", textDecoration: "none" }}
|
||||
>
|
||||
Matrix
|
||||
</a>
|
||||
<a
|
||||
href="https://nym.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
style={{ color: "var(--textMuted)", textDecoration: "none" }}
|
||||
>
|
||||
nymtech.net
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1 +1 @@
|
||||
Wednesday, March 18th 2026, 14:02:49 UTC
|
||||
Tuesday, March 24th 2026, 13:05:57 UTC
|
||||
|
||||
@@ -4,109 +4,86 @@ Start this nym-node
|
||||
Usage: nym-node run [OPTIONS]
|
||||
|
||||
Options:
|
||||
--id <ID>
|
||||
Id of the nym-node to use [env: NYMNODE_ID=] [default: default-nym-node]
|
||||
--config-file <CONFIG_FILE>
|
||||
Path to a configuration file of this node [env: NYMNODE_CONFIG=]
|
||||
--accept-operator-terms-and-conditions
|
||||
Explicitly specify whether you agree with the terms and conditions of a nym node operator as defined at <https://nymtech.net/terms-and-conditions/operators/v1.0.0> [env:
|
||||
NYMNODE_ACCEPT_OPERATOR_TERMS=]
|
||||
--deny-init
|
||||
Forbid a new node from being initialised if configuration file for the provided specification doesn't already exist [env: NYMNODE_DENY_INIT=]
|
||||
--init-only
|
||||
If this is a brand new nym-node, specify whether it should only be initialised without actually running the subprocesses [env: NYMNODE_INIT_ONLY=]
|
||||
--local
|
||||
Flag specifying this node will be running in a local setting [env: NYMNODE_LOCAL=]
|
||||
--mode [<MODE>...]
|
||||
Specifies the current mode(s) of this nym-node [env: NYMNODE_MODE=] [possible values: mixnode, entry-gateway, exit-gateway, exit-providers-only]
|
||||
--modes <MODES>
|
||||
Specifies the current mode(s) of this nym-node as a single flag [env: NYMNODE_MODES=] [possible values: mixnode, entry-gateway, exit-gateway, exit-providers-only]
|
||||
-w, --write-changes
|
||||
If this node has been initialised before, specify whether to write any new changes to the config file [env: NYMNODE_WRITE_CONFIG_CHANGES=]
|
||||
--bonding-information-output <BONDING_INFORMATION_OUTPUT>
|
||||
Specify output file for bonding information of this nym-node, i.e. its encoded keys. NOTE: the required bonding information is still a subject to change and this argument should be
|
||||
treated only as a preview of future features [env: NYMNODE_BONDING_INFORMATION_OUTPUT=]
|
||||
-o, --output <OUTPUT>
|
||||
Specify the output format of the bonding information (`text` or `json`) [env: NYMNODE_OUTPUT=] [default: text] [possible values: text, json]
|
||||
--public-ips <PUBLIC_IPS>
|
||||
Comma separated list of public ip addresses that will be announced to the nym-api and subsequently to the clients. In nearly all circumstances, it's going to be identical to the
|
||||
address you're going to use for bonding [env: NYMNODE_PUBLIC_IPS=]
|
||||
--hostname <HOSTNAME>
|
||||
Optional hostname associated with this gateway that will be announced to the nym-api and subsequently to the clients [env: NYMNODE_HOSTNAME=]
|
||||
--location <LOCATION>
|
||||
Optional **physical** location of this node's server. Either full country name (e.g. 'Poland'), two-letter alpha2 (e.g. 'PL'), three-letter alpha3 (e.g. 'POL') or three-digit
|
||||
numeric-3 (e.g. '616') can be provided [env: NYMNODE_LOCATION=]
|
||||
--http-bind-address <HTTP_BIND_ADDRESS>
|
||||
Socket address this node will use for binding its http API. default: `[::]:8080` [env: NYMNODE_HTTP_BIND_ADDRESS=]
|
||||
--landing-page-assets-path <LANDING_PAGE_ASSETS_PATH>
|
||||
Path to assets directory of custom landing page of this node [env: NYMNODE_HTTP_LANDING_ASSETS=]
|
||||
--http-access-token <HTTP_ACCESS_TOKEN>
|
||||
An optional bearer token for accessing certain http endpoints. Currently only used for prometheus metrics [env: NYMNODE_HTTP_ACCESS_TOKEN=]
|
||||
--expose-system-info <EXPOSE_SYSTEM_INFO>
|
||||
Specify whether basic system information should be exposed. default: true [env: NYMNODE_HTTP_EXPOSE_SYSTEM_INFO=] [possible values: true, false]
|
||||
--expose-system-hardware <EXPOSE_SYSTEM_HARDWARE>
|
||||
Specify whether basic system hardware information should be exposed. default: true [env: NYMNODE_HTTP_EXPOSE_SYSTEM_HARDWARE=] [possible values: true, false]
|
||||
--expose-crypto-hardware <EXPOSE_CRYPTO_HARDWARE>
|
||||
Specify whether detailed system crypto hardware information should be exposed. default: true [env: NYMNODE_HTTP_EXPOSE_CRYPTO_HARDWARE=] [possible values: true, false]
|
||||
--mixnet-bind-address <MIXNET_BIND_ADDRESS>
|
||||
Address this node will bind to for listening for mixnet packets default: `[::]:1789` [env: NYMNODE_MIXNET_BIND_ADDRESS=]
|
||||
--mixnet-announce-port <MIXNET_ANNOUNCE_PORT>
|
||||
If applicable, custom port announced in the self-described API that other clients and nodes will use. Useful when the node is behind a proxy [env: NYMNODE_MIXNET_ANNOUNCE_PORT=]
|
||||
--nym-api-urls <NYM_API_URLS>
|
||||
Addresses to nym APIs from which the node gets the view of the network [env: NYMNODE_NYM_APIS=]
|
||||
--nyxd-urls <NYXD_URLS>
|
||||
Addresses to nyxd chain endpoint which the node will use for chain interactions [env: NYMNODE_NYXD=]
|
||||
--enable-console-logging <ENABLE_CONSOLE_LOGGING>
|
||||
Specify whether running statistics of this node should be logged to the console [env: NYMNODE_ENABLE_CONSOLE_LOGGING=] [possible values: true, false]
|
||||
--wireguard-enabled <WIREGUARD_ENABLED>
|
||||
Specifies whether the wireguard service is enabled on this node [env: NYMNODE_WG_ENABLED=] [possible values: true, false]
|
||||
--wireguard-bind-address <WIREGUARD_BIND_ADDRESS>
|
||||
Socket address this node will use for binding its wireguard interface. default: `[::]:51822` [env: NYMNODE_WG_BIND_ADDRESS=]
|
||||
--wireguard-tunnel-announced-port <WIREGUARD_TUNNEL_ANNOUNCED_PORT>
|
||||
Tunnel port announced to external clients wishing to connect to the wireguard interface. Useful in the instances where the node is behind a proxy [env: NYMNODE_WG_ANNOUNCED_PORT=]
|
||||
--wireguard-private-network-prefix <WIREGUARD_PRIVATE_NETWORK_PREFIX>
|
||||
The prefix denoting the maximum number of the clients that can be connected via Wireguard. The maximum value for IPv4 is 32 and for IPv6 is 128 [env:
|
||||
NYMNODE_WG_PRIVATE_NETWORK_PREFIX=]
|
||||
--wireguard-userspace <WIREGUARD_USERSPACE>
|
||||
Use userspace implementation of WireGuard (wireguard-go) instead of kernel module. Useful in containerized environments without kernel WireGuard support [env: NYMNODE_WG_USERSPACE=]
|
||||
[possible values: true, false]
|
||||
--verloc-bind-address <VERLOC_BIND_ADDRESS>
|
||||
Socket address this node will use for binding its verloc API. default: `[::]:1790` [env: NYMNODE_VERLOC_BIND_ADDRESS=]
|
||||
--verloc-announce-port <VERLOC_ANNOUNCE_PORT>
|
||||
If applicable, custom port announced in the self-described API that other clients and nodes will use. Useful when the node is behind a proxy [env: NYMNODE_VERLOC_ANNOUNCE_PORT=]
|
||||
--entry-bind-address <ENTRY_BIND_ADDRESS>
|
||||
Socket address this node will use for binding its client websocket API. default: `[::]:9000` [env: NYMNODE_ENTRY_BIND_ADDRESS=]
|
||||
--announce-ws-port <ANNOUNCE_WS_PORT>
|
||||
Custom announced port for listening for websocket client traffic. If unspecified, the value from the `bind_address` will be used instead [env: NYMNODE_ENTRY_ANNOUNCE_WS_PORT=]
|
||||
--announce-wss-port <ANNOUNCE_WSS_PORT>
|
||||
If applicable, announced port for listening for secure websocket client traffic [env: NYMNODE_ENTRY_ANNOUNCE_WSS_PORT=]
|
||||
--enforce-zk-nyms <ENFORCE_ZK_NYMS>
|
||||
Indicates whether this gateway is accepting only coconut credentials for accessing the mixnet or if it also accepts non-paying clients [env: NYMNODE_ENFORCE_ZK_NYMS=] [possible
|
||||
values: true, false]
|
||||
--mnemonic <MNEMONIC>
|
||||
Custom cosmos wallet mnemonic used for zk-nym redemption. If no value is provided, a fresh mnemonic is going to be generated [env: NYMNODE_MNEMONIC=]
|
||||
--upgrade-mode-attestation-url <UPGRADE_MODE_ATTESTATION_URL>
|
||||
Endpoint to query to retrieve current upgrade mode attestation. This argument should never be set outside testnets and local networks [env: NYMNODE_UPGRADE_MODE_ATTESTATION_URL=]
|
||||
--upgrade-mode-attester-public-key <UPGRADE_MODE_ATTESTER_PUBLIC_KEY>
|
||||
Expected public key of the entity signing the published attestation. This argument should never be set outside testnets and local networks [env:
|
||||
NYMNODE_UPGRADE_MODE_ATTESTER_PUBKEY=]
|
||||
--upstream-exit-policy-url <UPSTREAM_EXIT_POLICY_URL>
|
||||
Specifies the url for an upstream source of the exit policy used by this node [env: NYMNODE_UPSTREAM_EXIT_POLICY=]
|
||||
--open-proxy <OPEN_PROXY>
|
||||
Specifies whether this exit node should run in 'open-proxy' mode and thus would attempt to resolve **ANY** request it receives [env: NYMNODE_OPEN_PROXY=] [possible values: true,
|
||||
false]
|
||||
--lp-control-bind-address <LP_CONTROL_BIND_ADDRESS>
|
||||
Bind address for the TCP LP control traffic. default: `[::]:41264` [env: NYMNODE_LP_CONTROL_BIND_ADDRESS=]
|
||||
--lp-control-announce-port <LP_CONTROL_ANNOUNCE_PORT>
|
||||
Custom announced port for listening for the TCP LP control traffic. If unspecified, the value from the `lp_control_bind_address` will be used instead [env:
|
||||
NYMNODE_LP_CONTROL_ANNOUNCE_PORT=]
|
||||
--lp-data-bind-address <LP_DATA_BIND_ADDRESS>
|
||||
Bind address for the UDP LP data traffic. default: `[::]:51264` [env: NYMNODE_LP_DATA_BIND_ADDRESS=]
|
||||
--lp-data-announce-port <LP_DATA_ANNOUNCE_PORT>
|
||||
Custom announced port for listening for the UDP LP data traffic. If unspecified, the value from the `lp_data_bind_address` will be used instead [env: NYMNODE_LP_DATA_ANNOUNCE_PORT=]
|
||||
--lp-use-mock-ecash <LP_USE_MOCK_ECASH>
|
||||
Use mock ecash manager for LP testing. WARNING: Only use this for local testing! Never enable in production. When enabled, the LP listener will accept any credential without
|
||||
blockchain verification [env: NYMNODE_LP_USE_MOCK_ECASH=] [possible values: true, false]
|
||||
-h, --help
|
||||
Print help
|
||||
--id <ID> Id of the nym-node to use [env: NYMNODE_ID=] [default: default-nym-node]
|
||||
--config-file <CONFIG_FILE> Path to a configuration file of this node [env: NYMNODE_CONFIG=]
|
||||
--accept-operator-terms-and-conditions Explicitly specify whether you agree with the terms and conditions of a nym node operator as defined at
|
||||
<https://nymtech.net/terms-and-conditions/operators/v1.0.0> [env: NYMNODE_ACCEPT_OPERATOR_TERMS=]
|
||||
--deny-init Forbid a new node from being initialised if configuration file for the provided specification doesn't already exist [env:
|
||||
NYMNODE_DENY_INIT=]
|
||||
--init-only If this is a brand new nym-node, specify whether it should only be initialised without actually running the subprocesses
|
||||
[env: NYMNODE_INIT_ONLY=]
|
||||
--local Flag specifying this node will be running in a local setting [env: NYMNODE_LOCAL=]
|
||||
--mode [<MODE>...] Specifies the current mode(s) of this nym-node [env: NYMNODE_MODE=] [possible values: mixnode, entry-gateway,
|
||||
exit-gateway, exit-providers-only]
|
||||
--modes <MODES> Specifies the current mode(s) of this nym-node as a single flag [env: NYMNODE_MODES=] [possible values: mixnode,
|
||||
entry-gateway, exit-gateway, exit-providers-only]
|
||||
-w, --write-changes If this node has been initialised before, specify whether to write any new changes to the config file [env:
|
||||
NYMNODE_WRITE_CONFIG_CHANGES=]
|
||||
--bonding-information-output <BONDING_INFORMATION_OUTPUT> Specify output file for bonding information of this nym-node, i.e. its encoded keys. NOTE: the required bonding
|
||||
information is still a subject to change and this argument should be treated only as a preview of future features [env:
|
||||
NYMNODE_BONDING_INFORMATION_OUTPUT=]
|
||||
-o, --output <OUTPUT> Specify the output format of the bonding information (`text` or `json`) [env: NYMNODE_OUTPUT=] [default: text] [possible
|
||||
values: text, json]
|
||||
--public-ips <PUBLIC_IPS> Comma separated list of public ip addresses that will be announced to the nym-api and subsequently to the clients. In
|
||||
nearly all circumstances, it's going to be identical to the address you're going to use for bonding [env:
|
||||
NYMNODE_PUBLIC_IPS=]
|
||||
--hostname <HOSTNAME> Optional hostname associated with this gateway that will be announced to the nym-api and subsequently to the clients [env:
|
||||
NYMNODE_HOSTNAME=]
|
||||
--location <LOCATION> Optional **physical** location of this node's server. Either full country name (e.g. 'Poland'), two-letter alpha2 (e.g.
|
||||
'PL'), three-letter alpha3 (e.g. 'POL') or three-digit numeric-3 (e.g. '616') can be provided [env: NYMNODE_LOCATION=]
|
||||
--http-bind-address <HTTP_BIND_ADDRESS> Socket address this node will use for binding its http API. default: `[::]:8080` [env: NYMNODE_HTTP_BIND_ADDRESS=]
|
||||
--landing-page-assets-path <LANDING_PAGE_ASSETS_PATH> Path to assets directory of custom landing page of this node [env: NYMNODE_HTTP_LANDING_ASSETS=]
|
||||
--http-access-token <HTTP_ACCESS_TOKEN> An optional bearer token for accessing certain http endpoints. Currently only used for prometheus metrics [env:
|
||||
NYMNODE_HTTP_ACCESS_TOKEN=]
|
||||
--expose-system-info <EXPOSE_SYSTEM_INFO> Specify whether basic system information should be exposed. default: true [env: NYMNODE_HTTP_EXPOSE_SYSTEM_INFO=]
|
||||
[possible values: true, false]
|
||||
--expose-system-hardware <EXPOSE_SYSTEM_HARDWARE> Specify whether basic system hardware information should be exposed. default: true [env:
|
||||
NYMNODE_HTTP_EXPOSE_SYSTEM_HARDWARE=] [possible values: true, false]
|
||||
--expose-crypto-hardware <EXPOSE_CRYPTO_HARDWARE> Specify whether detailed system crypto hardware information should be exposed. default: true [env:
|
||||
NYMNODE_HTTP_EXPOSE_CRYPTO_HARDWARE=] [possible values: true, false]
|
||||
--mixnet-bind-address <MIXNET_BIND_ADDRESS> Address this node will bind to for listening for mixnet packets default: `[::]:1789` [env: NYMNODE_MIXNET_BIND_ADDRESS=]
|
||||
--mixnet-announce-port <MIXNET_ANNOUNCE_PORT> If applicable, custom port announced in the self-described API that other clients and nodes will use. Useful when the node
|
||||
is behind a proxy [env: NYMNODE_MIXNET_ANNOUNCE_PORT=]
|
||||
--nym-api-urls <NYM_API_URLS> Addresses to nym APIs from which the node gets the view of the network [env: NYMNODE_NYM_APIS=]
|
||||
--nyxd-urls <NYXD_URLS> Addresses to nyxd chain endpoint which the node will use for chain interactions [env: NYMNODE_NYXD=]
|
||||
--enable-console-logging <ENABLE_CONSOLE_LOGGING> Specify whether running statistics of this node should be logged to the console [env: NYMNODE_ENABLE_CONSOLE_LOGGING=]
|
||||
[possible values: true, false]
|
||||
--wireguard-enabled <WIREGUARD_ENABLED> Specifies whether the wireguard service is enabled on this node [env: NYMNODE_WG_ENABLED=] [possible values: true, false]
|
||||
--wireguard-bind-address <WIREGUARD_BIND_ADDRESS> Socket address this node will use for binding its wireguard interface. default: `[::]:51822` [env:
|
||||
NYMNODE_WG_BIND_ADDRESS=]
|
||||
--wireguard-tunnel-announced-port <WIREGUARD_TUNNEL_ANNOUNCED_PORT> Tunnel port announced to external clients wishing to connect to the wireguard interface. Useful in the instances where the
|
||||
node is behind a proxy [env: NYMNODE_WG_ANNOUNCED_PORT=]
|
||||
--wireguard-private-network-prefix <WIREGUARD_PRIVATE_NETWORK_PREFIX> The prefix denoting the maximum number of the clients that can be connected via Wireguard. The maximum value for IPv4 is
|
||||
32 and for IPv6 is 128 [env: NYMNODE_WG_PRIVATE_NETWORK_PREFIX=]
|
||||
--wireguard-userspace <WIREGUARD_USERSPACE> Use userspace implementation of WireGuard (wireguard-go) instead of kernel module. Useful in containerized environments
|
||||
without kernel WireGuard support [env: NYMNODE_WG_USERSPACE=] [possible values: true, false]
|
||||
--verloc-bind-address <VERLOC_BIND_ADDRESS> Socket address this node will use for binding its verloc API. default: `[::]:1790` [env: NYMNODE_VERLOC_BIND_ADDRESS=]
|
||||
--verloc-announce-port <VERLOC_ANNOUNCE_PORT> If applicable, custom port announced in the self-described API that other clients and nodes will use. Useful when the node
|
||||
is behind a proxy [env: NYMNODE_VERLOC_ANNOUNCE_PORT=]
|
||||
--entry-bind-address <ENTRY_BIND_ADDRESS> Socket address this node will use for binding its client websocket API. default: `[::]:9000` [env:
|
||||
NYMNODE_ENTRY_BIND_ADDRESS=]
|
||||
--announce-ws-port <ANNOUNCE_WS_PORT> Custom announced port for listening for websocket client traffic. If unspecified, the value from the `bind_address` will
|
||||
be used instead [env: NYMNODE_ENTRY_ANNOUNCE_WS_PORT=]
|
||||
--announce-wss-port <ANNOUNCE_WSS_PORT> If applicable, announced port for listening for secure websocket client traffic [env: NYMNODE_ENTRY_ANNOUNCE_WSS_PORT=]
|
||||
--enforce-zk-nyms <ENFORCE_ZK_NYMS> Indicates whether this gateway is accepting only coconut credentials for accessing the mixnet or if it also accepts
|
||||
non-paying clients [env: NYMNODE_ENFORCE_ZK_NYMS=] [possible values: true, false]
|
||||
--mnemonic <MNEMONIC> Custom cosmos wallet mnemonic used for zk-nym redemption. If no value is provided, a fresh mnemonic is going to be
|
||||
generated [env: NYMNODE_MNEMONIC=]
|
||||
--upgrade-mode-attestation-url <UPGRADE_MODE_ATTESTATION_URL> Endpoint to query to retrieve current upgrade mode attestation. This argument should never be set outside testnets and
|
||||
local networks [env: NYMNODE_UPGRADE_MODE_ATTESTATION_URL=]
|
||||
--upgrade-mode-attester-public-key <UPGRADE_MODE_ATTESTER_PUBLIC_KEY> Expected public key of the entity signing the published attestation. This argument should never be set outside testnets
|
||||
and local networks [env: NYMNODE_UPGRADE_MODE_ATTESTER_PUBKEY=]
|
||||
--upstream-exit-policy-url <UPSTREAM_EXIT_POLICY_URL> Specifies the url for an upstream source of the exit policy used by this node [env: NYMNODE_UPSTREAM_EXIT_POLICY=]
|
||||
--open-proxy <OPEN_PROXY> Specifies whether this exit node should run in 'open-proxy' mode and thus would attempt to resolve **ANY** request it
|
||||
receives [env: NYMNODE_OPEN_PROXY=] [possible values: true, false]
|
||||
--lp-control-bind-address <LP_CONTROL_BIND_ADDRESS> Bind address for the TCP LP control traffic. default: `[::]:41264` [env: NYMNODE_LP_CONTROL_BIND_ADDRESS=]
|
||||
--lp-control-announce-port <LP_CONTROL_ANNOUNCE_PORT> Custom announced port for listening for the TCP LP control traffic. If unspecified, the value from the
|
||||
`lp_control_bind_address` will be used instead [env: NYMNODE_LP_CONTROL_ANNOUNCE_PORT=]
|
||||
--lp-data-bind-address <LP_DATA_BIND_ADDRESS> Bind address for the UDP LP data traffic. default: `[::]:51264` [env: NYMNODE_LP_DATA_BIND_ADDRESS=]
|
||||
--lp-data-announce-port <LP_DATA_ANNOUNCE_PORT> Custom announced port for listening for the UDP LP data traffic. If unspecified, the value from the `lp_data_bind_address`
|
||||
will be used instead [env: NYMNODE_LP_DATA_ANNOUNCE_PORT=]
|
||||
--lp-use-mock-ecash <LP_USE_MOCK_ECASH> Use mock ecash manager for LP testing. WARNING: Only use this for local testing! Never enable in production. When enabled,
|
||||
the LP listener will accept any credential without blockchain verification [env: NYMNODE_LP_USE_MOCK_ECASH=] [possible
|
||||
values: true, false]
|
||||
-h, --help Print help
|
||||
```
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import React, { useMemo, useEffect } from 'react';
|
||||
import type { AppProps } from 'next/app';
|
||||
import './styles.css';
|
||||
import { ThemeProvider, createTheme } from '@mui/material/styles';
|
||||
@@ -20,6 +20,17 @@ const MyApp: React.FC<AppProps> = ({ Component, pageProps }) => {
|
||||
}),
|
||||
[],
|
||||
);
|
||||
useEffect(() => {
|
||||
const handler = (e: MouseEvent) => {
|
||||
const img = e.target as HTMLElement;
|
||||
if (img.tagName === 'IMG' && img.closest('.nextra-content')) {
|
||||
img.classList.toggle('img-expanded');
|
||||
}
|
||||
};
|
||||
document.addEventListener('click', handler);
|
||||
return () => document.removeEventListener('click', handler);
|
||||
}, []);
|
||||
|
||||
const AnyComponent = Component as any;
|
||||
return (
|
||||
<ThemeProvider theme={muiTheme}>
|
||||
|
||||
@@ -4,5 +4,3 @@ Core components:
|
||||
* A **Mixnet**, which mixes Sphinx packet traffic so that it cannot be determined who is communicating with whom. Our mixnet is based on a modified version of the [**Loopix** design](concepts/loopix). This is made up of [Nym nodes](architecture/mixnet#nodes) runnning on servers around the world maintained by a decentralised group of Operators.
|
||||
* Various [**Nym clients**](architecture/mixnet#nym-clients) which manage sending and receiving Sphinx packets, encrypting/decrypting traffic, and providing [cover traffic](./concepts/cover-traffic) to hide 'real' traffic timing.
|
||||
* A CosmWasm-enabled blockchain called [**Nyx**](architecture/nyx), the home of the various smart contracts used by the mixnet. A subset of Nyx Validators run [NymAPI](./architecture/nyx#nymapi) instances, taking part in also producing and verifying [zk-nym credentials](cryptography/zk-nym).
|
||||
|
||||

|
||||
|
||||
@@ -1,21 +1,67 @@
|
||||
/* nym.com-aligned colour tokens */
|
||||
:root {
|
||||
--colorPrimary: #85E89D;
|
||||
--textPrimary: #FFFFFF;
|
||||
--bg-dark: #1E2426;
|
||||
--border-dark: #2E3538;
|
||||
/* nym docs – angular, clean styling (oxide-inspired) */
|
||||
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
src: url('/docs/fonts/JetBrainsMono-Regular.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/* dark mode background override */
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
src: url('/docs/fonts/JetBrainsMono-Medium.woff2') format('woff2');
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
src: url('/docs/fonts/JetBrainsMono-SemiBold.woff2') format('woff2');
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
src: url('/docs/fonts/JetBrainsMono-Bold.woff2') format('woff2');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
:root {
|
||||
--colorPrimary: #85E89D;
|
||||
--textPrimary: #E0E0E0;
|
||||
--textMuted: #8B9295;
|
||||
--bg-dark: #181C1E;
|
||||
--bg-code: #1C2022;
|
||||
--border-dark: #2A2F32;
|
||||
--border: #2A2F32;
|
||||
--font-mono: 'JetBrains Mono', 'SFMono-Regular', 'Consolas', 'Liberation Mono', 'Menlo', monospace;
|
||||
}
|
||||
|
||||
/* ── Global: kill all rounded corners ── */
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
/* ── Dark mode backgrounds ── */
|
||||
|
||||
html.dark {
|
||||
background-color: var(--bg-dark);
|
||||
}
|
||||
|
||||
html.dark body {
|
||||
background-color: var(--bg-dark);
|
||||
color: var(--textPrimary);
|
||||
}
|
||||
|
||||
/* nextra main content area bg */
|
||||
html.dark .nextra-nav-container,
|
||||
html.dark .nextra-sidebar-container,
|
||||
html.dark .nextra-content,
|
||||
@@ -24,28 +70,43 @@ html.dark .dark\:nx-bg-dark {
|
||||
background-color: var(--bg-dark) !important;
|
||||
}
|
||||
|
||||
/* ── Typography ── */
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: var(--font-mono);
|
||||
letter-spacing: -0.02em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
html.dark h1 {
|
||||
color: #FFFFFF;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
html.dark h2 {
|
||||
color: #F0F0F0;
|
||||
padding-bottom: 0.3em;
|
||||
border-bottom: 1px solid var(--border-dark);
|
||||
}
|
||||
|
||||
html.dark p, html.dark li {
|
||||
color: var(--textPrimary);
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
/* ── Layout ── */
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.nextra-code-block > pre {
|
||||
/* max-height: 350px !important; */
|
||||
max-height: none !important;
|
||||
scroll-y: auto !important;
|
||||
}
|
||||
|
||||
/* set width entire div */
|
||||
.nx-mx-auto.nx-flex.nx-max-w-\[90rem\] {
|
||||
max-width: 110rem;
|
||||
left-padding: 1%;
|
||||
}
|
||||
|
||||
.nextra-toc {
|
||||
width: 10px !important;
|
||||
padding-right: 0px;
|
||||
padding-left: 0px;
|
||||
/* text-align: right; */
|
||||
border-left: 1px solid var(--border-dark);
|
||||
}
|
||||
|
||||
.nextra-content {
|
||||
@@ -56,23 +117,26 @@ footer {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
:is(html[class~="dark"] .dark\:nx-bg-primary-300\/10) {
|
||||
background-color: hsl(var(black) 100% 77%/0.1) !important;
|
||||
/* ── Nav bar ── */
|
||||
|
||||
html.dark .nextra-nav-container {
|
||||
border-bottom: 1px solid var(--border-dark) !important;
|
||||
}
|
||||
|
||||
/* Sidebar active item */
|
||||
:is(html .dark\:nx-bg-primary-400\/10) {
|
||||
background: transparent !important;
|
||||
border-left: 2px solid #85E89D;
|
||||
color: #FFFFFF !important;
|
||||
html.dark .nextra-nav-container nav a,
|
||||
html.dark .nextra-nav-container nav button,
|
||||
html.dark .nextra-nav-container nav ul a {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
:is(html:not(.dark) .dark\:nx-bg-primary-400\/10) {
|
||||
background: transparent !important;
|
||||
border-left: 2px solid #4A9E5C;
|
||||
color: #242B2D !important;
|
||||
html.dark .nextra-nav-container nav a:hover,
|
||||
html.dark .nextra-nav-container nav ul a:hover {
|
||||
color: var(--colorPrimary) !important;
|
||||
}
|
||||
|
||||
/* ── Sidebar ── */
|
||||
|
||||
.nextra-sidebar-container {
|
||||
border-right: 1px solid var(--border-dark);
|
||||
width: 300px !important;
|
||||
@@ -82,21 +146,171 @@ footer {
|
||||
column-width: 500px;
|
||||
}
|
||||
|
||||
/* Links*/
|
||||
/* Sidebar font */
|
||||
html.dark .nextra-sidebar-container {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.82rem;
|
||||
}
|
||||
|
||||
/* Sidebar text: muted by default */
|
||||
html.dark .nextra-sidebar-container a {
|
||||
color: var(--textMuted) !important;
|
||||
}
|
||||
|
||||
html.dark .nextra-sidebar-container a:hover {
|
||||
color: var(--textPrimary) !important;
|
||||
}
|
||||
|
||||
/* Sidebar separator labels (not active items) */
|
||||
html.dark .nextra-sidebar-container li.nx-mt-5 .nx-font-semibold {
|
||||
color: var(--textMuted) !important;
|
||||
font-size: 0.7rem;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
/* Active sidebar item: left-border accent + subtle tint */
|
||||
:is(html .dark\:nx-bg-primary-400\/10) {
|
||||
background: rgba(133, 232, 157, 0.06) !important;
|
||||
border-left: 2px solid var(--colorPrimary);
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
html.dark .nextra-sidebar-container :is(.dark\:nx-bg-primary-400\/10) a {
|
||||
color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
:is(html:not(.dark) .dark\:nx-bg-primary-400\/10) {
|
||||
background: rgba(74, 158, 92, 0.08) !important;
|
||||
border-left: 2px solid #4A9E5C;
|
||||
color: #242B2D !important;
|
||||
}
|
||||
|
||||
:is(html[class~="dark"] .dark\:nx-bg-primary-300\/10) {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
/* ── TOC (hidden — subsections live in sidebar) ── */
|
||||
|
||||
.nextra-toc {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* ── Code blocks ── */
|
||||
|
||||
html.dark .nextra-code-block > pre {
|
||||
background-color: var(--bg-code) !important;
|
||||
border: 1px solid var(--border-dark);
|
||||
}
|
||||
|
||||
/* Language tag in code blocks */
|
||||
html.dark .nextra-code-block [class*="nx-absolute"] {
|
||||
color: var(--textMuted);
|
||||
font-size: 0.7rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
/* Inline code: subtle background, no border */
|
||||
html.dark code:not(pre code) {
|
||||
background-color: rgba(255, 255, 255, 0.06) !important;
|
||||
border: none !important;
|
||||
padding: 0.15em 0.4em;
|
||||
font-size: 0.88em;
|
||||
color: var(--textPrimary);
|
||||
}
|
||||
|
||||
/* ── Callouts: left-border accent ── */
|
||||
|
||||
html.dark .nextra-callout {
|
||||
border: none;
|
||||
border-left: 3px solid;
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
}
|
||||
|
||||
/* ── Tables: monospace uppercase headers ── */
|
||||
|
||||
html.dark table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
html.dark th {
|
||||
border-bottom: 1px solid var(--border-dark);
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.75rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--textMuted);
|
||||
padding: 0.6em 1em;
|
||||
}
|
||||
|
||||
html.dark td {
|
||||
border-bottom: 1px solid var(--border-dark);
|
||||
padding: 0.6em 1em;
|
||||
color: var(--textPrimary);
|
||||
}
|
||||
|
||||
html.dark tr:hover td {
|
||||
background-color: rgba(255, 255, 255, 0.02);
|
||||
}
|
||||
|
||||
/* ── Search box ── */
|
||||
|
||||
html.dark .nextra-search input {
|
||||
border: 1px solid var(--border-dark);
|
||||
background-color: var(--bg-dark) !important;
|
||||
color: var(--textMuted);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
html.dark .nextra-search input::placeholder {
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
font-size: 0.72rem;
|
||||
}
|
||||
|
||||
/* ── Links ── */
|
||||
|
||||
.nx-text-primary-600.nx-underline.nx-decoration-from-font {
|
||||
color: var(--colorPrimary) !important;
|
||||
}
|
||||
|
||||
.MuiTypography-root.MuiTypography-inherit.MuiLink-root.MuiLink-underlineAlways.css-1xr3c94-MuiTypography-root-MuiLink-root {
|
||||
.nx-text-primary-600 {
|
||||
color: var(--colorPrimary) !important;
|
||||
}
|
||||
|
||||
.nextra-scrollbar.nx-sticky {
|
||||
color: var(--colorPrimary) !important;
|
||||
}
|
||||
|
||||
/* ── Breadcrumbs / navigation links ── */
|
||||
|
||||
html.dark .nextra-breadcrumb {
|
||||
color: var(--textMuted);
|
||||
}
|
||||
|
||||
/* Prev/next page links */
|
||||
html.dark a.nx-flex.nx-items-center {
|
||||
border-color: var(--border-dark) !important;
|
||||
}
|
||||
|
||||
html.dark a.nx-flex.nx-items-center:hover {
|
||||
border-color: var(--colorPrimary) !important;
|
||||
}
|
||||
|
||||
/* ── Material UI overrides ── */
|
||||
|
||||
.MuiTypography-root.MuiTypography-inherit.MuiLink-root.MuiLink-underlineAlways {
|
||||
color: var(--colorPrimary) !important;
|
||||
}
|
||||
|
||||
/* Chips*/
|
||||
.chipContained {
|
||||
background-color: var(--colorPrimary) !important;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.MuiButton-root {
|
||||
color: var(--colorPrimary) !important;
|
||||
border-color: var(--colorPrimary) !important;
|
||||
@@ -111,11 +325,7 @@ footer {
|
||||
color: var(--colorPrimary) !important;
|
||||
}
|
||||
|
||||
.nextra-scrollbar.nx-sticky {
|
||||
color: var(--colorPrimary) !important;
|
||||
}
|
||||
|
||||
.nx-text-primary-600 {
|
||||
a.MuiLink-root {
|
||||
color: var(--colorPrimary) !important;
|
||||
}
|
||||
|
||||
@@ -127,10 +337,167 @@ input:focus-visible {
|
||||
border-color: var(--colorPrimary) !important;
|
||||
}
|
||||
|
||||
a.MuiLink-root {
|
||||
color: var(--colorPrimary) !important;
|
||||
.MuiPaper-root.MuiAccordion-root {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.MuiPaper-root.MuiAccordion-root {
|
||||
border-radius: 8px;
|
||||
/* ── Landing page ── */
|
||||
|
||||
.landing-heading {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.landing-card:hover {
|
||||
background-color: rgba(255, 255, 255, 0.03) !important;
|
||||
}
|
||||
|
||||
/* ── Invert diagrams in dark mode ── */
|
||||
|
||||
html.dark .nextra-content img:not([src*="landing"]) {
|
||||
filter: invert(1) hue-rotate(180deg) brightness(0.92) contrast(1.1);
|
||||
mix-blend-mode: lighten;
|
||||
cursor: zoom-in;
|
||||
}
|
||||
|
||||
/* Expanded image overlay */
|
||||
.nextra-content img.img-expanded {
|
||||
position: fixed !important;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw !important;
|
||||
height: 100vh !important;
|
||||
max-width: none !important;
|
||||
object-fit: contain;
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
z-index: 9999;
|
||||
cursor: zoom-out;
|
||||
padding: 2rem;
|
||||
mix-blend-mode: normal;
|
||||
filter: none;
|
||||
}
|
||||
|
||||
html.dark .nextra-content img.img-expanded {
|
||||
filter: invert(1) hue-rotate(180deg) brightness(0.92) contrast(1.1);
|
||||
mix-blend-mode: normal;
|
||||
}
|
||||
|
||||
/* ── Light mode ── */
|
||||
|
||||
html:not(.dark) {
|
||||
--colorPrimary: #1a7a32;
|
||||
--colorPrimary-light: #1a7a32;
|
||||
--bg-light: #F5F5F5;
|
||||
--border-light: #E0E0E0;
|
||||
--border: #E0E0E0;
|
||||
--textMuted: #6B7280;
|
||||
--textMuted-light: #6B7280;
|
||||
}
|
||||
|
||||
html:not(.dark) body {
|
||||
background-color: var(--bg-light);
|
||||
}
|
||||
|
||||
html:not(.dark) .nextra-nav-container,
|
||||
html:not(.dark) .nextra-sidebar-container,
|
||||
html:not(.dark) .nextra-content,
|
||||
html:not(.dark) .nx-bg-white {
|
||||
background-color: var(--bg-light) !important;
|
||||
}
|
||||
|
||||
/* Light mode links: darker green */
|
||||
html:not(.dark) .nx-text-primary-600 {
|
||||
color: var(--colorPrimary-light) !important;
|
||||
}
|
||||
|
||||
html:not(.dark) .nx-text-primary-600.nx-underline.nx-decoration-from-font {
|
||||
color: var(--colorPrimary-light) !important;
|
||||
}
|
||||
|
||||
/* Light mode sidebar */
|
||||
html:not(.dark) .nextra-sidebar-container {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.82rem;
|
||||
border-right: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
html:not(.dark) .nextra-sidebar-container a {
|
||||
color: var(--textMuted-light) !important;
|
||||
}
|
||||
|
||||
html:not(.dark) .nextra-sidebar-container a:hover {
|
||||
color: #111 !important;
|
||||
}
|
||||
|
||||
/* Light mode nav */
|
||||
html:not(.dark) .nextra-nav-container {
|
||||
border-bottom: 1px solid var(--border-light) !important;
|
||||
}
|
||||
|
||||
html:not(.dark) .nextra-nav-container nav a,
|
||||
html:not(.dark) .nextra-nav-container nav button,
|
||||
html:not(.dark) .nextra-nav-container nav ul a {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
html:not(.dark) .nextra-nav-container nav a:hover,
|
||||
html:not(.dark) .nextra-nav-container nav ul a:hover {
|
||||
color: var(--colorPrimary-light) !important;
|
||||
}
|
||||
|
||||
/* Light mode code */
|
||||
html:not(.dark) code:not(pre code) {
|
||||
background-color: rgba(0, 0, 0, 0.05) !important;
|
||||
border: none !important;
|
||||
padding: 0.15em 0.4em;
|
||||
font-size: 0.88em;
|
||||
}
|
||||
|
||||
/* Light mode callouts */
|
||||
html:not(.dark) .nextra-callout {
|
||||
border: none;
|
||||
border-left: 3px solid;
|
||||
background: rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
/* Light mode tables */
|
||||
html:not(.dark) th {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.75rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
color: var(--textMuted-light);
|
||||
}
|
||||
|
||||
/* Light mode search */
|
||||
html:not(.dark) .nextra-search input {
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.8rem;
|
||||
border: 1px solid var(--border-light);
|
||||
background-color: #FFFFFF !important;
|
||||
}
|
||||
|
||||
html:not(.dark) .nextra-search input::placeholder {
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.08em;
|
||||
font-size: 0.72rem;
|
||||
}
|
||||
|
||||
/* Light mode h2 border */
|
||||
html:not(.dark) h2 {
|
||||
padding-bottom: 0.3em;
|
||||
border-bottom: 1px solid var(--border-light);
|
||||
}
|
||||
|
||||
/* Light mode landing page */
|
||||
html:not(.dark) .landing-heading {
|
||||
color: #1a1a1a !important;
|
||||
}
|
||||
|
||||
html:not(.dark) .landing-card:hover {
|
||||
background-color: rgba(0, 0, 0, 0.02) !important;
|
||||
}
|
||||
|
||||
html:not(.dark) .landing-card {
|
||||
border-color: var(--border-light) !important;
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,93 @@
|
||||
Copyright 2020 The JetBrains Mono Project Authors (https://github.com/JetBrains/JetBrainsMono)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
https://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -139,7 +139,7 @@ const config: DocsThemeConfig = {
|
||||
</>
|
||||
);
|
||||
},
|
||||
logo: <span>Nym Docs</span>,
|
||||
logo: <span style={{ fontFamily: "var(--font-mono)", fontSize: "1.1rem", fontWeight: 700 }}>Nym Docs</span>,
|
||||
project: {
|
||||
link: "https://github.com/nymtech/nym",
|
||||
},
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ fallback_extensions = ["mdx", "md"]
|
||||
|
||||
# Remap /images to public/images for NextJS static assets
|
||||
# Lychee resolves /images to pages/images, but Next.js serves from public/images
|
||||
remap = ["pages/images public/images"]
|
||||
remap = ["pages/images public/images", "pages/docs/fonts public/fonts"]
|
||||
|
||||
# Exclude component snippets (TODO: verify which are still in use)
|
||||
exclude_path = ["components/"]
|
||||
|
||||
Reference in New Issue
Block a user