You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ScoreBreakdown rendered `<li>{suggestion}</li>` directly. when the LLM
returned StructuredSuggestion objects (with summary/details/impact/
platforms) instead of plain strings, svelte's text interpolation fell
back to String(obj) and shipped "[object Object]" to the page. fixed
with type-narrowing helpers (same pattern report.ts and ScoreDashboard
already use); structured suggestions now show their summary plus a
nested list of their details.
ScoreDashboard had the same class of bug in its non-deduplicated path
at the !structured fallback (`<p>{suggestion}</p>`). hardened with a
typeof guard so any malformed value renders empty rather than
"[object Object]".
JobDescriptionInput's debounced parser ran inside a fire-and-forget
async IIFE with no .catch(); a transient parser failure would surface
as an unhandled promise rejection. wrapped in try/catch with a
console.warn so the scan flow stays unaffected.
docs:
- api/rate-limits: documents the new 429 body shape (retryAfter field
+ reason discriminator) and the Retry-After header
- api/endpoints: documents the _cached response field, the in-memory
cache behavior, and lists the new auxiliary endpoints (/healthz,
/robots.txt, /sitemap.xml, /api/og, /share, /api/csp-report)
- pnpm build:docs run; static/docs refreshed
dry-tested via curl: /healthz, /robots.txt, /sitemap.xml, /api/og
(magic bytes valid + correct cache-control), /share, rate limiter
(11th request 429 with retry-after: 60), and a full LLM cache-hit
round-trip (46s -> 81ms, 573x). 183 tests + lint + typecheck + build
all green.
|`results[].breakdown`| object | Per-dimension scores and details |
121
+
|`results[].suggestions`| string \| StructuredItem[]| Platform-specific improvement tips. May be plain strings (rule-based) or structured objects (LLM-enhanced) |
122
+
|`_provider`| string | Which LLM provider handled the request (e.g. `gemma-3-27b`, `groq-llama-3.3-70b`) |
123
+
|`_fallback`| boolean |`true` when all providers failed and the client must fall back to local rule-based scoring |
124
+
|`_cached`| boolean |`true` when the response was served from the in-memory result cache (sub-100ms, zero LLM cost) |
125
+
126
+
The server keeps a SHA-256 keyed in-memory LRU of recent prompts (200 entries, 24h TTL). Identical input hits the cache and returns instantly — the `_cached` flag tells you whether the response was a hit. The cache lives per Vercel instance; cold starts begin empty.
Copy file name to clipboardExpand all lines: docs/src/content/docs/api/rate-limits.md
+14-4Lines changed: 14 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -32,18 +32,28 @@ Cache-Control: no-store
32
32
33
33
## Handling Rate Limits
34
34
35
-
When you receive a `429` response:
35
+
When you receive a `429` response, the body distinguishes which window was hit and the response includes a `Retry-After` header set to the seconds-until-reset for that window:
36
+
37
+
```http
38
+
HTTP/1.1 429 Too Many Requests
39
+
Retry-After: 60
40
+
Content-Type: application/json
41
+
```
36
42
37
43
```json
38
44
{
39
-
"error": "rate limit exceeded. try again in 60 seconds."
45
+
"error": "rate limit exceeded: too many requests this minute. retry after 60s.",
46
+
"retryAfter": 60
40
47
}
41
48
```
42
49
50
+
The error string ends with either `too many requests this minute` (per-minute window) or `daily limit reached` (per-day window). The `retryAfter` field (seconds) and the `Retry-After` header always match; clients can use either.
51
+
43
52
**Best practices:**
44
53
45
-
- Implement exponential backoff in your client
46
-
- Cache results locally to avoid redundant requests
54
+
- Honor the `Retry-After` header — it is the exact reset window for the limit you tripped
55
+
- Cache results locally to avoid redundant requests (the server also caches identical inputs in-memory; see the `_cached` flag in [endpoints](./endpoints))
56
+
- Implement exponential backoff for transient 5xx errors (rate-limit 429s should use Retry-After directly)
47
57
- For high-volume use, self-host with your own API keys
0 commit comments