Spaces:
Running
Running
Commit History
-
perf(api): compress + revalidate catalog responses
Catalog endpoints (`/api/apps`, `/api/js-apps`) previously shipped ~40KB of JSON uncompressed on every hit, with no cache headers and a body-embedded `cacheAge` counter that auto-invalidated Express's ETag every second. This commit: - Adds `compression` middleware: ~40KB JSON -> ~5.5KB on the wire (-86%). - Promotes `cacheAge` from body field to the standard `Age` HTTP header (RFC 7234 sec 5.1). With the volatile field gone, the response body is byte-stable across same-cache-window requests, so Express's default weak ETag becomes usable for conditional revalidation (`If-None-Match` -> 304 with no body). - Sets `Cache-Control: public, max-age=60, stale-while-revalidate=300` via a shared helper so both endpoints stay coherent. - Exposes `Age` via `Access-Control-Expose-Headers` so cross-origin JS clients (mobile shell, desktop store) can read it from `response.headers.get('age')`. - Updates `AppsContext` (same-origin website client) to read the…a91ec59
-
feat(api): mint per-user OpenAI Realtime ephemeral keys
New POST /api/openai/ephemeral endpoint: validates the caller's HF Bearer token via whoami-v2, rate-limits per HF user (60/hour default), and proxies POST /v1/realtime/sessions to OpenAI with the master OPENAI_API_KEY from the Space secrets. Lets the Reachy Mini mobile shell stop baking a long-lived OpenAI key into the distributed bundle (OpenAI ToS + extraction risk). Co-authored-by: Cursor <cursoragent@cursor.com>13ada57
-
feat(api): expose category taxonomy to clients
Ships the closed category taxonomy alongside the apps payload so clients (mobile shell, future website filter chips) no longer have to mirror the slug list by hand, which silently drifted over time (e.g. `games` missing from the mobile mirror, `dance` outliving its rename to `motion`). - `getPublicTaxonomy()` in `categories.js`: stable, minimal projection (`{slug, label, emoji, order}`) - the LLM-only `description` field stays internal. - `/api/js-apps` embeds it under `categorization.taxonomy` so the mobile catalog fetch stays a single round-trip. - New `GET /api/categories` for clients that only want the slug list (early UI scaffolding, tooling). 5-min cache aligned with the catalog TTL. Forward-compatible: old clients ignore the new fields; new clients fall back to a local snapshot when the field is missing. Co-authored-by: Cursor <cursoragent@cursor.com>20e2e73
-
refactor(icons): probe public/icon.svg instead of root icon.svg
Single source of truth: apps now ship only `public/icon.svg`, which Vite copies to `dist/icon.svg` for nginx serving (favicon, mountHost top-bar logo) and the catalog server resolves via the HF API. Co-authored-by: Cursor <cursoragent@cursor.com>f01ae59 -
refactor(api): scope dedup per route to surface JS-only same-name apps
Move the name-based dedup out of `fetchAppsFromHF` so each route can apply its own policy on top of a single raw cache: - `/api/apps` (showcase site) keeps the original global dedup, so Python forks of `reachy_mini_conversation_app` etc. still collapse to a single tile. - `/api/js-apps` (mobile shell) now dedups within the JS subset only, so a JS Space like `tfrere/emotions` no longer loses a name fight against an unrelated Python Space (`RemiFabre/emotions`) and surfaces correctly in the store. `getApps()` is renamed to `getRawApps()` to make the cache contract explicit, and `dedupAppsByName` is shared between `dedupGlobalApps` and `dedupJsApps` so the policies can diverge later without churn. Co-authored-by: Cursor <cursoragent@cursor.com>196fa01
-
feat(api): publish iconUrl on /api/js-apps from Space siblings
Detects a custom app glyph by scanning each Space's `siblings` (returned by HF's `?full=true`) for `icon.svg` or `icon.png` at the repo root, then emits an absolute `resolve/main/<file>` URL on the app entry as `iconUrl`. Falls back to `null` when neither candidate is present, so clients keep painting the front-matter emoji for the long tail of apps that don't ship a custom icon. SVG wins over PNG when both are present so authors can rely on a single vector asset across every mount point. Resolution lives server-side behind the existing 5-minute catalog cache, so the lookup cost stays O(apps) per refresh - independent of client fleet size. The HF API call already pulls `siblings` via `full=true`; no extra network roundtrip. Documents the convention in docs/APP_ICON_CONVENTION.md for app authors. Co-authored-by: Cursor <cursoragent@cursor.com>07a94f1
-
feat(api): /api/js-apps with LLM-inferred categories
Add a curated route that filters the catalog to JS-embeddable apps (`reachy_mini_js_app` tag) and enriches each entry with categories inferred by Llama-3.1-8B-Instruct via HF Inference Providers, from a closed taxonomy of 8 slugs (music, dance, voice, storytelling, kids, vision, companion, dev-tools). Inference results are persisted in a HF dataset (`tfrere/reachy-mini-app-categories` by default, override via HF_CATEGORIES_DATASET) and re-loaded at boot, so cold starts only re-classify what actually changed (lastModified-keyed staleness). Pre-existing /api/apps payload is unchanged: this is purely additive. Mobile shell can adopt /api/js-apps incrementally. - server/categories.js: 8-slug taxonomy + LLM-friendly descriptions - server/categorize.js: README fetch/clean + chat-completion call - server/categoryCache.js: in-mem map + dataset commit/load - server/index.js: route, warmup batch, manual refresh endpoint - .env.example: HF_TOKEN + HF_CATEGORIES_DATASET docs - .gitignore: igno…0441ab1
-
fix: deduplicate forked spaces with identical repo names
Forks of apps (e.g. reachy_mini_conversation_app) keep the same repo name, causing duplicates in the app store. Deduplicate by name with priority: 1) official, 2) oldest (original), 3) most likes. Also expose createdAt from HF API for accurate original detection. Co-authored-by: Cursor <cursoragent@cursor.com>faacae5
-
perf: reduce apps cache TTL from 24h to 5min
HF Hub API rate limits allow up to 1000 requests per 5-minute window for free users. With only 2 API calls per refresh, a 5-minute cache is well within limits and ensures new community apps appear quickly. Co-authored-by: Cursor <cursoragent@cursor.com>eee87e9
-
fix: pass OAuth clientId from server to frontend for Docker Spaces
Docker Spaces don't auto-inject window.huggingface.variables like static Spaces do. Add /api/oauth-config endpoint that exposes OAUTH_CLIENT_ID and OAUTH_SCOPES from server env vars to the frontend. AuthContext now fetches this config on mount and passes clientId to oauthLoginUrl(). Sign-in UI is hidden when OAuth is not available (e.g. local dev). Co-authored-by: Cursor <cursoragent@cursor.com>45671b3 -
Refactor API to desktop-compatible format
- Add url, source_kind, downloads, runtime fields - Move metadata into extra object structure - Update frontend to use new extra.* accessors - Enables desktop app to use website API directly Co-authored-by: Cursor <cursoragent@cursor.com>4d77ab0
-
Add Express server with 24h cache + differentiate web/python apps
- Add Express server that caches HF API responses for 24 hours - Fetch all reachy_mini tagged apps (not just python apps) - Differentiate web apps (open in new tab) vs python apps (install modal) - Web apps show purple "Web" badge and "Open" button - Dynamic app count on Home page (rounded to nearest 10) - Vite proxy config for local developmente8700c6