Files
nx9-www/www/index.html
T

2329 lines
89 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>NX9 — Next Generation 9 | Software people can own, understand, and control</title>
<meta
name="description"
content="NX9 is a philosophy-driven ecosystem of self-hosted, privacy-first Rust software by Sunil Thakare. No telemetry. No vendor lock-in. Software people can own, understand, and control."
/>
<meta name="color-scheme" content="light dark" />
<!-- Favicons & App Icons -->
<link rel="apple-touch-icon" sizes="57x57" href="/apple-icon-57x57.png" />
<link rel="apple-touch-icon" sizes="60x60" href="/apple-icon-60x60.png" />
<link rel="apple-touch-icon" sizes="72x72" href="/apple-icon-72x72.png" />
<link rel="apple-touch-icon" sizes="76x76" href="/apple-icon-76x76.png" />
<link rel="apple-touch-icon" sizes="114x114" href="/apple-icon-114x114.png" />
<link rel="apple-touch-icon" sizes="120x120" href="/apple-icon-120x120.png" />
<link rel="apple-touch-icon" sizes="144x144" href="/apple-icon-144x144.png" />
<link rel="apple-touch-icon" sizes="152x152" href="/apple-icon-152x152.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-icon-180x180.png" />
<link rel="icon" type="image/png" sizes="192x192" href="/android-icon-192x192.png" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="96x96" href="/favicon-96x96.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="manifest" href="/manifest.json" />
<meta name="theme-color" content="#020617" />
<style>
/* == 1. DESIGN TOKENS == */
:root {
--bg: #ffffff;
--bg-raised: #ffffff;
--surface: #f5f6f9;
--surface-hover: #eceff4;
--border: #e1e4ea;
--border-strong: #cbd0da;
--text: #12151a;
--text-secondary: #4b5563;
--text-muted: #6b7280;
--accent: #6d5df6;
--accent-strong: #5643e0;
--accent-soft: #eeecff;
--accent-contrast: #ffffff;
--dot: rgba(109, 93, 246, 0.14);
--line: rgba(109, 93, 246, 0.08);
--shadow: 0 1px 2px rgba(16, 20, 26, 0.04), 0 4px 16px rgba(16, 20, 26, 0.05);
--shadow-hover: 0 4px 10px rgba(109, 93, 246, 0.12), 0 16px 36px rgba(16, 20, 26, 0.1);
--radius: 10px;
--radius-sm: 6px;
--font-ui: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell,
sans-serif;
--font-mono: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
--content-max: 1180px;
--transition-theme: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease;
/* Gradient palette — reused across icons, borders and glow shadows */
--grad-1: linear-gradient(135deg, #7c5cf9, #b18bfa);
--grad-2: linear-gradient(135deg, #06b6d4, #5eead4);
--grad-3: linear-gradient(135deg, #f59e0b, #fb923c);
--grad-4: linear-gradient(135deg, #ec4899, #fb7185);
--grad-5: linear-gradient(135deg, #10b981, #6ee7b7);
--grad-6: linear-gradient(135deg, #3b82f6, #7dd3fc);
--grad-7: linear-gradient(135deg, #ef4444, #f97316);
--glow-1: rgba(124, 92, 249, 0.35);
--glow-2: rgba(6, 182, 212, 0.35);
--glow-3: rgba(245, 158, 11, 0.35);
--glow-4: rgba(236, 72, 153, 0.35);
--glow-5: rgba(16, 185, 129, 0.35);
--glow-6: rgba(59, 130, 246, 0.35);
--glow-7: rgba(239, 68, 68, 0.35);
}
html[data-theme="dark"] {
--bg: #0a0c10;
--bg-raised: #12151b;
--surface: #161a21;
--surface-hover: #1d222b;
--border: #262c37;
--border-strong: #363e4b;
--text: #eceef2;
--text-secondary: #a7aec0;
--text-muted: #7c8497;
--accent: #9d8bff;
--accent-strong: #b6a7ff;
--accent-soft: #1c1a33;
--accent-contrast: #0a0c10;
--dot: rgba(157, 139, 255, 0.16);
--line: rgba(157, 139, 255, 0.08);
--shadow: 0 1px 2px rgba(0, 0, 0, 0.35), 0 4px 20px rgba(0, 0, 0, 0.4);
--shadow-hover: 0 4px 14px rgba(157, 139, 255, 0.18), 0 18px 40px rgba(0, 0, 0, 0.45);
}
/* == 2. RESET & BASE == */
*,
*::before,
*::after {
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
-webkit-text-size-adjust: 100%;
}
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto;
}
*,
*::before,
*::after {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
scroll-behavior: auto !important;
}
}
body {
margin: 0;
font-family: var(--font-ui);
background-color: var(--bg);
color: var(--text);
line-height: 1.6;
transition: var(--transition-theme);
background-image: linear-gradient(var(--line) 1px, transparent 1px),
linear-gradient(90deg, var(--line) 1px, transparent 1px),
radial-gradient(var(--dot) 1px, transparent 1px);
background-size:
64px 64px,
64px 64px,
16px 16px;
background-position:
-1px -1px,
-1px -1px,
-1px -1px;
}
img {
max-width: 100%;
display: block;
}
a {
color: inherit;
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
h1,
h2,
h3,
h4,
p {
margin: 0;
}
button {
font-family: inherit;
}
table {
border-collapse: collapse;
width: 100%;
}
::selection {
background: var(--accent);
color: var(--accent-contrast);
}
a:focus-visible,
button:focus-visible,
summary:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
border-radius: var(--radius-sm);
}
.skip-link {
position: absolute;
left: 1rem;
top: -100px;
background: var(--accent);
color: var(--accent-contrast);
padding: 0.65rem 1.1rem;
border-radius: var(--radius-sm);
font-size: 0.9rem;
font-weight: 600;
z-index: 200;
transition: top 0.2s ease;
}
.skip-link:focus {
top: 1rem;
}
/* Hidden icon sprite sheet */
.icon-sprite {
position: absolute;
width: 0;
height: 0;
overflow: hidden;
}
.icon {
width: 20px;
height: 20px;
stroke: currentColor;
fill: none;
stroke-width: 1.8;
stroke-linecap: round;
stroke-linejoin: round;
flex-shrink: 0;
}
.icon-badge {
width: 46px;
height: 46px;
border-radius: var(--radius-sm);
display: flex;
align-items: center;
justify-content: center;
color: #fff;
margin-bottom: 1rem;
box-shadow: var(--shadow);
}
.icon-badge .icon {
width: 24px;
height: 24px;
}
/* Gradient utility classes */
.grad-1 {
background: var(--grad-1);
}
.grad-2 {
background: var(--grad-2);
}
.grad-3 {
background: var(--grad-3);
}
.grad-4 {
background: var(--grad-4);
}
.grad-5 {
background: var(--grad-5);
}
.grad-6 {
background: var(--grad-6);
}
.grad-7 {
background: var(--grad-7);
}
/* == 3. LAYOUT PRIMITIVES == */
.wrap {
max-width: var(--content-max);
margin-inline: auto;
padding-inline: 1.5rem;
}
section {
padding-block: clamp(3.5rem, 7vw, 6.5rem);
}
.section-head {
max-width: 680px;
margin-bottom: clamp(2rem, 4vw, 3rem);
}
.eyebrow {
display: inline-flex;
align-items: center;
gap: 0.4rem;
font-family: var(--font-mono);
font-size: 0.75rem;
letter-spacing: 0.14em;
text-transform: uppercase;
background: linear-gradient(90deg, var(--accent), #ec4899);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
margin-bottom: 0.75rem;
font-weight: 700;
}
.section-title {
font-size: clamp(1.6rem, 3.2vw, 2.25rem);
font-weight: 800;
letter-spacing: -0.01em;
margin-bottom: 0.75rem;
}
.section-sub {
color: var(--text-secondary);
font-size: 1.05rem;
max-width: 65ch;
}
/* == 4. NAVIGATION == */
.nav-logo {
width: 32px;
height: 32px;
flex: 0 0 32px;
display: block;
}
.brand-name {
color: #0a0a0a;
}
html[data-theme="dark"] .brand-name {
color: #fafafa;
}
@media (max-width: 600px) {
.nav-logo {
width: 28px;
height: 28px;
flex-basis: 28px;
}
}
.site-header {
position: sticky;
top: 0;
z-index: 100;
background-color: color-mix(in srgb, var(--bg) 85%, transparent);
backdrop-filter: saturate(160%) blur(10px);
-webkit-backdrop-filter: saturate(160%) blur(10px);
border-bottom: 1px solid var(--border);
transition: var(--transition-theme);
}
.nav-inner {
max-width: var(--content-max);
margin-inline: auto;
padding: 0.85rem 1.5rem;
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
}
.brand {
display: flex;
align-items: center;
gap: 0.5rem;
font-weight: 800;
font-size: 1.15rem;
letter-spacing: -0.01em;
text-decoration: none;
}
.nav-icon {
width: 31px;
height: 26px;
flex: 0 0 31px;
}
.nav-links {
display: flex;
align-items: center;
gap: 0.15rem;
}
.nav-links a {
text-decoration: none;
font-size: 0.9rem;
font-weight: 500;
color: var(--text-secondary);
padding: 0.5rem 0.65rem;
border-radius: var(--radius-sm);
transition:
color 0.15s ease,
background-color 0.15s ease;
}
.nav-links a:hover {
color: var(--text);
background-color: var(--surface);
}
.nav-links a.is-active {
color: var(--accent);
}
.nav-right {
display: flex;
align-items: center;
gap: 0.5rem;
}
.theme-toggle {
display: inline-flex;
align-items: center;
gap: 0.4rem;
background: var(--surface);
border: 1px solid var(--border);
color: var(--text);
border-radius: var(--radius);
padding: 0.45rem 0.7rem;
font-size: 0.82rem;
font-family: var(--font-mono);
cursor: pointer;
transition:
background-color 0.15s ease,
border-color 0.15s ease;
}
.theme-toggle:hover {
background: var(--surface-hover);
border-color: var(--border-strong);
}
.hamburger {
display: none;
background: transparent;
border: 1px solid var(--border);
border-radius: var(--radius-sm);
width: 40px;
height: 40px;
cursor: pointer;
color: var(--text);
align-items: center;
justify-content: center;
}
.hamburger span,
.hamburger span::before,
.hamburger span::after {
content: "";
display: block;
width: 18px;
height: 2px;
background: currentColor;
position: relative;
transition:
transform 0.2s ease,
opacity 0.2s ease;
}
.hamburger span::before {
position: absolute;
top: -6px;
}
.hamburger span::after {
position: absolute;
top: 6px;
}
.hamburger[aria-expanded="true"] span {
background: transparent;
}
.hamburger[aria-expanded="true"] span::before {
transform: translateY(6px) rotate(45deg);
}
.hamburger[aria-expanded="true"] span::after {
transform: translateY(-6px) rotate(-45deg);
}
@media (max-width: 860px) {
.hamburger {
display: inline-flex;
}
.nav-links {
position: fixed;
inset: 61px 0 auto 0;
flex-direction: column;
align-items: stretch;
background: var(--bg-raised);
border-bottom: 1px solid var(--border);
padding: 0.5rem;
gap: 0;
transform: translateY(-8px);
opacity: 0;
pointer-events: none;
transition:
transform 0.18s ease,
opacity 0.18s ease;
max-height: 80vh;
overflow-y: auto;
}
.nav-links.is-open {
transform: translateY(0);
opacity: 1;
pointer-events: auto;
}
.nav-links a {
padding: 0.85rem 1rem;
border-radius: var(--radius-sm);
}
}
/* == 5. HERO == */
.hero {
padding-block: clamp(4rem, 10vw, 7.5rem) clamp(3rem, 6vw, 5rem);
position: relative;
overflow: hidden;
}
.hero::before {
content: "";
position: absolute;
top: -20%;
right: -10%;
width: 560px;
height: 560px;
background: radial-gradient(circle, var(--glow-1), transparent 70%);
filter: blur(10px);
pointer-events: none;
opacity: 0.55;
z-index: 0;
}
.hero::after {
content: "";
position: absolute;
bottom: -30%;
left: -10%;
width: 480px;
height: 480px;
background: radial-gradient(circle, var(--glow-2), transparent 70%);
filter: blur(10px);
pointer-events: none;
opacity: 0.4;
z-index: 0;
}
.hero .wrap {
position: relative;
z-index: 1;
}
.hero-kicker {
font-family: var(--font-mono);
font-size: 0.8rem;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--text-muted);
margin-bottom: 1.25rem;
}
.hero-kicker::before {
content: "$ ";
color: var(--accent);
}
.hero-logo {
max-width: 600px;
width: 100%;
height: auto;
margin-bottom: 1rem;
filter: drop-shadow(0 20px 40px rgba(0, 0, 0, 0.3));
}
.hero h2 {
font-size: clamp(1.1rem, 2.6vw, 1.5rem);
font-weight: 500;
color: var(--text-secondary);
margin-top: 0.6rem;
letter-spacing: -0.005em;
}
.hero blockquote {
margin: 1.75rem 0 1.5rem;
padding-left: 1.1rem;
border-left: 3px solid transparent;
border-image: linear-gradient(180deg, var(--accent), #ec4899) 1;
font-size: clamp(1.05rem, 2vw, 1.3rem);
font-weight: 600;
max-width: 46ch;
}
.hero p.lede {
max-width: 64ch;
color: var(--text-secondary);
font-size: 1.05rem;
margin-bottom: 1.25rem;
}
.hero-byline {
font-size: 0.9rem;
color: var(--text-muted);
margin-bottom: 2rem;
}
.hero-byline strong {
color: var(--text-secondary);
}
.hero-ctas {
display: flex;
flex-wrap: wrap;
gap: 0.85rem;
}
.btn {
position: relative;
overflow: hidden;
display: inline-flex;
align-items: center;
gap: 0.5rem;
font-weight: 600;
font-size: 0.95rem;
padding: 0.75rem 1.4rem;
border-radius: var(--radius);
text-decoration: none;
cursor: pointer;
border: 1px solid transparent;
transition:
transform 0.15s ease,
box-shadow 0.15s ease,
background-color 0.15s ease,
border-color 0.15s ease;
}
.btn:active {
transform: translateY(1px);
}
.btn-primary {
background: linear-gradient(135deg, var(--accent), #ec4899);
color: #fff;
}
.btn-primary:hover {
box-shadow: 0 10px 24px var(--glow-1);
transform: translateY(-1px);
}
.btn-outline {
background: transparent;
color: var(--text);
border-color: var(--border-strong);
}
.btn-outline:hover {
background: var(--surface);
border-color: var(--accent);
}
.btn-sm {
padding: 0.5rem 0.9rem;
font-size: 0.85rem;
}
.btn .ripple {
position: absolute;
border-radius: 50%;
background: rgba(255, 255, 255, 0.5);
transform: scale(0);
pointer-events: none;
animation: ripple 0.6s ease-out;
}
html[data-theme="dark"] .btn-outline .ripple {
background: rgba(255, 255, 255, 0.18);
}
@keyframes ripple {
to {
transform: scale(3);
opacity: 0;
}
}
/* == 6. ABOUT == */
.about-panel {
background: linear-gradient(135deg, var(--accent-soft), var(--surface));
border: 1px solid var(--border);
border-radius: var(--radius);
padding: clamp(1.5rem, 4vw, 2.5rem);
font-size: 1.1rem;
color: var(--text-secondary);
line-height: 1.75;
}
.about-panel strong {
color: var(--text);
}
/* == 7. COLORFUL CARD GRIDS == */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
gap: 1.15rem;
}
.card {
background: var(--bg-raised);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 1.6rem;
position: relative;
overflow: hidden;
transition:
transform 0.2s ease,
box-shadow 0.2s ease,
border-color 0.2s ease;
}
.card::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: var(--card-grad, var(--grad-1));
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 14px 34px var(--card-glow, var(--glow-1));
border-color: var(--border-strong);
}
.card .icon-badge {
background: var(--card-grad, var(--grad-1));
}
.card h3 {
font-size: 1.08rem;
font-weight: 700;
margin-bottom: 0.5rem;
}
.card p {
color: var(--text-secondary);
font-size: 0.94rem;
}
.card ul {
margin-top: 0.6rem;
}
.card li {
color: var(--text-secondary);
font-size: 0.9rem;
position: relative;
padding-left: 1.1rem;
margin-top: 0.3rem;
}
.card li::before {
content: "●";
position: absolute;
left: 0;
top: 0.05em;
font-size: 0.55rem;
color: var(--accent);
}
.card .card-tag {
font-family: var(--font-mono);
font-size: 0.68rem;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--text-muted);
display: block;
margin-top: 0.9rem;
}
/* == 8. PROJECTS == */
.callout {
display: flex;
gap: 0.85rem;
align-items: flex-start;
background: var(--accent-soft);
border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--border));
border-radius: var(--radius);
padding: 1.1rem 1.3rem;
margin-bottom: 2rem;
font-size: 0.95rem;
color: var(--text-secondary);
}
.callout strong {
color: var(--text);
}
.callout .icon {
color: var(--accent);
margin-top: 0.15rem;
}
.project-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1.15rem;
}
@media (max-width: 780px) {
.project-grid {
grid-template-columns: 1fr;
}
}
.project-card {
background: var(--bg-raised);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 1.6rem;
display: flex;
flex-direction: column;
gap: 0.9rem;
position: relative;
overflow: hidden;
transition:
transform 0.2s ease,
box-shadow 0.2s ease,
border-color 0.2s ease;
}
.project-card::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: var(--card-grad, var(--grad-1));
}
.project-card:hover {
transform: translateY(-4px);
box-shadow: 0 14px 34px var(--card-glow, var(--glow-1));
border-color: var(--border-strong);
}
.project-card-head {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 0.75rem;
}
.project-title {
display: flex;
align-items: center;
gap: 0.65rem;
}
.project-title .icon-badge {
width: 38px;
height: 38px;
margin-bottom: 0;
border-radius: var(--radius-sm);
background: var(--card-grad, var(--grad-1));
}
.project-title .icon-badge .icon {
width: 19px;
height: 19px;
}
.project-card h3 {
font-family: var(--font-mono);
font-size: 1.02rem;
font-weight: 700;
}
.status-badge {
font-family: var(--font-mono);
font-size: 0.66rem;
letter-spacing: 0.06em;
text-transform: uppercase;
padding: 0.22rem 0.55rem;
border-radius: 999px;
white-space: nowrap;
color: #fff;
align-self: flex-start;
}
.project-card p.desc {
color: var(--text-secondary);
font-size: 0.93rem;
}
.tech-badges {
display: flex;
flex-wrap: wrap;
gap: 0.45rem;
margin-top: 0.5rem;
}
.tech-badge {
font-family: var(--font-mono);
font-size: 0.72rem;
color: #fff;
border-radius: var(--radius-sm);
padding: 0.22rem 0.55rem;
background: var(--card-grad, var(--grad-1));
opacity: 0.92;
}
.project-links {
display: flex;
gap: 0.6rem;
margin-top: auto;
padding-top: 0.5rem;
}
/* == 9. STATS == */
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 1rem;
text-align: center;
}
.stat {
background: var(--bg-raised);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 1.75rem 1rem;
position: relative;
overflow: hidden;
}
.stat::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: var(--card-grad, var(--grad-1));
}
.stat .num {
font-family: var(--font-mono);
font-size: clamp(1.8rem, 4vw, 2.5rem);
font-weight: 700;
display: block;
background: var(--card-grad, var(--grad-1));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.stat .label {
color: var(--text-secondary);
font-size: 0.85rem;
margin-top: 0.35rem;
}
/* == 10. POSITIONING TABLE == */
.positioning {
overflow-x: auto;
border-radius: var(--radius);
border: 1px solid var(--border);
}
.positioning table {
min-width: 560px;
}
.positioning th,
.positioning td {
text-align: left;
padding: 0.9rem 1.2rem;
font-size: 0.92rem;
}
.positioning thead th {
font-family: var(--font-mono);
font-size: 0.72rem;
letter-spacing: 0.06em;
text-transform: uppercase;
color: #fff;
padding-block: 1rem;
}
.positioning thead th:first-child {
background: var(--grad-7);
}
.positioning thead th:last-child {
background: var(--grad-5);
}
.positioning tbody tr {
border-top: 1px solid var(--border);
background: var(--bg-raised);
}
.positioning tbody tr:nth-child(even) {
background: var(--surface);
}
.positioning td:first-child {
color: var(--text-muted);
position: relative;
padding-left: 2.2rem;
}
.positioning td:first-child::before {
content: "✕";
position: absolute;
left: 1.2rem;
color: #ef4444;
font-weight: 700;
font-size: 0.8rem;
}
.positioning td:last-child {
color: var(--text);
font-weight: 600;
position: relative;
padding-left: 2.2rem;
}
.positioning td:last-child::before {
content: "✓";
position: absolute;
left: 1.2rem;
color: #10b981;
font-weight: 700;
font-size: 0.8rem;
}
/* == 11. VISION == */
.vision-panel {
position: relative;
overflow: hidden;
background: linear-gradient(135deg, var(--accent-soft), var(--surface));
border: 1px solid var(--border);
border-radius: var(--radius);
padding: clamp(1.75rem, 5vw, 3rem);
}
.vision-panel::after {
content: "";
position: absolute;
inset: 0;
border-radius: var(--radius);
padding: 1px;
background: linear-gradient(135deg, var(--accent), #ec4899, #06b6d4);
-webkit-mask:
linear-gradient(#000 0 0) content-box,
linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
opacity: 0.5;
pointer-events: none;
}
.vision-panel p {
font-size: clamp(1.1rem, 2.4vw, 1.4rem);
font-weight: 500;
letter-spacing: -0.005em;
color: var(--text);
max-width: 62ch;
position: relative;
}
.vision-panel p + p {
margin-top: 1.1rem;
color: var(--text-secondary);
font-weight: 400;
font-size: clamp(1rem, 2vw, 1.15rem);
}
/* == 12. VALUES == */
.value-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(155px, 1fr));
gap: 0.8rem;
}
.value-chip {
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 1.2rem 0.9rem;
text-align: center;
background: var(--bg-raised);
position: relative;
overflow: hidden;
transition:
transform 0.2s ease,
border-color 0.2s ease,
box-shadow 0.2s ease;
}
.value-chip::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: var(--card-grad, var(--grad-1));
}
.value-chip:hover {
transform: translateY(-3px);
box-shadow: 0 10px 24px var(--card-glow, var(--glow-1));
}
.value-chip .n {
font-family: var(--font-mono);
font-size: 0.7rem;
display: block;
margin-bottom: 0.5rem;
font-weight: 700;
background: var(--card-grad, var(--grad-1));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.value-chip .t {
font-weight: 600;
font-size: 0.95rem;
}
/* == 13. ROADMAP == */
.roadmap-intro {
color: var(--text-secondary);
max-width: 70ch;
margin-bottom: 2.5rem;
font-size: 1rem;
}
.roadmap-intro strong {
color: var(--text);
}
.circuit {
display: flex;
align-items: flex-start;
overflow-x: auto;
padding-block: 1rem 0.5rem;
scrollbar-width: thin;
}
.node {
flex: 1 0 100px;
min-width: 100px;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
position: relative;
padding-top: 2.75rem;
}
.node::before {
content: "";
position: absolute;
top: 12px;
left: -50%;
width: 100%;
height: 2px;
background: repeating-linear-gradient(90deg, var(--border-strong) 0 6px, transparent 6px 11px);
z-index: 0;
}
.node:first-child::before {
display: none;
}
.node.is-active::before {
background: repeating-linear-gradient(90deg, var(--accent) 0 6px, transparent 6px 11px);
}
.node .pad {
width: 28px;
height: 28px;
border-radius: 50%;
border: 2px solid var(--border-strong);
background: var(--bg-raised);
display: flex;
align-items: center;
justify-content: center;
font-family: var(--font-mono);
font-size: 0.72rem;
font-weight: 700;
color: var(--text-muted);
position: absolute;
top: 0;
z-index: 1;
transition:
transform 0.18s ease,
border-color 0.18s ease,
box-shadow 0.18s ease;
}
.node.is-active .pad {
border-color: transparent;
background: var(--card-grad, var(--grad-1));
color: #fff;
box-shadow: 0 0 0 4px var(--card-glow, var(--glow-1));
}
.node:hover .pad {
transform: scale(1.12);
}
.node .name {
font-family: var(--font-mono);
font-size: 0.82rem;
font-weight: 700;
margin-top: 0.4rem;
}
.node .state {
font-size: 0.72rem;
color: var(--text-muted);
margin-top: 0.15rem;
}
.node.is-active .state {
color: var(--accent);
font-weight: 600;
}
@media (max-width: 720px) {
.circuit {
flex-direction: column;
align-items: stretch;
overflow-x: visible;
}
.node {
flex-direction: row;
text-align: left;
padding: 0 0 1.75rem 2.9rem;
min-width: 0;
align-items: flex-start;
}
.node::before {
top: 0;
left: 13px;
width: 2px;
height: 100%;
background: repeating-linear-gradient(180deg, var(--border-strong) 0 6px, transparent 6px 11px);
}
.node.is-active::before {
background: repeating-linear-gradient(180deg, var(--accent) 0 6px, transparent 6px 11px);
}
.node .pad {
top: 0;
left: 0;
}
.node .name {
margin-top: 0;
margin-left: 0.15rem;
}
.node .text {
display: flex;
flex-direction: column;
}
}
.roadmap-footnote {
margin-top: 2rem;
font-size: 0.95rem;
color: var(--text-secondary);
border-top: 1px solid var(--border);
padding-top: 1.5rem;
}
.roadmap-footnote strong {
color: var(--text);
}
/* == 14. REVEAL ANIMATION == */
.reveal {
opacity: 0;
transform: translateY(14px);
transition:
opacity 0.5s ease,
transform 0.5s ease;
}
.reveal.is-visible {
opacity: 1;
transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
.reveal {
opacity: 1;
transform: none;
transition: none;
}
}
/* == 15. FOOTER == */
.site-footer {
border-top: 1px solid var(--border);
padding-block: 3rem 2rem;
margin-top: 2rem;
position: relative;
overflow: hidden;
}
.site-footer::before {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background: linear-gradient(
90deg,
var(--grad-1),
var(--grad-2),
var(--grad-3),
var(--grad-4),
var(--grad-5)
);
}
.footer-grid {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: 2rem;
}
.footer-brand .mark {
font-family: var(--font-mono);
font-weight: 800;
font-size: 1.3rem;
background: linear-gradient(135deg, var(--accent), #ec4899);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.footer-logo {
max-width: 300px;
width: 100%;
height: auto;
opacity: 0.5;
margin-bottom: 0.5rem;
}
.footer-brand .sub {
color: var(--text-muted);
font-size: 0.85rem;
margin-top: 0.2rem;
}
.footer-motto {
font-size: 0.95rem;
color: var(--text-secondary);
line-height: 1.7;
}
.footer-links {
display: flex;
gap: 1.5rem;
}
.footer-links a {
text-decoration: none;
color: var(--text-secondary);
font-size: 0.9rem;
font-weight: 600;
display: inline-flex;
align-items: center;
gap: 0.4rem;
}
.footer-links a:hover {
color: var(--accent);
}
.footer-bottom {
margin-top: 2.5rem;
padding-top: 1.5rem;
border-top: 1px solid var(--border);
font-family: var(--font-mono);
font-size: 0.78rem;
color: var(--text-muted);
text-align: center;
letter-spacing: 0.02em;
}
@media print {
.site-header,
.theme-toggle,
.hamburger,
.hero-ctas,
.btn,
.project-links,
.circuit {
display: none !important;
}
body {
background-image: none;
color: #000;
}
section {
padding-block: 1rem;
}
a {
color: #000;
text-decoration: underline;
}
.card::before,
.project-card::before,
.stat::before,
.value-chip::before {
display: none;
}
}
</style>
</head>
<body>
<a href="#main" class="skip-link">Skip to content</a>
<!-- ICON SPRITE -->
<svg class="icon-sprite" aria-hidden="true">
<defs>
<symbol id="i-key" viewBox="0 0 24 24">
<circle cx="8" cy="15" r="4" />
<path d="M11 12l9-9M17 6l3 3M14 9l2 2" />
</symbol>
<symbol id="i-server" viewBox="0 0 24 24">
<rect x="3" y="4" width="18" height="6" rx="1.5" />
<rect x="3" y="14" width="18" height="6" rx="1.5" />
<circle cx="7" cy="7" r="1" fill="currentColor" stroke="none" />
<circle cx="7" cy="17" r="1" fill="currentColor" stroke="none" />
</symbol>
<symbol id="i-gauge" viewBox="0 0 24 24">
<path d="M4 15a8 8 0 1116 0" />
<path d="M12 15l4-5" />
<circle cx="12" cy="15" r="1" fill="currentColor" stroke="none" />
</symbol>
<symbol id="i-lock" viewBox="0 0 24 24">
<rect x="5" y="11" width="14" height="9" rx="2" />
<path d="M8 11V7a4 4 0 018 0v4" />
</symbol>
<symbol id="i-shield-check" viewBox="0 0 24 24">
<path d="M12 3l7 3v6c0 4.5-3 7.5-7 9-4-1.5-7-4.5-7-9V6l7-3z" />
<path d="M9 12l2 2 4-4" />
</symbol>
<symbol id="i-wrench" viewBox="0 0 24 24">
<path d="M14.7 6.3a4 4 0 00-5.4 5.4L4 17v3h3l5.3-5.3a4 4 0 005.4-5.4l-2.5 2.5-2-2 2.5-2.5z" />
</symbol>
<symbol id="i-clock" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="8.5" />
<path d="M12 7v5l3.5 2" />
</symbol>
<symbol id="i-cpu" viewBox="0 0 24 24">
<rect x="6" y="6" width="12" height="12" rx="1.5" />
<path d="M9 3v3M15 3v3M9 18v3M15 18v3M3 9h3M3 15h3M18 9h3M18 15h3" />
</symbol>
<symbol id="i-box" viewBox="0 0 24 24">
<path d="M12 3l8 4.5v9L12 21l-8-4.5v-9L12 3z" />
<path d="M4.5 7.5L12 12l7.5-4.5M12 12v9" />
</symbol>
<symbol id="i-database" viewBox="0 0 24 24">
<ellipse cx="12" cy="6" rx="7" ry="3" />
<path d="M5 6v6c0 1.7 3.1 3 7 3s7-1.3 7-3V6" />
<path d="M5 12v6c0 1.7 3.1 3 7 3s7-1.3 7-3v-6" />
</symbol>
<symbol id="i-bolt" viewBox="0 0 24 24"><path d="M13 2L4 14h6l-1 8 9-12h-6l1-8z" /></symbol>
<symbol id="i-route" viewBox="0 0 24 24">
<circle cx="5" cy="6" r="2.3" />
<circle cx="19" cy="18" r="2.3" />
<path d="M5 8.3v3a4 4 0 004 4h6a4 4 0 004 4" />
</symbol>
<symbol id="i-layers" viewBox="0 0 24 24">
<path d="M12 3l9 5-9 5-9-5 9-5z" />
<path d="M3 13l9 5 9-5M3 8l9 5 9-5" />
</symbol>
<symbol id="i-terminal" viewBox="0 0 24 24">
<rect x="3" y="4" width="18" height="16" rx="2" />
<path d="M7 9l4 3-4 3M13 15h4" />
</symbol>
<symbol id="i-monitor" viewBox="0 0 24 24">
<rect x="3" y="4" width="18" height="12" rx="1.5" />
<path d="M8 20h8M12 16v4" />
<path d="M6 12l3-3 2 2 4-4" />
</symbol>
<symbol id="i-infinity" viewBox="0 0 24 24">
<path
d="M7 9a3.5 3.5 0 100 7 3.5 3.5 0 002.9-1.5L12 12l2.1 2.5A3.5 3.5 0 1017 9a3.5 3.5 0 00-2.9 1.5L12 13l-2.1-2.5A3.5 3.5 0 007 9z"
/>
</symbol>
<symbol id="i-chart" viewBox="0 0 24 24"><path d="M4 20V10M10 20V4M16 20v-7M22 20H2" /></symbol>
<symbol id="i-shield" viewBox="0 0 24 24">
<path d="M12 3l7 3v6c0 4.5-3 7.5-7 9-4-1.5-7-4.5-7-9V6l7-3z" />
</symbol>
<symbol id="i-link" viewBox="0 0 24 24">
<path d="M9 15l6-6" />
<path d="M11 6l1-1a4 4 0 015.5 5.5l-2 2" />
<path d="M13 18l-1 1a4 4 0 01-5.5-5.5l2-2" />
</symbol>
<symbol id="i-globe" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="8.5" />
<path
d="M3.5 12h17M12 3.5c2.5 2.3 4 5.3 4 8.5s-1.5 6.2-4 8.5c-2.5-2.3-4-5.3-4-8.5s1.5-6.2 4-8.5z"
/>
</symbol>
<symbol id="i-flag" viewBox="0 0 24 24">
<path d="M5 3v18" />
<path d="M5 4h13l-3 4 3 4H5" />
</symbol>
<symbol id="i-info" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="8.5" />
<path d="M12 11v5.5M12 8v.01" />
</symbol>
<symbol id="i-git" viewBox="0 0 24 24">
<circle cx="6" cy="6" r="2.2" />
<circle cx="6" cy="18" r="2.2" />
<circle cx="18" cy="12" r="2.2" />
<path d="M6 8.2v7.6M6 8.2c0 4 3 5.8 6 5.8h4" />
</symbol>
</defs>
</svg>
<header class="site-header">
<div class="nav-inner">
<a href="#home" class="brand" aria-label="NX9 — Host Yourself">
<svg
class="nav-logo"
viewBox="0 0 335.05563 357.12827"
preserveAspectRatio="xMidYMid meet"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
>
<g id="layer1" transform="matrix(3.7795276,0,0,3.7795276,-26.765107,-97.222608)">
<g
id="g19"
transform="matrix(0.36886531,0,0,0.35629784,-228.21758,-224.7539)"
style="fill: #ff0000"
>
<path
d="m 705.5,704.4 c -4.1,1.8 -8.3,6.9 -9,10.9 -0.4,1.8 -0.4,11.8 -0.1,22.2 0.3,10.5 0.5,20.8 0.5,23 -0.2,5.7 -0.2,43.3 -0.1,47.5 0.1,1.9 -0.1,10.1 -0.4,18.2 L 695.9,841 H 712 v -24 h 132 v 16 h 16.2 l -0.6,-10.8 c -0.4,-5.9 -0.6,-12.3 -0.5,-14.2 0.1,-1.9 0.2,-12.6 0.2,-23.8 -0.1,-25.1 -0.1,-24.3 0.1,-49.9 0.1,-23.6 0,-24 -7.4,-29.1 l -3.3,-2.2 h -70.1 c -56,0.1 -70.7,0.3 -73.1,1.4 M 844,734.5 V 752 H 712 v -35 h 132 z m 0,49.5 v 17 H 712 v -34 h 132 z"
style="fill: #ff0000; stroke-width: 0"
/>
<path
d="m 721,734.5 v 7.5 h 15 v -15 h -15 z m 24.7,-6.8 c -0.4,0.3 -0.7,3.7 -0.7,7.5 v 6.8 h 33 v -15 h -15.8 c -8.7,0 -16.2,0.3 -16.5,0.7 M 721,784.5 v 7.5 h 15 v -15 h -15 z m 24,0 v 7.5 h 33 v -15 h -33 z m -24,49 v 7.5 h 15 v -15 h -15 z m 24,0 v 7.5 h 33 v -15 h -33 z m -104,20.3 -3.1,3.1 0.3,51.5 0.3,51.5 2.3,2.3 c 2.1,2.2 3.1,2.3 19.5,2.6 10.3,0.2 18.6,-0.1 20.8,-0.7 4.3,-1.3 5.9,-4.3 5.9,-11.3 0,-4.4 0.2,-4.9 1.7,-4.3 1,0.3 14.5,4.9 30,10.1 26.1,8.9 28.8,9.6 36,9.6 9.3,0 18.3,-2.7 25.4,-7.5 9.2,-6.2 90.9,-72.9 93.5,-76.2 6.6,-8.6 6.1,-19.1 -1.2,-26.6 -5.1,-5.2 -10.8,-7.3 -18.2,-6.6 -7.8,0.7 -14.3,3 -40.7,14.7 -12.5,5.5 -23,10 -23.5,10 -0.4,0 -1.3,-1.3 -2,-2.9 -1.6,-3.8 -7.3,-9.5 -11.9,-11.8 -3.2,-1.6 -6.6,-1.8 -34.1,-1.8 -29.5,0 -30.7,0.1 -37,2.3 -3.6,1.3 -9,4.1 -12.2,6.2 l -5.6,3.7 -1.7,-4.4 c -2.2,-5.7 -6.7,-10.8 -11.9,-13.6 -3.4,-1.8 -6.2,-2.2 -16.8,-2.5 L 644,850.8 Z m 27.5,14.7 2.5,2.4 V 950 h -17 v -84 h 6 c 5.1,0 6.5,0.4 8.5,2.5 m 192.7,-0.8 c 2.1,1.9 2.2,3.2 0.6,6.8 -1.3,3 -87.5,72.8 -94.2,76.3 -2.5,1.4 -6.9,2.6 -10.3,2.9 -5.4,0.4 -8.1,-0.3 -37.8,-10.5 l -32,-10.9 v -16.4 c 0,-15.6 0.1,-16.7 2.6,-21.9 3.6,-7.7 7.7,-12.1 15.1,-16.1 l 6.3,-3.4 28.8,-0.3 28.7,-0.3 3,3 c 3.8,3.8 3.9,7.8 0.4,12 l -2.6,3.1 H 737 v 15 h 15.8 c 8.6,0 17.5,-0.5 19.7,-1.1 5.1,-1.4 12,-6.2 14.1,-9.8 1.3,-2.3 6.4,-4.9 27.2,-14.1 14,-6.3 28.3,-12.4 31.6,-13.6 7.3,-2.8 13.3,-3 15.8,-0.7"
style="fill: #ff0000; stroke-width: 0"
/>
</g>
</g>
</svg>
<span class="brand-name">NX9</span>
</a>
<nav class="nav-links" id="navLinks" aria-label="Primary">
<a href="#home" data-nav="home">Home</a> <a href="#philosophy" data-nav="philosophy">Philosophy</a>
<a href="#architecture" data-nav="architecture">Architecture</a>
<a href="#projects" data-nav="projects">Projects</a> <a href="#vision" data-nav="vision">Vision</a>
<a href="#values" data-nav="values">Values</a> <a href="#roadmap" data-nav="roadmap">Roadmap</a>
<a href="case-study.html" target="_self">Case Study</a>
</nav>
<div class="nav-right">
<button class="theme-toggle" id="themeToggle" type="button" aria-label="Toggle color theme">
<span id="themeIcon" aria-hidden="true">◐</span> <span id="themeLabel">Theme</span>
</button>
<button
class="hamburger"
id="hamburger"
type="button"
aria-label="Toggle navigation menu"
aria-expanded="false"
aria-controls="navLinks"
>
<span></span>
</button>
</div>
</div>
</header>
<main id="main">
<section class="hero" id="home">
<div class="wrap">
<p class="hero-kicker">nx9 --version</p>
<!-- Change logo color as per the theme -->
<img
id="heroLogo"
src="logo-dark-main.svg"
alt="NX9 Logo"
class="hero-logo reveal"
/>
<h2>Next Generation 9</h2>
<blockquote>Software people can own, understand, and control.</blockquote>
<p class="lede">
NX9 is a philosophy-driven ecosystem of independent, self-hosted, privacy-first infrastructure
software — single-binary Rust applications built for people and organizations who would rather
run their own infrastructure than rent someone else's. No telemetry. No subscriptions. No
mandatory cloud.
</p>
<p class="hero-byline">
Built and maintained by <strong>Sunil Thakare</strong> (<span
style="font-family: var(--font-mono)"
>@thakares</span
>)
</p>
<div class="hero-ctas">
<a href="#projects" class="btn btn-primary">View Projects</a>
<a href="#philosophy" class="btn btn-outline">Read Philosophy</a>
</div>
</div>
</section>
<section id="about" aria-labelledby="about-heading">
<div class="wrap">
<div class="about-panel reveal">
<p id="about-heading">
<strong>NX9</strong> is not a framework, and it is not a cloud product that happens to
support self-hosting. It is a collection of carefully engineered, single-binary Rust
applications — designed for individuals and organizations that value ownership, simplicity,
and independence, and built to run equally well on a Raspberry Pi, a mini PC, a VPS, or
air-gapped government infrastructure.
</p>
</div>
</div>
</section>
<section id="philosophy" aria-labelledby="philosophy-title">
<div class="wrap">
<div class="section-head reveal">
<p class="eyebrow">
<svg class="icon" style="width: 14px; height: 14px"><use href="#i-flag" /></svg> 01 — Design
Philosophy
</p>
<h2 class="section-title" id="philosophy-title">Principles That Don't Change Per Project</h2>
<p class="section-sub">
Nine commitments that stay constant across every NX9 application, regardless of what it
does.
</p>
</div>
<div class="card-grid" id="philosophyGrid"></div>
</div>
</section>
<section id="architecture" aria-labelledby="architecture-title">
<div class="wrap">
<div class="section-head reveal">
<p class="eyebrow">
<svg class="icon" style="width: 14px; height: 14px"><use href="#i-layers" /></svg> 02 —
Architecture
</p>
<h2 class="section-title" id="architecture-title">Core Architectural Pillars</h2>
<p class="section-sub">
Every NX9 application is built on the same nine foundations — the same reason a BZOD
deployment and a ChronoSeal deployment feel like they came from the same shop.
</p>
</div>
<div class="card-grid" id="architectureGrid"></div>
<div class="section-head reveal" style="margin-top: 3.5rem">
<p class="eyebrow">
<svg class="icon" style="width: 14px; height: 14px"><use href="#i-shield-check" /></svg>
Security Stack
</p>
<h2 class="section-title">Embedded, Not Bolted On</h2>
<p class="section-sub">
Modern cryptographic primitives and hardened defaults, standardized across the whole
ecosystem.
</p>
</div>
<div class="card-grid" id="securityGrid"></div>
<div class="section-head reveal" style="margin-top: 3.5rem">
<p class="eyebrow">
<svg class="icon" style="width: 14px; height: 14px"><use href="#i-chart" /></svg>
Positioning
</p>
<h2 class="section-title">The NX9 Trade-off, Made Explicit</h2>
</div>
<div class="positioning reveal">
<table>
<thead>
<tr>
<th>Traditional Stack</th>
<th>NX9</th>
</tr>
</thead>
<tbody id="positioningBody"></tbody>
</table>
</div>
</div>
</section>
<section id="projects" aria-labelledby="projects-title">
<div class="wrap">
<div class="section-head reveal">
<p class="eyebrow">
<svg class="icon" style="width: 14px; height: 14px"><use href="#i-box" /></svg> 03 —
Ecosystem
</p>
<h2 class="section-title" id="projects-title">Current Projects</h2>
<p class="section-sub">
Four projects are currently available. The NX9 ecosystem is designed to grow into a family
of nine focused, self-hosted applications.
</p>
</div>
<div class="callout reveal">
<svg class="icon"><use href="#i-info" /></svg>
<p>
<strong>Codeberg is the canonical home of NX9.</strong> GitHub repositories are maintained
as mirrors to improve discoverability and make adoption easier.
</p>
</div>
<div class="project-grid" id="projectGrid"></div>
<div class="stats-grid" id="statsGrid" style="margin-top: 3rem"></div>
</div>
</section>
<section id="vision" aria-labelledby="vision-title">
<div class="wrap">
<div class="section-head reveal">
<p class="eyebrow">
<svg class="icon" style="width: 14px; height: 14px"><use href="#i-globe" /></svg> 04 —
Vision
</p>
<h2 class="section-title" id="vision-title">Why NX9 Exists</h2>
</div>
<div class="vision-panel reveal">
<p>
In an era of cloud lock-in, subscriptions, and heavy dependencies, NX9 builds software that
serves humanity — not platforms.
</p>
<p>Technology should empower people to own their infrastructure, data, and future.</p>
</div>
</div>
</section>
<section id="values" aria-labelledby="values-title">
<div class="wrap">
<div class="section-head reveal">
<p class="eyebrow">
<svg class="icon" style="width: 14px; height: 14px"><use href="#i-key" /></svg> 05 — Values
</p>
<h2 class="section-title" id="values-title">Core Values</h2>
<p class="section-sub">The twelve commitments every NX9 decision is measured against.</p>
</div>
<div class="value-grid" id="valueGrid"></div>
</div>
</section>
<section id="roadmap" aria-labelledby="roadmap-title">
<div class="wrap">
<div class="section-head reveal">
<p class="eyebrow">
<svg class="icon" style="width: 14px; height: 14px"><use href="#i-route" /></svg> 06 —
Roadmap
</p>
<h2 class="section-title" id="roadmap-title">Roadmap to Nine</h2>
</div>
<p class="roadmap-intro reveal">
<strong
>NX9 is not a single application — it is an ecosystem of nine focused, interoperable
tools</strong
>
built around ownership, privacy, simplicity, and open standards. Four projects are already
available, with five more planned to complete the vision.
</p>
<div
class="circuit reveal"
id="circuit"
role="list"
aria-label="NX9 ecosystem roadmap, four of nine milestones complete"
></div>
<p class="roadmap-footnote reveal">
Nodes are ordered by ship date, not ambition —
<strong>chronoseal, dns-server, auth,</strong> and <strong>url-shortener</strong> shipped in
that sequence. Five more applications are planned to complete the family of nine, reusing the
same Tokio · Axum · SQLite · Argon2 · Ed25519 · BLAKE3 foundation.
</p>
</div>
</section>
</main>
<footer class="site-footer">
<div class="wrap">
<div class="footer-grid">
<div class="footer-brand">
<img id="footerLogo" src="logo-dark-main.svg" alt="NX9 Logo" class="footer-logo" />
<div class="sub">Next Generation 9</div>
</div>
<p class="footer-motto">
Software people can own,<br />understand,<br />and control.<br /><br /><strong
>Always Free. Always Open. Always Yours.</strong
>
</p>
<nav class="footer-links" aria-label="Repository links">
<a href="https://codeberg.org/thakares" target="_blank" rel="noopener noreferrer"
><svg class="icon" style="width: 16px; height: 16px"><use href="#i-git" /></svg> Codeberg</a
>
<a href="https://github.com/thakares?tab=repositories" target="_blank" rel="noopener noreferrer"
><svg class="icon" style="width: 16px; height: 16px"><use href="#i-link" /></svg> GitHub</a
>
</nav>
</div>
<div class="footer-bottom">
© <span id="year"></span> NX9 — an open-source ecosystem by Sunil Thakare. MIT / Apache-2.0.
</div>
</div>
</footer>
<script>
(function () {
"use strict";
/* == THEME == */
const root = document.documentElement;
const themeToggle = document.getElementById("themeToggle");
const themeIcon = document.getElementById("themeIcon");
const themeLabel = document.getElementById("themeLabel");
const heroLogo = document.getElementById("heroLogo");
const footerLogo = document.getElementById("footerLogo");
const STORAGE_KEY = "nx9-theme";
function updateThemeLogos(theme) {
const logo =
theme === "dark"
? "logo-light-main.svg"
: "logo-dark-main.svg";
if (heroLogo) heroLogo.src = logo;
if (footerLogo) footerLogo.src = logo;
}
function applyTheme(theme) {
root.setAttribute("data-theme", theme);
updateThemeLogos(theme);
themeIcon.textContent = theme === "dark" ? "●" : "○";
themeLabel.textContent = theme === "dark" ? "Dark" : "Light";
themeToggle.setAttribute(
"aria-pressed",
theme === "dark" ? "true" : "false",
);
}
function initTheme() {
const stored = localStorage.getItem(STORAGE_KEY);
if (stored === "light" || stored === "dark") {
applyTheme(stored);
return;
}
const prefersDark = window.matchMedia(
"(prefers-color-scheme: dark)",
).matches;
applyTheme(prefersDark ? "dark" : "light");
}
themeToggle.addEventListener("click", function () {
const current = root.getAttribute("data-theme");
const next = current === "dark" ? "light" : "dark";
applyTheme(next);
localStorage.setItem(STORAGE_KEY, next);
});
window
.matchMedia("(prefers-color-scheme: dark)")
.addEventListener("change", function (e) {
if (!localStorage.getItem(STORAGE_KEY)) {
applyTheme(e.matches ? "dark" : "light");
}
});
initTheme();
/* == MOBILE NAV == */
const hamburger = document.getElementById("hamburger");
const navLinks = document.getElementById("navLinks");
hamburger.addEventListener("click", function () {
const isOpen = navLinks.classList.toggle("is-open");
hamburger.setAttribute(
"aria-expanded",
isOpen ? "true" : "false",
);
});
navLinks.querySelectorAll("a").forEach(function (link) {
link.addEventListener("click", function () {
navLinks.classList.remove("is-open");
hamburger.setAttribute("aria-expanded", "false");
});
});
/* == ICON HELPER == */
function iconSvg(id) {
return '<svg class="icon"><use href="#' + id + '"/></svg>';
}
/* == DATA: DESIGN PHILOSOPHY == */
const philosophy = [
{
icon: "i-key",
grad: 1,
glow: "--glow-1",
title: "Operator Ownership",
body: "The operator owns the binaries, the configuration, the databases, the backups, and the encryption keys. No service depends on proprietary APIs or cloud-hosted control planes.",
},
{
icon: "i-server",
grad: 6,
glow: "--glow-6",
title: "Self-Hosting First",
body: "Every decision begins with one question: “Can this be deployed and operated by a single administrator?” If it needs Kubernetes or a managed database, the design is reconsidered.",
},
{
icon: "i-gauge",
grad: 3,
glow: "--glow-3",
title: "Simplicity Over Complexity",
body: "One binary. One configuration. One SQLite database. One administrator. Simple systems are easier to understand, secure, and recover.",
},
{
icon: "i-lock",
grad: 4,
glow: "--glow-4",
title: "Privacy by Default",
body: "Applications never assume cloud connectivity, analytics collection, telemetry uploads, or third-party tracking. Users decide what information leaves their infrastructure.",
},
{
icon: "i-shield-check",
grad: 5,
glow: "--glow-5",
title: "Security by Design",
body: "Argon2id, Ed25519, BLAKE3, RBAC, CSRF protection, and audit logs are embedded throughout the stack — not added later.",
},
{
icon: "i-wrench",
grad: 2,
glow: "--glow-2",
title: "Operational Excellence",
body: "Diagnostics, backups, restore procedures, migration tools, CLI administration, and documentation, in every project, from day one.",
},
{
icon: "i-clock",
grad: 7,
glow: "--glow-7",
title: "Long-Term Stability",
body: "NX9 intentionally avoids dependency churn. The goal is software that remains understandable and maintainable years into the future.",
},
{
icon: "i-git",
grad: 4,
glow: "--glow-4",
title: "Open Source First",
body: "Every NX9 codebase is 100% open source under permissive licenses. You have the fundamental right to inspect, build, and modify the software.",
},
{
icon: "i-infinity",
grad: 5,
glow: "--glow-5",
title: "Zero Vendor Lock-In",
body: "All data is stored in standard SQLite files, configurations are plain text, and architectures strictly avoid proprietary integrations.",
},
];
const philosophyGrid = document.getElementById("philosophyGrid");
philosophy.forEach(function (p) {
const card = document.createElement("article");
card.className = "card reveal";
card.style.setProperty(
"--card-grad",
"var(--grad-" + p.grad + ")",
);
card.style.setProperty(
"--card-glow",
"var(" + p.glow + ")",
);
card.innerHTML =
'<div class="icon-badge">' +
iconSvg(p.icon) +
"</div>" +
"<h3>" +
p.title +
"</h3>" +
"<p>" +
p.body +
"</p>";
philosophyGrid.appendChild(card);
});
/* == DATA: ARCHITECTURAL PILLARS == */
const architecture = [
{
icon: "i-cpu",
grad: 1,
glow: "--glow-1",
title: "Pure Rust",
body: "Memory safety, zero-cost abstractions, and fearless concurrency. Rust 2021 Edition, release-mode optimization, no runtime interpreter.",
tag: "~10–12 MB per binary",
},
{
icon: "i-box",
grad: 6,
glow: "--glow-6",
title: "Single Binary Deployment",
body: "One executable contains the HTTP server, business logic, auth, migrations, CLI, and templates. No JVM, no Node.js, no Python, no app server.",
tag: "cargo build --release",
},
{
icon: "i-database",
grad: 5,
glow: "--glow-5",
title: "SQLite First",
body: "ACID transactions, WAL concurrency, zero administration, and portable files. Several projects isolate data across multiple databases for tenant isolation.",
tag: "users.db · system.db · content.db",
},
{
icon: "i-bolt",
grad: 3,
glow: "--glow-3",
title: "Tokio Async Runtime",
body: "Asynchronous I/O and lightweight tasks power web servers, DNS resolution, and background workers with high concurrency.",
tag: "async / await",
},
{
icon: "i-route",
grad: 4,
glow: "--glow-4",
title: "Axum Web Layer",
body: "Routing, middleware, REST APIs, HTML rendering, authentication, and sessions — integrated naturally with Tokio and Rust's type system.",
tag: "HTTP · middleware · sessions",
},
{
icon: "i-layers",
grad: 2,
glow: "--glow-2",
title: "Layered Architecture",
body: "auth / cli / db / handlers / jobs / services / templates / utils / web — each layer owns one responsibility, for easier testing and lower coupling.",
tag: "src/ layout",
},
{
icon: "i-terminal",
grad: 7,
glow: "--glow-7",
title: "CLI-First Operations",
body: "serve · doctor · backup · restore · migrate · create-admin · init — every service is administrable headless, over SSH, from a script.",
tag: "automation-friendly",
},
{
icon: "i-shield",
grad: 1,
glow: "--glow-1",
title: "Security Stack",
body: "Argon2id password hashing, Ed25519 signatures, BLAKE3 hashing, CSRF protection, RBAC, and hardened compiler flags — RELRO, PIE, least privilege.",
tag: "defense in depth",
},
{
icon: "i-monitor",
grad: 6,
glow: "--glow-6",
title: "Operational Tooling",
body: "Health checks, migration verification, automatic backups, restore tools, Docker support, systemd units, and structured logging, out of the box.",
tag: "diagnostics · systemd · docker",
},
];
const architectureGrid =
document.getElementById("architectureGrid");
architecture.forEach(function (a) {
const card = document.createElement("article");
card.className = "card reveal";
card.style.setProperty(
"--card-grad",
"var(--grad-" + a.grad + ")",
);
card.style.setProperty(
"--card-glow",
"var(" + a.glow + ")",
);
card.innerHTML =
'<div class="icon-badge">' +
iconSvg(a.icon) +
"</div>" +
"<h3>" +
a.title +
"</h3>" +
"<p>" +
a.body +
"</p>" +
'<span class="card-tag">' +
a.tag +
"</span>";
architectureGrid.appendChild(card);
});
/* == DATA: SECURITY == */
const security = [
{
icon: "i-shield-check",
grad: 4,
glow: "--glow-4",
title: "Argon2id Hashing",
body: "Memory-hard, CPU-hard password hashing by default for all user credentials.",
},
{
icon: "i-key",
grad: 1,
glow: "--glow-1",
title: "Ed25519 Signatures",
body: "Fast, secure public-key cryptography for tokens and inter-service authentication.",
},
{
icon: "i-lock",
grad: 6,
glow: "--glow-6",
title: "Strict RBAC",
body: "Role-Based Access Control enforced at the middleware layer before business logic executes.",
},
{
icon: "i-shield",
grad: 5,
glow: "--glow-5",
title: "CSRF & Security Headers",
body: "Double-submit cookies, strict transport security, and hardened Content Security Policies built-in.",
},
];
const securityGrid =
document.getElementById("securityGrid");
security.forEach(function (s) {
const card = document.createElement("article");
card.className = "card reveal";
card.style.setProperty(
"--card-grad",
"var(--grad-" + s.grad + ")",
);
card.style.setProperty(
"--card-glow",
"var(" + s.glow + ")",
);
card.innerHTML =
'<div class="icon-badge">' +
iconSvg(s.icon) +
"</div>" +
"<h3>" +
s.title +
"</h3>" +
"<p>" +
s.body +
"</p>";
securityGrid.appendChild(card);
});
/* == DATA: POSITIONING == */
const positioningBody =
document.getElementById("positioningBody");
const posData = [
{
bad: "Requires Kubernetes & Helm",
good: "Deployed via a single binary or systemd",
},
{
bad: "Hidden telemetry and usage analytics",
good: "Zero tracking, completely air-gapped capable",
},
{
bad: "1GB+ RAM for a 'Hello World' microservice",
good: "10-20MB RAM for a high-traffic production service",
},
{
bad: "Forced cloud subscriptions",
good: "Your hardware, your data, your rules",
},
{
bad: "Complex web of dependencies",
good: "Static binaries with SQLite built-in",
},
];
posData.forEach((p) => {
positioningBody.innerHTML += `<tr><td>${p.bad}</td><td>${p.good}</td></tr>`;
});
/* == DATA: PROJECTS == */
const projectGrid =
document.getElementById("projectGrid");
const projects = [
{
title: "nx9-url-shortener",
desc: "A lightweight, self-hosted URL management platform. Combines URL shortening, analytics, QR codes, password protection, and API automation with zero external dependencies.",
status: "STABLE",
icon: "i-link",
tech: ["Rust", "SQLite", "Axum", "Askama"],
grad: 2,
glow: "--glow-2",
link: "https://codeberg.org/thakares/nx9-url-shortener",
github: "https://github.com/thakares/nx9-url-shortener",
},
{
title: "nx9-auth",
desc: "Identity and Access Management (IAM) service. Provides authentication, authorization, session management, and RBAC in a single incredibly fast deployable binary.",
status: "BETA",
icon: "i-lock",
tech: ["Rust", "SQLite", "Security"],
grad: 4,
glow: "--glow-4",
link: "https://codeberg.org/thakares/nx9-auth",
github: "https://github.com/thakares/nx9-auth",
},
{
title: "nx9-dns-server",
desc: "High-performance, fully RFC-compliant authoritative DNS server leveraging modern async networking and a robust SQLite backend.",
status: "ALPHA",
icon: "i-globe",
tech: ["Rust", "DNS", "Async"],
grad: 6,
glow: "--glow-6",
link: "https://codeberg.org/thakares/nx9-dns-server",
github: "https://github.com/thakares/nx9-dns-server",
},
{
title: "nx9-chronoseal-rs",
desc: "Privacy-first browser attestation framework for anti-bot and anti-AI scraping. Uses Ed25519 heartbeat chains and WASM attestation without tracking users.",
status: "STABLE",
icon: "i-shield",
tech: ["Rust", "WASM", "Ed25519"],
grad: 5,
glow: "--glow-5",
link: "https://codeberg.org/thakares/nx9-chronoseal-rs",
github: "https://github.com/thakares/nx9-chronoseal-rs",
},
];
projects.forEach((p) => {
projectGrid.innerHTML += `
<div
class="project-card reveal"
style="--card-grad: var(--grad-${p.grad}); --card-glow: var(${p.glow})"
>
<div class="project-card-head">
<div class="project-title">
<div class="icon-badge">${iconSvg(p.icon)}</div>
<h3>${p.title}</h3>
</div>
<span
class="status-badge"
style="background: var(--grad-${
p.grad === 5
? 5
: p.grad === 4
? 4
: p.grad === 6
? 6
: 2
})"
>
${p.status}
</span>
</div>
<p class="desc">${p.desc}</p>
<div class="tech-badges">
${p.tech
.map(
(t) =>
`<span class="tech-badge" style="background: var(--grad-${p.grad})">${t}</span>`,
)
.join("")}
</div>
<div class="project-links">
<a
href="${p.link}"
target="_blank"
rel="noopener noreferrer"
class="btn btn-sm btn-outline"
>
<svg class="icon" style="width:14px;height:14px">
<use href="#i-git"/>
</svg>
Codeberg
</a>
<a
href="${p.github}"
target="_blank"
rel="noopener noreferrer"
class="btn btn-sm btn-outline"
>
<svg class="icon" style="width:14px;height:14px">
<use href="#i-link"/>
</svg>
GitHub
</a>
</div>
</div>
`;
});
/* == DATA: STATS == */
const statsGrid = document.getElementById("statsGrid");
const stats = [
{
num: "0",
label: "External Dependencies",
grad: 1,
},
{
num: "1",
label: "Binary to Deploy",
grad: 6,
},
{
num: "9",
label: "Core Projects",
grad: 4,
},
{
num: "<15MB",
label: "RAM per Service",
grad: 5,
},
];
stats.forEach((s) => {
statsGrid.innerHTML += `
<div
class="stat reveal"
style="--card-grad: var(--grad-${s.grad})"
>
<span class="num">${s.num}</span>
<span class="label">${s.label}</span>
</div>
`;
});
/* == DATA: VALUES == */
const valueGrid = document.getElementById("valueGrid");
const values = [
{ num: "01", text: "User Ownership", grad: 1, glow: "--glow-1" },
{ num: "02", text: "Absolute Privacy", grad: 2, glow: "--glow-2" },
{ num: "03", text: "Open Source", grad: 3, glow: "--glow-3" },
{ num: "04", text: "Simplicity First", grad: 4, glow: "--glow-4" },
{ num: "05", text: "CLI Automation", grad: 5, glow: "--glow-5" },
{ num: "06", text: "Open Standards", grad: 6, glow: "--glow-6" },
{ num: "07", text: "Long-term Stability", grad: 7, glow: "--glow-7" },
{ num: "08", text: "Linux Native", grad: 1, glow: "--glow-1" },
{ num: "09", text: "Zero Tracking", grad: 2, glow: "--glow-2" },
{ num: "10", text: "No Vendor Lock", grad: 3, glow: "--glow-3" },
{ num: "11", text: "Performant", grad: 4, glow: "--glow-4" },
{ num: "12", text: "Understandable", grad: 5, glow: "--glow-5" },
];
values.forEach((v) => {
valueGrid.innerHTML += `
<div
class="value-chip reveal"
style="--card-grad: var(--grad-${v.grad}); --card-glow: var(${v.glow})"
>
<span class="n">${v.num}</span>
<span class="t">${v.text}</span>
</div>
`;
});
/* == DATA: ROADMAP == */
const circuit = document.getElementById("circuit");
const roadmap = [
{ num: "01", name: "ChronoSeal", state: "STABLE", active: true },
{ num: "02", name: "DNS Server", state: "ALPHA", active: true },
{ num: "03", name: "Auth", state: "BETA", active: true },
{ num: "04", name: "URL Shortener", state: "STABLE", active: true },
{ num: "05", name: "Project 5", state: "PLANNED", active: false },
{ num: "06", name: "Project 6", state: "PLANNED", active: false },
{ num: "07", name: "Project 7", state: "PLANNED", active: false },
{ num: "08", name: "Project 8", state: "PLANNED", active: false },
{ num: "09", name: "Project 9", state: "PLANNED", active: false },
];
roadmap.forEach((r) => {
circuit.innerHTML += `
<div class="node ${r.active ? "is-active" : ""} reveal">
<div class="pad">${r.num}</div>
<div class="text">
<div class="name">${r.name}</div>
<div class="state">${r.state}</div>
</div>
</div>
`;
});
/* == REVEAL ANIMATIONS == */
const observerOptions = {
root: null,
rootMargin: "0px",
threshold: 0.1,
};
const observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add("is-visible");
observer.unobserve(entry.target);
}
});
},
observerOptions,
);
document
.querySelectorAll(".reveal")
.forEach((el) => observer.observe(el));
// Set copyright year
document.getElementById("year").textContent =
new Date().getFullYear();
})();
</script>
</body>
</html>