---
import Base from '../layouts/Base.astro';
---
<Base title="nex — nex the briw">
<!-- Hero -->
<section class="hero">
<div class="container">
<p class="eyebrow">nix-darwin · NixOS · homebrew</p>
<h1><span class="c-nix">n</span><span class="c-brew">e</span><span class="c-nix">x</span> the <span class="c-brew">br</span><span class="c-nix">i</span><span class="c-brew">w</span>.</h1>
<p class="tagline">
Manage packages across <strong>Nix</strong> and <strong>Homebrew</strong>.
Define machines with TOML profiles.
Provision NixOS from a USB stick.
</p>
<div class="install-block" id="install">
<div class="install-cmd" role="button" tabindex="0" id="install-btn">
<code>curl -fsSL https://nex.styrene.io/install.sh | sh</code>
<span class="copy-hint" id="copy-hint">click to copy</span>
</div>
<p class="install-alt">
or <code>cargo install nex-pkg</code>
· <code>nix profile add github:styrene-lab/nex</code>
</p>
</div>
</div>
</section>
<!-- What it does -->
<section class="demo">
<div class="container">
<div class="terminal">
<div class="terminal-bar">
<span class="dot red"></span>
<span class="dot yellow"></span>
<span class="dot green"></span>
<span class="terminal-title">~</span>
</div>
<pre><code><span class="prompt">$</span> <span class="cmd">nex install</span> htop bat eza
<span class="added">+</span> htop
<span class="added">+</span> bat
<span class="added">+</span> eza
<span class="status">>>> switching...</span>
<span class="status">>>> done</span>
<span class="prompt">$</span> <span class="cmd">nex install --cask</span> slack
<span class="added">+</span> slack
<span class="status">>>> switching...</span>
<span class="status">>>> done</span>
<span class="prompt">$</span> <span class="cmd">nex remove</span> htop
<span class="removed">-</span> htop
<span class="status">>>> switching...</span>
<span class="status">>>> done</span></code></pre>
</div>
</div>
</section>
<!-- Features -->
<section id="features">
<div class="container">
<h2>How it works</h2>
<div class="features-grid">
<div class="feature">
<h3>Install</h3>
<p>
<code>nex install foo</code> resolves whether a package belongs
in Nix or Homebrew, edits the right config file, and rebuilds.
Works on macOS and NixOS.
</p>
</div>
<div class="feature">
<h3>Profile</h3>
<p>
A TOML file that defines your machine: packages, shell, git,
system preferences, GPU drivers, desktop environment.
Profiles compose via <code>extends</code> for team/personal layering.
</p>
</div>
<div class="feature">
<h3>Forge</h3>
<p>
<code>nex forge user/profile --disk /dev/sdX</code> burns a
bootable NixOS USB with your profile baked in.
<code>nex polymerize</code> is the guided installer on the target.
</p>
</div>
<div class="feature">
<h3>Build</h3>
<p>
<code>nex build-image user/profile</code> produces an OCI
container from a profile. Same packages, different target.
Podman, docker, or any OCI runtime.
</p>
</div>
<div class="feature">
<h3>Develop</h3>
<p>
<code>nex develop user/repo</code> enters a flake dev shell.
<code>nex dev user/repo</code> adds
<a href="https://github.com/styrene-lab/omegon">omegon</a>
as the AI coding agent.
</p>
</div>
<div class="feature">
<h3>Rollback</h3>
<p>
Every install is backed up before rebuild. If the build fails,
config is restored. <code>nex rollback</code> reverts the system
to the previous generation.
</p>
</div>
</div>
</div>
</section>
<!-- Usage -->
<section id="usage">
<div class="container">
<h2>Commands</h2>
<div class="usage-grid">
<div class="usage-item">
<code class="usage-cmd">nex init</code>
<span class="usage-desc">Bootstrap nix-darwin or NixOS</span>
</div>
<div class="usage-item">
<code class="usage-cmd">nex install htop</code>
<span class="usage-desc">Add a package</span>
</div>
<div class="usage-item">
<code class="usage-cmd">nex remove htop</code>
<span class="usage-desc">Remove a package</span>
</div>
<div class="usage-item">
<code class="usage-cmd">nex profile apply user/repo</code>
<span class="usage-desc">Apply a machine profile</span>
</div>
<div class="usage-item">
<code class="usage-cmd">nex forge user/profile</code>
<span class="usage-desc">Burn a NixOS USB</span>
</div>
<div class="usage-item">
<code class="usage-cmd">nex polymerize</code>
<span class="usage-desc">Install NixOS (on target)</span>
</div>
<div class="usage-item">
<code class="usage-cmd">nex build-image user/profile</code>
<span class="usage-desc">Build an OCI container</span>
</div>
<div class="usage-item">
<code class="usage-cmd">nex dev user/repo</code>
<span class="usage-desc">Dev shell + omegon</span>
</div>
<div class="usage-item">
<code class="usage-cmd">nex switch</code>
<span class="usage-desc">Rebuild and activate</span>
</div>
<div class="usage-item">
<code class="usage-cmd">nex rollback</code>
<span class="usage-desc">Revert to previous generation</span>
</div>
<div class="usage-item">
<code class="usage-cmd">nex update</code>
<span class="usage-desc">Update inputs + rebuild</span>
</div>
<div class="usage-item">
<code class="usage-cmd">nex doctor</code>
<span class="usage-desc">Check and fix issues</span>
</div>
</div>
</div>
</section>
<!-- Why -->
<section class="why">
<div class="container">
<h2>Why nex?</h2>
<div class="comparison">
<div class="comparison-col before">
<h3>Before</h3>
<pre><code>vim ~/macos-nix/nix/modules/home/base.nix
<span class="fg-dim"># which list was it... brews? casks?</span>
darwin-rebuild switch --flake .#Chriss-MacBook
<span class="fg-dim"># build failed. revert manually.</span>
<span class="fg-dim"># new linux box? start over.</span>
<span class="fg-dim"># container? write a Dockerfile.</span></code></pre>
</div>
<div class="comparison-col after">
<h3>After</h3>
<pre><code>nex install zed
<span class="fg-dim"># resolves source, edits config, rebuilds.</span>
nex profile apply user/my-profile
<span class="fg-dim"># mac, linux, or container. same file.</span>
nex forge user/my-profile --disk /dev/sdX
<span class="fg-dim"># bootable NixOS USB. one command.</span></code></pre>
</div>
</div>
</div>
</section>
</Base>
<script>
const btn = document.getElementById('install-btn');
const hint = document.getElementById('copy-hint');
if (btn && hint) {
btn.addEventListener('click', async () => {
await navigator.clipboard.writeText('curl -fsSL https://nex.styrene.io/install.sh | sh');
hint.textContent = 'copied!';
setTimeout(() => { hint.textContent = 'click to copy'; }, 2000);
});
}
</script>
<style>
/* Hero */
.hero {
padding-top: 8rem;
padding-bottom: 4rem;
text-align: center;
}
.eyebrow {
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 0.15em;
color: var(--primary);
margin-bottom: 1rem;
font-weight: 600;
}
.hero h1 {
font-family: var(--mono);
font-size: clamp(2.5rem, 8vw, 4.5rem);
font-weight: 700;
color: var(--fg);
line-height: 1.1;
margin-bottom: 1.5rem;
}
.c-nix { color: var(--c-nix); }
.c-brew { color: var(--c-brew); }
.tagline {
font-size: 1.15rem;
color: var(--fg-dim);
max-width: 560px;
margin: 0 auto 2.5rem;
line-height: 1.7;
}
.tagline strong {
color: var(--fg);
}
/* Install block */
.install-block {
max-width: 580px;
margin: 0 auto;
}
.install-cmd {
background: var(--bg-code);
border: 1px solid var(--border-dim);
border-radius: 8px;
padding: 1rem 1.5rem;
font-family: var(--mono);
font-size: 0.95rem;
color: var(--primary);
cursor: pointer;
position: relative;
transition: border-color 0.15s;
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
}
.install-cmd:hover {
border-color: var(--primary-dim);
}
.copy-hint {
font-size: 0.7rem;
color: var(--fg-muted);
white-space: nowrap;
}
.install-alt {
margin-top: 0.75rem;
font-size: 0.8rem;
color: var(--fg-muted);
}
.install-alt code {
color: var(--fg-dim);
background: var(--bg-code);
padding: 0.15em 0.4em;
border-radius: 3px;
font-size: 0.8rem;
}
/* Terminal demo */
.demo {
padding-top: 2rem;
}
.terminal {
background: var(--bg-code);
border: 1px solid var(--border-dim);
border-radius: 10px;
overflow: hidden;
max-width: 600px;
margin: 0 auto;
}
.terminal-bar {
background: #1a1b22;
padding: 0.6rem 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.dot {
width: 10px;
height: 10px;
border-radius: 50%;
}
.dot.red { background: #ff5f57; }
.dot.yellow { background: #febc2e; }
.dot.green { background: #28c840; }
.terminal-title {
margin-left: 0.5rem;
font-size: 0.75rem;
color: var(--fg-muted);
font-family: var(--mono);
}
.terminal pre {
padding: 1.25rem 1.5rem;
font-size: 0.85rem;
line-height: 1.7;
overflow-x: auto;
}
.prompt { color: var(--fg-muted); }
.cmd { color: var(--primary); font-weight: 600; }
.added { color: #28c840; font-weight: 700; }
.removed { color: #ff5f57; font-weight: 700; }
.status { color: var(--primary-dim); }
/* Features */
#features h2, #usage h2, .why h2 {
font-family: var(--mono);
font-size: 1.8rem;
margin-bottom: 2rem;
color: var(--fg);
}
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 1.5rem;
}
.feature {
background: var(--bg-card);
border: 1px solid var(--border-dim);
border-radius: 8px;
padding: 1.5rem;
}
.feature h3 {
font-family: var(--mono);
font-size: 1rem;
color: var(--primary);
margin-bottom: 0.75rem;
}
.feature p {
font-size: 0.9rem;
color: var(--fg-dim);
line-height: 1.6;
}
.feature code {
color: var(--fg);
background: var(--bg-code);
padding: 0.1em 0.35em;
border-radius: 3px;
font-size: 0.85em;
}
/* Usage grid */
.usage-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 0.5rem;
}
.usage-item {
display: flex;
align-items: baseline;
gap: 1rem;
padding: 0.6rem 0;
border-bottom: 1px solid var(--border-dim);
}
.usage-cmd {
font-family: var(--mono);
font-size: 0.85rem;
color: var(--primary);
white-space: nowrap;
min-width: 240px;
}
.usage-desc {
font-size: 0.85rem;
color: var(--fg-dim);
}
/* Why / comparison */
.comparison {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1.5rem;
}
.comparison-col {
background: var(--bg-card);
border: 1px solid var(--border-dim);
border-radius: 8px;
padding: 1.5rem;
}
.comparison-col h3 {
font-family: var(--mono);
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.1em;
margin-bottom: 1rem;
}
.before h3 { color: var(--fg-muted); }
.after h3 { color: var(--primary); }
.comparison pre {
font-size: 0.8rem;
line-height: 1.7;
overflow-x: auto;
}
.comparison .fg-dim { color: var(--fg-muted); }
.after pre code {
color: var(--primary);
font-size: 1.1rem;
font-weight: 600;
}
@media (max-width: 640px) {
.comparison {
grid-template-columns: 1fr;
}
.usage-item {
flex-direction: column;
gap: 0.25rem;
}
.usage-cmd { min-width: auto; }
.install-cmd {
flex-direction: column;
gap: 0.5rem;
font-size: 0.8rem;
}
}
</style>