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>

247
website/examples/index.html Normal file
View File

@@ -0,0 +1,247 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lux by Example</title>
<meta name="description" content="Learn Lux through annotated example programs.">
<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>
.examples-container {
display: grid;
grid-template-columns: 250px 1fr;
max-width: 1200px;
margin: 0 auto;
min-height: calc(100vh - 80px);
}
.examples-sidebar {
background: var(--bg-secondary);
padding: var(--space-lg);
border-right: 1px solid var(--border-subtle);
position: sticky;
top: 60px;
height: calc(100vh - 60px);
overflow-y: auto;
}
.examples-sidebar h2 {
font-size: 1rem;
color: var(--text-muted);
margin-bottom: var(--space-md);
text-transform: uppercase;
letter-spacing: 0.05em;
text-align: left;
}
.examples-sidebar ul {
list-style: none;
margin-bottom: var(--space-lg);
}
.examples-sidebar li {
margin-bottom: var(--space-xs);
}
.examples-sidebar a {
display: block;
padding: var(--space-xs) var(--space-sm);
color: var(--text-secondary);
border-radius: 4px;
transition: all 0.2s ease;
}
.examples-sidebar a:hover {
color: var(--gold);
background: var(--bg-glass);
}
.examples-sidebar a.active {
color: var(--gold);
background: var(--bg-glass);
border-left: 2px solid var(--gold);
}
.examples-content {
padding: var(--space-xl);
}
.examples-content h1 {
margin-bottom: var(--space-md);
}
.examples-intro {
max-width: 700px;
margin-bottom: var(--space-xl);
}
.examples-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: var(--space-lg);
}
.example-card {
background: var(--bg-glass);
border: 1px solid var(--border-subtle);
border-radius: 8px;
padding: var(--space-lg);
transition: all 0.2s ease;
}
.example-card:hover {
border-color: var(--border-gold);
transform: translateY(-2px);
}
.example-card h3 {
color: var(--gold);
margin-bottom: var(--space-sm);
}
.example-card p {
font-size: 0.95rem;
margin-bottom: var(--space-md);
}
.example-card a {
font-size: 0.9rem;
}
@media (max-width: 768px) {
.examples-container {
grid-template-columns: 1fr;
}
.examples-sidebar {
position: static;
height: auto;
}
}
</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/" class="active">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="examples-container">
<aside class="examples-sidebar">
<h2>Basics</h2>
<ul>
<li><a href="hello-world.html">Hello World</a></li>
<li><a href="values.html">Values</a></li>
<li><a href="variables.html">Variables</a></li>
<li><a href="functions.html">Functions</a></li>
<li><a href="closures.html">Closures</a></li>
<li><a href="recursion.html">Recursion</a></li>
</ul>
<h2>Types</h2>
<ul>
<li><a href="records.html">Records</a></li>
<li><a href="variants.html">Variants</a></li>
<li><a href="generics.html">Generics</a></li>
<li><a href="option.html">Option</a></li>
<li><a href="result.html">Result</a></li>
</ul>
<h2>Effects</h2>
<ul>
<li><a href="console-io.html">Console I/O</a></li>
<li><a href="file-operations.html">File Operations</a></li>
<li><a href="http-requests.html">HTTP Requests</a></li>
<li><a href="random-numbers.html">Random Numbers</a></li>
<li><a href="time-sleep.html">Time & Sleep</a></li>
<li><a href="state-management.html">State Management</a></li>
<li><a href="error-handling.html">Error Handling</a></li>
</ul>
<h2>Data</h2>
<ul>
<li><a href="json-parsing.html">JSON Parsing</a></li>
<li><a href="json-generation.html">JSON Generation</a></li>
<li><a href="string-processing.html">String Processing</a></li>
<li><a href="list-operations.html">List Operations</a></li>
<li><a href="sqlite-database.html">SQLite Database</a></li>
<li><a href="postgresql.html">PostgreSQL</a></li>
</ul>
<h2>Concurrent</h2>
<ul>
<li><a href="spawning-tasks.html">Spawning Tasks</a></li>
<li><a href="channels.html">Channels</a></li>
<li><a href="producer-consumer.html">Producer/Consumer</a></li>
<li><a href="parallel-map.html">Parallel Map</a></li>
</ul>
<h2>Web</h2>
<ul>
<li><a href="http-server.html">HTTP Server</a></li>
<li><a href="rest-api.html">REST API</a></li>
<li><a href="middleware.html">Middleware</a></li>
<li><a href="routing.html">Routing</a></li>
</ul>
</aside>
<div class="examples-content">
<h1>Lux by Example</h1>
<div class="examples-intro">
<p>Learn Lux through annotated example programs. Each example is self-contained and demonstrates a specific concept or pattern.</p>
<p>Click any example to see the full code with explanations.</p>
</div>
<div class="examples-grid">
<div class="example-card">
<h3>Hello World</h3>
<p>Your first Lux program. Learn about the main function and Console effect.</p>
<a href="hello-world.html">View example &rarr;</a>
</div>
<div class="example-card">
<h3>Effects Basics</h3>
<p>Understand how effects make side effects explicit in type signatures.</p>
<a href="console-io.html">View example &rarr;</a>
</div>
<div class="example-card">
<h3>Pattern Matching</h3>
<p>Destructure data with exhaustive pattern matching.</p>
<a href="variants.html">View example &rarr;</a>
</div>
<div class="example-card">
<h3>HTTP Server</h3>
<p>Build a simple web server with effect-tracked I/O.</p>
<a href="http-server.html">View example &rarr;</a>
</div>
<div class="example-card">
<h3>JSON Processing</h3>
<p>Parse and generate JSON data with type safety.</p>
<a href="json-parsing.html">View example &rarr;</a>
</div>
<div class="example-card">
<h3>Concurrency</h3>
<p>Spawn tasks and communicate via channels.</p>
<a href="spawning-tasks.html">View example &rarr;</a>
</div>
</div>
</div>
</main>
</body>
</html>