921124f
commit 921124f
5 files changed
+550 -71
Showing 5 changed files+550-71
▼docs_site/astro.config.mjs
+2-1
| @@ -17,6 +17,7 @@ export default defineConfig({ | ||
17 | 17 | }, |
18 | 18 | social: [ |
19 | 19 | { icon: 'github', label: 'GitHub', href: 'https://github.com/swadhinbiswas/JustAPI' }, |
20 | + { icon: 'x.com', label: 'X (Twitter)', href: 'https://x.com/justapidev' }, | |
20 | 21 | ], |
21 | 22 | customCss: ['./src/styles/custom.css'], |
22 | 23 | editLink: { |
| @@ -76,7 +77,7 @@ export default defineConfig({ | ||
76 | 77 | url: site, |
77 | 78 | downloadUrl: 'https://pypi.org/project/justapi/', |
78 | 79 | installUrl: 'https://pypi.org/project/justapi/', |
79 | - softwareVersion: '2.0.0', | |
80 | + softwareVersion: '2.0.8', | |
80 | 81 | offers: { |
81 | 82 | '@type': 'Offer', |
82 | 83 | price: '0', |
83 | 84 | |
▼docs_site/public/_headers
+16-0
| @@ -0,0 +1,16 @@ | ||
1 | +/* | |
2 | + X-Frame-Options: DENY | |
3 | + X-Content-Type-Options: nosniff | |
4 | + Referrer-Policy: strict-origin-when-cross-origin | |
5 | + Permissions-Policy: camera=(), microphone=(), geolocation=() | |
6 | + Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data: | |
7 | + Strict-Transport-Security: max-age=31536000; includeSubDomains; preload | |
8 | + | |
9 | +/_astro/* | |
10 | + Cache-Control: public, max-age=31536000, immutable | |
11 | + | |
12 | +/*.html | |
13 | + Cache-Control: public, max-age=0, must-revalidate | |
14 | + | |
15 | +/sitemap-index.xml | |
16 | + Cache-Control: public, max-age=86400 | |
0 | 17 | |
▼docs_site/public/robots.txt
+7-0
| @@ -0,0 +1,7 @@ | ||
1 | +User-agent: * | |
2 | +Allow: / | |
3 | + | |
4 | +Sitemap: https://justapi.dev/sitemap-index.xml | |
5 | + | |
6 | +# Disallow admin/private paths | |
7 | +Disallow: /_astro/ | |
0 | 8 | |
▼docs_site/src/content/docs/index.mdx
+88-18
| @@ -1,6 +1,6 @@ | ||
1 | 1 | --- |
2 | -title: JustAPI Documentation | |
3 | -description: JustAPI — the fastest FastAPI alternative. A Rust-powered Python web framework with 700k+ RPS, zero-GIL execution, and drop-in FastAPI compatibility. The production-grade FastAPI replacement. | |
2 | +title: JustAPI Documentation — The Fastest FastAPI Alternative | |
3 | +description: JustAPI — a Rust-powered Python web framework. Drop-in FastAPI replacement with 700k+ RPS, zero-GIL execution, and automatic OpenAPI docs. | |
4 | 4 | template: splash |
5 | 5 | hero: |
6 | 6 | tagline: The speed of Rust. The elegance of Python. A drop-in replacement for FastAPI engineered for extreme throughput. |
| @@ -11,50 +11,120 @@ hero: | ||
11 | 11 | link: /getting-started/overview/ |
12 | 12 | icon: right-arrow |
13 | 13 | variant: primary |
14 | + - text: Tutorial — User Guide | |
15 | + link: /tutorials/python-types/ | |
16 | + icon: open-book | |
17 | + variant: minimal | |
14 | 18 | - text: View on GitHub |
15 | 19 | link: https://github.com/swadhinbiswas/JustAPI |
16 | 20 | icon: external |
21 | + variant: minimal | |
17 | 22 | --- |
18 | 23 | |
19 | 24 | import { Card, CardGrid } from '@astrojs/starlight/components'; |
20 | 25 | |
21 | -## Key Features | |
26 | +## Why JustAPI? | |
27 | + | |
28 | +JustAPI moves the entire networking stack out of Python. Same FastAPI syntax. Same Pydantic models. 20× the throughput. | |
22 | 29 | |
23 | 30 | <CardGrid stack> |
24 | - <Card title="⚡ 700,000+ Requests / Sec" icon="rocket"> | |
25 | - 20× faster than FastAPI + Uvicorn. Networking, TLS, routing, schema validation, and JSON serialization run entirely in Rust at native speed. | |
31 | + <Card title="700,000+ Requests / Sec" icon="rocket"> | |
32 | + Networking, TLS, routing, schema validation, and JSON serialization run entirely in Rust at native speed. 20× faster than FastAPI + Uvicorn. | |
26 | 33 | </Card> |
27 | - <Card title="🐍 FastAPI Compatibility" icon="star"> | |
28 | - Same `@app.get()` decorators, same Pydantic v2 schemas, same `Depends()` dependency injection. Easily migrate existing FastAPI applications. | |
34 | + <Card title="FastAPI Compatibility" icon="star"> | |
35 | + Same `@app.get()` decorators, same Pydantic v2 schemas, same `Depends()` dependency injection. Migrate existing FastAPI applications with one import change. | |
29 | 36 | </Card> |
30 | - <Card title="🛡️ Zero-GIL Fast Path" icon="shield"> | |
31 | - Rust code releases the Python GIL via `py.allow_threads` during all I/O, routing, DB queries, and validation. Fully supports Python 3.13t/3.14t free-threading. | |
37 | + <Card title="Zero-GIL Fast Path" icon="shield"> | |
38 | + Rust releases the Python GIL during all I/O, routing, and validation. Fully supports Python 3.13t/3.14t free-threading. Native fast path at 724k+ RPS. | |
32 | 39 | </Card> |
33 | - <Card title="🗄️ Multi-Database & Multi-Protocol" icon="setting"> | |
34 | - Natively supports SQL (Postgres, MySQL, SQLite), Analytical OLAP (DuckDB, ClickHouse), NoSQL (Mongo, Redis), and REST, GraphQL, gRPC, and JSON-RPC 2.0. | |
40 | + <Card title="Multi-Database & Multi-Protocol" icon="setting"> | |
41 | + SQL (Postgres, MySQL, SQLite), OLAP (DuckDB), NoSQL (Redis, MongoDB), and REST, GraphQL, gRPC, JSON-RPC 2.0 — all in one framework. | |
35 | 42 | </Card> |
36 | 43 | </CardGrid> |
37 | 44 | |
38 | -## Live Benchmark Comparison | |
45 | +## Performance | |
39 | 46 | |
40 | 47 | | Framework | Requests/sec | p50 Latency | p99 Latency | |
41 | 48 | |---|--:|--:|--:| |
42 | -| **JustAPI 🦀** | **701,234** | **0.07 ms** | **0.19 ms** | | |
49 | +| **JustAPI (native fast path)** | **701,234** | **0.07 ms** | **0.19 ms** | | |
50 | +| **JustAPI (Python handler)** | **60,297** | **1.03 ms** | **5.21 ms** | | |
51 | +| Robyn 0.88 | 39,103 | 1.78 ms | 11.47 ms | | |
43 | 52 | | Granian | 69,195 | 0.72 ms | 3.87 ms | |
44 | 53 | | FastAPI + Uvicorn | 36,189 | 1.72 ms | 24.63 ms | |
45 | 54 | |
46 | -## Quick Example | |
55 | +All measurements on the same hardware (i5-13600K, 20 threads), 100 concurrent connections, 30s duration. See [Benchmarks](/reference/adr-index/) for methodology. | |
56 | + | |
57 | +## Quick Start | |
47 | 58 | |
48 | 59 | ```python |
49 | 60 | from justapi import JustAPIApp |
50 | 61 | |
51 | -app = JustAPIApp(title="My High-Speed API") | |
62 | +app = JustAPIApp(title="My API") | |
52 | 63 | |
53 | 64 | @app.get("/") |
54 | -def hello(request): | |
55 | - return {"message": "Hello from Rust-powered JustAPI!"} | |
65 | +def hello(): | |
66 | + return {"message": "Hello from JustAPI!"} | |
56 | 67 | |
57 | 68 | @app.get("/items/{item_id}") |
58 | -def read_item(request, item_id: int, q: str | None = None): | |
69 | +def read_item(item_id: int, q: str | None = None): | |
59 | 70 | return {"item_id": item_id, "q": q} |
60 | 71 | ``` |
72 | + | |
73 | +```bash | |
74 | +pip install justapi | |
75 | +python main.py | |
76 | +``` | |
77 | + | |
78 | +Open [http://localhost:8000/docs](http://localhost:8000/docs) for interactive Swagger UI documentation. | |
79 | + | |
80 | +## Learn | |
81 | + | |
82 | +<CardGrid> | |
83 | + <Card title="Python Types" icon="pencil"> | |
84 | + [Type hints, Pydantic models, validation →](/tutorials/python-types/) | |
85 | + </Card> | |
86 | + <Card title="Async / Await" icon="moon"> | |
87 | + [Concurrency model, when to use async →](/tutorials/async-await/) | |
88 | + </Card> | |
89 | + <Card title="Path & Query" icon="list"> | |
90 | + [Parameters, validation, constraints →](/tutorials/path-params/) | |
91 | + </Card> | |
92 | + <Card title="Request Body" icon="document"> | |
93 | + [Pydantic, nested models, fields →](/tutorials/request-body/) | |
94 | + </Card> | |
95 | + <Card title="Dependencies" icon="puzzle"> | |
96 | + [DI, sub-dependencies, yield cleanup →](/tutorials/dependencies/classes-as-dependencies/) | |
97 | + </Card> | |
98 | + <Card title="Security" icon="lock"> | |
99 | + [OAuth2, JWT, API keys →](/tutorials/security/first-steps/) | |
100 | + </Card> | |
101 | +</CardGrid> | |
102 | + | |
103 | +## Install | |
104 | + | |
105 | +```bash | |
106 | +# pip | |
107 | +pip install justapi | |
108 | + | |
109 | +# uv (recommended) | |
110 | +uv pip install justapi | |
111 | + | |
112 | +# run without installing | |
113 | +uvx justapi create my_app | |
114 | +``` | |
115 | + | |
116 | +## Migration | |
117 | + | |
118 | +Migrating from FastAPI? One import change: | |
119 | + | |
120 | +```python | |
121 | +# Before (FastAPI) | |
122 | +from fastapi import FastAPI | |
123 | +app = FastAPI() | |
124 | + | |
125 | +# After (JustAPI) | |
126 | +from justapi import JustAPIApp | |
127 | +app = JustAPIApp() | |
128 | +``` | |
129 | + | |
130 | +Everything else stays the same — decorators, Pydantic models, dependency injection, OpenAPI docs. | |
61 | 131 | |
▼docs_site/src/styles/custom.css
+437-52
| @@ -1,69 +1,242 @@ | ||
1 | +/* ═══════════════════════════════════════════════════════════════════ | |
2 | + JustAPI Documentation — Design System | |
3 | + Premium, FastAPI-level documentation styling | |
4 | + ═══════════════════════════════════════════════════════════════════ */ | |
5 | + | |
6 | +/* ─── Custom Properties ─── */ | |
1 | 7 | :root { |
8 | + /* Accent palette */ | |
2 | 9 | --sl-color-accent-low: #2a1147; |
3 | 10 | --sl-color-accent: #8b5cf6; |
4 | 11 | --sl-color-accent-high: #c4b5fd; |
12 | + | |
13 | + /* Neutrals */ | |
5 | 14 | --sl-color-white: #ffffff; |
6 | - --sl-color-gray-1: #f3f4f6; | |
7 | - --sl-color-gray-2: #e5e7eb; | |
8 | - --sl-color-gray-3: #9ca3af; | |
9 | - --sl-color-gray-4: #4b5563; | |
10 | - --sl-color-gray-5: #1f2937; | |
11 | - --sl-color-gray-6: #111827; | |
12 | - --sl-color-black: #0b0f19; | |
15 | + --sl-color-gray-1: #f8fafc; | |
16 | + --sl-color-gray-2: #f1f5f9; | |
17 | + --sl-color-gray-3: #94a3b8; | |
18 | + --sl-color-gray-4: #64748b; | |
19 | + --sl-color-gray-5: #334155; | |
20 | + --sl-color-gray-6: #1e293b; | |
21 | + --sl-color-black: #020617; | |
22 | + | |
23 | + /* Brand */ | |
13 | 24 | --sl-color-orange: #e6522c; |
14 | 25 | --sl-color-blue: #3b82f6; |
26 | + --sl-color-green: #10b981; | |
27 | + --sl-color-red: #ef4444; | |
28 | + --sl-color-yellow: #f59e0b; | |
29 | + | |
30 | + /* Typography */ | |
31 | + --sl-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; | |
32 | + --sl-font-mono: 'JetBrains Mono', 'Fira Code', 'Cascadia Code', 'SF Mono', monospace; | |
33 | + | |
34 | + /* Spacing */ | |
35 | + --sl-content-width: 72rem; | |
36 | + --sl-sidebar-width: 18rem; | |
37 | + --sl-toc-width: 14rem; | |
15 | 38 | } |
16 | 39 | |
40 | +/* ─── Dark Mode ─── */ | |
17 | 41 | [data-theme='dark'] { |
18 | - --sl-color-bg: #0b0f19; | |
19 | - --sl-color-bg-nav: #111827; | |
42 | + --sl-color-bg: #020617; | |
43 | + --sl-color-bg-nav: #0f172a; | |
20 | 44 | --sl-color-bg-sidebar: #0f172a; |
45 | + --sl-color-bg-hover: #1e293b; | |
46 | + --sl-color-text: #e2e8f0; | |
47 | + --sl-color-text-muted: #94a3b8; | |
48 | + --sl-color-border: #1e293b; | |
21 | 49 | } |
22 | 50 | |
23 | -.hero-gradient { | |
24 | - background: linear-gradient(135deg, #e6522c 0%, #8b5cf6 50%, #3b82f6 100%); | |
25 | - -webkit-background-clip: text; | |
26 | - -webkit-text-fill-color: transparent; | |
27 | - background-clip: text; | |
51 | +/* ─── Light Mode ─── */ | |
52 | +[data-theme='light'] { | |
53 | + --sl-color-bg: #ffffff; | |
54 | + --sl-color-bg-nav: #f8fafc; | |
55 | + --sl-color-bg-sidebar: #f8fafc; | |
56 | + --sl-color-bg-hover: #f1f5f9; | |
57 | + --sl-color-text: #1e293b; | |
58 | + --sl-color-text-muted: #64748b; | |
59 | + --sl-color-border: #e2e8f0; | |
28 | 60 | } |
29 | 61 | |
30 | -.benchmark-card { | |
31 | - border: 1px solid rgba(139, 92, 246, 0.3); | |
32 | - border-radius: 12px; | |
33 | - padding: 1.5rem; | |
34 | - background: rgba(17, 24, 39, 0.7); | |
35 | - backdrop-filter: blur(12px); | |
36 | - margin-bottom: 1.5rem; | |
62 | +/* ─── Global Typography ─── */ | |
63 | +html { | |
64 | + font-family: var(--sl-font); | |
65 | + -webkit-font-smoothing: antialiased; | |
66 | + -moz-osx-font-smoothing: grayscale; | |
67 | + text-rendering: optimizeLegibility; | |
68 | + scroll-behavior: smooth; | |
37 | 69 | } |
38 | 70 | |
39 | -.site-title { | |
40 | - font-weight: 700; | |
71 | +body { | |
72 | + line-height: 1.7; | |
73 | + letter-spacing: -0.011em; | |
74 | +} | |
75 | + | |
76 | +/* ─── Headings ─── */ | |
77 | +.content h1 { | |
78 | + font-size: 2.25rem; | |
79 | + font-weight: 800; | |
80 | + letter-spacing: -0.025em; | |
81 | + line-height: 1.2; | |
82 | + margin-bottom: 1rem; | |
41 | 83 | } |
42 | 84 | |
43 | 85 | .content h2 { |
44 | - margin-top: 2.5rem; | |
45 | - border-bottom: 1px solid var(--sl-color-gray-5); | |
46 | - padding-bottom: 0.5rem; | |
86 | + font-size: 1.5rem; | |
87 | + font-weight: 700; | |
88 | + letter-spacing: -0.02em; | |
89 | + margin-top: 3rem; | |
90 | + margin-bottom: 1rem; | |
91 | + padding-bottom: 0.75rem; | |
92 | + border-bottom: 1px solid var(--sl-color-border, #e2e8f0); | |
47 | 93 | } |
48 | 94 | |
49 | 95 | .content h3 { |
96 | + font-size: 1.2rem; | |
97 | + font-weight: 600; | |
50 | 98 | margin-top: 2rem; |
99 | + margin-bottom: 0.75rem; | |
100 | + letter-spacing: -0.01em; | |
101 | +} | |
102 | + | |
103 | +.content h4 { | |
104 | + font-size: 1rem; | |
105 | + font-weight: 600; | |
106 | + margin-top: 1.5rem; | |
107 | +} | |
108 | + | |
109 | +/* ─── Links ─── */ | |
110 | +.content a { | |
111 | + color: var(--sl-color-accent); | |
112 | + text-decoration: none; | |
113 | + transition: color 0.15s ease; | |
114 | +} | |
115 | + | |
116 | +.content a:hover { | |
117 | + color: var(--sl-color-accent-high); | |
118 | + text-decoration: underline; | |
119 | + text-decoration-thickness: 2px; | |
120 | + text-underline-offset: 3px; | |
121 | +} | |
122 | + | |
123 | +/* ─── Code Blocks ─── */ | |
124 | +code { | |
125 | + font-family: var(--sl-font-mono); | |
126 | + font-size: 0.85em; | |
127 | + border-radius: 6px; | |
128 | + padding: 0.15em 0.4em; | |
129 | + background: var(--sl-color-gray-2, #f1f5f9); | |
51 | 130 | } |
52 | 131 | |
132 | +[data-theme='dark'] code { | |
133 | + background: rgba(139, 92, 246, 0.15); | |
134 | + color: #c4b5fd; | |
135 | +} | |
136 | + | |
137 | +pre { | |
138 | + font-family: var(--sl-font-mono); | |
139 | + font-size: 0.875rem; | |
140 | + line-height: 1.6; | |
141 | + border-radius: 12px; | |
142 | + border: 1px solid var(--sl-color-border, #e2e8f0); | |
143 | + padding: 1.25rem; | |
144 | + overflow-x: auto; | |
145 | + background: #0f172a !important; | |
146 | +} | |
147 | + | |
148 | +[data-theme='dark'] pre { | |
149 | + background: #0b0f19 !important; | |
150 | + border-color: #1e293b; | |
151 | +} | |
152 | + | |
153 | +pre code { | |
154 | + background: none; | |
155 | + padding: 0; | |
156 | + border-radius: 0; | |
157 | +} | |
158 | + | |
159 | +/* ─── Tables ─── */ | |
53 | 160 | .content table { |
161 | + width: 100%; | |
54 | 162 | font-size: 0.875rem; |
163 | + border-collapse: separate; | |
164 | + border-spacing: 0; | |
165 | + border-radius: 12px; | |
166 | + overflow: hidden; | |
167 | + border: 1px solid var(--sl-color-border, #e2e8f0); | |
168 | + margin: 1.5rem 0; | |
169 | +} | |
170 | + | |
171 | +.content thead { | |
172 | + background: var(--sl-color-gray-6, #1e293b); | |
173 | +} | |
174 | + | |
175 | +[data-theme='dark'] .content thead { | |
176 | + background: #1e293b; | |
177 | +} | |
178 | + | |
179 | +[data-theme='light'] .content thead { | |
180 | + background: #f1f5f9; | |
55 | 181 | } |
56 | 182 | |
57 | 183 | .content th { |
58 | - background: var(--sl-color-gray-6); | |
59 | 184 | font-weight: 600; |
185 | + text-align: left; | |
186 | + padding: 0.75rem 1rem; | |
187 | + border-bottom: 2px solid var(--sl-color-border, #e2e8f0); | |
60 | 188 | } |
61 | 189 | |
62 | -.content td, | |
63 | -.content th { | |
64 | - border-color: var(--sl-color-gray-5); | |
190 | +.content td { | |
191 | + padding: 0.75rem 1rem; | |
192 | + border-bottom: 1px solid var(--sl-color-border, #e2e8f0); | |
193 | +} | |
194 | + | |
195 | +.content tbody tr:last-child td { | |
196 | + border-bottom: none; | |
197 | +} | |
198 | + | |
199 | +.content tbody tr:hover { | |
200 | + background: var(--sl-color-bg-hover, #f8fafc); | |
201 | +} | |
202 | + | |
203 | +/* ─── Callouts / Asides ─── */ | |
204 | +.starlight-aside { | |
205 | + border-radius: 12px; | |
206 | + border-left-width: 4px; | |
207 | + padding: 1rem 1.25rem; | |
208 | + margin: 1.5rem 0; | |
65 | 209 | } |
66 | 210 | |
211 | +.starlight-aside--note { | |
212 | + border-left-color: var(--sl-color-blue); | |
213 | + background: rgba(59, 130, 246, 0.05); | |
214 | +} | |
215 | + | |
216 | +.starlight-aside--tip { | |
217 | + border-left-color: var(--sl-color-green); | |
218 | + background: rgba(16, 185, 129, 0.05); | |
219 | +} | |
220 | + | |
221 | +.starlight-aside--caution { | |
222 | + border-left-color: var(--sl-color-yellow); | |
223 | + background: rgba(245, 158, 11, 0.05); | |
224 | +} | |
225 | + | |
226 | +.starlight-aside--danger { | |
227 | + border-left-color: var(--sl-color-red); | |
228 | + background: rgba(239, 68, 68, 0.05); | |
229 | +} | |
230 | + | |
231 | +/* ─── Hero Gradient ─── */ | |
232 | +.hero-gradient { | |
233 | + background: linear-gradient(135deg, #e6522c 0%, #8b5cf6 50%, #3b82f6 100%); | |
234 | + -webkit-background-clip: text; | |
235 | + -webkit-text-fill-color: transparent; | |
236 | + background-clip: text; | |
237 | +} | |
238 | + | |
239 | +/* ─── Feature Grid ─── */ | |
67 | 240 | .feature-grid { |
68 | 241 | display: grid; |
69 | 242 | grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); |
| @@ -72,35 +245,84 @@ | ||
72 | 245 | } |
73 | 246 | |
74 | 247 | .feature-card { |
75 | - border: 1px solid var(--sl-color-gray-5); | |
76 | - border-radius: 12px; | |
77 | - padding: 1.5rem; | |
78 | - background: var(--sl-color-gray-6); | |
79 | - transition: border-color 0.2s, transform 0.2s; | |
248 | + border: 1px solid var(--sl-color-border, #e2e8f0); | |
249 | + border-radius: 16px; | |
250 | + padding: 1.75rem; | |
251 | + background: var(--sl-color-bg, #ffffff); | |
252 | + transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); | |
253 | + position: relative; | |
254 | + overflow: hidden; | |
255 | +} | |
256 | + | |
257 | +.feature-card::before { | |
258 | + content: ''; | |
259 | + position: absolute; | |
260 | + top: 0; | |
261 | + left: 0; | |
262 | + right: 0; | |
263 | + height: 3px; | |
264 | + background: linear-gradient(90deg, var(--sl-color-accent), var(--sl-color-blue)); | |
265 | + opacity: 0; | |
266 | + transition: opacity 0.25s ease; | |
80 | 267 | } |
81 | 268 | |
82 | 269 | .feature-card:hover { |
83 | 270 | border-color: var(--sl-color-accent); |
84 | - transform: translateY(-2px); | |
271 | + transform: translateY(-4px); | |
272 | + box-shadow: 0 20px 40px -12px rgba(139, 92, 246, 0.15); | |
273 | +} | |
274 | + | |
275 | +.feature-card:hover::before { | |
276 | + opacity: 1; | |
85 | 277 | } |
86 | 278 | |
87 | 279 | .feature-card h3 { |
88 | 280 | margin-top: 0; |
89 | 281 | font-size: 1.1rem; |
282 | + font-weight: 600; | |
283 | +} | |
284 | + | |
285 | +/* ─── Benchmark Card ─── */ | |
286 | +.benchmark-card { | |
287 | + border: 1px solid rgba(139, 92, 246, 0.3); | |
288 | + border-radius: 16px; | |
289 | + padding: 1.75rem; | |
290 | + background: rgba(17, 24, 39, 0.7); | |
291 | + backdrop-filter: blur(16px); | |
292 | + margin-bottom: 1.5rem; | |
293 | + position: relative; | |
294 | + overflow: hidden; | |
90 | 295 | } |
91 | 296 | |
297 | +.benchmark-card::before { | |
298 | + content: ''; | |
299 | + position: absolute; | |
300 | + top: 0; | |
301 | + left: 0; | |
302 | + right: 0; | |
303 | + height: 2px; | |
304 | + background: linear-gradient(90deg, var(--sl-color-orange), var(--sl-color-accent), var(--sl-color-blue)); | |
305 | +} | |
306 | + | |
307 | +/* ─── Performance Table ─── */ | |
92 | 308 | .performance-table { |
93 | 309 | width: 100%; |
94 | - border-collapse: collapse; | |
310 | + border-collapse: separate; | |
311 | + border-spacing: 0; | |
312 | + border-radius: 12px; | |
313 | + overflow: hidden; | |
314 | + border: 1px solid var(--sl-color-border, #e2e8f0); | |
95 | 315 | } |
96 | 316 | |
97 | 317 | .performance-table th { |
98 | 318 | text-align: left; |
99 | - padding: 0.75rem 1rem; | |
319 | + padding: 1rem 1.25rem; | |
320 | + font-weight: 600; | |
321 | + background: var(--sl-color-gray-6, #1e293b); | |
100 | 322 | } |
101 | 323 | |
102 | 324 | .performance-table td { |
103 | - padding: 0.75rem 1rem; | |
325 | + padding: 1rem 1.25rem; | |
104 | 326 | text-align: right; |
105 | 327 | } |
106 | 328 | |
| @@ -112,30 +334,193 @@ | ||
112 | 334 | .performance-table .winner { |
113 | 335 | color: var(--sl-color-accent-high); |
114 | 336 | font-weight: 700; |
337 | + font-size: 1.1em; | |
115 | 338 | } |
116 | 339 | |
117 | -code { | |
118 | - font-size: 0.85em; | |
340 | +.performance-table tbody tr:hover { | |
341 | + background: var(--sl-color-bg-hover, #f8fafc); | |
342 | +} | |
343 | + | |
344 | +/* ─── Sidebar ─── */ | |
345 | +.sidebar-title { | |
346 | + font-weight: 700; | |
347 | + font-size: 0.8rem; | |
348 | + text-transform: uppercase; | |
349 | + letter-spacing: 0.05em; | |
350 | + color: var(--sl-color-text-muted, #64748b); | |
351 | +} | |
352 | + | |
353 | +/* ─── Badge Styling ─── */ | |
354 | +.badge--success { | |
355 | + background: rgba(16, 185, 129, 0.15); | |
356 | + color: var(--sl-color-green); | |
357 | + border: 1px solid rgba(16, 185, 129, 0.3); | |
358 | + border-radius: 9999px; | |
359 | + padding: 0.15em 0.6em; | |
360 | + font-size: 0.75rem; | |
361 | + font-weight: 600; | |
362 | +} | |
363 | + | |
364 | +/* ─── Card Grid Overrides ─── */ | |
365 | +.sl-card-grid { | |
366 | + gap: 1.25rem; | |
367 | +} | |
368 | + | |
369 | +.sl-card { | |
370 | + border-radius: 12px; | |
371 | + border: 1px solid var(--sl-color-border, #e2e8f0); | |
372 | + transition: all 0.2s ease; | |
373 | +} | |
374 | + | |
375 | +.sl-card:hover { | |
376 | + border-color: var(--sl-color-accent); | |
377 | + box-shadow: 0 8px 24px -8px rgba(139, 92, 246, 0.12); | |
378 | +} | |
379 | + | |
380 | +/* ─── TOC (Table of Contents) ─── */ | |
381 | +.toc-panel { | |
382 | + font-size: 0.85rem; | |
383 | +} | |
384 | + | |
385 | +.toc-panel a { | |
386 | + transition: color 0.15s ease; | |
387 | +} | |
388 | + | |
389 | +/* ─── Breadcrumbs ─── */ | |
390 | +.breadcrumbs a { | |
391 | + font-size: 0.85rem; | |
392 | + color: var(--sl-color-text-muted, #64748b); | |
393 | + transition: color 0.15s ease; | |
394 | +} | |
395 | + | |
396 | +.breadcrumbs a:hover { | |
397 | + color: var(--sl-color-accent); | |
398 | +} | |
399 | + | |
400 | +/* ─── Navigation (Prev/Next) ─── */ | |
401 | +.prev-next-nav a { | |
402 | + border-radius: 12px; | |
403 | + transition: all 0.2s ease; | |
404 | + border: 1px solid var(--sl-color-border, #e2e8f0); | |
405 | +} | |
406 | + | |
407 | +.prev-next-nav a:hover { | |
408 | + border-color: var(--sl-color-accent); | |
409 | + box-shadow: 0 4px 12px -4px rgba(139, 92, 246, 0.15); | |
410 | +} | |
411 | + | |
412 | +/* ─── Search ─── */ | |
413 | +.search-input { | |
414 | + border-radius: 10px !important; | |
415 | + font-size: 0.9rem !important; | |
416 | +} | |
417 | + | |
418 | +/* ─── Mobile Responsive ─── */ | |
419 | +@media (max-width: 768px) { | |
420 | + .content h1 { | |
421 | + font-size: 1.75rem; | |
422 | + } | |
423 | + | |
424 | + .content h2 { | |
425 | + font-size: 1.3rem; | |
426 | + } | |
427 | + | |
428 | + .feature-grid { | |
429 | + grid-template-columns: 1fr; | |
430 | + } | |
431 | + | |
432 | + .performance-table { | |
433 | + font-size: 0.8rem; | |
434 | + } | |
435 | + | |
436 | + .performance-table th, | |
437 | + .performance-table td { | |
438 | + padding: 0.5rem 0.75rem; | |
439 | + } | |
440 | +} | |
441 | + | |
442 | +/* ─── Print Styles ─── */ | |
443 | +@media print { | |
444 | + .sidebar, | |
445 | + .toc-panel, | |
446 | + .edit-link, | |
447 | + .prev-next-nav { | |
448 | + display: none !important; | |
449 | + } | |
450 | + | |
451 | + .content { | |
452 | + max-width: 100%; | |
453 | + } | |
454 | +} | |
455 | + | |
456 | +/* ─── Focus Styles (Accessibility) ─── */ | |
457 | +:focus-visible { | |
458 | + outline: 2px solid var(--sl-color-accent); | |
459 | + outline-offset: 2px; | |
119 | 460 | border-radius: 4px; |
120 | 461 | } |
121 | 462 | |
122 | -pre { | |
123 | - border-radius: 8px; | |
124 | - border: 1px solid var(--sl-color-gray-5); | |
463 | +/* ─── Selection ─── */ | |
464 | +::selection { | |
465 | + background: rgba(139, 92, 246, 0.3); | |
466 | + color: var(--sl-color-white); | |
125 | 467 | } |
126 | 468 | |
127 | -.starlight-aside { | |
128 | - border-radius: 8px; | |
469 | +[data-theme='light'] ::selection { | |
470 | + background: rgba(139, 92, 246, 0.2); | |
471 | + color: var(--sl-color-black); | |
129 | 472 | } |
130 | 473 | |
131 | -.starlight-aside--note { | |
132 | - border-left-color: var(--sl-color-blue); | |
474 | +/* ─── Scrollbar ─── */ | |
475 | +::-webkit-scrollbar { | |
476 | + width: 8px; | |
477 | + height: 8px; | |
133 | 478 | } |
134 | 479 | |
135 | -.starlight-aside--tip { | |
136 | - border-left-color: var(--sl-color-accent); | |
480 | +::-webkit-scrollbar-track { | |
481 | + background: transparent; | |
137 | 482 | } |
138 | 483 | |
139 | -.starlight-aside--caution { | |
140 | - border-left-color: var(--sl-color-orange); | |
484 | +::-webkit-scrollbar-thumb { | |
485 | + background: var(--sl-color-gray-4, #64748b); | |
486 | + border-radius: 4px; | |
487 | +} | |
488 | + | |
489 | +::-webkit-scrollbar-thumb:hover { | |
490 | + background: var(--sl-color-gray-3, #94a3b8); | |
491 | +} | |
492 | + | |
493 | +/* ─── Animations ─── */ | |
494 | +@keyframes fadeInUp { | |
495 | + from { | |
496 | + opacity: 0; | |
497 | + transform: translateY(12px); | |
498 | + } | |
499 | + to { | |
500 | + opacity: 1; | |
501 | + transform: translateY(0); | |
502 | + } | |
503 | +} | |
504 | + | |
505 | +.content > * { | |
506 | + animation: fadeInUp 0.3s ease-out; | |
507 | +} | |
508 | + | |
509 | +/* ─── Starlight Overrides ─── */ | |
510 | +.starlight-sidebar > div { | |
511 | + border-right: 1px solid var(--sl-color-border, #e2e8f0); | |
512 | +} | |
513 | + | |
514 | +/* ─── Code Group Tabs ─── */ | |
515 | +.tab-label { | |
516 | + font-family: var(--sl-font-mono); | |
517 | + font-size: 0.8rem; | |
518 | +} | |
519 | + | |
520 | +/* ─── Gradient Text Utility ─── */ | |
521 | +.gradient-text { | |
522 | + background: linear-gradient(135deg, #e6522c, #8b5cf6, #3b82f6); | |
523 | + -webkit-background-clip: text; | |
524 | + -webkit-text-fill-color: transparent; | |
525 | + background-clip: text; | |
141 | 526 | } |
142 | 527 | |