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 | .venv/ | 29 | .venv/ | ||
| 30 | .pytest_cache/ | 30 | .pytest_cache/ | ||
| 31 | .ruff_cache/ | 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 | 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). | 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 | ### 4.4 Homepage | 155 | ### 4.4 Homepage | ||
modified
hfmarketdata/api/openapi.py
+1 −0
@@ -97,6 +97,7 @@ def build(app: FastAPI) -> dict: | |||||
| 97 | responses["422"]["description"] = "`VALIDATION_ERROR` — " + CODES["VALIDATION_ERROR"] | 97 | responses["422"]["description"] = "`VALIDATION_ERROR` — " + CODES["VALIDATION_ERROR"] | ||
| 98 | responses["422"]["content"] = {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}} | 98 | responses["422"]["content"] = {"application/json": {"schema": {"$ref": "#/components/schemas/Error"}}} | ||
| 99 | schema["info"]["x-logo"] = {"url": settings.public_url + "/logo.svg"} | 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 | schema["info"]["x-tiers"] = { | 101 | schema["info"]["x-tiers"] = { | ||
| 101 | "keyless": {"window": "1h", "requests": 30, "rows": 100_000, "max_rows_per_request": 5_000}, | 102 | "keyless": {"window": "1h", "requests": 30, "rows": 100_000, "max_rows_per_request": 5_000}, | ||
| 102 | "free": {"window": "1m", "requests": 120, "rows": 1_000_000, "max_rows_per_request": 50_000}, | 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 | // Route table — one lazy chunk per area. Owners: web-core (home, pricing, docs, status, layout), | 1 | // Route table — one lazy chunk per area. Owners: web-core (home, pricing, docs, status, layout), | ||
| 2 | // web-app (playground, auth, dashboard, admin), mcp-skills (integrations). | 2 | // web-app (playground, auth, dashboard, admin), mcp-skills (integrations). | ||
| 3 | import React, { Suspense, lazy } from 'react' | 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 | import Layout from './app/Layout.jsx' | 5 | import Layout from './app/Layout.jsx' | ||
| 6 | 6 | ||||
| 7 | const Home = lazy(() => import('./pages/home/Home.jsx')) | 7 | const Home = lazy(() => import('./pages/home/Home.jsx')) | ||
| 8 | const Docs = lazy(() => import('./pages/docs/Docs.jsx')) | 8 | const Docs = lazy(() => import('./pages/docs/Docs.jsx')) | ||
| 9 | const Playground = lazy(() => import('./pages/playground/Playground.jsx')) | 9 | const Playground = lazy(() => import('./pages/playground/Playground.jsx')) | ||
| 10 | const Integrations = lazy(() => import('./pages/integrations/Integrations.jsx')) | 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 | const Status = lazy(() => import('./pages/status/Status.jsx')) | 12 | const Status = lazy(() => import('./pages/status/Status.jsx')) | ||
| 13 | const Auth = lazy(() => import('./pages/auth/Auth.jsx')) | 13 | const Auth = lazy(() => import('./pages/auth/Auth.jsx')) | ||
| 14 | const Dashboard = lazy(() => import('./pages/dashboard/Dashboard.jsx')) | 14 | const Dashboard = lazy(() => import('./pages/dashboard/Dashboard.jsx')) | ||
@@ -24,7 +24,8 @@ export default function App() { | |||||
| 24 | <Route path="/docs/*" element={<Docs />} /> | 24 | <Route path="/docs/*" element={<Docs />} /> | ||
| 25 | <Route path="/playground" element={<Playground />} /> | 25 | <Route path="/playground" element={<Playground />} /> | ||
| 26 | <Route path="/integrations/*" element={<Integrations />} /> | 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 | <Route path="/status" element={<Status />} /> | 29 | <Route path="/status" element={<Status />} /> | ||
| 29 | <Route path="/signin" element={<Auth mode="signin" />} /> | 30 | <Route path="/signin" element={<Auth mode="signin" />} /> | ||
| 30 | <Route path="/signup" element={<Auth mode="signup" />} /> | 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 | const NAV = [ | 6 | const NAV = [ | ||
| 7 | ['/docs', 'Docs'], ['/playground', 'Playground'], ['/integrations', 'Integrations'], | 7 | ['/docs', 'Docs'], ['/playground', 'Playground'], ['/integrations', 'Integrations'], | ||
| 8 | − ['/pricing', 'Pricing / Limits'], ['/status', 'Status'], | 8 | + ['/limits', 'Limits'], ['/status', 'Status'], | ||
| 9 | ] | 9 | ] | ||
| 10 | 10 | ||||
| 11 | export default function Layout({ children }) { | 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 | export const TIERS = [ | 7 | export const TIERS = [ | ||
| 8 | { id: 'keyless', name: 'Keyless (per IP)', window: 'hour', requests: 30, rows: 100_000, maxRows: 5_000 }, | 8 | { id: 'keyless', name: 'Keyless (per IP)', window: 'hour', requests: 30, rows: 100_000, maxRows: 5_000 }, | ||
| 9 | { id: 'free', name: 'Free account + API key', window: 'minute', requests: 120, rows: 1_000_000, maxRows: 50_000 }, | 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 | export function rateHeaders(res) { | 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 | import React from 'react' | 1 | import React from 'react' | ||
| 2 | // Placeholder — implemented by the owning agent (see App.jsx header). Keep the default export name. | 2 | // Placeholder — implemented by the owning agent (see App.jsx header). Keep the default export name. | ||
| 3 | −export default function Pricing() { | 3 | +export default function Limits() { | ||
| 4 | − return <main className="page"><h1>Pricing</h1><p className="muted">Coming soon.</p></main> | 4 | + return <main className="page"><h1>Limits</h1><p className="muted">Coming soon.</p></main> | ||
| 5 | } | 5 | } | ||
| 6 | 6 | ||||