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:
mfahampshire
2026-03-24 15:08:07 +00:00
committed by GitHub
parent 3f00e2c317
commit b6df383584
13 changed files with 1093 additions and 263 deletions
+492 -108
View File
@@ -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" }}
>
&rsaquo;
</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" }}>
&rsaquo;
</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
```
+12 -1
View File
@@ -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).
![arch_overview](/images/network/arch/overall-arch.png)
+410 -43
View File
@@ -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;
}
@@ -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.
+1 -1
View File
@@ -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
View File
@@ -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/"]