web: pas de tarification — page Limits (/limits, /pricing redirige), libellés « free, higher limits on request », x-pricing OpenAPI
7 changed files +13 −8
modified
.gitignore
+3 −0
@@ -29,3 +29,6 @@ hfmarketdata/venv/ | ||
| 29 | 29 | .venv/ |
| 30 | 30 | .pytest_cache/ |
| 31 | 31 | .ruff_cache/ |
| 32 | + | |
| 33 | +# worktrees des agents / état local Claude | |
| 34 | +.claude/ | |
modified
docs/UPGRADE-PLAN.md
+1 −1
@@ -149,7 +149,7 @@ Getting started Guides Reference (OpenAPI) | ||
| 149 | 149 | └────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ |
| 150 | 150 | ``` |
| 151 | 151 | |
| 152 | −### 4.3 Pricing / Limits (`/pricing`) | |
| 152 | +### 4.3 Access & limits (`/limits`) — tout est gratuit | |
| 153 | 153 | Tableau 3 colonnes (Keyless · Free account · High usage) avec les 6 chiffres, CTA « Create free account » et « Request high usage → contact@spboucher.ai », encart « incitations » (Parquet = ½ coût, bulk hors quota, ETag/304 gratuits). |
| 154 | 154 | |
| 155 | 155 | ### 4.4 Homepage |
modified
hfmarketdata/api/openapi.py
+1 −0
@@ -97,6 +97,7 @@ def build(app: FastAPI) -> dict: | ||
| 97 | 97 | responses["422"]["description"] = "`VALIDATION_ERROR` — " + CODES["VALIDATION_ERROR"] |
| 98 | 98 | responses["422"]["content"] = {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}} |
| 99 | 99 | schema["info"]["x-logo"] = {"url": settings.public_url + "/logo.svg"} |
| 100 | + schema["info"]["x-pricing"] = {"free": True, "note": "HF Market Data is free. Higher limits are granted on request (free) — e-mail %s." % settings.contact_email} | |
| 100 | 101 | schema["info"]["x-tiers"] = { |
| 101 | 102 | "keyless": {"window": "1h", "requests": 30, "rows": 100_000, "max_rows_per_request": 5_000}, |
| 102 | 103 | "free": {"window": "1m", "requests": 120, "rows": 1_000_000, "max_rows_per_request": 50_000}, |
modified
hfmarketdata/web/src/App.jsx
+4 −3
@@ -1,14 +1,14 @@ | ||
| 1 | 1 | // Route table — one lazy chunk per area. Owners: web-core (home, pricing, docs, status, layout), |
| 2 | 2 | // web-app (playground, auth, dashboard, admin), mcp-skills (integrations). |
| 3 | 3 | import React, { Suspense, lazy } from 'react' |
| 4 | −import { Route, Routes } from 'react-router-dom' | |
| 4 | +import { Navigate, Route, Routes } from 'react-router-dom' | |
| 5 | 5 | import Layout from './app/Layout.jsx' |
| 6 | 6 | |
| 7 | 7 | const Home = lazy(() => import('./pages/home/Home.jsx')) |
| 8 | 8 | const Docs = lazy(() => import('./pages/docs/Docs.jsx')) |
| 9 | 9 | const Playground = lazy(() => import('./pages/playground/Playground.jsx')) |
| 10 | 10 | const Integrations = lazy(() => import('./pages/integrations/Integrations.jsx')) |
| 11 | −const Pricing = lazy(() => import('./pages/pricing/Pricing.jsx')) | |
| 11 | +const Limits = lazy(() => import('./pages/limits/Limits.jsx')) | |
| 12 | 12 | const Status = lazy(() => import('./pages/status/Status.jsx')) |
| 13 | 13 | const Auth = lazy(() => import('./pages/auth/Auth.jsx')) |
| 14 | 14 | const Dashboard = lazy(() => import('./pages/dashboard/Dashboard.jsx')) |
@@ -24,7 +24,8 @@ export default function App() { | ||
| 24 | 24 | <Route path="/docs/*" element={<Docs />} /> |
| 25 | 25 | <Route path="/playground" element={<Playground />} /> |
| 26 | 26 | <Route path="/integrations/*" element={<Integrations />} /> |
| 27 | − <Route path="/pricing" element={<Pricing />} /> | |
| 27 | + <Route path="/limits" element={<Limits />} /> | |
| 28 | + <Route path="/pricing" element={<Navigate to="/limits" replace />} /> | |
| 28 | 29 | <Route path="/status" element={<Status />} /> |
| 29 | 30 | <Route path="/signin" element={<Auth mode="signin" />} /> |
| 30 | 31 | <Route path="/signup" element={<Auth mode="signup" />} /> |
modified
hfmarketdata/web/src/app/Layout.jsx
+1 −1
@@ -5,7 +5,7 @@ import { CONTACT_EMAIL } from './api.js' | ||
| 5 | 5 | |
| 6 | 6 | const NAV = [ |
| 7 | 7 | ['/docs', 'Docs'], ['/playground', 'Playground'], ['/integrations', 'Integrations'], |
| 8 | − ['/pricing', 'Pricing / Limits'], ['/status', 'Status'], | |
| 8 | + ['/limits', 'Limits'], ['/status', 'Status'], | |
| 9 | 9 | ] |
| 10 | 10 | |
| 11 | 11 | export default function Layout({ children }) { |
modified
hfmarketdata/web/src/app/api.js
+1 −1
@@ -7,7 +7,7 @@ export const CONTACT_EMAIL = 'contact@spboucher.ai' | ||
| 7 | 7 | export const TIERS = [ |
| 8 | 8 | { id: 'keyless', name: 'Keyless (per IP)', window: 'hour', requests: 30, rows: 100_000, maxRows: 5_000 }, |
| 9 | 9 | { id: 'free', name: 'Free account + API key', window: 'minute', requests: 120, rows: 1_000_000, maxRows: 50_000 }, |
| 10 | − { id: 'high_usage', name: 'High usage (on request)', window: 'minute', requests: 600, rows: 10_000_000, maxRows: 200_000 }, | |
| 10 | + { id: 'high_usage', name: 'Higher limits (free, on request)', window: 'minute', requests: 600, rows: 10_000_000, maxRows: 200_000 }, | |
| 11 | 11 | ] |
| 12 | 12 | |
| 13 | 13 | export function rateHeaders(res) { |
renamed
hfmarketdata/web/src/pages/pricing/Pricing.jsx → hfmarketdata/web/src/pages/limits/Limits.jsx
+2 −2
@@ -1,5 +1,5 @@ | ||
| 1 | 1 | import React from 'react' |
| 2 | 2 | // Placeholder — implemented by the owning agent (see App.jsx header). Keep the default export name. |
| 3 | −export default function Pricing() { | |
| 4 | − return <main className="page"><h1>Pricing</h1><p className="muted">Coming soon.</p></main> | |
| 3 | +export default function Limits() { | |
| 4 | + return <main className="page"><h1>Limits</h1><p className="muted">Coming soon.</p></main> | |
| 5 | 5 | } |
| 6 | 6 | |