feat: rebuild website with full learning funnel

Website rebuilt from scratch based on analysis of 11 beloved language
websites (Elm, Zig, Gleam, Swift, Kotlin, Haskell, OCaml, Crystal, Roc,
Rust, Go).

New website structure:
- Homepage with hero, playground, three pillars, install guide
- Language Tour with interactive lessons (hello world, types, effects)
- Examples cookbook with categorized sidebar
- API documentation index
- Installation guide (Nix and source)
- Sleek/noble design (black/gold, serif typography)

Also includes:
- New stdlib/json.lux module for JSON serialization
- Enhanced stdlib/http.lux with middleware and routing
- New string functions (charAt, indexOf, lastIndexOf, repeat)
- LSP improvements (rename, signature help, formatting)
- Package manager transitive dependency resolution
- Updated documentation for effects and stdlib
- New showcase example (task_manager.lux)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-16 23:05:35 -05:00
parent 5a853702d1
commit 7e76acab18
44 changed files with 12468 additions and 3354 deletions

View File

@@ -0,0 +1,239 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTTP Server - Lux by Example</title>
<meta name="description" content="Build an HTTP server in Lux.">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>&#10024;</text></svg>">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600&family=Playfair+Display:wght@400;600;700&family=Source+Serif+4:opsz,wght@8..60,400;8..60,500;8..60,600&display=swap" rel="stylesheet">
<link rel="stylesheet" href="../static/style.css">
<style>
.example-container {
max-width: 900px;
margin: 0 auto;
padding: var(--space-xl) var(--space-lg);
}
.example-header {
margin-bottom: var(--space-xl);
}
.example-header h1 {
margin-bottom: var(--space-sm);
}
.example-header p {
font-size: 1.1rem;
}
.code-block {
background: var(--code-bg);
border: 1px solid var(--code-border);
border-radius: 8px;
margin: var(--space-lg) 0;
overflow: hidden;
}
.code-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--space-sm) var(--space-md);
background: var(--bg-secondary);
border-bottom: 1px solid var(--code-border);
}
.code-filename {
color: var(--text-muted);
font-family: var(--font-code);
font-size: 0.85rem;
}
.code-content {
padding: var(--space-md);
overflow-x: auto;
}
.code-content pre {
font-family: var(--font-code);
font-size: 0.9rem;
line-height: 1.6;
margin: 0;
}
.explanation {
background: var(--bg-glass);
border: 1px solid var(--border-subtle);
border-radius: 8px;
padding: var(--space-lg);
margin: var(--space-lg) 0;
}
.explanation h2 {
font-size: 1.25rem;
margin-bottom: var(--space-md);
text-align: left;
}
.explanation ul {
padding-left: var(--space-lg);
}
.explanation li {
color: var(--text-secondary);
margin-bottom: var(--space-sm);
}
.explanation code {
background: var(--code-bg);
padding: 0.1em 0.3em;
border-radius: 3px;
font-size: 0.9em;
color: var(--gold);
}
.run-it {
background: var(--bg-tertiary);
border: 1px solid var(--border-subtle);
border-radius: 8px;
padding: var(--space-lg);
margin: var(--space-lg) 0;
}
.run-it h3 {
margin-bottom: var(--space-md);
}
.run-it pre {
background: var(--code-bg);
padding: var(--space-md);
border-radius: 6px;
font-family: var(--font-code);
font-size: 0.9rem;
}
.example-nav {
display: flex;
justify-content: space-between;
margin-top: var(--space-xl);
padding-top: var(--space-lg);
border-top: 1px solid var(--border-subtle);
}
.example-nav a {
color: var(--text-secondary);
padding: var(--space-sm) var(--space-md);
border: 1px solid var(--border-subtle);
border-radius: 4px;
}
.example-nav a:hover {
color: var(--gold);
border-color: var(--border-gold);
}
</style>
</head>
<body>
<nav>
<a href="/" class="logo">Lux</a>
<ul class="nav-links" id="nav-links">
<li><a href="/install">Install</a></li>
<li><a href="/tour/">Tour</a></li>
<li><a href="/examples/">Examples</a></li>
<li><a href="/docs/">Docs</a></li>
<li><a href="/play">Play</a></li>
<li><a href="https://git.qrty.ink/blu/lux" class="nav-source">Source</a></li>
</ul>
</nav>
<main class="example-container">
<header class="example-header">
<h1>HTTP Server</h1>
<p>Build a simple HTTP server with effect-tracked I/O. The type signature tells you exactly what side effects this code performs.</p>
</header>
<div class="code-block">
<div class="code-header">
<span class="code-filename">server.lux</span>
</div>
<div class="code-content">
<pre><code><span class="cm">// A simple HTTP server in Lux</span>
<span class="cm">// Notice the effect signature: {HttpServer, Console}</span>
<span class="kw">fn</span> <span class="fn">handleRequest</span>(req: <span class="ty">Request</span>): <span class="ty">Response</span> = {
<span class="kw">match</span> req.path {
<span class="st">"/"</span> => Response {
status: <span class="num">200</span>,
body: <span class="st">"Welcome to Lux!"</span>
},
<span class="st">"/api/hello"</span> => Response {
status: <span class="num">200</span>,
body: Json.stringify({ message: <span class="st">"Hello, World!"</span> })
},
_ => Response {
status: <span class="num">404</span>,
body: <span class="st">"Not Found"</span>
}
}
}
<span class="kw">fn</span> <span class="fn">main</span>(): <span class="ty">Unit</span> <span class="kw">with</span> {<span class="ef">HttpServer</span>, <span class="ef">Console</span>} = {
<span class="ef">HttpServer</span>.listen(<span class="num">8080</span>)
<span class="ef">Console</span>.print(<span class="st">"Server listening on http://localhost:8080"</span>)
<span class="kw">loop</span> {
<span class="kw">let</span> req = <span class="ef">HttpServer</span>.accept()
<span class="ef">Console</span>.print(req.method + <span class="st">" "</span> + req.path)
<span class="kw">let</span> response = handleRequest(req)
<span class="ef">HttpServer</span>.respond(response.status, response.body)
}
}
<span class="kw">run</span> main() <span class="kw">with</span> {}</code></pre>
</div>
</div>
<div class="explanation">
<h2>Key Concepts</h2>
<ul>
<li><code>with {HttpServer, Console}</code> - The function signature declares exactly which effects this code uses</li>
<li><code>HttpServer.listen(port)</code> - Start listening on a port</li>
<li><code>HttpServer.accept()</code> - Wait for and return the next request</li>
<li><code>HttpServer.respond(status, body)</code> - Send a response</li>
<li>Pattern matching on <code>req.path</code> for routing</li>
</ul>
</div>
<div class="explanation">
<h2>Why Effects Matter Here</h2>
<ul>
<li>The type signature <code>with {HttpServer, Console}</code> tells you this function does network I/O and console output</li>
<li>Pure functions like <code>handleRequest</code> have no effects - they're easy to test</li>
<li>For testing, you can swap the <code>HttpServer</code> handler to simulate requests without a real network</li>
</ul>
</div>
<div class="run-it">
<h3>Run It</h3>
<pre>$ lux run server.lux
Server listening on http://localhost:8080
# In another terminal:
$ curl http://localhost:8080/
Welcome to Lux!
$ curl http://localhost:8080/api/hello
{"message":"Hello, World!"}</pre>
</div>
<nav class="example-nav">
<a href="index.html">&larr; All Examples</a>
<a href="rest-api.html">REST API &rarr;</a>
</nav>
</main>
</body>
</html>