diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 3304ae9..fb5c728 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -638,7 +638,7 @@ STATIC_CACHE_PRELOAD=true STATIC_CACHE_GC_PERCENT=400 ./bin/static-web ### GC tuning -`gc_percent` sets the Go runtime `GOGC` target. A higher value means the GC runs less often, trading memory for throughput. The handler's hot path is allocation-free, and fasthttp reuses per-connection buffers (unlike net/http which allocates per-request). Recommended values: +`gc_percent` sets the Go runtime `GOGC` target. A higher value means the GC runs less often, trading memory for throughput. The handler's hot path has near-zero allocations, and fasthttp reuses per-connection buffers (unlike net/http which allocates per-request). Recommended values: | `gc_percent` | Behaviour | |---|---| diff --git a/docs/index.html b/docs/index.html index 40980f9..82addb0 100644 --- a/docs/index.html +++ b/docs/index.html @@ -48,7 +48,7 @@ @@ -298,12 +298,14 @@

Everything You Need

-
โšก
+
+ +

Near-Zero Alloc Hot Path

~141k req/sec โ€” 55% faster than Bun. Built on fasthttp with direct ctx.SetBody() and pre-formatted headers โ€” no formatting allocations on cache hits.

-
๐Ÿ—œ๏ธ
+

gzip + Brotli

On-the-fly gzip via pooled writers, plus pre-compressed .gz/.br sidecar file @@ -311,7 +313,7 @@

gzip + Brotli

-
๐Ÿ”’
+

TLS 1.2 / 1.3

Modern cipher suites, automatic HTTPโ†’HTTPS redirects, HSTS, and HTTP/2 via ALPN negotiation โ€” just set @@ -319,7 +321,7 @@

TLS 1.2 / 1.3

-
๐Ÿ›ก๏ธ
+

Security Hardened

Path traversal prevention, dotfile blocking, CSP, HSTS, Referrer-Policy, Permissions-Policy โ€” set on @@ -327,12 +329,12 @@

Security Hardened

-
๐Ÿ“ฆ
+

Smart Caching

Byte-accurate LRU cache with startup preloading, configurable max size, per-file size cap, optional TTL expiry, ETag, and live flush via SIGHUP without downtime.

-
๐Ÿ”„
+

HTTP/2 & Range Requests

Full HTTP/2 support, byte-range serving for video / large files, conditional requests (ETag, @@ -340,7 +342,7 @@

HTTP/2 & Range Requests

-
๐ŸŒ
+

CORS Built-In

Wildcard or per-origin CORS. Preflight returns 204 with proper headers. Wildcard emits literal @@ -348,7 +350,7 @@

CORS Built-In

-
๐Ÿณ
+

Container Ready

Most settings overridable via environment variables. Graceful shutdown on SIGTERM/SIGINT with @@ -356,7 +358,7 @@

Container Ready

-
๐Ÿ“‚
+

Directory Listing

Optional HTML directory index with breadcrumb nav, sorted entries, human-readable sizes, and automatic @@ -511,7 +513,7 @@

Request Pipeline

-
๐ŸŒ
+

HTTP Request

Incoming GET / HEAD / OPTIONS

@@ -523,7 +525,7 @@

HTTP Request

-
๐Ÿ›ก๏ธ
+

Recovery Middleware

Panic โ†’ 500, log stack trace

@@ -535,7 +537,7 @@

Recovery Middleware

-
๐Ÿ“
+

Logging Middleware

Pooled status writer, method / path / status / bytes / duration

@@ -547,7 +549,7 @@

Logging Middleware

-
๐Ÿ”
+

Security Middleware

Method whitelist ยท security headers ยท path safety (cached) ยท dotfile block ยท CORS

@@ -559,7 +561,7 @@

Security Middleware

-
๐Ÿ—œ๏ธ
+

Compress Middleware

Post-processing gzip via pooled writers ยท content-type / size gating

@@ -571,7 +573,7 @@

Compress Middleware

-
โšก
+

File Handler

@@ -603,19 +605,19 @@

Performance Benchmarks

- โšก static-web (fasthttp) + static-web (fasthttp) ~141,000 619 µs 2.46 ms - ๐Ÿฅˆ Bun (native static) + Bun (native static) ~90,000 1.05 ms 2.33 ms - ๐Ÿ“ฆ static-web (old net/http) + static-web (old net/http) ~76,000 1.25 ms 3.15 ms @@ -627,24 +629,24 @@

Performance Benchmarks

-
๐Ÿง 
+

fasthttp + Preload

- Built on fasthttp with zero per-request allocations. --preload loads all files into RAM at startup. Cache hits use direct ctx.SetBody() with pre-formatted headers. + Built on fasthttp with near-zero per-request allocations. --preload loads all files into RAM at startup. Cache hits use direct ctx.SetBody() with pre-formatted headers.

-
๐Ÿ”ค
+

55% Faster Than Bun

With fasthttp + preload, static-web reaches ~141k req/sec โ€” 55% faster than Bun at ~90k req/sec, while offering full security headers, TLS, and compression out of the box.

-
โ™ป๏ธ
+

GC tuned

- gc_percent = 400 reduces GC frequency by 4x. The hot path is allocation-free โ€” fasthttp reuses per-connection buffers, eliminating the per-request allocations of net/http. + gc_percent = 400 reduces GC frequency by 4x. The hot path has near-zero allocations โ€” fasthttp reuses per-connection buffers, eliminating the per-request allocations of net/http.

@@ -669,7 +671,7 @@

Configuration Reference

- ๐Ÿ–ฅ๏ธ server + server
@@ -1018,7 +1020,7 @@

Security Model

aria-controls="sec-panel-path" id="sec-tab-path" > - ๐Ÿ” Path Safety + Path Safety
@@ -1303,7 +1305,7 @@

Legal

diff --git a/docs/script.js b/docs/script.js index c6649bf..d04fd57 100644 --- a/docs/script.js +++ b/docs/script.js @@ -332,7 +332,7 @@ document.querySelectorAll('a[href^="#"]').forEach(function (link) { โ€” Groups elements by parent section for incremental delays =========================== */ (function initReveal() { - var selectors = '.feature-card, .pipeline-step, .perf-card'; + var selectors = ".feature-card, .pipeline-step, .perf-card, .section-title, .section-description, .cta-card"; var targets = document.querySelectorAll(selectors); if (!targets.length) return; diff --git a/docs/styles.css b/docs/styles.css index 3be82c8..4dce2dd 100644 --- a/docs/styles.css +++ b/docs/styles.css @@ -2,24 +2,24 @@ CSS Variables & Design System =========================== */ :root { - --color-bg: #0a0a0f; - --color-bg-secondary: #12121a; - --color-bg-tertiary: #1a1a25; - --color-text: #e4e4e7; + --color-bg: #000000; + --color-bg-secondary: #0a0a0a; + --color-bg-tertiary: #111111; + --color-text: #ededed; --color-text-secondary: #a1a1aa; --color-text-muted: #71717a; - --color-primary: #6366f1; - --color-primary-light: #818cf8; + --color-primary: #ffffff; + --color-primary-light: #e4e4e7; --color-secondary: #8b5cf6; --color-accent: #22d3ee; --color-accent-green: #34d399; --color-border: #27272a; --color-border-light: #3f3f46; - --gradient-primary: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #a855f7 100%); + --gradient-primary: linear-gradient(135deg, #ffffff 0%, #a1a1aa 100%); --gradient-accent: linear-gradient(135deg, #22d3ee 0%, #34d399 100%); - --gradient-glow: linear-gradient(135deg, rgba(99,102,241,0.3) 0%, rgba(139,92,246,0.3) 100%); - --shadow-glow: 0 0 60px rgba(99,102,241,0.3); - --font-sans: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + --gradient-glow: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 100%); + --shadow-glow: 0 0 60px rgba(255,255,255,0.05); + --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; --font-mono: 'JetBrains Mono', 'Fira Code', monospace; --radius-sm: 6px; --radius-md: 12px; @@ -73,6 +73,20 @@ a { color: inherit; text-decoration: none; } top: 16px; } +/* =========================== + Scroll-Reveal (injected by JS but base defined here for no-FOUC) + =========================== */ +.reveal { + opacity: 0; + transform: translateY(24px); + transition: opacity 0.6s cubic-bezier(0.4, 0, 0.2, 1), transform 0.6s cubic-bezier(0.4, 0, 0.2, 1); +} + +.reveal.visible { + opacity: 1; + transform: translateY(0); +} + /* =========================== Navigation =========================== */ @@ -80,7 +94,7 @@ a { color: inherit; text-decoration: none; } display: flex; justify-content: space-between; align-items: center; - padding: 20px 40px; + padding: 16px 40px; max-width: 1400px; margin: 0 auto; position: relative; @@ -134,7 +148,7 @@ a { color: inherit; text-decoration: none; } display: inline-flex; align-items: center; gap: 8px; - padding: 9px 18px; + padding: 8px 16px; background: var(--color-bg-tertiary); border: 1px solid var(--color-border); border-radius: var(--radius-full); @@ -150,7 +164,7 @@ a { color: inherit; text-decoration: none; } .nav-cta:hover { border-color: var(--color-primary); color: var(--color-text); - background: rgba(99,102,241,0.1); + background: rgba(255,255,255,0.1); } /* Hamburger Button */ @@ -202,7 +216,7 @@ a { color: inherit; text-decoration: none; } position: relative; display: flex; flex-direction: column; - min-height: 100vh; + min-height: 65vh; overflow: hidden; background: var(--color-bg); } @@ -224,20 +238,20 @@ a { color: inherit; text-decoration: none; } align-items: center; justify-content: center; text-align: center; - padding: 20px 20px 48px; + padding: 16px 16px 24px; position: relative; z-index: 2; } .hero-logo { - margin-bottom: 16px; + margin-bottom: 12px; animation: float 6s ease-in-out infinite; } .hero-logo-svg { width: 80px; height: 80px; - filter: drop-shadow(0 0 40px rgba(99,102,241,0.45)); + filter: drop-shadow(0 0 40px rgba(255,255,255,0.45)); } @keyframes float { @@ -246,13 +260,13 @@ a { color: inherit; text-decoration: none; } } .hero-title { - font-size: clamp(2.8rem, 6vw, 4.2rem); + font-size: clamp(2.6rem, 5vw, 4rem); font-weight: 800; background: var(--gradient-primary); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; - margin-bottom: 8px; + margin-bottom: 4px; letter-spacing: -0.03em; } @@ -260,15 +274,15 @@ a { color: inherit; text-decoration: none; } font-size: clamp(1rem, 2.5vw, 1.3rem); color: var(--color-text-secondary); font-weight: 500; - margin-bottom: 12px; + margin-bottom: 8px; } .hero-description { font-size: 1rem; color: var(--color-text-muted); max-width: 620px; - margin-bottom: 28px; - line-height: 1.75; + margin-bottom: 16px; + line-height: 1.6; } .hero-description strong { color: var(--color-accent); } @@ -279,11 +293,11 @@ a { color: inherit; text-decoration: none; } grid-template-columns: repeat(4, auto); align-items: center; column-gap: 0; - margin-bottom: 24px; + margin-bottom: 16px; background: var(--color-bg-tertiary); border: 1px solid var(--color-border); border-radius: var(--radius-lg); - padding: 14px 24px; + padding: 12px 20px; } .stat { @@ -323,7 +337,7 @@ a { color: inherit; text-decoration: none; } .hero-actions { display: flex; gap: 12px; - margin-bottom: 20px; + margin-bottom: 16px; flex-wrap: wrap; justify-content: center; } @@ -332,27 +346,31 @@ a { color: inherit; text-decoration: none; } display: inline-flex; align-items: center; gap: 8px; - padding: 14px 28px; + padding: 12px 24px; border-radius: var(--radius-md); font-weight: 600; - font-size: 0.95rem; - transition: all 0.3s ease; + font-size: 0.9rem; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); border: none; cursor: pointer; font-family: var(--font-sans); + position: relative; + overflow: hidden; } -.btn-icon { width: 18px; height: 18px; } +.btn-icon { width: 18px; height: 18px; transition: transform 0.3s ease; } + +.btn:hover .btn-icon { transform: scale(1.1); } .btn-primary { background: var(--gradient-primary); - color: white; - box-shadow: 0 4px 20px rgba(99,102,241,0.4); + color: #000; + box-shadow: 0 4px 20px rgba(255,255,255,0.2); } .btn-primary:hover { - transform: translateY(-2px); - box-shadow: 0 6px 32px rgba(99,102,241,0.55); + transform: translateY(-2px) scale(1.02); + box-shadow: 0 8px 32px rgba(255,255,255,0.4); } .btn-secondary { @@ -362,8 +380,10 @@ a { color: inherit; text-decoration: none; } } .btn-secondary:hover { - background: var(--color-border); - border-color: var(--color-border-light); + background: var(--color-bg-secondary); + border-color: var(--color-primary-light); + transform: translateY(-2px); + box-shadow: 0 8px 24px rgba(255,255,255,0.1); } /* Install bar (hero + CTA shared) */ @@ -410,7 +430,7 @@ a { color: inherit; text-decoration: none; } transform: translate(-50%, -50%); width: 900px; height: 900px; - background: radial-gradient(circle, rgba(99,102,241,0.13) 0%, transparent 65%); + background: radial-gradient(circle, rgba(255,255,255,0.13) 0%, transparent 65%); pointer-events: none; z-index: 1; } @@ -425,7 +445,7 @@ a { color: inherit; text-decoration: none; } .section-inner { max-width: 1200px; margin: 0 auto; - padding: 56px 20px; + padding: 40px 20px; } .section-inner--narrow { @@ -447,7 +467,7 @@ a { color: inherit; text-decoration: none; } text-align: center; color: var(--color-text-secondary); font-size: 1rem; - margin-bottom: 36px; + margin-bottom: 24px; max-width: 600px; margin-left: auto; margin-right: auto; @@ -506,14 +526,14 @@ a { color: inherit; text-decoration: none; } background: var(--color-bg-tertiary); border: 1px solid var(--color-border); border-radius: var(--radius-lg); - padding: 22px; + padding: 20px; transition: all 0.3s ease; } .feature-card:hover { - border-color: var(--color-primary); - transform: translateY(-3px); - box-shadow: 0 8px 30px rgba(99,102,241,0.15); + border-color: var(--color-secondary); + transform: translateY(-4px); + box-shadow: 0 12px 40px rgba(139, 92, 246, 0.15), 0 0 20px rgba(139, 92, 246, 0.1); } .feature-icon { font-size: 1.8rem; margin-bottom: 10px; } @@ -536,7 +556,7 @@ a { color: inherit; text-decoration: none; } .feature-card p code { font-family: var(--font-mono); font-size: 0.82em; - background: rgba(99,102,241,0.15); + background: rgba(255,255,255,0.15); padding: 1px 5px; border-radius: 4px; color: var(--color-primary-light); @@ -574,7 +594,7 @@ a { color: inherit; text-decoration: none; } .tab-btn[aria-selected="true"] { background: var(--gradient-primary); border-color: transparent; - color: white; + color: #000; } .tab-btn:focus-visible { @@ -622,7 +642,7 @@ a { color: inherit; text-decoration: none; } } .code-block pre { - padding: 18px 20px; + padding: 16px 20px; overflow-x: auto; font-family: var(--font-mono); font-size: 0.85rem; @@ -661,15 +681,15 @@ a { color: inherit; text-decoration: none; } background: var(--color-bg-tertiary); border: 1px solid var(--color-border); border-radius: var(--radius-md); - padding: 14px 18px; + padding: 12px 16px; transition: all 0.25s; } .pipeline-step:hover { border-color: var(--color-border-light); } .pipeline-step--highlight { - border-color: rgba(99,102,241,0.4); - background: rgba(99,102,241,0.07); + border-color: rgba(255,255,255,0.4); + background: rgba(255,255,255,0.07); } .pipeline-step--highlight:hover { border-color: var(--color-primary); } @@ -704,7 +724,7 @@ a { color: inherit; text-decoration: none; } /* Benchmark table wrapper โ€” border-radius fix (border-collapse: collapse kills border-radius) */ .benchmark-table-wrap { max-width: 760px; - margin: 0 auto 28px; + margin: 0 auto 20px; overflow-x: auto; } @@ -740,7 +760,7 @@ a { color: inherit; text-decoration: none; } } .benchmark-table tr.highlight td { - background: rgba(99,102,241,0.08); + background: rgba(255,255,255,0.08); color: var(--color-text); } @@ -761,10 +781,14 @@ a { color: inherit; text-decoration: none; } border: 1px solid var(--color-border); border-radius: var(--radius-lg); padding: 20px; - transition: all 0.25s; + transition: all 0.3s ease; } -.perf-card:hover { border-color: var(--color-border-light); } +.perf-card:hover { + border-color: var(--color-accent); + transform: translateY(-4px); + box-shadow: 0 12px 40px rgba(34, 211, 238, 0.15), 0 0 20px rgba(34, 211, 238, 0.1); +} .perf-card-icon { font-size: 1.6rem; margin-bottom: 8px; } @@ -784,7 +808,7 @@ a { color: inherit; text-decoration: none; } .perf-card p code { font-family: var(--font-mono); font-size: 0.82em; - background: rgba(99,102,241,0.15); + background: rgba(255,255,255,0.15); padding: 1px 5px; border-radius: 4px; color: var(--color-primary-light); @@ -876,7 +900,7 @@ a { color: inherit; text-decoration: none; } .security-panel-lead code { font-family: var(--font-mono); font-size: 0.88em; - background: rgba(99,102,241,0.12); + background: rgba(255,255,255,0.12); padding: 1px 5px; border-radius: 4px; color: var(--color-primary-light); @@ -910,7 +934,7 @@ a { color: inherit; text-decoration: none; } content: counter(sec-counter); min-width: 22px; height: 22px; - background: rgba(99,102,241,0.2); + background: rgba(255,255,255,0.2); color: var(--color-primary-light); border-radius: 50%; display: flex; @@ -925,7 +949,7 @@ a { color: inherit; text-decoration: none; } .security-list li code { font-family: var(--font-mono); font-size: 0.82em; - background: rgba(99,102,241,0.12); + background: rgba(255,255,255,0.12); padding: 1px 5px; border-radius: 4px; color: var(--color-primary-light); @@ -943,7 +967,7 @@ a { color: inherit; text-decoration: none; } .security-note code { font-family: var(--font-mono); font-size: 0.88em; - background: rgba(99,102,241,0.12); + background: rgba(255,255,255,0.12); padding: 1px 5px; border-radius: 4px; color: var(--color-primary-light); @@ -990,7 +1014,7 @@ a { color: inherit; text-decoration: none; } background: var(--color-bg-tertiary); border: 1px solid var(--color-border); border-radius: var(--radius-lg); - padding: 44px 36px; + padding: 32px 36px; position: relative; overflow: hidden; } @@ -1044,7 +1068,7 @@ a { color: inherit; text-decoration: none; } .footer { background: var(--color-bg-secondary); border-top: 1px solid var(--color-border); - padding: 40px 20px 24px; + padding: 32px 20px 24px; } .footer-content { @@ -1122,28 +1146,16 @@ a { color: inherit; text-decoration: none; } .footer-bottom a:hover { color: var(--color-primary); } -/* =========================== - Scroll-Reveal (injected by JS but base defined here for no-FOUC) - =========================== */ -.reveal { - opacity: 0; - transform: translateY(24px); - transition: opacity 0.5s ease, transform 0.5s ease; -} - -.reveal.visible { - opacity: 1; - transform: none; -} - /* =========================== Responsive =========================== */ @media (max-width: 768px) { - .nav { padding: 16px 20px; } + .nav { padding: 12px 16px; gap: 16px; } + .nav-logo { gap: 8px; } + .logo-text { font-size: 1.1rem; } .nav-links { display: none; } .nav-cta { display: none; } - .nav-hamburger { display: flex; } + .nav-hamburger { display: flex; width: 36px; height: 36px; } /* Mobile nav overlay */ .nav-open .nav-links { @@ -1152,7 +1164,7 @@ a { color: inherit; text-decoration: none; } position: fixed; inset: 0; z-index: 100; - background: rgba(10, 10, 15, 0.97); + background: rgba(10, 10, 15, 0.98); backdrop-filter: blur(12px); align-items: center; justify-content: center; @@ -1167,41 +1179,47 @@ a { color: inherit; text-decoration: none; } } .hero { min-height: auto; } - .hero-content { padding: 20px 16px 40px; } - .hero-logo-svg { width: 72px; height: 72px; } + .hero-content { padding: 12px 12px 24px; } + .hero-logo-svg { width: 64px; height: 64px; } + .hero-title { font-size: 2.2rem; } + .hero-subtitle { font-size: 1rem; } .hero-stats { grid-template-columns: repeat(2, auto); - padding: 16px; - gap: 8px; - row-gap: 12px; + padding: 12px; + gap: 12px; + row-gap: 16px; + width: 100%; + margin-bottom: 16px; } /* Hide dividers on mobile 2ร—2 grid */ .stat-divider { display: none; } - .stat { padding: 0 12px; } + .stat { padding: 0 8px; } .stat-value { font-size: 1.05rem; } .hero-install, .cta-install { - padding: 12px 12px 12px 16px; + padding: 8px 8px 8px 16px; + width: 100%; } - .install-code { font-size: 0.75rem; } + .install-code { font-size: 0.75rem; overflow-x: auto; flex: 1; } - .section-inner { padding: 44px 16px; } + .section-inner { padding: 48px 16px; } - .features-grid { grid-template-columns: 1fr; } + .features-grid { grid-template-columns: 1fr; gap: 12px; } - .pipeline { padding: 0 4px; } - .pipeline-step { padding: 14px 16px; } - .pipeline-info p { font-size: 0.78rem; } + .pipeline { padding: 0; } + .pipeline-step { padding: 14px 16px; flex-direction: column; text-align: center; gap: 10px; } + .pipeline-icon { width: auto; } + .pipeline-info p { font-size: 0.8rem; } - .perf-cards { grid-template-columns: 1fr; } + .perf-cards { grid-template-columns: 1fr; gap: 12px; } .cta-card { padding: 32px 16px; } - .cta-install { padding: 10px 12px; } + .cta-install { padding: 8px 12px; } .footer-content { flex-direction: column; gap: 32px; } .footer-links-group { gap: 28px; } @@ -1232,4 +1250,4 @@ a { color: inherit; text-decoration: none; } ::-webkit-scrollbar-thumb { background: var(--color-border); border-radius: 4px; } ::-webkit-scrollbar-thumb:hover { background: var(--color-border-light); } -::selection { background: rgba(99,102,241,0.3); color: var(--color-text); } +::selection { background: rgba(255,255,255,0.3); color: var(--color-text); }