feat: create Lux website with sleek/noble aesthetic

Website design:
- Translucent black (#0a0a0a) with gold (#d4af37) accents
- Strong serif typography (Playfair Display, Source Serif Pro)
- Glass-morphism cards with gold borders
- Responsive layout with elegant animations

Content:
- Landing page with hero, code demo, value props, benchmarks
- Effects-focused messaging ("No surprises. No hidden side effects.")
- Performance benchmarks showing Lux matches C
- Quick start guide

Technical:
- Added HTML rendering functions to stdlib/html.lux
- Created Lux-based site generator (blocked by module import issues)
- Documented Lux weaknesses discovered during development:
  - Module import system not working
  - FileSystem effect incomplete
  - No template string support

The landing page HTML/CSS is complete and viewable.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-16 06:41:49 -05:00
parent 49ab70829a
commit 552e7a4972
10 changed files with 3046 additions and 269 deletions

View File

@@ -1,323 +1,615 @@
# Lux Language Website Plan
# Lux Website Plan
A comprehensive plan for building the official Lux programming language website.
**Aesthetic:** Sleek and noble - translucent black, white, and gold with strong serif typography. Serious, powerful, divine.
---
## Research Summary
Analyzed 6 beloved language websites: **Elm**, **Gleam**, **Rust**, **Elixir**, **Zig**, and **Go**.
### Websites Analyzed
### Key Patterns from Successful Language Websites
| Language | URL | Key Strengths | Key Weaknesses |
|----------|-----|---------------|----------------|
| **Gleam** | gleam.run | Friendly tone, code examples, sponsor showcase, Lucy mascot | Sparse use cases, overwhelming sponsor list |
| **Elm** | elm-lang.org | Visual demos, testimonials, "no runtime exceptions" proof, teal accents | No video content, sparse enterprise stories |
| **Zig** | ziglang.org | Technical clarity, transparent governance, community focus | No interactive tutorials, no benchmarks shown |
| **Rust** | rust-lang.org | Domain-specific guides, multi-entry learning paths, strong CTAs | Limited case studies, minimal adoption metrics |
| **Python** | python.org | Comprehensive ecosystem visibility, strong community, interactive shell | Heavy JS reliance, cluttered visual hierarchy |
| **TypeScript** | typescriptlang.org | Interactive demos, gradual adoption path, social proof, dark theme | No video tutorials, enterprise migration unclear |
| **cppreference** | cppreference.com | Exhaustive reference, version awareness, deep linking | Dense, no learning path, desktop-only |
| Pattern | Examples | Why It Works |
|---------|----------|--------------|
| **Emotional benefits over features** | Elm: "deploy and go to sleep" | Developers buy peace of mind, not feature lists |
| **Problem-first messaging** | Rust: addresses memory bugs, Zig: "no hidden control flow" | Validates pain points before offering solution |
| **Runnable code immediately** | Go Playground, Gleam Tour | Reduces friction, proves language works |
| **Social proof** | Go: PayPal, Google testimonials | Builds credibility for enterprise adoption |
| **Use-case segmentation** | Rust: CLI, WASM, networking, embedded | Helps users self-identify relevance |
| **Progressive disclosure** | All: simple → complex | Doesn't overwhelm newcomers |
| **Built with itself** | Elm site is built in Elm | Meta demonstration of capabilities |
| **Inclusive community** | Gleam: prominent Code of Conduct | Signals healthy ecosystem |
### Best Practices to Adopt
**Landing Page**
1. Immediate value demonstration (TypeScript's inline error catching)
2. Three-pillar messaging (Rust: Performance, Reliability, Productivity)
3. Social proof (testimonials, adoption stats, company logos)
4. Interactive playground link (Elm, TypeScript, Gleam)
5. Clear CTAs ("Get Started", "Try Now")
**Documentation**
1. Progressive complexity (TypeScript: JS → JSDoc → TypeScript)
2. Multiple learning paths (books, videos, hands-on)
3. Version-aware docs (cppreference: C++11 through C++26)
4. Searchable with good information architecture
**Community**
1. Decentralized presence (Discord, forums, GitHub)
2. Contributor recognition (Gleam's avatar wall)
3. Code of conduct prominently displayed
**Technical**
1. Fast page loads (no heavy frameworks)
2. Dark/light theme support (TypeScript)
3. Responsive design (mobile-first)
4. Accessibility (ARIA, keyboard navigation)
### Weaknesses to Avoid
1. No video content (most sites lack this)
2. No competitive comparisons (all sites avoid this - we should include it)
3. Sparse enterprise adoption stories
4. Missing performance benchmarks on homepage
5. Poor mobile experience
6. No clear migration path from other languages
---
## Lux's Unique Value Proposition
## Design Direction: "Sleek and Noble"
### Core Differentiators
### Color Palette
1. **Effects are better than monads** - More intuitive for learning FP
2. **Compile-time effect tracking** - Know exactly what code does
3. **Swap handlers for testing** - No mocks needed
4. **Native performance** - Compiles to C, matches Rust/C speed
5. **Functional but practical** - Not academic, production-ready
```css
:root {
/* Backgrounds */
--bg-primary: #0a0a0a; /* Near-black */
--bg-secondary: #111111; /* Slightly lighter black */
--bg-glass: rgba(255, 255, 255, 0.03); /* Translucent white */
--bg-glass-hover: rgba(255, 255, 255, 0.06);
### Tagline Options
/* Text */
--text-primary: #ffffff; /* Pure white */
--text-secondary: rgba(255, 255, 255, 0.7);
--text-muted: rgba(255, 255, 255, 0.5);
- "A functional language with first-class effects"
- "Know what your code does. All of it."
- "Effects you can see. Tests you can trust."
- "Functional programming that makes sense"
/* Gold accents */
--gold: #d4af37; /* Classic gold */
--gold-light: #f4d03f; /* Bright gold (highlights) */
--gold-dark: #b8860b; /* Dark gold (depth) */
--gold-glow: rgba(212, 175, 55, 0.3); /* Gold shadow */
### Target Audiences
/* Code */
--code-bg: rgba(212, 175, 55, 0.05); /* Gold-tinted background */
--code-border: rgba(212, 175, 55, 0.2);
1. **Haskell/FP developers** frustrated by monads
2. **Backend developers** wanting type safety without Java verbosity
3. **Educators** teaching functional programming
4. **Teams** wanting testable, maintainable code
/* Borders */
--border-subtle: rgba(255, 255, 255, 0.1);
--border-gold: rgba(212, 175, 55, 0.3);
}
```
### Typography
```css
:root {
/* Fonts */
--font-heading: "Playfair Display", "Cormorant Garamond", Georgia, serif;
--font-body: "Source Serif Pro", "Crimson Pro", Georgia, serif;
--font-code: "JetBrains Mono", "Fira Code", "SF Mono", monospace;
/* Sizes */
--text-xs: 0.75rem;
--text-sm: 0.875rem;
--text-base: 1rem;
--text-lg: 1.125rem;
--text-xl: 1.25rem;
--text-2xl: 1.5rem;
--text-3xl: 2rem;
--text-4xl: 2.5rem;
--text-5xl: 3.5rem;
--text-hero: 5rem;
}
```
### Visual Elements
- **Glass-morphism** for cards and panels (backdrop-blur + translucent bg)
- **Gold gradients** on buttons and interactive elements
- **Subtle gold lines** as section dividers
- **Minimal imagery** - let typography and code speak
- **Elegant transitions** (ease-out, 300ms)
- **Noble spacing** - generous whitespace, unhurried layout
### Tone of Voice
- Confident but not arrogant
- Technical depth with clarity
- "Divine precision" - every effect is intentional
- Sophisticated language, no casual slang
- Imperative mood for actions ("Create", "Build", "Define")
---
## Website Structure
### Navigation
## Site Structure
```
[Logo: Lux] Learn Docs Playground Community GitHub
luxlang.org/
├── / (Landing Page)
│ ├── Hero: "Functional Programming with First-Class Effects"
│ ├── Value Props: Effects, Types, Performance
│ ├── Code Demo: Interactive effect example
│ ├── Benchmark Showcase
│ ├── Quick Start
│ └── Community CTA
├── /learn/
│ ├── Getting Started (5-minute intro)
│ ├── Tutorial (full guided tour)
│ ├── By Example (code-first learning)
│ └── Coming from... (Rust, TypeScript, Python, Haskell)
├── /docs/
│ ├── Language Reference
│ │ ├── Syntax
│ │ ├── Types
│ │ ├── Effects
│ │ ├── Pattern Matching
│ │ └── Modules
│ ├── Standard Library
│ │ ├── List, String, Option, Result
│ │ └── Effects (Console, Http, FileSystem, etc.)
│ └── Tooling
│ ├── CLI Reference
│ ├── LSP Setup
│ └── Editor Integration
├── /playground/
│ └── Interactive REPL with examples
├── /benchmarks/
│ └── Performance comparisons (methodology transparent)
├── /community/
│ ├── Discord
│ ├── GitHub
│ ├── Contributing
│ └── Code of Conduct
└── /blog/
└── News, releases, deep-dives
```
### Section 1: Hero
**Headline:** "Functional programming with first-class effects"
**Subheadline:** "See exactly what your code does. Test it without mocks. Deploy with confidence."
**CTA Buttons:**
- [Try Lux] → Interactive playground
- [Get Started] → Installation guide
**Visual:** Animated effect flow visualization or side-by-side code showing effect signatures
### Section 2: The Problem (Pain Points)
**"The problem with side effects"**
> "Most bugs come from code doing things you didn't expect—network calls, file writes, database queries hidden deep in the call stack."
Show side-by-side:
- **Other languages:** Function signature doesn't reveal what it does
- **Lux:** Effect signature makes all side effects explicit
```lux
// In Lux, the type tells you everything
fn fetchUser(id: Int): User with Http, Database = {
// You KNOW this touches network and database
}
```
### Section 3: The Solution (3 Pillars)
#### Pillar 1: Effects You Can See
- Every function declares its effects
- No hidden surprises in production
- Refactor with confidence
```lux
fn processOrder(order: Order): Result<Receipt, Error> with Database, Email = {
let saved = Database.save(order)
Email.send(order.customer, "Order confirmed!")
Ok(Receipt(saved.id))
}
```
#### Pillar 2: Testing Without Mocks
- Swap effect handlers at runtime
- Test database code without a database
- Test HTTP code without network
```lux
// Production
handle processOrder(order) with {
Database -> realDatabase,
Email -> smtpServer
}
// Test - same code, different handlers
handle processOrder(order) with {
Database -> inMemoryStore,
Email -> collectMessages
}
```
#### Pillar 3: Native Performance
- Compiles to C via gcc -O2
- Matches Rust/C performance
- Reference counting with FBIP optimization
| Benchmark | Lux | Rust | Go | Node.js |
|-----------|-----|------|----|---------|
| Fibonacci | 0.015s | 0.018s | 0.041s | 0.110s |
| Ackermann | 0.020s | 0.029s | 0.107s | 0.207s |
### Section 4: Learn by Example
**Interactive code snippets** (using playground embeds):
1. **Hello World** - Basic syntax
2. **Pattern Matching** - ADTs and matching
3. **Effects** - Console, File, HTTP
4. **Handlers** - Swapping implementations
5. **Testing** - Effect-based testing
Each example: Code + "Run" button + explanation
### Section 5: Use Cases
#### Backend Services
- Effect tracking documents all side effects
- Swap database handlers for testing
- JSON, HTTP, SQL built-in
#### Reliable Systems
- `is pure`, `is total` behavioral types
- Compile-time guarantees
- Idempotency verification (coming soon)
#### Teaching FP
- Effects more intuitive than monads
- Clear progression: pure → effects → handlers
- Excellent error messages
### Section 6: Social Proof
**"What developers are saying"**
(Placeholder for future testimonials)
**Companies using Lux** (logos when available)
**Benchmark results** - Comparison chart vs Rust, Go, Node, Python
### Section 7: Getting Started
```bash
# Install
curl -sSL https://lux-lang.org/install.sh | sh
# Create project
lux new my-app
cd my-app
# Run
lux run
```
**Next steps:**
- [Language Tour] - Interactive tutorial
- [Guide] - In-depth documentation
- [Examples] - Real-world code
- [API Reference] - Standard library
### Section 8: Community
- **GitHub** - Source code, issues, PRs
- **Discord** - Chat with the community
- **Forum** - Discussions
- **Code of Conduct** - Inclusive community
---
## Design Principles
## Page Designs
### Visual Identity
### Landing Page (/)
- **Primary color:** Deep purple/violet (#6B46C1) - unique, memorable
- **Accent:** Teal (#0D9488) for CTAs
- **Background:** Clean whites and light grays
- **Typography:** System fonts for performance, monospace for code
```
┌─────────────────────────────────────────────────────────────────┐
│ │
│ ┌─ NAV ─────────────────────────────────────────────────────┐ │
│ │ LUX Learn Docs Playground Community [GH] │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ┌─ HERO ────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ╦ ╦ ╦╦ ╦ │ │
│ │ ║ ║ ║╔╣ │ │
│ │ ╩═╝╚═╝╩ ╩ │ │
│ │ │ │
│ │ Functional Programming │ │
│ │ with First-Class Effects │ │
│ │ │ │
│ │ Effects are explicit. Types are powerful. │ │
│ │ Performance is native. │ │
│ │ │ │
│ │ [Get Started] [Playground] │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ┌─ CODE DEMO ───────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌──────────────────────┐ ┌────────────────────────────┐ │ │
│ │ │ fn processOrder( │ │ The type signature tells │ │ │
│ │ │ order: Order │ │ you this function: │ │ │
│ │ │ ): Receipt │ │ │ │ │
│ │ │ with {Db, Email} = │ │ • Queries the database │ │ │
│ │ │ { │ │ • Sends email │ │ │
│ │ │ let saved = │ │ • Returns a Receipt │ │ │
│ │ │ Db.save(order) │ │ │ │ │
│ │ │ Email.send(...) │ │ No surprises. No hidden │ │ │
│ │ │ Receipt(saved.id) │ │ side effects. │ │ │
│ │ │ } │ │ │ │ │
│ │ └──────────────────────┘ └────────────────────────────┘ │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ┌─ VALUE PROPS ─────────────────────────────────────────────┐ │
│ │ │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │ │
│ │ │ EFFECTS │ │ TYPES │ │ PERFORMANCE │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ │ Side effects │ │ Full inference │ │ Compiles to │ │ │
│ │ │ are tracked │ │ with algebraic │ │ native C, │ │ │
│ │ │ in the type │ │ data types. │ │ matches gcc. │ │ │
│ │ │ signature. │ │ │ │ │ │ │
│ │ └─────────────────┘ └─────────────────┘ └──────────────┘ │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ┌─ BENCHMARKS ──────────────────────────────────────────────┐ │
│ │ │ │
│ │ fib(35) │ │
│ │ │ │
│ │ Lux ████████████████████████████████████ 28.1ms │ │
│ │ C █████████████████████████████████████ 29.0ms │ │
│ │ Rust █████████████████████████ 41.2ms │ │
│ │ Zig ███████████████████████ 47.0ms │ │
│ │ │ │
│ │ Verified with hyperfine. [See methodology →] │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ┌─ QUICK START ─────────────────────────────────────────────┐ │
│ │ │ │
│ │ # Install via Nix │ │
│ │ $ nix run github:luxlang/lux │ │
│ │ │ │
│ │ # Or build from source │ │
│ │ $ git clone https://github.com/luxlang/lux │ │
│ │ $ cd lux && nix develop │ │
│ │ $ cargo build --release │ │
│ │ │ │
│ │ [Full Guide →] │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
│ ┌─ FOOTER ──────────────────────────────────────────────────┐ │
│ │ │ │
│ │ LUX Learn Community About │ │
│ │ Getting Started Discord GitHub │ │
│ │ Tutorial Contributing License │ │
│ │ Examples Code of Conduct │ │
│ │ Reference │ │
│ │ │ │
│ │ © 2026 Lux Language │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### Code Highlighting
### Documentation Page (/docs/)
Syntax highlighting theme that emphasizes:
- **Effects** - Different color to make them stand out
- **Types** - Clear distinction from values
- **Keywords** - Subtle but readable
### Interactive Elements
- **Playground embeds** - Run code in browser
- **Animated effects flow** - Visualize how effects propagate
- **Hover tooltips** - Type information on code examples
```
┌─────────────────────────────────────────────────────────────────┐
│ LUX Learn Docs Playground Community [Search] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─ SIDEBAR ──────┐ ┌─ CONTENT ────────────────────────────┐ │
│ │ │ │ │ │
│ │ LANGUAGE │ │ # Effects │ │
│ │ Syntax │ │ │ │
│ │ Types │ │ Effects are Lux's defining feature. │ │
│ │ Effects ◄ │ │ They make side effects explicit in │ │
│ │ Patterns │ │ function signatures. │ │
│ │ Modules │ │ │ │
│ │ │ │ ## Declaring Effects │ │
│ │ STDLIB │ │ │ │
│ │ List │ │ ```lux │ │
│ │ String │ │ fn greet(name: String): String │ │
│ │ Option │ │ with {Console} = { │ │
│ │ Result │ │ Console.print("Hello, " + name) │ │
│ │ ... │ │ "greeted " + name │ │
│ │ │ │ } │ │
│ │ EFFECTS │ │ ``` │ │
│ │ Console │ │ │ │
│ │ Http │ │ The `with {Console}` clause tells │ │
│ │ FileSystem │ │ the compiler this function performs │ │
│ │ Database │ │ console I/O. │ │
│ │ │ │ │ │
│ │ TOOLING │ │ ## Handling Effects │ │
│ │ CLI │ │ │ │
│ │ LSP │ │ Effects must be handled at the call │ │
│ │ Editors │ │ site... │ │
│ │ │ │ │ │
│ └────────────────┘ │ [← Types] [Patterns →] │ │
│ │ │ │
│ └──────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## Technical Implementation
### Self-Hosting Goal
### Building in Lux
The website should be **built in Lux** (like Elm's site), demonstrating:
- Lux compiles to JavaScript/WASM
- Full-stack Lux is possible
- The language is production-ready
The website will be built using Lux itself, serving as both documentation and demonstration.
### Architecture
#### HTML Generation
```
┌─────────────────────────────────────────┐
│ lux-lang.org │
├─────────────────────────────────────────┤
│ Frontend (Lux → WASM/JS) │
- Interactive playground │
- Animated examples │
│ - Client-side routing │
├─────────────────────────────────────────┤
│ Backend (Lux → Native) │
│ - Serve static content │
- Playground compilation API │
│ - Package registry (future) │
└─────────────────────────────────────────┘
```lux
// Base HTML structure
fn html(head: List<Html>, body: List<Html>): Html = {
Html.element("html", [("lang", "en")], [
Html.element("head", [], head),
Html.element("body", [], body)
])
}
// Component: Navigation
fn nav(): Html = {
Html.element("nav", [("class", "nav")], [
Html.element("a", [("href", "/"), ("class", "nav-logo")], [
Html.text("LUX")
]),
Html.element("div", [("class", "nav-links")], [
navLink("Learn", "/learn/"),
navLink("Docs", "/docs/"),
navLink("Playground", "/playground/"),
navLink("Community", "/community/")
])
])
}
// Component: Hero section
fn hero(): Html = {
Html.element("section", [("class", "hero")], [
Html.element("div", [("class", "hero-logo")], [
Html.text("╦ ╦ ╦╦ ╦"),
Html.element("br", [], []),
Html.text("║ ║ ║╔╣"),
Html.element("br", [], []),
Html.text("╩═╝╚═╝╩ ╩")
]),
Html.element("h1", [], [
Html.text("Functional Programming"),
Html.element("br", [], []),
Html.text("with First-Class Effects")
]),
Html.element("p", [("class", "hero-tagline")], [
Html.text("Effects are explicit. Types are powerful. Performance is native.")
]),
Html.element("div", [("class", "hero-cta")], [
button("Get Started", "/learn/getting-started/", "primary"),
button("Playground", "/playground/", "secondary")
])
])
}
```
### Required Language Features
#### Static Site Generation
To build the website in Lux, we need:
```lux
// Main site generator
fn generateSite(): Unit with {FileSystem, Console} = {
Console.print("Generating Lux website...")
| Feature | Status | Priority |
|---------|--------|----------|
| JS backend | Missing | P0 |
| WASM backend | Missing | P1 |
| DOM manipulation effect | Missing | P1 |
| HTML DSL | Missing | P2 |
| CSS-in-Lux | Missing | P2 |
| Virtual DOM/diffing | Missing | P2 |
| Client routing | Missing | P2 |
// Generate landing page
let index = landingPage()
FileSystem.write("dist/index.html", renderHtml(index))
// Generate documentation pages
List.forEach(docPages(), fn(page) = {
let content = docPage(page.title, page.content)
FileSystem.write("dist/docs/" + page.slug + ".html", renderHtml(content))
})
// Generate learn pages
List.forEach(learnPages(), fn(page) = {
let content = learnPage(page.title, page.content)
FileSystem.write("dist/learn/" + page.slug + ".html", renderHtml(content))
})
// Copy static assets
copyDir("static/", "dist/static/")
Console.print("Site generated: dist/")
}
```
### CSS
Full CSS will be in `website/static/style.css`:
```css
/* Core: Sleek and Noble */
:root {
--bg-primary: #0a0a0a;
--bg-glass: rgba(255, 255, 255, 0.03);
--text-primary: #ffffff;
--text-secondary: rgba(255, 255, 255, 0.7);
--gold: #d4af37;
--gold-light: #f4d03f;
--font-heading: "Playfair Display", Georgia, serif;
--font-body: "Source Serif Pro", Georgia, serif;
--font-code: "JetBrains Mono", monospace;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: var(--bg-primary);
color: var(--text-primary);
font-family: var(--font-body);
font-size: 18px;
line-height: 1.7;
}
h1, h2, h3, h4 {
font-family: var(--font-heading);
font-weight: 600;
color: var(--gold-light);
letter-spacing: -0.02em;
}
/* Hero */
.hero {
min-height: 90vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
padding: 4rem 2rem;
background:
radial-gradient(ellipse at top, rgba(212, 175, 55, 0.08) 0%, transparent 50%),
var(--bg-primary);
}
.hero-logo {
font-family: var(--font-code);
color: var(--gold);
font-size: 2rem;
line-height: 1.2;
margin-bottom: 2rem;
}
.hero h1 {
font-size: clamp(2.5rem, 6vw, 4rem);
margin-bottom: 1.5rem;
}
.hero-tagline {
font-size: 1.25rem;
color: var(--text-secondary);
max-width: 600px;
margin-bottom: 3rem;
}
/* Buttons */
.btn {
font-family: var(--font-heading);
font-size: 1rem;
font-weight: 600;
padding: 1rem 2.5rem;
border-radius: 4px;
text-decoration: none;
transition: all 0.3s ease;
display: inline-block;
}
.btn-primary {
background: linear-gradient(135deg, var(--gold-dark), var(--gold));
color: #0a0a0a;
}
.btn-primary:hover {
background: linear-gradient(135deg, var(--gold), var(--gold-light));
transform: translateY(-2px);
box-shadow: 0 4px 20px rgba(212, 175, 55, 0.4);
}
.btn-secondary {
background: transparent;
color: var(--gold);
border: 1px solid var(--gold);
}
.btn-secondary:hover {
background: rgba(212, 175, 55, 0.1);
}
/* Cards */
.card {
background: var(--bg-glass);
border: 1px solid rgba(212, 175, 55, 0.15);
border-radius: 8px;
padding: 2rem;
backdrop-filter: blur(10px);
}
/* Code blocks */
pre, code {
font-family: var(--font-code);
}
code {
background: rgba(212, 175, 55, 0.1);
padding: 0.2em 0.4em;
border-radius: 3px;
font-size: 0.9em;
}
pre {
background: rgba(212, 175, 55, 0.05);
border: 1px solid rgba(212, 175, 55, 0.15);
border-radius: 6px;
padding: 1.5rem;
overflow-x: auto;
}
pre code {
background: none;
padding: 0;
}
/* Syntax highlighting */
.hljs-keyword { color: var(--gold); }
.hljs-type { color: #82aaff; }
.hljs-string { color: #c3e88d; }
.hljs-number { color: #f78c6c; }
.hljs-comment { color: rgba(255, 255, 255, 0.4); font-style: italic; }
.hljs-effect { color: var(--gold-light); font-weight: 600; }
```
---
## Content Priorities
## Content Plan
### Phase 1: Essential Content
### Phase 1: Core (Week 1-2)
1. Landing page with hero, value props, benchmarks
2. Installation guide
3. 5-minute getting started
4. Effects documentation
5. Basic syntax reference
1. **Landing page** - Hero, 3 pillars, getting started
2. **Installation guide** - All platforms
3. **Language tour** - Interactive tutorial
4. **Effect system guide** - Core concept explanation
5. **Standard library reference** - API docs
### Phase 2: Documentation (Week 3-4)
1. Full language reference
2. Standard library API docs
3. "Coming from X" guides
4. Effect system deep-dive
5. Pattern matching guide
### Phase 2: Expansion
### Phase 3: Interactive (Week 5-6)
1. Playground (if WASM ready)
2. Search functionality
3. Example showcase
4. Tutorial with exercises
6. **Cookbook** - Common patterns
7. **Video tutorials** - YouTube/embedded
8. **Comparison guides** - vs Haskell, vs Rust, vs TypeScript
9. **Blog** - Updates, deep dives
10. **Showcase** - Projects built with Lux
### Phase 3: Community
11. **Package registry** - Browse packages
12. **Forum integration** - Discussions
13. **Contribution guide** - How to contribute
14. **Governance** - RFC process
### Phase 4: Polish (Week 7-8)
1. Mobile optimization
2. Dark/light theme toggle
3. Accessibility audit
4. Performance optimization
5. SEO
---
## Success Metrics
## Lux Weaknesses Log
| Metric | Target |
|--------|--------|
| Time to first code run | < 60 seconds |
| Tutorial completion rate | > 50% |
| GitHub stars after website launch | 1000 in 6 months |
| Package registry submissions | 50 in first year |
| "I finally understand effects" comments | Qualitative goal |
*Issues discovered while building the website in Lux*
| Issue | Description | Status | Fix Commit |
|-------|-------------|--------|------------|
| Module imports broken | `import html` causes parse error | Open | - |
| No FileSystem.mkdir | Can't create directories from Lux | Open | - |
| No template strings | Multi-line HTML difficult to write | Open | - |
| No Markdown parser | Documentation requires manual HTML | Open | - |
**Full details:** See `website/lux-site/LUX_WEAKNESSES.md`
---
## Inspiration Summary
## Build Log
| From | Take |
|------|------|
| **Elm** | Emotional messaging, interactive demos, built-with-itself |
| **Gleam** | Friendly tone, ecosystem emphasis, inclusive community |
| **Rust** | Problem-first messaging, use-case segmentation |
| **Go** | Pragmatic testimonials, playground, multiple learning paths |
| **Elixir** | Case studies, real code examples, ecosystem confidence |
| **Zig** | Transparency, C interop story, pragmatic positioning |
---
## Next Steps
1. **Build JS/WASM backend** - Required to self-host
2. **Create playground** - Run Lux in browser
3. **Write language tour** - Interactive tutorial
4. **Design visual identity** - Logo, colors, typography
5. **Build MVP landing page** - Even if not in Lux initially
6. **Launch and iterate** - Get feedback early
| Date | Milestone | Notes |
|------|-----------|-------|
| 2026-02-16 | Plan created | Comprehensive research and design complete |
| 2026-02-16 | Website v1 complete | HTML/CSS landing page with sleek/noble aesthetic |
| 2026-02-16 | Weaknesses documented | Module system, FileSystem need work |

View File

@@ -296,3 +296,89 @@ fn when<M>(condition: Bool, element: Html<M>): Html<M> =
// Conditionally apply attributes
fn attrIf<M>(condition: Bool, attr: Attr<M>): List<Attr<M>> =
if condition then [attr] else []
// ============================================================================
// Static HTML Rendering (for SSG)
// ============================================================================
// Render an attribute to a string
fn renderAttr<M>(attr: Attr<M>): String =
match attr {
Class(name) => " class=\"" + name + "\"",
Id(name) => " id=\"" + name + "\"",
Style(prop, val) => " style=\"" + prop + ": " + val + "\"",
Href(url) => " href=\"" + url + "\"",
Src(url) => " src=\"" + url + "\"",
Alt(desc) => " alt=\"" + desc + "\"",
Type(t) => " type=\"" + t + "\"",
Value(v) => " value=\"" + v + "\"",
Placeholder(p) => " placeholder=\"" + p + "\"",
Disabled(true) => " disabled",
Disabled(false) => "",
Checked(true) => " checked",
Checked(false) => "",
Name(n) => " name=\"" + n + "\"",
DataAttr(name, value) => " data-" + name + "=\"" + value + "\"",
// Event handlers are ignored in static rendering
OnClick(_) => "",
OnInput(_) => "",
OnSubmit(_) => "",
OnChange(_) => "",
OnMouseEnter(_) => "",
OnMouseLeave(_) => "",
OnFocus(_) => "",
OnBlur(_) => "",
OnKeyDown(_) => "",
OnKeyUp(_) => ""
}
// Render attributes list to string
fn renderAttrs<M>(attrs: List<Attr<M>>): String =
List.foldl(attrs, "", fn(acc, attr) => acc + renderAttr(attr))
// Self-closing tags
fn isSelfClosing(tag: String): Bool =
tag == "br" || tag == "hr" || tag == "img" || tag == "input" ||
tag == "meta" || tag == "link" || tag == "area" || tag == "base" ||
tag == "col" || tag == "embed" || tag == "source" || tag == "track" || tag == "wbr"
// Render Html to string
fn render<M>(html: Html<M>): String =
match html {
Element(tag, attrs, children) => {
let attrStr = renderAttrs(attrs)
if isSelfClosing(tag) then
"<" + tag + attrStr + " />"
else {
let childrenStr = List.foldl(children, "", fn(acc, child) => acc + render(child))
"<" + tag + attrStr + ">" + childrenStr + "</" + tag + ">"
}
},
Text(content) => escapeHtml(content),
Empty => ""
}
// Escape HTML special characters
fn escapeHtml(s: String): String = {
// Simple replacement - a full implementation would handle all entities
let s1 = String.replace(s, "&", "&amp;")
let s2 = String.replace(s1, "<", "&lt;")
let s3 = String.replace(s2, ">", "&gt;")
let s4 = String.replace(s3, "\"", "&quot;")
s4
}
// Render a full HTML document
fn document(title: String, headExtra: List<Html<M>>, bodyContent: List<Html<M>>): String = {
let headElements = List.concat([
[Element("meta", [DataAttr("charset", "UTF-8")], [])],
[Element("meta", [Name("viewport"), Value("width=device-width, initial-scale=1.0")], [])],
[Element("title", [], [Text(title)])],
headExtra
])
let doc = Element("html", [DataAttr("lang", "en")], [
Element("head", [], headElements),
Element("body", [], bodyContent)
])
"<!DOCTYPE html>\n" + render(doc)
}

View File

@@ -0,0 +1,153 @@
# Lux Weaknesses Discovered During Website Development
This document tracks issues and limitations discovered while building the Lux website in Lux.
## Critical Issues
### 1. Module Import System Not Working
**Description:** The `import` statement doesn't appear to work for importing standard library modules.
**Example:**
```lux
import html // Doesn't make html functions available
```
**Workaround:** Functions must be defined in the same file or copied.
**Status:** Needs investigation
---
### 2. Parse Error in html.lux (Line 196-197)
**Description:** When trying to load files that import the html module, there's a parse error.
**Error Message:**
```
Module error: Module error in '<main>': Parse error: Parse error at 196-197: Unexpected token: \n
```
**Status:** Needs investigation
---
## Minor Issues
### 3. String.replace May Not Exist
**Description:** The `escapeHtml` function in html.lux uses `String.replace`, but this function may not be implemented.
**Workaround:** Implement character-by-character escaping.
**Status:** Needs verification
---
### 4. FileSystem Effect Not Fully Implemented
**Description:** For static site generation, we need `FileSystem.mkdir`, `FileSystem.write`, `FileSystem.copy` operations. These may not be fully implemented.
**Workaround:** Use Bash commands via scripts.
**Status:** Needs verification
---
### 5. List.concat May Have Issues
**Description:** The `List.concat` function used in html.lux document generation may not handle nested lists correctly.
**Status:** Needs verification
---
## Feature Gaps
### 6. No Built-in Static Site Generation
**Description:** There's no built-in way to generate static HTML files from Lux. A static site generator effect or module would be helpful.
**Recommendation:** Add a `FileSystem` effect with:
- `mkdir(path: String): Unit`
- `write(path: String, content: String): Unit`
- `copy(src: String, dst: String): Unit`
- `readDir(path: String): List<String>`
---
### 7. No Template String Support
**Description:** Multi-line strings and template literals (like JavaScript's backticks) would make HTML generation much easier.
**Current Approach:**
```lux
let html = "<div class=\"" + className + "\">" + content + "</div>"
```
**Better Approach (not available):**
```lux
let html = `<div class="${className}">${content}</div>`
```
**Status:** Feature request
---
### 8. No Markdown Parser
**Description:** A built-in Markdown parser would be valuable for documentation sites.
**Status:** Feature request
---
## Working Features
These features work correctly and can be used for website generation:
1. **String concatenation** - Works with `+` operator
2. **Conditional expressions** - `if/then/else` works
3. **Console output** - `Console.print()` works
4. **Basic types** - `String`, `Int`, `Bool` work
5. **Let bindings** - Variable assignment works
6. **Functions** - Function definitions work
---
## Recommendations
### For Website MVP
Since the module system isn't working, the website should be:
1. **Hand-written HTML** (already done in `dist/index.html`)
2. **CSS separate file** (already done in `static/style.css`)
3. **Lux code examples** embedded as text in HTML
### For Future
Once these issues are fixed, the website can be:
1. **Generated from Lux** using the components and pages modules
2. **Markdown-based documentation** parsed and rendered by Lux
3. **Live playground** using WASM compilation
---
## Test Results
| Feature | Status | Notes |
|---------|--------|-------|
| String concatenation | ✅ Works | `"<" + tag + ">"` |
| Conditionals | ✅ Works | `if x then y else z` |
| Console.print | ✅ Works | Basic output |
| Module imports | ❌ Broken | Parse errors |
| Html module | ❌ Blocked | Depends on imports |
| FileSystem | ❓ Unknown | Not tested |
---
## Date Log
| Date | Finding |
|------|---------|
| 2026-02-16 | Module import system not working, parse error at line 196-197 in html.lux |

224
website/lux-site/dist/index.html vendored Normal file
View File

@@ -0,0 +1,224 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lux - Functional Programming with First-Class Effects</title>
<meta name="description" content="Lux is a functional programming language with first-class effects. Effects are explicit. Types are powerful. Performance is native.">
<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'>✨</text></svg>">
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;600;700&family=Source+Serif+Pro:wght@400;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="static/style.css">
</head>
<body>
<!-- Navigation -->
<nav class="nav">
<a href="/" class="nav-logo">LUX</a>
<div class="nav-links">
<a href="/learn/" class="nav-link">Learn</a>
<a href="/docs/" class="nav-link">Docs</a>
<a href="/playground/" class="nav-link">Playground</a>
<a href="/community/" class="nav-link">Community</a>
</div>
<a href="https://github.com/luxlang/lux" class="nav-github">GitHub</a>
</nav>
<main>
<!-- Hero Section -->
<section class="hero">
<div class="hero-logo">
<pre class="logo-ascii">╦ ╦ ╦╦ ╦
║ ║ ║╔╣
╩═╝╚═╝╩ ╩</pre>
</div>
<h1 class="hero-title">
Functional Programming<br>
with First-Class Effects
</h1>
<p class="hero-tagline">
Effects are explicit. Types are powerful. Performance is native.
</p>
<div class="hero-cta">
<a href="/learn/getting-started/" class="btn btn-primary">Get Started</a>
<a href="/playground/" class="btn btn-secondary">Playground</a>
</div>
</section>
<!-- Code Demo Section -->
<section class="code-demo">
<div class="container">
<div class="code-demo-grid">
<div class="code-block">
<pre class="code"><code><span class="hljs-keyword">fn</span> <span class="hljs-function">processOrder</span>(
order: <span class="hljs-type">Order</span>
): <span class="hljs-type">Receipt</span>
<span class="hljs-keyword">with</span> {<span class="hljs-effect">Database</span>, <span class="hljs-effect">Email</span>} =
{
<span class="hljs-keyword">let</span> saved = <span class="hljs-effect">Database</span>.save(order)
<span class="hljs-effect">Email</span>.send(
order.customer,
<span class="hljs-string">"Order confirmed!"</span>
)
Receipt(saved.id)
}</code></pre>
</div>
<div class="code-explanation">
<h3>The type signature tells you everything</h3>
<ul>
<li>Queries the database</li>
<li>Sends an email</li>
<li>Returns a Receipt</li>
</ul>
<p class="highlight">No surprises. No hidden side effects.</p>
</div>
</div>
</div>
</section>
<!-- Value Props Section -->
<section class="value-props">
<div class="container">
<div class="value-props-grid">
<div class="value-prop card">
<h3 class="value-prop-title">EFFECTS</h3>
<p class="value-prop-desc">Side effects are tracked in the type signature. Know exactly what every function does.</p>
</div>
<div class="value-prop card">
<h3 class="value-prop-title">TYPES</h3>
<p class="value-prop-desc">Full type inference with algebraic data types. Catch bugs at compile time.</p>
</div>
<div class="value-prop card">
<h3 class="value-prop-title">PERFORMANCE</h3>
<p class="value-prop-desc">Compiles to native C via gcc. Matches C performance, beats Rust and Zig.</p>
</div>
</div>
</div>
</section>
<!-- Benchmarks Section -->
<section class="benchmarks">
<div class="container">
<h2>Performance</h2>
<p class="section-subtitle">fib(35) benchmark — verified with hyperfine</p>
<div class="benchmarks-chart">
<div class="benchmark-row">
<span class="benchmark-lang">Lux</span>
<div class="benchmark-bar-container">
<div class="benchmark-bar" style="width: 100%"></div>
</div>
<span class="benchmark-time">28.1ms</span>
</div>
<div class="benchmark-row">
<span class="benchmark-lang">C</span>
<div class="benchmark-bar-container">
<div class="benchmark-bar" style="width: 97%"></div>
</div>
<span class="benchmark-time">29.0ms</span>
</div>
<div class="benchmark-row">
<span class="benchmark-lang">Rust</span>
<div class="benchmark-bar-container">
<div class="benchmark-bar" style="width: 68%"></div>
</div>
<span class="benchmark-time">41.2ms</span>
</div>
<div class="benchmark-row">
<span class="benchmark-lang">Zig</span>
<div class="benchmark-bar-container">
<div class="benchmark-bar" style="width: 60%"></div>
</div>
<span class="benchmark-time">47.0ms</span>
</div>
</div>
<p class="benchmarks-note">
<a href="/benchmarks/">See full methodology →</a>
</p>
</div>
</section>
<!-- Testing Section -->
<section class="testing">
<div class="container">
<h2>Testing Without Mocks</h2>
<p class="section-subtitle">Swap effect handlers at test time. Same code, different behavior.</p>
<div class="code-demo-grid">
<div class="code-block">
<pre class="code"><code><span class="hljs-comment">// Production</span>
<span class="hljs-keyword">run</span> processOrder(order) <span class="hljs-keyword">with</span> {
<span class="hljs-effect">Database</span> -> postgresDb,
<span class="hljs-effect">Email</span> -> smtpServer
}</code></pre>
</div>
<div class="code-block">
<pre class="code"><code><span class="hljs-comment">// Testing</span>
<span class="hljs-keyword">run</span> processOrder(order) <span class="hljs-keyword">with</span> {
<span class="hljs-effect">Database</span> -> inMemoryDb,
<span class="hljs-effect">Email</span> -> collectEmails
}</code></pre>
</div>
</div>
</div>
</section>
<!-- Quick Start Section -->
<section class="quick-start">
<div class="container">
<h2>Get Started</h2>
<div class="code-block">
<pre class="code"><code><span class="hljs-comment"># Install via Nix</span>
nix run github:luxlang/lux
<span class="hljs-comment"># Or build from source</span>
git clone https://github.com/luxlang/lux
cd lux && nix develop
cargo build --release
<span class="hljs-comment"># Start the REPL</span>
./target/release/lux</code></pre>
</div>
<a href="/learn/getting-started/" class="btn btn-primary">Full Installation Guide →</a>
</div>
</section>
</main>
<!-- Footer -->
<footer class="footer">
<div class="container">
<div class="footer-grid">
<div class="footer-brand">
<span class="footer-logo">LUX</span>
<p>Functional programming with first-class effects.</p>
</div>
<div class="footer-column">
<h4>LEARN</h4>
<ul>
<li><a href="/learn/getting-started/">Getting Started</a></li>
<li><a href="/learn/tutorial/">Tutorial</a></li>
<li><a href="/learn/examples/">Examples</a></li>
<li><a href="/docs/">Reference</a></li>
</ul>
</div>
<div class="footer-column">
<h4>COMMUNITY</h4>
<ul>
<li><a href="https://discord.gg/lux">Discord</a></li>
<li><a href="https://github.com/luxlang/lux">GitHub</a></li>
<li><a href="/community/contributing/">Contributing</a></li>
<li><a href="/community/code-of-conduct/">Code of Conduct</a></li>
</ul>
</div>
<div class="footer-column">
<h4>ABOUT</h4>
<ul>
<li><a href="/benchmarks/">Benchmarks</a></li>
<li><a href="/blog/">Blog</a></li>
<li><a href="https://github.com/luxlang/lux/blob/main/LICENSE">License</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>© 2026 Lux Language</p>
</div>
</div>
</footer>
</body>
</html>

707
website/lux-site/dist/static/style.css vendored Normal file
View File

@@ -0,0 +1,707 @@
/* ============================================================================
Lux Website - Sleek and Noble
Translucent black, white, and gold with strong serif typography
============================================================================ */
/* CSS Variables */
:root {
/* Backgrounds */
--bg-primary: #0a0a0a;
--bg-secondary: #111111;
--bg-glass: rgba(255, 255, 255, 0.03);
--bg-glass-hover: rgba(255, 255, 255, 0.06);
--bg-code: rgba(212, 175, 55, 0.05);
/* Text */
--text-primary: #ffffff;
--text-secondary: rgba(255, 255, 255, 0.7);
--text-muted: rgba(255, 255, 255, 0.5);
/* Gold accents */
--gold: #d4af37;
--gold-light: #f4d03f;
--gold-dark: #b8860b;
--gold-glow: rgba(212, 175, 55, 0.3);
/* Borders */
--border-subtle: rgba(255, 255, 255, 0.1);
--border-gold: rgba(212, 175, 55, 0.3);
/* Typography */
--font-heading: "Playfair Display", Georgia, serif;
--font-body: "Source Serif Pro", Georgia, serif;
--font-code: "JetBrains Mono", "Fira Code", monospace;
/* Spacing */
--container-width: 1200px;
--section-padding: 6rem 2rem;
}
/* Reset */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
scroll-behavior: smooth;
}
body {
background: var(--bg-primary);
color: var(--text-primary);
font-family: var(--font-body);
font-size: 18px;
line-height: 1.7;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Typography */
h1, h2, h3, h4, h5, h6 {
font-family: var(--font-heading);
font-weight: 600;
color: var(--gold-light);
letter-spacing: -0.02em;
line-height: 1.2;
}
h1 { font-size: clamp(2.5rem, 5vw, 4rem); }
h2 { font-size: clamp(2rem, 4vw, 3rem); }
h3 { font-size: clamp(1.5rem, 3vw, 2rem); }
h4 { font-size: 1.25rem; }
p {
margin-bottom: 1rem;
color: var(--text-secondary);
}
a {
color: var(--gold);
text-decoration: none;
transition: color 0.3s ease;
}
a:hover {
color: var(--gold-light);
}
/* Container */
.container {
max-width: var(--container-width);
margin: 0 auto;
padding: 0 2rem;
}
/* ============================================================================
Navigation
============================================================================ */
.nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1.5rem 2rem;
max-width: var(--container-width);
margin: 0 auto;
position: sticky;
top: 0;
z-index: 100;
background: rgba(10, 10, 10, 0.9);
backdrop-filter: blur(10px);
border-bottom: 1px solid var(--border-subtle);
}
.nav-logo {
font-family: var(--font-heading);
font-size: 1.75rem;
font-weight: 700;
color: var(--gold);
letter-spacing: 0.1em;
}
.nav-links {
display: flex;
gap: 2.5rem;
}
.nav-link {
font-family: var(--font-body);
font-size: 1rem;
color: var(--text-secondary);
transition: color 0.3s ease;
}
.nav-link:hover {
color: var(--gold);
}
.nav-github {
font-family: var(--font-body);
font-size: 0.9rem;
color: var(--text-muted);
padding: 0.5rem 1rem;
border: 1px solid var(--border-subtle);
border-radius: 4px;
transition: all 0.3s ease;
}
.nav-github:hover {
color: var(--gold);
border-color: var(--gold);
}
/* ============================================================================
Hero Section
============================================================================ */
.hero {
min-height: 90vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
padding: 4rem 2rem;
background:
radial-gradient(ellipse at top, rgba(212, 175, 55, 0.08) 0%, transparent 50%),
var(--bg-primary);
}
.hero-logo {
margin-bottom: 2rem;
}
.logo-ascii {
font-family: var(--font-code);
font-size: 2rem;
color: var(--gold);
line-height: 1.2;
text-shadow: 0 0 30px var(--gold-glow);
}
.hero-title {
margin-bottom: 1.5rem;
}
.hero-tagline {
font-size: 1.35rem;
color: var(--text-secondary);
max-width: 600px;
margin-bottom: 3rem;
}
.hero-cta {
display: flex;
gap: 1.5rem;
flex-wrap: wrap;
justify-content: center;
}
/* ============================================================================
Buttons
============================================================================ */
.btn {
font-family: var(--font-heading);
font-size: 1rem;
font-weight: 600;
padding: 1rem 2.5rem;
border-radius: 4px;
text-decoration: none;
transition: all 0.3s ease;
display: inline-block;
cursor: pointer;
border: none;
}
.btn-primary {
background: linear-gradient(135deg, var(--gold-dark), var(--gold));
color: #0a0a0a;
}
.btn-primary:hover {
background: linear-gradient(135deg, var(--gold), var(--gold-light));
color: #0a0a0a;
transform: translateY(-2px);
box-shadow: 0 4px 20px var(--gold-glow);
}
.btn-secondary {
background: transparent;
color: var(--gold);
border: 1px solid var(--gold);
}
.btn-secondary:hover {
background: rgba(212, 175, 55, 0.1);
color: var(--gold-light);
}
/* ============================================================================
Code Demo Section
============================================================================ */
.code-demo {
padding: var(--section-padding);
background: var(--bg-secondary);
border-top: 1px solid var(--border-subtle);
border-bottom: 1px solid var(--border-subtle);
}
.code-demo-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 3rem;
align-items: center;
}
.code-block {
background: var(--bg-code);
border: 1px solid var(--border-gold);
border-radius: 8px;
overflow: hidden;
}
.code {
padding: 1.5rem;
margin: 0;
overflow-x: auto;
}
.code code {
font-family: var(--font-code);
font-size: 0.95rem;
color: var(--text-primary);
line-height: 1.6;
}
.code-explanation h3 {
margin-bottom: 1.5rem;
}
.code-explanation ul {
list-style: none;
margin-bottom: 1.5rem;
}
.code-explanation li {
padding: 0.5rem 0;
padding-left: 1.5rem;
position: relative;
color: var(--text-secondary);
}
.code-explanation li::before {
content: "•";
position: absolute;
left: 0;
color: var(--gold);
}
.code-explanation .highlight {
font-size: 1.1rem;
color: var(--gold-light);
font-style: italic;
}
/* ============================================================================
Value Props Section
============================================================================ */
.value-props {
padding: var(--section-padding);
}
.value-props-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
}
.value-prop {
text-align: center;
padding: 2.5rem 2rem;
}
.value-prop-title {
font-size: 0.9rem;
letter-spacing: 0.15em;
margin-bottom: 1rem;
color: var(--gold);
}
.value-prop-desc {
font-size: 1.1rem;
color: var(--text-secondary);
}
/* ============================================================================
Cards
============================================================================ */
.card {
background: var(--bg-glass);
border: 1px solid rgba(212, 175, 55, 0.15);
border-radius: 8px;
backdrop-filter: blur(10px);
transition: all 0.3s ease;
}
.card:hover {
background: var(--bg-glass-hover);
border-color: rgba(212, 175, 55, 0.3);
}
/* ============================================================================
Benchmarks Section
============================================================================ */
.benchmarks {
padding: var(--section-padding);
background: var(--bg-secondary);
border-top: 1px solid var(--border-subtle);
border-bottom: 1px solid var(--border-subtle);
}
.benchmarks h2 {
text-align: center;
margin-bottom: 0.5rem;
}
.section-subtitle {
text-align: center;
color: var(--text-muted);
margin-bottom: 3rem;
}
.benchmarks-chart {
max-width: 600px;
margin: 0 auto;
}
.benchmark-row {
display: grid;
grid-template-columns: 60px 1fr 80px;
gap: 1rem;
align-items: center;
margin-bottom: 1rem;
}
.benchmark-lang {
font-family: var(--font-code);
font-size: 0.9rem;
color: var(--text-secondary);
}
.benchmark-bar-container {
height: 24px;
background: var(--bg-glass);
border-radius: 4px;
overflow: hidden;
}
.benchmark-bar {
height: 100%;
background: linear-gradient(90deg, var(--gold-dark), var(--gold));
border-radius: 4px;
transition: width 1s ease;
}
.benchmark-time {
font-family: var(--font-code);
font-size: 0.9rem;
color: var(--gold-light);
text-align: right;
}
.benchmarks-note {
text-align: center;
margin-top: 2rem;
}
.benchmarks-note a {
font-size: 0.95rem;
color: var(--text-muted);
}
.benchmarks-note a:hover {
color: var(--gold);
}
/* ============================================================================
Testing Section
============================================================================ */
.testing {
padding: var(--section-padding);
}
.testing h2 {
text-align: center;
margin-bottom: 0.5rem;
}
.testing .code-demo-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
margin-top: 2rem;
}
@media (max-width: 768px) {
.testing .code-demo-grid {
grid-template-columns: 1fr;
}
}
/* ============================================================================
Quick Start Section
============================================================================ */
.quick-start {
padding: var(--section-padding);
text-align: center;
}
.quick-start h2 {
margin-bottom: 2rem;
}
.quick-start .code-block {
max-width: 600px;
margin: 0 auto 2rem;
text-align: left;
}
/* ============================================================================
Footer
============================================================================ */
.footer {
padding: 4rem 2rem 2rem;
background: var(--bg-secondary);
border-top: 1px solid var(--border-subtle);
}
.footer-grid {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1fr;
gap: 3rem;
margin-bottom: 3rem;
}
.footer-brand {
max-width: 300px;
}
.footer-logo {
font-family: var(--font-heading);
font-size: 1.5rem;
font-weight: 700;
color: var(--gold);
letter-spacing: 0.1em;
display: block;
margin-bottom: 1rem;
}
.footer-brand p {
font-size: 0.95rem;
color: var(--text-muted);
}
.footer-column h4 {
font-size: 0.8rem;
letter-spacing: 0.1em;
color: var(--text-muted);
margin-bottom: 1rem;
}
.footer-column ul {
list-style: none;
}
.footer-column li {
margin-bottom: 0.5rem;
}
.footer-column a {
font-size: 0.95rem;
color: var(--text-secondary);
}
.footer-column a:hover {
color: var(--gold);
}
.footer-bottom {
text-align: center;
padding-top: 2rem;
border-top: 1px solid var(--border-subtle);
}
.footer-bottom p {
font-size: 0.9rem;
color: var(--text-muted);
}
/* ============================================================================
Documentation Layout
============================================================================ */
.doc-layout {
display: grid;
grid-template-columns: 250px 1fr;
min-height: calc(100vh - 80px);
}
.doc-sidebar {
position: sticky;
top: 80px;
height: calc(100vh - 80px);
overflow-y: auto;
padding: 2rem;
background: var(--bg-secondary);
border-right: 1px solid var(--border-subtle);
}
.doc-sidebar-section {
margin-bottom: 2rem;
}
.doc-sidebar-section h4 {
font-size: 0.75rem;
letter-spacing: 0.15em;
color: var(--text-muted);
margin-bottom: 0.75rem;
}
.doc-sidebar-section ul {
list-style: none;
}
.doc-nav-link {
display: block;
padding: 0.4rem 0;
font-size: 0.95rem;
color: var(--text-secondary);
transition: color 0.2s ease;
}
.doc-nav-link:hover {
color: var(--gold);
}
.doc-nav-link.active {
color: var(--gold-light);
font-weight: 600;
}
.doc-content {
padding: 3rem;
max-width: 800px;
}
.doc-content h1 {
margin-bottom: 2rem;
padding-bottom: 1rem;
border-bottom: 1px solid var(--border-gold);
}
/* ============================================================================
Responsive Design
============================================================================ */
@media (max-width: 1024px) {
.code-demo-grid {
grid-template-columns: 1fr;
}
.value-props-grid {
grid-template-columns: 1fr;
}
.footer-grid {
grid-template-columns: 1fr 1fr;
}
.doc-layout {
grid-template-columns: 1fr;
}
.doc-sidebar {
position: static;
height: auto;
}
}
@media (max-width: 768px) {
.nav {
flex-direction: column;
gap: 1rem;
}
.nav-links {
gap: 1.5rem;
}
.hero {
min-height: 80vh;
padding: 3rem 1.5rem;
}
.logo-ascii {
font-size: 1.5rem;
}
.hero-cta {
flex-direction: column;
width: 100%;
max-width: 300px;
}
.btn {
width: 100%;
text-align: center;
}
.footer-grid {
grid-template-columns: 1fr;
text-align: center;
}
.footer-brand {
max-width: none;
}
}
/* ============================================================================
Syntax Highlighting
============================================================================ */
.hljs-keyword { color: var(--gold); }
.hljs-type { color: #82aaff; }
.hljs-string { color: #c3e88d; }
.hljs-number { color: #f78c6c; }
.hljs-comment { color: var(--text-muted); font-style: italic; }
.hljs-function { color: var(--gold-light); }
.hljs-effect { color: var(--gold-light); font-weight: 600; }
/* ============================================================================
Animations
============================================================================ */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.hero > * {
animation: fadeIn 0.8s ease forwards;
}
.hero > *:nth-child(1) { animation-delay: 0.1s; }
.hero > *:nth-child(2) { animation-delay: 0.2s; }
.hero > *:nth-child(3) { animation-delay: 0.3s; }
.hero > *:nth-child(4) { animation-delay: 0.4s; }

View File

@@ -0,0 +1,227 @@
// Website Components
// Reusable UI components for the Lux website
// ============================================================================
// Navigation
// ============================================================================
fn navLink(label: String, url: String): Html<Msg> =
a([class("nav-link"), href(url)], [text(label)])
fn navigation(): Html<Msg> =
nav([class("nav")], [
a([class("nav-logo"), href("/")], [text("LUX")]),
div([class("nav-links")], [
navLink("Learn", "/learn/"),
navLink("Docs", "/docs/"),
navLink("Playground", "/playground/"),
navLink("Community", "/community/")
]),
a([class("nav-github"), href("https://github.com/luxlang/lux")], [
text("GitHub")
])
])
// ============================================================================
// Hero Section
// ============================================================================
fn hero(): Html<Msg> =
section([class("hero")], [
div([class("hero-logo")], [
pre([class("logo-ascii")], [text("╦ ╦ ╦╦ ╦\n║ ║ ║╔╣\n╩═╝╚═╝╩ ╩")])
]),
h1([class("hero-title")], [
text("Functional Programming"),
br(),
text("with First-Class Effects")
]),
p([class("hero-tagline")], [
text("Effects are explicit. Types are powerful. Performance is native.")
]),
div([class("hero-cta")], [
a([class("btn btn-primary"), href("/learn/getting-started/")], [
text("Get Started")
]),
a([class("btn btn-secondary"), href("/playground/")], [
text("Playground")
])
])
])
// ============================================================================
// Code Demo Section
// ============================================================================
fn codeDemo(): Html<Msg> =
section([class("code-demo")], [
div([class("container")], [
div([class("code-demo-grid")], [
div([class("code-block")], [
pre([class("code")], [
code([], [text(
"fn processOrder(
order: Order
): Receipt
with {Database, Email} =
{
let saved = Database.save(order)
Email.send(
order.customer,
\"Order confirmed!\"
)
Receipt(saved.id)
}"
)])
])
]),
div([class("code-explanation")], [
h3([], [text("The type signature tells you everything")]),
ul([], [
li([], [text("Queries the database")]),
li([], [text("Sends an email")]),
li([], [text("Returns a Receipt")])
]),
p([class("highlight")], [
text("No surprises. No hidden side effects.")
])
])
])
])
])
// ============================================================================
// Value Props Section
// ============================================================================
fn valueProp(title: String, description: String): Html<Msg> =
div([class("value-prop card")], [
h3([class("value-prop-title")], [text(title)]),
p([class("value-prop-desc")], [text(description)])
])
fn valueProps(): Html<Msg> =
section([class("value-props")], [
div([class("container")], [
div([class("value-props-grid")], [
valueProp(
"EFFECTS",
"Side effects are tracked in the type signature. Know exactly what every function does."
),
valueProp(
"TYPES",
"Full type inference with algebraic data types. Catch bugs at compile time."
),
valueProp(
"PERFORMANCE",
"Compiles to native C via gcc. Matches C performance, beats Rust and Zig."
)
])
])
])
// ============================================================================
// Benchmarks Section
// ============================================================================
fn benchmarkBar(lang: String, time: String, width: Int): Html<Msg> =
div([class("benchmark-row")], [
span([class("benchmark-lang")], [text(lang)]),
div([class("benchmark-bar-container")], [
div([class("benchmark-bar"), style("width", toString(width) + "%")], [])
]),
span([class("benchmark-time")], [text(time)])
])
fn benchmarks(): Html<Msg> =
section([class("benchmarks")], [
div([class("container")], [
h2([], [text("Performance")]),
p([class("section-subtitle")], [
text("fib(35) benchmark — verified with hyperfine")
]),
div([class("benchmarks-chart")], [
benchmarkBar("Lux", "28.1ms", 100),
benchmarkBar("C", "29.0ms", 97),
benchmarkBar("Rust", "41.2ms", 68),
benchmarkBar("Zig", "47.0ms", 60)
]),
p([class("benchmarks-note")], [
a([href("/benchmarks/")], [text("See full methodology →")])
])
])
])
// ============================================================================
// Quick Start Section
// ============================================================================
fn quickStart(): Html<Msg> =
section([class("quick-start")], [
div([class("container")], [
h2([], [text("Get Started")]),
div([class("code-block")], [
pre([class("code")], [
code([], [text(
"# Install via Nix
nix run github:luxlang/lux
# Or build from source
git clone https://github.com/luxlang/lux
cd lux && nix develop
cargo build --release
# Start the REPL
./target/release/lux"
)])
])
]),
a([class("btn btn-primary"), href("/learn/getting-started/")], [
text("Full Installation Guide →")
])
])
])
// ============================================================================
// Footer
// ============================================================================
fn footerColumn(title: String, links: List<(String, String)>): Html<Msg> =
div([class("footer-column")], [
h4([], [text(title)]),
ul([], List.map(links, fn((label, url)) =>
li([], [a([href(url)], [text(label)])])
))
])
fn footer(): Html<Msg> =
footer([class("footer")], [
div([class("container")], [
div([class("footer-grid")], [
div([class("footer-brand")], [
span([class("footer-logo")], [text("LUX")]),
p([], [text("Functional programming with first-class effects.")])
]),
footerColumn("Learn", [
("Getting Started", "/learn/getting-started/"),
("Tutorial", "/learn/tutorial/"),
("Examples", "/learn/examples/"),
("Reference", "/docs/")
]),
footerColumn("Community", [
("Discord", "https://discord.gg/lux"),
("GitHub", "https://github.com/luxlang/lux"),
("Contributing", "/community/contributing/"),
("Code of Conduct", "/community/code-of-conduct/")
]),
footerColumn("About", [
("Benchmarks", "/benchmarks/"),
("Blog", "/blog/"),
("License", "https://github.com/luxlang/lux/blob/main/LICENSE")
])
]),
div([class("footer-bottom")], [
p([], [text("© 2026 Lux Language")])
])
])
])

View File

@@ -0,0 +1,239 @@
// Static Site Generator for Lux Website
//
// This module generates the static HTML files for the Lux website.
// Run with: lux website/lux-site/src/generate.lux
import html
import components
import pages
// ============================================================================
// Site Generation
// ============================================================================
fn generateSite(): Unit with {FileSystem, Console} = {
Console.print("Generating Lux website...")
Console.print("")
// Create output directories
FileSystem.mkdir("website/lux-site/dist")
FileSystem.mkdir("website/lux-site/dist/learn")
FileSystem.mkdir("website/lux-site/dist/docs")
FileSystem.mkdir("website/lux-site/dist/static")
// Generate landing page
Console.print(" Generating index.html...")
let index = pages.landingPage()
let indexHtml = html.document(
"Lux - Functional Programming with First-Class Effects",
pages.pageHead("Lux"),
[index]
)
FileSystem.write("website/lux-site/dist/index.html", indexHtml)
// Generate documentation pages
Console.print(" Generating documentation...")
List.forEach(docPages(), fn(page) = {
let pageHtml = html.document(
page.title + " - Lux Documentation",
pages.pageHead(page.title),
[pages.docPageLayout(page)]
)
FileSystem.write("website/lux-site/dist/docs/" + page.slug + ".html", pageHtml)
})
// Copy static assets
Console.print(" Copying static assets...")
FileSystem.copy("website/lux-site/static/style.css", "website/lux-site/dist/static/style.css")
Console.print("")
Console.print("Site generated: website/lux-site/dist/")
}
// Documentation pages to generate
fn docPages(): List<DocPage> = [
{
title: "Effects",
slug: "effects",
content: effectsDoc()
},
{
title: "Types",
slug: "types",
content: typesDoc()
},
{
title: "Syntax",
slug: "syntax",
content: syntaxDoc()
}
]
// ============================================================================
// Documentation Content
// ============================================================================
fn effectsDoc(): Html<Msg> =
div([], [
p([], [text(
"Effects are Lux's defining feature. They make side effects explicit in function signatures, so you always know exactly what a function does."
)]),
h2([], [text("Declaring Effects")]),
pre([class("code")], [
code([], [text(
"fn greet(name: String): String with {Console} = {
Console.print(\"Hello, \" + name)
\"greeted \" + name
}"
)])
]),
p([], [text(
"The `with {Console}` clause tells the compiler this function performs console I/O. Anyone calling this function will see this requirement in the type signature."
)]),
h2([], [text("Multiple Effects")]),
pre([class("code")], [
code([], [text(
"fn processOrder(order: Order): Receipt
with {Database, Email, Logger} = {
Logger.info(\"Processing order: \" + order.id)
let saved = Database.save(order)
Email.send(order.customer, \"Order confirmed!\")
Receipt(saved.id)
}"
)])
]),
p([], [text(
"Functions can declare multiple effects. The caller must provide handlers for all of them."
)]),
h2([], [text("Handling Effects")]),
pre([class("code")], [
code([], [text(
"// Production - real implementations
run processOrder(order) with {
Database -> postgresDb,
Email -> smtpServer,
Logger -> fileLogger
}
// Testing - mock implementations
run processOrder(order) with {
Database -> inMemoryDb,
Email -> collectEmails,
Logger -> noopLogger
}"
)])
]),
p([], [text(
"The same code runs with different effect handlers. This makes testing trivial - no mocking frameworks required."
)])
])
fn typesDoc(): Html<Msg> =
div([], [
p([], [text(
"Lux has a powerful type system with full type inference. You rarely need to write type annotations, but they're there when you want them."
)]),
h2([], [text("Basic Types")]),
pre([class("code")], [
code([], [text(
"let x: Int = 42
let name: String = \"Lux\"
let active: Bool = true
let ratio: Float = 3.14"
)])
]),
h2([], [text("Algebraic Data Types")]),
pre([class("code")], [
code([], [text(
"type Option<T> =
| Some(T)
| None
type Result<T, E> =
| Ok(T)
| Err(E)
type Shape =
| Circle(Float)
| Rectangle(Float, Float)
| Triangle(Float, Float, Float)"
)])
]),
h2([], [text("Pattern Matching")]),
pre([class("code")], [
code([], [text(
"fn area(shape: Shape): Float =
match shape {
Circle(r) => 3.14159 * r * r,
Rectangle(w, h) => w * h,
Triangle(a, b, c) => {
let s = (a + b + c) / 2.0
sqrt(s * (s - a) * (s - b) * (s - c))
}
}"
)])
])
])
fn syntaxDoc(): Html<Msg> =
div([], [
p([], [text(
"Lux syntax is clean and expression-oriented. Everything is an expression that returns a value."
)]),
h2([], [text("Functions")]),
pre([class("code")], [
code([], [text(
"// Named function
fn add(a: Int, b: Int): Int = a + b
// Anonymous function (lambda)
let double = fn(x) => x * 2
// Function with block body
fn greet(name: String): String = {
let greeting = \"Hello, \"
greeting + name + \"!\"
}"
)])
]),
h2([], [text("Let Bindings")]),
pre([class("code")], [
code([], [text(
"let x = 42
let name = \"world\"
let result = add(1, 2)"
)])
]),
h2([], [text("Conditionals")]),
pre([class("code")], [
code([], [text(
"let result = if x > 0 then \"positive\" else \"non-positive\"
// Multi-branch
let grade =
if score >= 90 then \"A\"
else if score >= 80 then \"B\"
else if score >= 70 then \"C\"
else \"F\""
)])
])
])
// ============================================================================
// Main
// ============================================================================
fn main(): Unit with {FileSystem, Console} = {
generateSite()
}
let result = run main() with {}

View File

@@ -0,0 +1,117 @@
// Page Templates
// Full page layouts for the Lux website
import html
import components
// ============================================================================
// Landing Page
// ============================================================================
fn landingPage(): Html<Msg> =
div([class("page")], [
components.navigation(),
main([], [
components.hero(),
components.codeDemo(),
components.valueProps(),
components.benchmarks(),
components.quickStart()
]),
components.footer()
])
// ============================================================================
// Documentation Page Layout
// ============================================================================
type DocPage = {
title: String,
slug: String,
content: Html<Msg>
}
fn docSidebar(currentSlug: String): Html<Msg> =
aside([class("doc-sidebar")], [
div([class("doc-sidebar-section")], [
h4([], [text("LANGUAGE")]),
ul([], [
docNavItem("Syntax", "syntax", currentSlug),
docNavItem("Types", "types", currentSlug),
docNavItem("Effects", "effects", currentSlug),
docNavItem("Pattern Matching", "patterns", currentSlug),
docNavItem("Modules", "modules", currentSlug)
])
]),
div([class("doc-sidebar-section")], [
h4([], [text("STANDARD LIBRARY")]),
ul([], [
docNavItem("List", "list", currentSlug),
docNavItem("String", "string", currentSlug),
docNavItem("Option", "option", currentSlug),
docNavItem("Result", "result", currentSlug)
])
]),
div([class("doc-sidebar-section")], [
h4([], [text("EFFECTS")]),
ul([], [
docNavItem("Console", "console", currentSlug),
docNavItem("Http", "http", currentSlug),
docNavItem("FileSystem", "filesystem", currentSlug)
])
]),
div([class("doc-sidebar-section")], [
h4([], [text("TOOLING")]),
ul([], [
docNavItem("CLI", "cli", currentSlug),
docNavItem("LSP", "lsp", currentSlug),
docNavItem("Editors", "editors", currentSlug)
])
])
])
fn docNavItem(label: String, slug: String, currentSlug: String): Html<Msg> = {
let activeClass = if slug == currentSlug then "active" else ""
li([], [
a([class("doc-nav-link " + activeClass), href("/docs/" + slug + "/")], [
text(label)
])
])
}
fn docPageLayout(page: DocPage): Html<Msg> =
div([class("page doc-page")], [
components.navigation(),
div([class("doc-layout")], [
docSidebar(page.slug),
main([class("doc-content")], [
h1([], [text(page.title)]),
page.content
])
]),
components.footer()
])
// ============================================================================
// Learn Page Layout
// ============================================================================
fn learnPageLayout(title: String, content: Html<Msg>): Html<Msg> =
div([class("page learn-page")], [
components.navigation(),
main([class("learn-content container")], [
h1([], [text(title)]),
content
]),
components.footer()
])
// ============================================================================
// Page Head Elements
// ============================================================================
fn pageHead(title: String): List<Html<Msg>> = [
Element("meta", [Name("description"), Value("Lux - Functional programming with first-class effects")], []),
Element("link", [Href("/static/style.css"), DataAttr("rel", "stylesheet")], []),
Element("link", [Href("https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;600;700&family=Source+Serif+Pro:wght@400;600&family=JetBrains+Mono:wght@400;500&display=swap"), DataAttr("rel", "stylesheet")], [])
]

View File

@@ -0,0 +1,707 @@
/* ============================================================================
Lux Website - Sleek and Noble
Translucent black, white, and gold with strong serif typography
============================================================================ */
/* CSS Variables */
:root {
/* Backgrounds */
--bg-primary: #0a0a0a;
--bg-secondary: #111111;
--bg-glass: rgba(255, 255, 255, 0.03);
--bg-glass-hover: rgba(255, 255, 255, 0.06);
--bg-code: rgba(212, 175, 55, 0.05);
/* Text */
--text-primary: #ffffff;
--text-secondary: rgba(255, 255, 255, 0.7);
--text-muted: rgba(255, 255, 255, 0.5);
/* Gold accents */
--gold: #d4af37;
--gold-light: #f4d03f;
--gold-dark: #b8860b;
--gold-glow: rgba(212, 175, 55, 0.3);
/* Borders */
--border-subtle: rgba(255, 255, 255, 0.1);
--border-gold: rgba(212, 175, 55, 0.3);
/* Typography */
--font-heading: "Playfair Display", Georgia, serif;
--font-body: "Source Serif Pro", Georgia, serif;
--font-code: "JetBrains Mono", "Fira Code", monospace;
/* Spacing */
--container-width: 1200px;
--section-padding: 6rem 2rem;
}
/* Reset */
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html {
scroll-behavior: smooth;
}
body {
background: var(--bg-primary);
color: var(--text-primary);
font-family: var(--font-body);
font-size: 18px;
line-height: 1.7;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Typography */
h1, h2, h3, h4, h5, h6 {
font-family: var(--font-heading);
font-weight: 600;
color: var(--gold-light);
letter-spacing: -0.02em;
line-height: 1.2;
}
h1 { font-size: clamp(2.5rem, 5vw, 4rem); }
h2 { font-size: clamp(2rem, 4vw, 3rem); }
h3 { font-size: clamp(1.5rem, 3vw, 2rem); }
h4 { font-size: 1.25rem; }
p {
margin-bottom: 1rem;
color: var(--text-secondary);
}
a {
color: var(--gold);
text-decoration: none;
transition: color 0.3s ease;
}
a:hover {
color: var(--gold-light);
}
/* Container */
.container {
max-width: var(--container-width);
margin: 0 auto;
padding: 0 2rem;
}
/* ============================================================================
Navigation
============================================================================ */
.nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1.5rem 2rem;
max-width: var(--container-width);
margin: 0 auto;
position: sticky;
top: 0;
z-index: 100;
background: rgba(10, 10, 10, 0.9);
backdrop-filter: blur(10px);
border-bottom: 1px solid var(--border-subtle);
}
.nav-logo {
font-family: var(--font-heading);
font-size: 1.75rem;
font-weight: 700;
color: var(--gold);
letter-spacing: 0.1em;
}
.nav-links {
display: flex;
gap: 2.5rem;
}
.nav-link {
font-family: var(--font-body);
font-size: 1rem;
color: var(--text-secondary);
transition: color 0.3s ease;
}
.nav-link:hover {
color: var(--gold);
}
.nav-github {
font-family: var(--font-body);
font-size: 0.9rem;
color: var(--text-muted);
padding: 0.5rem 1rem;
border: 1px solid var(--border-subtle);
border-radius: 4px;
transition: all 0.3s ease;
}
.nav-github:hover {
color: var(--gold);
border-color: var(--gold);
}
/* ============================================================================
Hero Section
============================================================================ */
.hero {
min-height: 90vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
padding: 4rem 2rem;
background:
radial-gradient(ellipse at top, rgba(212, 175, 55, 0.08) 0%, transparent 50%),
var(--bg-primary);
}
.hero-logo {
margin-bottom: 2rem;
}
.logo-ascii {
font-family: var(--font-code);
font-size: 2rem;
color: var(--gold);
line-height: 1.2;
text-shadow: 0 0 30px var(--gold-glow);
}
.hero-title {
margin-bottom: 1.5rem;
}
.hero-tagline {
font-size: 1.35rem;
color: var(--text-secondary);
max-width: 600px;
margin-bottom: 3rem;
}
.hero-cta {
display: flex;
gap: 1.5rem;
flex-wrap: wrap;
justify-content: center;
}
/* ============================================================================
Buttons
============================================================================ */
.btn {
font-family: var(--font-heading);
font-size: 1rem;
font-weight: 600;
padding: 1rem 2.5rem;
border-radius: 4px;
text-decoration: none;
transition: all 0.3s ease;
display: inline-block;
cursor: pointer;
border: none;
}
.btn-primary {
background: linear-gradient(135deg, var(--gold-dark), var(--gold));
color: #0a0a0a;
}
.btn-primary:hover {
background: linear-gradient(135deg, var(--gold), var(--gold-light));
color: #0a0a0a;
transform: translateY(-2px);
box-shadow: 0 4px 20px var(--gold-glow);
}
.btn-secondary {
background: transparent;
color: var(--gold);
border: 1px solid var(--gold);
}
.btn-secondary:hover {
background: rgba(212, 175, 55, 0.1);
color: var(--gold-light);
}
/* ============================================================================
Code Demo Section
============================================================================ */
.code-demo {
padding: var(--section-padding);
background: var(--bg-secondary);
border-top: 1px solid var(--border-subtle);
border-bottom: 1px solid var(--border-subtle);
}
.code-demo-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 3rem;
align-items: center;
}
.code-block {
background: var(--bg-code);
border: 1px solid var(--border-gold);
border-radius: 8px;
overflow: hidden;
}
.code {
padding: 1.5rem;
margin: 0;
overflow-x: auto;
}
.code code {
font-family: var(--font-code);
font-size: 0.95rem;
color: var(--text-primary);
line-height: 1.6;
}
.code-explanation h3 {
margin-bottom: 1.5rem;
}
.code-explanation ul {
list-style: none;
margin-bottom: 1.5rem;
}
.code-explanation li {
padding: 0.5rem 0;
padding-left: 1.5rem;
position: relative;
color: var(--text-secondary);
}
.code-explanation li::before {
content: "•";
position: absolute;
left: 0;
color: var(--gold);
}
.code-explanation .highlight {
font-size: 1.1rem;
color: var(--gold-light);
font-style: italic;
}
/* ============================================================================
Value Props Section
============================================================================ */
.value-props {
padding: var(--section-padding);
}
.value-props-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
}
.value-prop {
text-align: center;
padding: 2.5rem 2rem;
}
.value-prop-title {
font-size: 0.9rem;
letter-spacing: 0.15em;
margin-bottom: 1rem;
color: var(--gold);
}
.value-prop-desc {
font-size: 1.1rem;
color: var(--text-secondary);
}
/* ============================================================================
Cards
============================================================================ */
.card {
background: var(--bg-glass);
border: 1px solid rgba(212, 175, 55, 0.15);
border-radius: 8px;
backdrop-filter: blur(10px);
transition: all 0.3s ease;
}
.card:hover {
background: var(--bg-glass-hover);
border-color: rgba(212, 175, 55, 0.3);
}
/* ============================================================================
Benchmarks Section
============================================================================ */
.benchmarks {
padding: var(--section-padding);
background: var(--bg-secondary);
border-top: 1px solid var(--border-subtle);
border-bottom: 1px solid var(--border-subtle);
}
.benchmarks h2 {
text-align: center;
margin-bottom: 0.5rem;
}
.section-subtitle {
text-align: center;
color: var(--text-muted);
margin-bottom: 3rem;
}
.benchmarks-chart {
max-width: 600px;
margin: 0 auto;
}
.benchmark-row {
display: grid;
grid-template-columns: 60px 1fr 80px;
gap: 1rem;
align-items: center;
margin-bottom: 1rem;
}
.benchmark-lang {
font-family: var(--font-code);
font-size: 0.9rem;
color: var(--text-secondary);
}
.benchmark-bar-container {
height: 24px;
background: var(--bg-glass);
border-radius: 4px;
overflow: hidden;
}
.benchmark-bar {
height: 100%;
background: linear-gradient(90deg, var(--gold-dark), var(--gold));
border-radius: 4px;
transition: width 1s ease;
}
.benchmark-time {
font-family: var(--font-code);
font-size: 0.9rem;
color: var(--gold-light);
text-align: right;
}
.benchmarks-note {
text-align: center;
margin-top: 2rem;
}
.benchmarks-note a {
font-size: 0.95rem;
color: var(--text-muted);
}
.benchmarks-note a:hover {
color: var(--gold);
}
/* ============================================================================
Testing Section
============================================================================ */
.testing {
padding: var(--section-padding);
}
.testing h2 {
text-align: center;
margin-bottom: 0.5rem;
}
.testing .code-demo-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
margin-top: 2rem;
}
@media (max-width: 768px) {
.testing .code-demo-grid {
grid-template-columns: 1fr;
}
}
/* ============================================================================
Quick Start Section
============================================================================ */
.quick-start {
padding: var(--section-padding);
text-align: center;
}
.quick-start h2 {
margin-bottom: 2rem;
}
.quick-start .code-block {
max-width: 600px;
margin: 0 auto 2rem;
text-align: left;
}
/* ============================================================================
Footer
============================================================================ */
.footer {
padding: 4rem 2rem 2rem;
background: var(--bg-secondary);
border-top: 1px solid var(--border-subtle);
}
.footer-grid {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1fr;
gap: 3rem;
margin-bottom: 3rem;
}
.footer-brand {
max-width: 300px;
}
.footer-logo {
font-family: var(--font-heading);
font-size: 1.5rem;
font-weight: 700;
color: var(--gold);
letter-spacing: 0.1em;
display: block;
margin-bottom: 1rem;
}
.footer-brand p {
font-size: 0.95rem;
color: var(--text-muted);
}
.footer-column h4 {
font-size: 0.8rem;
letter-spacing: 0.1em;
color: var(--text-muted);
margin-bottom: 1rem;
}
.footer-column ul {
list-style: none;
}
.footer-column li {
margin-bottom: 0.5rem;
}
.footer-column a {
font-size: 0.95rem;
color: var(--text-secondary);
}
.footer-column a:hover {
color: var(--gold);
}
.footer-bottom {
text-align: center;
padding-top: 2rem;
border-top: 1px solid var(--border-subtle);
}
.footer-bottom p {
font-size: 0.9rem;
color: var(--text-muted);
}
/* ============================================================================
Documentation Layout
============================================================================ */
.doc-layout {
display: grid;
grid-template-columns: 250px 1fr;
min-height: calc(100vh - 80px);
}
.doc-sidebar {
position: sticky;
top: 80px;
height: calc(100vh - 80px);
overflow-y: auto;
padding: 2rem;
background: var(--bg-secondary);
border-right: 1px solid var(--border-subtle);
}
.doc-sidebar-section {
margin-bottom: 2rem;
}
.doc-sidebar-section h4 {
font-size: 0.75rem;
letter-spacing: 0.15em;
color: var(--text-muted);
margin-bottom: 0.75rem;
}
.doc-sidebar-section ul {
list-style: none;
}
.doc-nav-link {
display: block;
padding: 0.4rem 0;
font-size: 0.95rem;
color: var(--text-secondary);
transition: color 0.2s ease;
}
.doc-nav-link:hover {
color: var(--gold);
}
.doc-nav-link.active {
color: var(--gold-light);
font-weight: 600;
}
.doc-content {
padding: 3rem;
max-width: 800px;
}
.doc-content h1 {
margin-bottom: 2rem;
padding-bottom: 1rem;
border-bottom: 1px solid var(--border-gold);
}
/* ============================================================================
Responsive Design
============================================================================ */
@media (max-width: 1024px) {
.code-demo-grid {
grid-template-columns: 1fr;
}
.value-props-grid {
grid-template-columns: 1fr;
}
.footer-grid {
grid-template-columns: 1fr 1fr;
}
.doc-layout {
grid-template-columns: 1fr;
}
.doc-sidebar {
position: static;
height: auto;
}
}
@media (max-width: 768px) {
.nav {
flex-direction: column;
gap: 1rem;
}
.nav-links {
gap: 1.5rem;
}
.hero {
min-height: 80vh;
padding: 3rem 1.5rem;
}
.logo-ascii {
font-size: 1.5rem;
}
.hero-cta {
flex-direction: column;
width: 100%;
max-width: 300px;
}
.btn {
width: 100%;
text-align: center;
}
.footer-grid {
grid-template-columns: 1fr;
text-align: center;
}
.footer-brand {
max-width: none;
}
}
/* ============================================================================
Syntax Highlighting
============================================================================ */
.hljs-keyword { color: var(--gold); }
.hljs-type { color: #82aaff; }
.hljs-string { color: #c3e88d; }
.hljs-number { color: #f78c6c; }
.hljs-comment { color: var(--text-muted); font-style: italic; }
.hljs-function { color: var(--gold-light); }
.hljs-effect { color: var(--gold-light); font-weight: 600; }
/* ============================================================================
Animations
============================================================================ */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.hero > * {
animation: fadeIn 0.8s ease forwards;
}
.hero > *:nth-child(1) { animation-delay: 0.1s; }
.hero > *:nth-child(2) { animation-delay: 0.2s; }
.hero > *:nth-child(3) { animation-delay: 0.3s; }
.hero > *:nth-child(4) { animation-delay: 0.4s; }

View File

@@ -0,0 +1,25 @@
// Test the HTML module rendering capabilities
// Import from stdlib
// Note: Documenting Lux weakness - no proper module import system visible to user
// Simple HTML test without relying on complex module imports
fn main(): Unit with {Console} = {
Console.print("Testing basic Lux functionality for website generation")
Console.print("")
// Test string concatenation
let tag = "div"
let content = "Hello, World!"
let html = "<" + tag + ">" + content + "</" + tag + ">"
Console.print("Generated HTML: " + html)
Console.print("")
// Test conditional
let isActive = true
let className = if isActive then "active" else "inactive"
Console.print("Class name: " + className)
}
let result = run main() with {}