diff --git a/package-lock.json b/package-lock.json index 742ade6..881f713 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@astrojs/starlight": "^0.37.7", "@fontsource/inter": "^5.2.8", + "@fontsource/space-grotesk": "^5.2.10", "@resvg/resvg-js": "^2.6.2", "@tailwindcss/vite": "^4.2.1", "astro": "^5.6.1", @@ -722,6 +723,15 @@ "url": "https://github.com/sponsors/ayuhito" } }, + "node_modules/@fontsource/space-grotesk": { + "version": "5.2.10", + "resolved": "https://registry.npmjs.org/@fontsource/space-grotesk/-/space-grotesk-5.2.10.tgz", + "integrity": "sha512-XNXEbT74OIITPqw2H6HXwPDp85fy43uxfBwFR5PU+9sLnjuLj12KlhVM9nZVN6q6dlKjkuN8JisW/OBxwxgUew==", + "license": "OFL-1.1", + "funding": { + "url": "https://github.com/sponsors/ayuhito" + } + }, "node_modules/@img/colour": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", diff --git a/package.json b/package.json index ea3d236..39d80a4 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dependencies": { "@astrojs/starlight": "^0.37.7", "@fontsource/inter": "^5.2.8", + "@fontsource/space-grotesk": "^5.2.10", "@resvg/resvg-js": "^2.6.2", "@tailwindcss/vite": "^4.2.1", "astro": "^5.6.1", diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png index 6924392..a7460a6 100644 Binary files a/public/apple-touch-icon.png and b/public/apple-touch-icon.png differ diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png index e2a3076..31aca54 100644 Binary files a/public/favicon-16x16.png and b/public/favicon-16x16.png differ diff --git a/public/favicon-180x180.png b/public/favicon-180x180.png index 6924392..a7460a6 100644 Binary files a/public/favicon-180x180.png and b/public/favicon-180x180.png differ diff --git a/public/favicon-192x192.png b/public/favicon-192x192.png index 977ee4a..b7a3bf7 100644 Binary files a/public/favicon-192x192.png and b/public/favicon-192x192.png differ diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png index dba9fc7..0864de8 100644 Binary files a/public/favicon-32x32.png and b/public/favicon-32x32.png differ diff --git a/public/favicon-512x512.png b/public/favicon-512x512.png index f5fa35c..6103d3a 100644 Binary files a/public/favicon-512x512.png and b/public/favicon-512x512.png differ diff --git a/public/favicon.svg b/public/favicon.svg index 0eb8638..a0b3571 100644 --- a/public/favicon.svg +++ b/public/favicon.svg @@ -1,5 +1,9 @@ - - - ilo + + + ilo diff --git a/scripts/generate-favicons.mjs b/scripts/generate-favicons.mjs new file mode 100644 index 0000000..5a20c1c --- /dev/null +++ b/scripts/generate-favicons.mjs @@ -0,0 +1,100 @@ +// Regenerates the favicon set with the brand wordmark in Space Grotesk. +// Source of truth: ilo Design System handoff (chats/chat2.md) — Space Grotesk +// 700 swapped in to fix the system-ui rendering bug in the previous favicon. + +import satori from 'satori'; +import { Resvg } from '@resvg/resvg-js'; +import { readFileSync, writeFileSync } from 'node:fs'; +import { resolve } from 'node:path'; + +const FONT = readFileSync( + resolve( + process.cwd(), + 'node_modules/@fontsource/space-grotesk/files/space-grotesk-latin-700-normal.woff', + ), +); + +// Tile dimensions are normalised to 32 — satori scales linearly via the +// outer width/height. Inside the tile we keep the same proportions as the +// hand-authored 32x32 SVG: 8/32 corner radius, wordmark optically centred. +function tile(size) { + const fontSize = size * 0.5; // 16 at 32px — matches prior hand-tuned value + const radius = size * 0.25; // 8 at 32px + return { + type: 'div', + props: { + style: { + width: `${size}px`, + height: `${size}px`, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + background: '#0a0a10', + borderRadius: `${radius}px`, + fontFamily: 'Space Grotesk', + }, + children: [ + { + type: 'div', + props: { + style: { + fontSize: `${fontSize}px`, + fontWeight: 700, + color: '#e09422', + letterSpacing: '-0.04em', + lineHeight: 1, + // Optical baseline tweak — Space Grotesk hangs slightly low. + marginTop: `${-size * 0.04}px`, + }, + children: 'ilo', + }, + }, + ], + }, + }; +} + +async function renderPng(size) { + const svg = await satori(tile(size), { + width: size, + height: size, + fonts: [ + { name: 'Space Grotesk', data: FONT, weight: 700, style: 'normal' }, + ], + }); + const resvg = new Resvg(svg, { fitTo: { mode: 'width', value: size } }); + return resvg.render().asPng(); +} + +// Hand-authored SVG favicon — embedded @import so modern browsers render +// in Space Grotesk directly. The PNGs below cover everything else. +const SVG = ` + + + ilo + +`; + +const PUB = resolve(process.cwd(), 'public'); +writeFileSync(resolve(PUB, 'favicon.svg'), SVG); + +const sizes = [ + ['favicon-16x16.png', 16], + ['favicon-32x32.png', 32], + ['favicon-180x180.png', 180], + ['favicon-192x192.png', 192], + ['favicon-512x512.png', 512], + ['apple-touch-icon.png', 180], +]; + +for (const [name, size] of sizes) { + const png = await renderPng(size); + writeFileSync(resolve(PUB, name), png); + console.log(`wrote public/${name} (${size}x${size})`); +} + +console.log('wrote public/favicon.svg'); diff --git a/src/pages/index.astro b/src/pages/index.astro index 3d46fde..5bded9f 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -42,38 +42,71 @@ import { SITE_URL, softwareApplicationSchema, websiteSchema } from '../lib/schem
-
-
-
programming language for AI agents
-

- Designed for machines.
- 0.33× the tokens. 0.22× the characters. Type-verified before execution. -

-
-
- - - -
-
- $ - curl -fsSL https://ilo-lang.ai/install.sh | sh - - -
+ +
-
- - Get Started - - - - View on GitHub - + +
+
+
+ Python · 30 tokens + 93 chars +
+
def tot(p: float, q: float, r: float) -> float:
+    s = p * q
+    t = s * r
+    return s + t
+
+
+
+ ilo · 10 tokens + 38 chars +
+
-- subtotal + tax
+tot p:n q:n r:n>n
+  s=*p q
+  t=*s r
+  +s t
+
+
+ 0.33× + the tokens · 0.22× the characters · same semantics +
@@ -165,29 +198,6 @@ import { SITE_URL, softwareApplicationSchema, websiteSchema } from '../lib/schem - -
-
-
-
67%
-
fewer tokens
-
vs Python
-
-
-
-
78%
-
fewer characters
-
vs Python
-
-
-
-
-
type-verified
-
before execution
-
-
-
-
@@ -270,38 +280,45 @@ import { SITE_URL, softwareApplicationSchema, websiteSchema } from '../lib/schem
-

What ilo Optimizes For

-

Six principles, all measured against one metric: total tokens from intent to working code.

+
+
The Six Principles
+

Every design decision is evaluated against one number.

+

+ If a feature reduces total tokens from intent to working code, it's in. + If it increases that number, it's out. No exceptions for elegance, + readability, or convention. +

+
01

Token-Conservative

-

The north star. Every choice evaluated against total token cost across the full loop—not just short syntax, but retries, errors, and context loading.

+

Every choice evaluated against total token cost — generation, errors, retries, context loading. Prefix notation. Single-char names. Guards instead of nested if/else.

02

Constrained

-

Small vocabulary. Closed world. Few ways to do things. Fewer valid next-tokens means fewer wrong choices means fewer retries.

+

Small vocabulary, closed world. Every callable function is known ahead of time. The agent cannot hallucinate an API. Fewer valid next-tokens means fewer retries.

03

Self-Contained

-

Each unit carries its own context: deps, types, rules. The agent never needs to hunt for definitions elsewhere.

+

Each unit carries its own context: deps, types, rules. The less context required per step, the more of the window is available for the actual task.

04

Language-Agnostic

-

Minimise dependency on English or any natural language. Sigils and short names over prose keywords.

+

Minimise dependency on English. Single-char sigils outperform keywords. Agents learn the full vocabulary from spec + examples with 10/10 accuracy.

05

Graph-Reducible

-

When analysing code, load only the relevant subgraph. As programs grow, the savings compound.

+

The dependency graph is explicit and queryable. ilo graph extracts call graphs, types, callers as JSON. Modify one function, load 6–10% of the code.

06
-

Structured Compiler-to-Agent Surface

-

Every path from the compiler to an agent is machine-readable by default. JSON out, zero screen-scraping.

+

Structured Surface

+

Every CLI subcommand has --json. Every diagnostic carries an error code, source span, and FixSafety. Zero screen-scraping, zero retry cycles from format ambiguity.

@@ -311,6 +328,47 @@ import { SITE_URL, softwareApplicationSchema, websiteSchema } from '../lib/schem
+ +
+
+
+
Honest benchmarks
+

Three engines. None of them is the fastest. That's not the metric.

+

+ ilo runs on a bytecode VM, a Cranelift JIT, and a Cranelift AOT compiler. + They sit in the middle of the runtime field—faster than Python or Ruby, slower than V8 or Go. + The number that matters is the one above the keyboard, not the one below it. +

+
+ +
+
+ numeric · sum 1..1000 · median ns/call · 10000 iterations + Darwin arm64 +
+
+
Rustnative
329ns
+
LuaJITJIT
442ns
+
Node/V8JIT
451ns
+
KotlinJVM
528ns
+
Gonative
665ns
+
PyPy 3JIT
1.5µs
+
ilo JITCranelift
4.2µs
+
ilo AOTCranelift
5.3µs
+
PHPinterp
6.7µs
+
ilo VMbytecode
14.7µs
+
Python 3interp
29.5µs
+
+
+ 7 more benchmarks in the full table—string, record, mixed, foreach, recurse… + All benchmarks + + +
+
+
+
+

Make your agents more efficient.

@@ -371,6 +429,10 @@ import { SITE_URL, softwareApplicationSchema, websiteSchema } from '../lib/schem --accent: #f59e0b; --accent-bright: #fbbf24; --accent-dim: rgba(245, 158, 11, 0.08); + /* Positive-delta semantic — "fewer tokens" / "+x faster" only. + Not a second brand colour. See src/styles/global.css. */ + --positive: #c8f04a; + --positive-dim: rgba(200, 240, 74, 0.10); --font-display: 'Bricolage Grotesque', system-ui, sans-serif; --font-body: 'Bricolage Grotesque', system-ui, sans-serif; --font-mono: 'JetBrains Mono', ui-monospace, monospace; @@ -696,6 +758,225 @@ import { SITE_URL, softwareApplicationSchema, websiteSchema } from '../lib/schem color: var(--accent); } + /* ===== HERO (two-column) ===== */ + .hero-grid-2col { + display: grid; + grid-template-columns: 1.05fr 1fr; + gap: 56px; + align-items: center; + position: relative; + z-index: 1; + } + + .hero-left { + display: flex; + flex-direction: column; + gap: 20px; + text-align: left; + } + + .hero-kicker { + font-family: var(--font-mono); + font-size: 0.72rem; + font-weight: 500; + color: var(--accent); + text-transform: uppercase; + letter-spacing: 0.1em; + } + + .hero-headline { + font-family: var(--font-display); + font-size: clamp(2.2rem, 4.6vw, 3.6rem); + font-weight: 700; + letter-spacing: -0.035em; + line-height: 1.05; + color: var(--text); + } + + .hero-headline-accent { + color: var(--accent); + } + + .hero-sub { + font-size: 1.05rem; + line-height: 1.6; + color: var(--text-muted); + max-width: 560px; + } + + .hero-sub-strong { + font-style: normal; + color: var(--text); + font-weight: 500; + } + + .hero-install { + display: flex; + align-items: stretch; + background: var(--bg-card); + border: 1px solid var(--border); + border-radius: 8px; + max-width: 540px; + box-shadow: + 0 0 0 1px rgba(224, 148, 34, 0.08), + 0 8px 32px rgba(224, 148, 34, 0.06); + overflow: hidden; + font-family: var(--font-mono); + font-size: 0.88rem; + margin-top: 6px; + } + + .hero-install-prompt { + padding: 14px 0 14px 18px; + color: var(--text-dim); + user-select: none; + } + + .hero-install-cmd { + flex: 1; + padding: 14px 14px; + color: var(--text); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .hero-install-copy { + display: flex; + align-items: center; + gap: 6px; + background: transparent; + border: none; + border-left: 1px solid var(--border); + color: var(--accent); + padding: 0 18px; + font-family: var(--font-body); + font-size: 0.82rem; + font-weight: 500; + cursor: pointer; + transition: color 0.15s; + } + + .hero-install-copy:hover { + color: var(--accent-bright); + } + + .hero-install-copy.is-copied { + color: var(--positive); + } + + .hero-license { + display: inline-flex; + align-items: center; + gap: 6px; + font-size: 0.85rem; + color: var(--text-dim); + transition: color 0.15s; + } + + .hero-license:hover { + color: var(--text-muted); + } + + .hero-right { + display: flex; + flex-direction: column; + gap: 14px; + } + + .hero-frame { + background: var(--bg-raised); + border: 1px solid var(--border); + border-radius: 10px; + overflow: hidden; + } + + .hero-frame--py { + opacity: 0.82; + } + + .hero-frame--ilo { + border-color: rgba(224, 148, 34, 0.32); + box-shadow: 0 0 32px rgba(224, 148, 34, 0.05); + } + + .hero-frame-head { + display: flex; + justify-content: space-between; + padding: 10px 16px; + font-family: var(--font-mono); + font-size: 0.72rem; + color: var(--text-dim); + border-bottom: 1px solid var(--border); + } + + .hero-frame-head--accent { + color: var(--accent); + } + + .hero-frame-body { + padding: 16px 18px; + font-family: var(--font-mono); + font-size: 0.82rem; + line-height: 1.55; + color: var(--text); + overflow-x: auto; + } + + .hero-frame-body code { + font-family: inherit; + white-space: pre; + } + + .hero-ratio { + display: flex; + align-items: baseline; + gap: 14px; + padding-left: 4px; + } + + .hero-ratio-num { + font-family: var(--font-display); + font-weight: 700; + font-size: 2rem; + color: var(--accent); + letter-spacing: -0.02em; + line-height: 1; + } + + .hero-ratio-cap { + color: var(--text-muted); + font-size: 0.85rem; + } + + /* Buttons: extra ghost variant for "Read the manifesto" */ + .btn-ghost { + background: transparent; + color: var(--text); + border: 1px solid var(--border); + padding: 12px 18px; + border-radius: 8px; + font-family: var(--font-body); + font-weight: 500; + font-size: 0.9rem; + transition: border-color 0.15s, color 0.15s; + } + + .btn-ghost:hover { + border-color: rgba(255, 255, 255, 0.18); + color: var(--text); + } + + @media (max-width: 900px) { + .hero-grid-2col { + grid-template-columns: 1fr; + gap: 36px; + } + .hero-right { + order: 2; + } + } + /* ===== STATS ===== */ .stats { padding: 5rem 0; @@ -725,6 +1006,10 @@ import { SITE_URL, softwareApplicationSchema, websiteSchema } from '../lib/schem line-height: 1; } + .stat--positive .stat-number { + color: var(--positive); + } + .stat-label { font-size: 1rem; font-weight: 500; @@ -836,8 +1121,8 @@ import { SITE_URL, softwareApplicationSchema, websiteSchema } from '../lib/schem } .code-badge--accent { - color: var(--accent); - background: var(--accent-dim); + color: var(--positive); + background: var(--positive-dim); } .code-body { @@ -1331,6 +1616,32 @@ import { SITE_URL, softwareApplicationSchema, websiteSchema } from '../lib/schem /* ===== SIX PRINCIPLES ===== */ .manifesto-section { padding: 6rem 0; + border-top: 1px solid var(--border); + } + + .manifesto-head { + max-width: 760px; + margin: 0 auto 3rem; + text-align: center; + } + + .manifesto-kicker { + font-family: var(--font-mono); + font-size: 0.7rem; + font-weight: 500; + color: var(--accent); + text-transform: uppercase; + letter-spacing: 0.08em; + margin-bottom: 14px; + } + + .manifesto-card code { + font-family: var(--font-mono); + font-size: 0.82em; + background: rgba(255, 255, 255, 0.06); + padding: 0.05em 0.35em; + border-radius: 4px; + color: var(--text); } .manifesto-grid { @@ -1460,6 +1771,142 @@ import { SITE_URL, softwareApplicationSchema, websiteSchema } from '../lib/schem color: var(--accent); } + /* ===== HONEST BENCHMARKS ===== */ + .benchmarks { + padding: 6rem 0; + border-top: 1px solid var(--border); + } + + .bench-head { + max-width: 760px; + margin: 0 auto 3rem; + text-align: center; + } + + .bench-kicker { + font-family: var(--font-mono); + font-size: 0.7rem; + font-weight: 500; + color: var(--accent); + text-transform: uppercase; + letter-spacing: 0.08em; + margin-bottom: 14px; + } + + .bench-card { + background: var(--bg-card); + border: 1px solid var(--border); + border-radius: 12px; + overflow: hidden; + } + + .bench-meta { + display: flex; + justify-content: space-between; + align-items: baseline; + flex-wrap: wrap; + gap: 8px; + padding: 14px 24px; + border-bottom: 1px solid var(--border); + font-family: var(--font-mono); + font-size: 0.72rem; + color: var(--text-dim); + } + + .bench-rows { + padding: 18px 24px; + display: flex; + flex-direction: column; + gap: 10px; + } + + .bench-row { + display: grid; + grid-template-columns: 110px 78px 1fr 80px; + align-items: center; + gap: 14px; + } + + .bench-lang { + font-family: var(--font-display); + font-size: 0.92rem; + color: var(--text); + font-weight: 400; + } + + .bench-row--ilo .bench-lang { + color: var(--accent); + font-weight: 600; + } + + .bench-tag { + font-family: var(--font-mono); + font-size: 0.68rem; + color: var(--text-dim); + } + + .bench-bar { + height: 6px; + background: rgba(255, 255, 255, 0.04); + border-radius: 3px; + overflow: hidden; + } + + .bench-fill { + height: 100%; + background: var(--text-dim); + border-radius: 3px; + } + + .bench-fill--ilo { + background: var(--accent); + } + + .bench-ns { + font-family: var(--font-mono); + font-size: 0.82rem; + color: var(--text-muted); + text-align: right; + } + + .bench-row--ilo .bench-ns { + color: var(--accent); + } + + .bench-foot { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 12px; + padding: 14px 24px; + border-top: 1px solid var(--border); + font-size: 0.85rem; + color: var(--text-muted); + } + + .bench-link { + display: inline-flex; + align-items: center; + gap: 6px; + color: var(--accent); + font-weight: 500; + transition: color 0.2s; + } + + .bench-link:hover { + color: var(--accent-bright); + } + + @media (max-width: 640px) { + .bench-row { + grid-template-columns: 90px 1fr 70px; + } + .bench-tag { + display: none; + } + } + /* ===== FINAL CTA ===== */ .final-cta { padding: 6rem 0; @@ -1672,47 +2119,26 @@ import { SITE_URL, softwareApplicationSchema, websiteSchema } from '../lib/schem