Skip to content
Open
270 changes: 270 additions & 0 deletions doc/research/mobbin-ui-patterns.md

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions src/components/global/SiteFooter.astro
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ try {
<div class="footer-cta-inner">
<div class="footer-cta-text">
<p class="footer-cta-title">Less noise. Better context.</p>
<p class="footer-cta-sub">Install rtk and cut token costs by <strong>60-90%</strong> with zero config changes.</p>
<p class="footer-cta-sub">Install rtk and reduce CLI output noise by <strong>60-90%</strong> — leading to cost savings with zero config changes.</p>
</div>
<div class="footer-cta-actions">
<a href="/#install" class="btn btn-primary btn-sm">Install rtk</a>
Expand All @@ -50,7 +50,7 @@ try {
<img src="/brand/logo.png" alt="rtk logo" width="22" height="22" style="border-radius:var(--radius-xs);">
<span>rtk</span>
</a>
<p class="footer-tagline">Rust Token Killer — reduce AI coding token usage by 60-90% with zero config.</p>
<p class="footer-tagline">Rust Token Killer — reduce CLI output noise by 60-90% before it reaches the AI context window.</p>
<div class="footer-version">
<span class="footer-version-badge">
<IconStar size={12} filled />
Expand Down Expand Up @@ -78,7 +78,7 @@ try {
<li><a href="/#install">Homebrew</a></li>
<li><a href="/#install">One-liner (curl)</a></li>
<li><a href="/#install">Via Cargo</a></li>
<li><a href="https://github.com/rtk-ai/rtk/releases" target="_blank" rel="noopener">Pre-built Binaries</a></li>
<li><a href="https://github.com/rtk-ai/rtk/releases/latest" target="_blank" rel="noopener">Pre-built Binaries</a></li>
<li><a href="/docs/">Getting Started</a></li>
<li><a href="/savings/">Token Savings</a></li>
</ul>
Expand All @@ -91,9 +91,9 @@ try {
<li><a href="/docs/">Guide</a></li>
<li><a href="/docs/getting-started/installation/">Installation</a></li>
<li><a href="/docs/getting-started/quick-start/">Quick Start</a></li>
<li><a href="/docs/what-rtk-covers/">What RTK Optimizes</a></li>
<li><a href="/docs/troubleshooting/">Troubleshooting</a></li>
<li><a href="https://github.com/rtk-ai/rtk/blob/master/CHANGELOG.md" target="_blank" rel="noopener">Changelog</a></li>
<li><a href="/docs/resources/what-rtk-covers/">What RTK Optimizes</a></li>
<li><a href="/docs/resources/troubleshooting/">Troubleshooting</a></li>
<li><a href="/changelog/">Changelog</a></li>
</ul>
</div>

Expand All @@ -116,7 +116,7 @@ try {
</ul>
<h3 class="footer-col-title" style="margin-top:24px;">Legal</h3>
<ul class="footer-col-links">
<li><a href="https://github.com/rtk-ai/rtk/blob/master/LICENSE" target="_blank" rel="noopener">MIT License</a></li>
<li><a href="https://github.com/rtk-ai/rtk/blob/master/LICENSE" target="_blank" rel="noopener">Apache 2.0 License</a></li>
<li><a href="https://github.com/rtk-ai/rtk/blob/master/CONTRIBUTING.md" target="_blank" rel="noopener">Contributing</a></li>
</ul>
</div>
Expand All @@ -130,7 +130,7 @@ try {
<li><a href="https://discord.gg/RySmvNF5kF" target="_blank" rel="noopener">Discord Server</a></li>
<li><a href="https://github.com/rtk-ai/rtk/issues" target="_blank" rel="noopener">Report Issues</a></li>
<li><a href="https://github.com/rtk-ai/rtk/discussions" target="_blank" rel="noopener">Discussions</a></li>
<li><a href="https://twitter.com/intent/tweet?url=https://www.rtk-ai.app&text=Cut+Claude+Code+token+costs+by+60-90%25+with+RTK" target="_blank" rel="noopener">Share on X</a></li>
<li><a href="https://twitter.com/intent/tweet?url=https://www.rtk-ai.app&text=RTK+reduces+CLI+output+noise+by+60-90%25+before+it+hits+the+AI+context+window" target="_blank" rel="noopener">Share on X</a></li>
<li><a href="https://ko-fi.com/patrickszymkowiak" target="_blank" rel="noopener">Support the project</a></li>
</ul>
</div>
Expand All @@ -142,7 +142,7 @@ try {
<div class="footer-bottom">
<div class="footer-bottom-inner">
<p class="footer-bottom-left">
<span class="footer-copyright">MIT License</span>
<span class="footer-copyright">Apache 2.0</span>
<span class="footer-bottom-sep">&middot;</span>
Built by RTK Team
<span class="footer-bottom-sep">&middot;</span>
Expand Down
90 changes: 90 additions & 0 deletions src/components/landing/DemoSlideshow.astro
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const { lang } = Astro.props
<button class="slide-tab" data-slide="1">git diff</button>
<button class="slide-tab" data-slide="2">git status</button>
<button class="slide-tab" data-slide="3">find</button>
<button class="slide-tab" data-slide="4">vitest run</button>
<button class="slide-tab" data-slide="5">ls -la</button>
</div>

<div class="slideshow-viewport">
Expand Down Expand Up @@ -207,6 +209,92 @@ src/parser/ error.rs formatter.rs</code></pre>
</div>
</div>
</div>
<!-- Slide 4: vitest run -->
<div class="slide" data-index="4">
<div class="demo-grid">
<div class="demo-card">
<div class="demo-card-header">
<span class="demo-dot red"></span>
<span class="demo-label">vitest run</span>
<span class="demo-tokens">~3,400 tokens</span>
</div>
<pre><code> ✓ src/utils/format.test.ts (3)
✓ src/utils/parse.test.ts (8)
✓ src/api/users.test.ts (12)
✓ src/api/orders.test.ts (9)
✗ src/components/Cart.test.tsx (2)
× CartTotal renders with discounts
AssertionError: expected 42.00 to equal 37.80
× CartTotal handles empty cart
TypeError: Cannot read prop 'total' of undefined
✓ src/hooks/useAuth.test.ts (5)
✓ src/hooks/useCart.test.ts (7)
✓ src/pages/Checkout.test.tsx (4)
✓ src/pages/Home.test.tsx (6)

Test Files 1 failed | 7 passed (8)
Tests 2 failed | 54 passed (56)
Start at 14:22:41
Duration 4.2s (transform 210ms, setup 95ms)</code></pre>
</div>
<div class="demo-card demo-after">
<div class="demo-card-header">
<span class="demo-dot green"></span>
<span class="demo-label">rtk vitest run</span>
<span class="demo-tokens">~51 tokens</span>
<span class="demo-savings">-98%</span>
</div>
<pre><code>&#x2717; 2 failures in 1 file

src/components/Cart.test.tsx
&#x2717; CartTotal renders with discounts
expected 42.00 to equal 37.80
&#x2717; CartTotal handles empty cart
Cannot read prop 'total' of undefined

2 failed | 54 passed (4.2s)</code></pre>
</div>
</div>
</div>

<!-- Slide 5: ls -la -->
<div class="slide" data-index="5">
<div class="demo-grid">
<div class="demo-card">
<div class="demo-card-header">
<span class="demo-dot red"></span>
<span class="demo-label">ls -la</span>
<span class="demo-tokens">~210 tokens</span>
</div>
<pre><code>total 64
drwxr-xr-x 14 user staff 448B 3 Sep 09:12 .
drwxr-xr-x 24 user staff 768B 1 Sep 15:30 ..
-rw-r--r-- 1 user staff 1.2K 30 Aug 11:45 .gitignore
-rw-r--r-- 1 user staff 2.3K 2 Sep 16:22 Cargo.toml
drwxr-xr-x 3 user staff 96B 28 Aug 09:10 docs
drwxr-xr-x 2 user staff 64B 1 Sep 11:25 examples
-rw-r--r-- 1 user staff 18K 3 Sep 09:12 index.html
-rw-r--r-- 1 user staff 892B 29 Aug 14:33 install.sh
-rw-r--r-- 1 user staff 1.1K 28 Aug 09:08 LICENSE
-rw-r--r-- 1 user staff 3.4K 2 Sep 09:15 README.md
drwxr-xr-x 18 user staff 576B 3 Sep 09:11 src
drwxr-xr-x 4 user staff 128B 1 Sep 16:47 tests</code></pre>
</div>
<div class="demo-card demo-after">
<div class="demo-card-header">
<span class="demo-dot green"></span>
<span class="demo-label">rtk ls -la</span>
<span class="demo-tokens">~42 tokens</span>
<span class="demo-savings">-80%</span>
</div>
<pre><code>src/ (18 files) tests/ (4 files)
docs/ (3 files) examples/ (2 files)

Cargo.toml README.md install.sh
index.html LICENSE .gitignore</code></pre>
</div>
</div>
</div>
</div>

<div class="slideshow-controls">
Expand All @@ -218,6 +306,8 @@ src/parser/ error.rs formatter.rs</code></pre>
<span class="dot" data-slide="1"></span>
<span class="dot" data-slide="2"></span>
<span class="dot" data-slide="3"></span>
<span class="dot" data-slide="4"></span>
<span class="dot" data-slide="5"></span>
</div>
<button class="slide-arrow slide-next" aria-label={t('aria.next', lang)}>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="9 18 15 12 9 6"/></svg>
Expand Down
61 changes: 53 additions & 8 deletions src/components/landing/Hero.astro
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ interface Props {
}
const { lang } = Astro.props

let stars = 31000
let stars = 47000

try {
const headers: Record<string, string> = { 'User-Agent': 'rtk-landing' }
Expand All @@ -22,6 +22,9 @@ try {
} catch {}

const starsLabel = stars >= 1000 ? `${(stars / 1000).toFixed(1)}k` : String(stars)
const countupStars = stars >= 1000 ? (stars / 1000).toFixed(1) : String(stars)
const starsDecimals = stars >= 1000 ? '1' : '0'
const starsSuffix = stars >= 1000 ? 'k' : ''
---
<section class="hero">
<div class="hero-inner">
Expand All @@ -40,26 +43,25 @@ const starsLabel = stars >= 1000 ? `${(stars / 1000).toFixed(1)}k` : String(star

<div class="hero-stats">
<div class="stat">
<span class="stat-value">89%</span>
<span class="stat-value" data-countup="89" data-suffix="%">89%</span>
<span class="stat-label">avg noise removed</span>
</div>
<div class="stat-sep"></div>
<div class="stat">
<span class="stat-value">2,900+</span>
<span class="stat-value" data-countup="2900" data-suffix="+" data-comma>2,900+</span>
<span class="stat-label">commands measured</span>
</div>
<div class="stat-sep"></div>
<div class="stat">
<span class="stat-value" id="github-stars-count">{starsLabel}</span>
<span class="stat-value" id="github-stars-count" data-countup={countupStars} data-suffix={starsSuffix} data-decimal={starsDecimals}>{starsLabel}</span>
<span class="stat-label">GitHub stars</span>
</div>
</div>

<div class="hero-cta">
<a href="#install" class="btn btn-primary">{t('hero.cta_install', lang)}</a>
<a href="https://github.com/rtk-ai/rtk" class="btn btn-ghost" target="_blank" rel="noopener">
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>
<span>{t('hero.cta_star', lang)}</span>
<a href="/docs/" class="btn btn-ghost">
{t('ui.nav_docs', lang)}
</a>
</div>
</div>
Expand Down Expand Up @@ -123,6 +125,46 @@ const starsLabel = stars >= 1000 ? `${(stars / 1000).toFixed(1)}k` : String(star
</div>
</section>

<script>
const els = document.querySelectorAll<HTMLElement>('[data-countup]')

const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (!entry.isIntersecting) return
observer.unobserve(entry.target)
const el = entry.target as HTMLElement
const target = parseFloat(el.dataset.countup ?? '0')
const suffix = el.dataset.suffix ?? ''
const comma = 'comma' in el.dataset
const decimals = parseInt(el.dataset.decimal ?? '0')
const duration = 1400
const t0 = performance.now()
Comment on lines +128 to +142

const tick = (now: number) => {
const p = Math.min((now - t0) / duration, 1)
const eased = 1 - Math.pow(1 - p, 3)
const val = eased * target
let text: string
if (decimals > 0) {
text = val.toFixed(decimals)
} else if (comma) {
text = Math.round(val).toLocaleString()
} else {
text = String(Math.round(val))
}
el.textContent = text + suffix
if (p < 1) requestAnimationFrame(tick)
}
requestAnimationFrame(tick)
})
},
{ threshold: 0.3 }
)

els.forEach((el) => observer.observe(el))
</script>

<style>
.hero {
max-width: var(--max-w);
Expand Down Expand Up @@ -160,7 +202,10 @@ const starsLabel = stars >= 1000 ? `${(stars / 1000).toFixed(1)}k` : String(star
}

.hero-accent {
color: var(--accent);
background: linear-gradient(135deg, var(--accent) 0%, var(--cyan) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}

.hero-sub {
Expand Down
8 changes: 4 additions & 4 deletions src/components/landing/Install.astro
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ const personas = [
{
id: 'claude-code',
tabKey: 'install.tab.cc',
initCmd: 'rtk init --claude-code',
initCmd: 'rtk init --global',
noteKey: 'install.note.cc',
},
{
id: 'cursor',
tabKey: 'install.tab.cursor',
initCmd: 'rtk init --cursor',
initCmd: 'rtk init --global --cursor',
noteKey: 'install.note.cursor',
},
{
Expand Down Expand Up @@ -85,7 +85,7 @@ const personas = [
<h3>{t('install.binaries', lang)}</h3>
<p>{t('install.binaries_desc', lang)}</p>
<div class="code-block">
<a href="https://github.com/rtk-ai/rtk/releases" target="_blank" rel="noopener" class="releases-link">{t('install.releases', lang)}</a>
<a href="https://github.com/rtk-ai/rtk/releases/latest" target="_blank" rel="noopener" class="releases-link">{t('install.releases', lang)}</a>
</div>
</div>
</div>
Expand Down Expand Up @@ -118,7 +118,7 @@ const personas = [
</div>
<div class="install-step">
<span class="install-step-num">2</span>
<code id="install-step-2-cmd">rtk init --claude-code</code>
<code id="install-step-2-cmd">rtk init --global</code>
</div>
<div class="install-step">
<span class="install-step-num">3</span>
Expand Down
10 changes: 5 additions & 5 deletions src/components/pages/LandingPage.astro
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const schemaOrg = {
'@id': 'https://www.rtk-ai.app/#software',
name: 'RTK — Rust Token Killer',
description:
'RTK compresses CLI command outputs before they reach the AI context window, reducing token usage by 60-90% with zero config changes. Open source, MIT licensed, written in Rust.',
'RTK compresses CLI command outputs before they reach the AI context window, reducing token output by 60-90% with zero config changes. Open source, Apache 2.0 licensed, written in Rust.',
url: 'https://www.rtk-ai.app',
applicationCategory: 'DeveloperApplication',
operatingSystem: 'macOS, Linux, Windows',
Expand All @@ -67,7 +67,7 @@ const schemaOrg = {
priceCurrency: 'USD',
availability: 'https://schema.org/InStock',
},
license: 'https://opensource.org/licenses/MIT',
license: 'https://www.apache.org/licenses/LICENSE-2.0',
downloadUrl: 'https://github.com/rtk-ai/rtk',
author: { '@id': 'https://www.rtk-ai.app/#organization' },
featureList: [
Expand Down Expand Up @@ -104,7 +104,7 @@ const schemaOrg = {
'@type': 'HowToStep',
position: 2,
name: 'Activate the auto-rewrite hook',
text: 'Run rtk init --claude-code for Claude Code (installs a PreToolUse hook) or rtk init --global for other AI tools (installs a shell hook). Both transparently rewrite commands to rtk equivalents, compressing output before it reaches the context window.',
text: 'Run rtk init --global for Claude Code and most AI tools (installs a PreToolUse hook that transparently rewrites commands to rtk equivalents). For Cursor, use rtk init --global --cursor. Your existing workflow stays unchanged; RTK intercepts commands and compresses output before it reaches the context window.',
url: 'https://www.rtk-ai.app/#install',
},
{
Expand All @@ -121,7 +121,7 @@ const schemaOrg = {
'@id': 'https://www.rtk-ai.app/#webpage',
url: 'https://www.rtk-ai.app/',
name: 'RTK — Rust Token Killer',
description: 'RTK reduces AI coding token usage by 60-90% — measured across 2,900+ real commands. 89% avg noise removed, 3x longer sessions, zero config. Free, open source, MIT, written in Rust.',
description: 'RTK reduces CLI output noise by 60-90% before it reaches the AI context window — measured across 2,900+ real commands. 89% avg noise removed, 3x longer sessions, zero config. Free, open source, Apache 2.0, written in Rust.',
inLanguage: 'en',
dateModified: buildDate,
isPartOf: { '@type': 'WebSite', name: 'RTK', url: 'https://www.rtk-ai.app' },
Expand All @@ -136,7 +136,7 @@ const schemaOrg = {
---
<Layout
title="RTK — Rust Token Killer"
description="RTK reduces AI coding token usage by 60-90% — measured across 2,900+ real commands. 89% avg noise removed, 3x longer sessions, zero config. MIT licensed."
description="RTK reduces CLI output noise by 60-90% before it hits the AI context window — measured across 2,900+ real commands. 89% avg noise removed, 3x longer sessions, zero config. Apache 2.0."
schemaOrg={schemaOrg}
>
<a href="#main-content" class="skip-to-content">Skip to content</a>
Expand Down
6 changes: 3 additions & 3 deletions src/components/pages/ProductIcmPage.astro
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const schema = {
datePublished: '2025-09-01',
dateModified: buildDate,
offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD', availability: 'https://schema.org/InStock' },
license: 'https://opensource.org/licenses/MIT',
license: 'https://www.apache.org/licenses/LICENSE-2.0',
downloadUrl: 'https://github.com/rtk-ai/icm',
author: { '@type': 'Organization', name: 'RTK AI', url: 'https://www.rtk-ai.app' },
featureList: [
Expand All @@ -44,7 +44,7 @@ const schema = {
name: 'What is ICM — Infinite Context Memory?',
acceptedAnswer: {
'@type': 'Answer',
text: 'ICM is permanent persistent memory for AI agents. It is a single Rust binary with SQLite storage that exposes 22 MCP tools. ICM provides three memory systems: episodic memories with temporal decay (4 importance levels), semantic knowledge graphs with typed relations, and a correction feedback system. It auto-configures 14 AI editors including Claude Code, Cursor, Windsurf, VS Code, Gemini Code Assist, Zed, Amp, Amazon Q, Cline, Roo Code, Kilo Code, Codex CLI, and OpenCode. 100% local, zero API keys required, MIT licensed.',
text: 'ICM is permanent persistent memory for AI agents. It is a single Rust binary with SQLite storage that exposes 22 MCP tools. ICM provides three memory systems: episodic memories with temporal decay (4 importance levels), semantic knowledge graphs with typed relations, and a correction feedback system. It auto-configures 14 AI editors including Claude Code, Cursor, Windsurf, VS Code, Gemini Code Assist, Zed, Amp, Amazon Q, Cline, Roo Code, Kilo Code, Codex CLI, and OpenCode. 100% local, zero API keys required, Apache 2.0 licensed.',
},
},
{
Expand Down Expand Up @@ -135,7 +135,7 @@ const schema = {

<!-- Hero -->
<section class="hero">
<div class="hero-badge">Open Source &middot; MIT License &middot; Written in Rust</div>
<div class="hero-badge">Open Source &middot; Apache 2.0 &middot; Written in Rust</div>
<h1>Your AI forgets everything.<br><span class="gradient-text">ICM fixes that.</span></h1>
<p class="hero-sub">
<strong>ICM</strong> gives AI agents real persistent memory.
Expand Down
Loading