[{"data":1,"prerenderedAt":457},["ShallowReactive",2],{"navigation_docs":3,"-reference-rate-limiting":100,"-reference-rate-limiting-surround":454},[4,35,80,90],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":6},"Getting Started",false,"\u002Fgetting-started","1.getting-started",[10,15,20,25,30],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F2.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F3.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Project Structure","\u002Fgetting-started\u002Fproject-structure","1.getting-started\u002F4.project-structure","i-lucide-folder-tree",{"title":26,"path":27,"stem":28,"icon":29},"Backend Server","\u002Fgetting-started\u002Fbackend","1.getting-started\u002F6.backend","i-lucide-server",{"title":31,"path":32,"stem":33,"icon":34},"Troubleshooting","\u002Fgetting-started\u002Ftroubleshooting","1.getting-started\u002F8.troubleshooting","i-lucide-wrench",{"title":36,"icon":6,"path":37,"stem":38,"children":39,"page":6},"API","\u002Fapi","2.api",[40,45,50,55,60,65,70,75],{"title":41,"path":42,"stem":43,"icon":44},"API Overview","\u002Fapi\u002Foverview","2.api\u002F1.overview","i-lucide-zap",{"title":46,"path":47,"stem":48,"icon":49},"TMDB Integration","\u002Fapi\u002Ftmdb-proxy","2.api\u002F2.tmdb-proxy","i-si-movie-line",{"title":51,"path":52,"stem":53,"icon":54},"Watched and My List APIs","\u002Fapi\u002Fwatched-movies","2.api\u002F3.watched-movies","i-lucide-eye",{"title":56,"path":57,"stem":58,"icon":59},"Recommendation Generation","\u002Fapi\u002Fgemini-recommendations","2.api\u002F4.gemini-recommendations","i-lucide-sparkles",{"title":61,"path":62,"stem":63,"icon":64},"Movie Search API","\u002Fapi\u002Fmovie-search","2.api\u002F5.movie-search","i-lucide-search",{"title":66,"path":67,"stem":68,"icon":69},"TMDB Import","\u002Fapi\u002Ftmdb-import","2.api\u002F6.tmdb-import","i-lucide-database",{"title":71,"path":72,"stem":73,"icon":74},"Movie Details & Caching","\u002Fapi\u002Fmovie-details","2.api\u002F7.movie-details","i-lucide-film",{"title":76,"path":77,"stem":78,"icon":79},"Recommendations (Cached)","\u002Fapi\u002Frecommendations-cache","2.api\u002F8.recommendations-cache","i-lucide-brain",{"title":81,"icon":6,"path":82,"stem":83,"children":84,"page":6},"Frontend","\u002Ffrontend","4.frontend",[85],{"title":86,"path":87,"stem":88,"icon":89},"Components","\u002Ffrontend\u002Fcomponents","4.frontend\u002F1.components","i-lucide-layout",{"title":91,"icon":6,"path":92,"stem":93,"children":94,"page":6},"Reference","\u002Freference","5.reference",[95],{"title":96,"path":97,"stem":98,"icon":99},"Rate Limiting","\u002Freference\u002Frate-limiting","5.reference\u002F2.rate-limiting","i-lucide-shield",{"id":101,"title":96,"body":102,"description":447,"extension":448,"links":449,"meta":450,"navigation":451,"path":97,"seo":452,"stem":98,"__hash__":453},"docs\u002F5.reference\u002F2.rate-limiting.md",{"type":103,"value":104,"toc":440},"minimark",[105,117,122,184,196,200,203,247,250,269,276,280,287,357,364,368,371,390,394,397,427,436],[106,107,108,109,116],"p",{},"TMDB-backed requests and recommendation generation are rate-limited using ",[110,111,115],"a",{"href":112,"rel":113},"https:\u002F\u002Fupstash.com\u002Fdocs\u002Fredis\u002Fsdks\u002Fratelimit-ts\u002Foverview",[114],"nofollow","Upstash Ratelimit"," with Upstash Redis.",[118,119,121],"h2",{"id":120},"limits","Limits",[123,124,125,144],"table",{},[126,127,128],"thead",{},[129,130,131,135,138,141],"tr",{},[132,133,134],"th",{},"Limiter",[132,136,137],{},"Limit",[132,139,140],{},"Window",[132,142,143],{},"Key",[145,146,147,168],"tbody",{},[129,148,149,156,159,162],{},[150,151,152],"td",{},[153,154,155],"code",{},"tmdbLimiter",[150,157,158],{},"40 requests",[150,160,161],{},"1 second",[150,163,164,165],{},"Global key ",[153,166,167],{},"tmdb:global",[129,169,170,175,178,181],{},[150,171,172],{},[153,173,174],{},"recommendationLimiter",[150,176,177],{},"10 requests",[150,179,180],{},"1 day",[150,182,183],{},"Authenticated user ID",[106,185,186,187,191,192,195],{},"The TMDB limiter uses a ",[188,189,190],"strong",{},"fixed window",". The recommendation limiter uses a ",[188,193,194],{},"sliding window",".",[118,197,199],{"id":198},"response-headers","Response Headers",[106,201,202],{},"TMDB-backed responses include:",[123,204,205,215],{},[126,206,207],{},[129,208,209,212],{},[132,210,211],{},"Header",[132,213,214],{},"Description",[145,216,217,227,237],{},[129,218,219,224],{},[150,220,221],{},[153,222,223],{},"X-RateLimit-Limit",[150,225,226],{},"Total requests allowed in the window",[129,228,229,234],{},[150,230,231],{},[153,232,233],{},"X-RateLimit-Remaining",[150,235,236],{},"Requests remaining in the current window",[129,238,239,244],{},[150,240,241],{},[153,242,243],{},"X-RateLimit-Reset",[150,245,246],{},"Timestamp (ms) when the window resets",[106,248,249],{},"The TMDB helper also emits:",[251,252,253,259,264],"ul",{},[254,255,256],"li",{},[153,257,258],{},"X-TMDB-RateLimit-Limit",[254,260,261],{},[153,262,263],{},"X-TMDB-RateLimit-Remaining",[254,265,266],{},[153,267,268],{},"X-TMDB-RateLimit-Reset",[106,270,271,272,275],{},"Recommendation generation responses include the standard ",[153,273,274],{},"X-RateLimit-*"," headers with the per-user daily quota values.",[118,277,279],{"id":278},"rate-limit-exceeded","Rate Limit Exceeded",[106,281,282,283,286],{},"When the TMDB limit is exceeded the server responds with ",[153,284,285],{},"429 Too Many Requests",":",[288,289,294],"pre",{"className":290,"code":291,"language":292,"meta":293,"style":293},"language-json shiki shiki-themes material-theme-lighter github-light github-dark","{\n  \"statusCode\": 429,\n  \"message\": \"Rate limit exceeded for TMDB API. Please try again later.\"\n}\n","json","",[153,295,296,305,328,351],{"__ignoreMap":293},[297,298,301],"span",{"class":299,"line":300},"line",1,[297,302,304],{"class":303},"sP7_E","{\n",[297,306,308,312,316,319,321,325],{"class":299,"line":307},2,[297,309,311],{"class":310},"s39Yj","  \"",[297,313,315],{"class":314},"sseR_","statusCode",[297,317,318],{"class":310},"\"",[297,320,286],{"class":303},[297,322,324],{"class":323},"srdBf"," 429",[297,326,327],{"class":303},",\n",[297,329,331,333,336,338,340,344,348],{"class":299,"line":330},3,[297,332,311],{"class":310},[297,334,335],{"class":314},"message",[297,337,318],{"class":310},[297,339,286],{"class":303},[297,341,343],{"class":342},"sjJ54"," \"",[297,345,347],{"class":346},"s_sjI","Rate limit exceeded for TMDB API. Please try again later.",[297,349,350],{"class":342},"\"\n",[297,352,354],{"class":299,"line":353},4,[297,355,356],{"class":303},"}\n",[106,358,359,360,363],{},"When the recommendation limit is exceeded the server responds with ",[153,361,362],{},"429"," and a daily quota message.",[118,365,367],{"id":366},"implementation","Implementation",[106,369,370],{},"The limiters are defined in their owning utility domains and applied in:",[251,372,373,382],{},[254,374,375,378,379,381],{},[153,376,377],{},"server\u002Futils\u002Ftmdb\u002Frate-limit.ts"," before outbound TMDB requests (",[153,380,155],{},")",[254,383,384,387,388,381],{},[153,385,386],{},"server\u002Futils\u002Frecommendations\u002Frate-limit.ts"," for authenticated recommendation generation (",[153,389,174],{},[118,391,393],{"id":392},"environment-setup","Environment Setup",[106,395,396],{},"Two Upstash Redis environment variables are required:",[288,398,402],{"className":399,"code":400,"language":401,"meta":293,"style":293},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark","UPSTASH_REDIS_REST_URL=https:\u002F\u002Fyour-db.upstash.io\nUPSTASH_REDIS_REST_TOKEN=your_token_here\n","bash",[153,403,404,417],{"__ignoreMap":293},[297,405,406,410,414],{"class":299,"line":300},[297,407,409],{"class":408},"su5hD","UPSTASH_REDIS_REST_URL",[297,411,413],{"class":412},"smGrS","=",[297,415,416],{"class":346},"https:\u002F\u002Fyour-db.upstash.io\n",[297,418,419,422,424],{"class":299,"line":307},[297,420,421],{"class":408},"UPSTASH_REDIS_REST_TOKEN",[297,423,413],{"class":412},[297,425,426],{"class":346},"your_token_here\n",[106,428,429,430,435],{},"Get these from ",[110,431,434],{"href":432,"rel":433},"https:\u002F\u002Fconsole.upstash.com",[114],"Upstash console"," after creating a Redis database.",[437,438,439],"style",{},"html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sseR_, html code.shiki .sseR_{--shiki-light:#9C3EDA;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":293,"searchDepth":307,"depth":307,"links":441},[442,443,444,445,446],{"id":120,"depth":307,"text":121},{"id":198,"depth":307,"text":199},{"id":278,"depth":307,"text":279},{"id":366,"depth":307,"text":367},{"id":392,"depth":307,"text":393},"Rate limiting for TMDB-backed requests and recommendation generation","md",null,{},{"icon":99},{"title":96,"description":447},"f9AxRiCbEAiw6kkw4WrKLRv-LfA5cxYeo8iKxJDnqxM",[455,449],{"title":86,"path":87,"stem":88,"description":456,"icon":89,"children":-1},"Vue components and pages structure",1782138813000]