[{"data":1,"prerenderedAt":2786},["ShallowReactive",2],{"navigation_docs":3,"docs-navigation-with-icons":419,"-docs-api-best-practices":561,"-docs-api-best-practices-surround":2783},[4,66,87,124,405],{"title":5,"path":6,"stem":7,"children":8,"page":65},"Api","\u002Fdocs\u002Fapi","docs\u002Fapi",[9,13,17,21,25,29,33,37,41,45,49,53,57,61],{"title":10,"path":11,"stem":12},"Best Practices","\u002Fdocs\u002Fapi\u002Fbest-practices","docs\u002Fapi\u002Fbest-practices",{"title":14,"path":15,"stem":16},"Blog","\u002Fdocs\u002Fapi\u002Fblog","docs\u002Fapi\u002Fblog",{"title":18,"path":19,"stem":20},"Code Examples","\u002Fdocs\u002Fapi\u002Fcode-examples","docs\u002Fapi\u002Fcode-examples",{"title":22,"path":23,"stem":24},"Collections","\u002Fdocs\u002Fapi\u002Fcollections","docs\u002Fapi\u002Fcollections",{"title":26,"path":27,"stem":28},"Field Types","\u002Fdocs\u002Fapi\u002Ffield-types","docs\u002Fapi\u002Ffield-types",{"title":30,"path":31,"stem":32},"Rate Limits & Errors","\u002Fdocs\u002Fapi\u002Flimits-and-errors","docs\u002Fapi\u002Flimits-and-errors",{"title":34,"path":35,"stem":36},"Media","\u002Fdocs\u002Fapi\u002Fmedia","docs\u002Fapi\u002Fmedia",{"title":38,"path":39,"stem":40},"Overview","\u002Fdocs\u002Fapi\u002Foverview","docs\u002Fapi\u002Foverview",{"title":42,"path":43,"stem":44},"Pages","\u002Fdocs\u002Fapi\u002Fpages","docs\u002Fapi\u002Fpages",{"title":46,"path":47,"stem":48},"Query Parameters","\u002Fdocs\u002Fapi\u002Fquery-parameters","docs\u002Fapi\u002Fquery-parameters",{"title":50,"path":51,"stem":52},"Responses & Caching","\u002Fdocs\u002Fapi\u002Fresponses","docs\u002Fapi\u002Fresponses",{"title":54,"path":55,"stem":56},"Troubleshooting","\u002Fdocs\u002Fapi\u002Ftroubleshooting","docs\u002Fapi\u002Ftroubleshooting",{"title":58,"path":59,"stem":60},"Validation","\u002Fdocs\u002Fapi\u002Fvalidation","docs\u002Fapi\u002Fvalidation",{"title":62,"path":63,"stem":64},"Webhooks","\u002Fdocs\u002Fapi\u002Fwebhooks","docs\u002Fapi\u002Fwebhooks",false,{"title":67,"path":68,"stem":69,"children":70,"page":65},"Getting Started","\u002Fdocs\u002Fgetting-started","docs\u002Fgetting-started",[71,75,79,83],{"title":72,"path":73,"stem":74},"Authentication","\u002Fdocs\u002Fgetting-started\u002Fauthentication","docs\u002Fgetting-started\u002Fauthentication",{"title":76,"path":77,"stem":78},"Introduction","\u002Fdocs\u002Fgetting-started\u002Fintroduction","docs\u002Fgetting-started\u002Fintroduction",{"title":80,"path":81,"stem":82},"Quickstart","\u002Fdocs\u002Fgetting-started\u002Fquickstart","docs\u002Fgetting-started\u002Fquickstart",{"title":84,"path":85,"stem":86},"Write Operations","\u002Fdocs\u002Fgetting-started\u002Fwrite-operations","docs\u002Fgetting-started\u002Fwrite-operations",{"title":88,"path":89,"stem":90,"children":91,"page":65},"Guides","\u002Fdocs\u002Fguides","docs\u002Fguides",[92,96,100,104,108,112,116,120],{"title":93,"path":94,"stem":95},"Admin Interface","\u002Fdocs\u002Fguides\u002Fadmin-interface","docs\u002Fguides\u002Fadmin-interface",{"title":97,"path":98,"stem":99},"ButterCMS Migration","\u002Fdocs\u002Fguides\u002Fbuttercms-migration","docs\u002Fguides\u002Fbuttercms-migration",{"title":101,"path":102,"stem":103},"Migrations","\u002Fdocs\u002Fguides\u002Fmigrations","docs\u002Fguides\u002Fmigrations",{"title":105,"path":106,"stem":107},"Page Management","\u002Fdocs\u002Fguides\u002Fpage-management","docs\u002Fguides\u002Fpage-management",{"title":109,"path":110,"stem":111},"Public API Usage","\u002Fdocs\u002Fguides\u002Fpublic-api-usage","docs\u002Fguides\u002Fpublic-api-usage",{"title":113,"path":114,"stem":115},"Schema Builder","\u002Fdocs\u002Fguides\u002Fschema-builder","docs\u002Fguides\u002Fschema-builder",{"title":117,"path":118,"stem":119},"User Management","\u002Fdocs\u002Fguides\u002Fuser-management","docs\u002Fguides\u002Fuser-management",{"title":121,"path":122,"stem":123},"Rich Text Editor","\u002Fdocs\u002Fguides\u002Fwysiwyg-editor","docs\u002Fguides\u002Fwysiwyg-editor",{"title":125,"path":126,"stem":127,"children":128,"page":65},"Sdk","\u002Fdocs\u002Fsdk","docs\u002Fsdk",[129,132,136,140,144],{"title":38,"path":130,"stem":131},"\u002Fdocs\u002Fsdk\u002Freadme","docs\u002Fsdk\u002FREADME",{"title":133,"path":134,"stem":135},"Astro","\u002Fdocs\u002Fsdk\u002Fastro","docs\u002Fsdk\u002Fastro",{"title":137,"path":138,"stem":139},"Next.js","\u002Fdocs\u002Fsdk\u002Fnextjs","docs\u002Fsdk\u002Fnextjs",{"title":141,"path":142,"stem":143},"Nuxt","\u002Fdocs\u002Fsdk\u002Fnuxt","docs\u002Fsdk\u002Fnuxt",{"title":145,"path":146,"stem":147,"children":148,"page":65},"Reference","\u002Fdocs\u002Fsdk\u002Freference","docs\u002Fsdk\u002Freference",[149,153,222,235,380],{"title":150,"path":151,"stem":152},"@tentocms\u002Fclient","\u002Fdocs\u002Fsdk\u002Freference\u002Freadme","docs\u002Fsdk\u002Freference\u002FREADME",{"title":154,"path":155,"stem":156,"children":157,"page":65},"Classes","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses","docs\u002Fsdk\u002Freference\u002Fclasses",[158,162,166,170,174,178,182,186,190,194,198,202,206,210,214,218],{"title":159,"path":160,"stem":161},"Class: BlogCategoriesResource","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses\u002Fblogcategoriesresource","docs\u002Fsdk\u002Freference\u002Fclasses\u002FBlogCategoriesResource",{"title":163,"path":164,"stem":165},"Class: BlogPostsResource","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses\u002Fblogpostsresource","docs\u002Fsdk\u002Freference\u002Fclasses\u002FBlogPostsResource",{"title":167,"path":168,"stem":169},"Class: BlogResource","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses\u002Fblogresource","docs\u002Fsdk\u002Freference\u002Fclasses\u002FBlogResource",{"title":171,"path":172,"stem":173},"Class: BlogTagsResource","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses\u002Fblogtagsresource","docs\u002Fsdk\u002Freference\u002Fclasses\u002FBlogTagsResource",{"title":175,"path":176,"stem":177},"Class: CollectionsResource","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses\u002Fcollectionsresource","docs\u002Fsdk\u002Freference\u002Fclasses\u002FCollectionsResource",{"title":179,"path":180,"stem":181},"Class: CollectionsWriteResource","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses\u002Fcollectionswriteresource","docs\u002Fsdk\u002Freference\u002Fclasses\u002FCollectionsWriteResource",{"title":183,"path":184,"stem":185},"Class: MediaResource","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses\u002Fmediaresource","docs\u002Fsdk\u002Freference\u002Fclasses\u002FMediaResource",{"title":187,"path":188,"stem":189},"Class: MediaWriteResource","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses\u002Fmediawriteresource","docs\u002Fsdk\u002Freference\u002Fclasses\u002FMediaWriteResource",{"title":191,"path":192,"stem":193},"Class: PagesResource","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses\u002Fpagesresource","docs\u002Fsdk\u002Freference\u002Fclasses\u002FPagesResource",{"title":195,"path":196,"stem":197},"Class: PagesWriteResource","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses\u002Fpageswriteresource","docs\u002Fsdk\u002Freference\u002Fclasses\u002FPagesWriteResource",{"title":199,"path":200,"stem":201},"Class: TentoAuthenticationError","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses\u002Ftentoauthenticationerror","docs\u002Fsdk\u002Freference\u002Fclasses\u002FTentoAuthenticationError",{"title":203,"path":204,"stem":205},"Class: TentoClient","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses\u002Ftentoclient","docs\u002Fsdk\u002Freference\u002Fclasses\u002FTentoClient",{"title":207,"path":208,"stem":209},"Class: TentoError","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses\u002Ftentoerror","docs\u002Fsdk\u002Freference\u002Fclasses\u002FTentoError",{"title":211,"path":212,"stem":213},"Class: TentoNetworkError","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses\u002Ftentonetworkerror","docs\u002Fsdk\u002Freference\u002Fclasses\u002FTentoNetworkError",{"title":215,"path":216,"stem":217},"Class: TentoNotFoundError","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses\u002Ftentonotfounderror","docs\u002Fsdk\u002Freference\u002Fclasses\u002FTentoNotFoundError",{"title":219,"path":220,"stem":221},"Class: TentoRateLimitError","\u002Fdocs\u002Fsdk\u002Freference\u002Fclasses\u002Ftentoratelimiterror","docs\u002Fsdk\u002Freference\u002Fclasses\u002FTentoRateLimitError",{"title":223,"path":224,"stem":225,"children":226,"page":65},"Functions","\u002Fdocs\u002Fsdk\u002Freference\u002Ffunctions","docs\u002Fsdk\u002Freference\u002Ffunctions",[227,231],{"title":228,"path":229,"stem":230},"Function: getUrl()","\u002Fdocs\u002Fsdk\u002Freference\u002Ffunctions\u002Fgeturl","docs\u002Fsdk\u002Freference\u002Ffunctions\u002FgetUrl",{"title":232,"path":233,"stem":234},"Function: mockMedia()","\u002Fdocs\u002Fsdk\u002Freference\u002Ffunctions\u002Fmockmedia","docs\u002Fsdk\u002Freference\u002Ffunctions\u002FmockMedia",{"title":236,"path":237,"stem":238,"children":239,"page":65},"Interfaces","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces","docs\u002Fsdk\u002Freference\u002Finterfaces",[240,244,248,252,256,260,264,268,272,276,280,284,288,292,296,300,304,308,312,316,320,324,328,332,336,340,344,348,352,356,360,364,368,372,376],{"title":241,"path":242,"stem":243},"Interface: BlogAuthor","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fblogauthor","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FBlogAuthor",{"title":245,"path":246,"stem":247},"Interface: BlogCategory","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fblogcategory","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FBlogCategory",{"title":249,"path":250,"stem":251},"Interface: BlogPost","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fblogpost","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FBlogPost",{"title":253,"path":254,"stem":255},"Interface: BlogPostListOptions","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fblogpostlistoptions","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FBlogPostListOptions",{"title":257,"path":258,"stem":259},"Interface: BlogTag","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fblogtag","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FBlogTag",{"title":261,"path":262,"stem":263},"Interface: CollectionItemResponse\u003CT>","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fcollectionitemresponse","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FCollectionItemResponse",{"title":265,"path":266,"stem":267},"Interface: CollectionListOptions","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fcollectionlistoptions","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FCollectionListOptions",{"title":269,"path":270,"stem":271},"Interface: CollectionListResponse\u003CT>","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fcollectionlistresponse","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FCollectionListResponse",{"title":273,"path":274,"stem":275},"Interface: CollectionTypeMeta","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fcollectiontypemeta","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FCollectionTypeMeta",{"title":277,"path":278,"stem":279},"Interface: CreateCollectionItemInput","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fcreatecollectioniteminput","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FCreateCollectionItemInput",{"title":281,"path":282,"stem":283},"Interface: CreatePageInput","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fcreatepageinput","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FCreatePageInput",{"title":285,"path":286,"stem":287},"Interface: DryRunResult","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fdryrunresult","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FDryRunResult",{"title":289,"path":290,"stem":291},"Interface: FilterCondition","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Ffiltercondition","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FFilterCondition",{"title":293,"path":294,"stem":295},"Interface: ItemResponse\u003CT>","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fitemresponse","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FItemResponse",{"title":297,"path":298,"stem":299},"Interface: ListResponse\u003CT>","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Flistresponse","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FListResponse",{"title":301,"path":302,"stem":303},"Interface: Media","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fmedia","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FMedia",{"title":305,"path":306,"stem":307},"Interface: MediaItem","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fmediaitem","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FMediaItem",{"title":309,"path":310,"stem":311},"Interface: MediaOption","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fmediaoption","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FMediaOption",{"title":313,"path":314,"stem":315},"Interface: MediaTransformOptions","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fmediatransformoptions","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FMediaTransformOptions",{"title":317,"path":318,"stem":319},"Interface: Page\u003CTContent>","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fpage","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FPage",{"title":321,"path":322,"stem":323},"Interface: PageGetOptions","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fpagegetoptions","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FPageGetOptions",{"title":325,"path":326,"stem":327},"Interface: PageListOptions","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fpagelistoptions","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FPageListOptions",{"title":329,"path":330,"stem":331},"Interface: PageWithRedirect\u003CTContent>","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fpagewithredirect","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FPageWithRedirect",{"title":333,"path":334,"stem":335},"Interface: PaginationMeta","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fpaginationmeta","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FPaginationMeta",{"title":337,"path":338,"stem":339},"Interface: PreviewOption","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fpreviewoption","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FPreviewOption",{"title":341,"path":342,"stem":343},"Interface: RedirectInfo","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fredirectinfo","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FRedirectInfo",{"title":345,"path":346,"stem":347},"Interface: RefTypesOption","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Freftypesoption","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FRefTypesOption",{"title":349,"path":350,"stem":351},"Interface: SeoMetadata","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fseometadata","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FSeoMetadata",{"title":353,"path":354,"stem":355},"Interface: TentoClientConfig","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Ftentoclientconfig","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FTentoClientConfig",{"title":357,"path":358,"stem":359},"Interface: TentoMedia","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Ftentomedia","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FTentoMedia",{"title":361,"path":362,"stem":363},"Interface: UpdateCollectionItemInput","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fupdatecollectioniteminput","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FUpdateCollectionItemInput",{"title":365,"path":366,"stem":367},"Interface: UpdatePageInput","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fupdatepageinput","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FUpdatePageInput",{"title":369,"path":370,"stem":371},"Interface: UploadMediaInput","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fuploadmediainput","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FUploadMediaInput",{"title":373,"path":374,"stem":375},"Interface: WriteCollectionItem","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fwritecollectionitem","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FWriteCollectionItem",{"title":377,"path":378,"stem":379},"Interface: WritePage","\u002Fdocs\u002Fsdk\u002Freference\u002Finterfaces\u002Fwritepage","docs\u002Fsdk\u002Freference\u002Finterfaces\u002FWritePage",{"title":381,"path":382,"stem":383,"children":384,"page":65},"Type Aliases","\u002Fdocs\u002Fsdk\u002Freference\u002Ftype-aliases","docs\u002Fsdk\u002Freference\u002Ftype-aliases",[385,389,393,397,401],{"title":386,"path":387,"stem":388},"Type Alias: BlogPostListItem","\u002Fdocs\u002Fsdk\u002Freference\u002Ftype-aliases\u002Fblogpostlistitem","docs\u002Fsdk\u002Freference\u002Ftype-aliases\u002FBlogPostListItem",{"title":390,"path":391,"stem":392},"Type Alias: BlogPostListResponse","\u002Fdocs\u002Fsdk\u002Freference\u002Ftype-aliases\u002Fblogpostlistresponse","docs\u002Fsdk\u002Freference\u002Ftype-aliases\u002FBlogPostListResponse",{"title":394,"path":395,"stem":396},"Type Alias: CollectionItem\u003CTContent>","\u002Fdocs\u002Fsdk\u002Freference\u002Ftype-aliases\u002Fcollectionitem","docs\u002Fsdk\u002Freference\u002Ftype-aliases\u002FCollectionItem",{"title":398,"path":399,"stem":400},"Type Alias: FilterOperator","\u002Fdocs\u002Fsdk\u002Freference\u002Ftype-aliases\u002Ffilteroperator","docs\u002Fsdk\u002Freference\u002Ftype-aliases\u002FFilterOperator",{"title":402,"path":403,"stem":404},"Type Alias: MediaMode","\u002Fdocs\u002Fsdk\u002Freference\u002Ftype-aliases\u002Fmediamode","docs\u002Fsdk\u002Freference\u002Ftype-aliases\u002FMediaMode",{"title":406,"path":407,"stem":408,"children":409,"page":65},"Typegen","\u002Fdocs\u002Ftypegen","docs\u002Ftypegen",[410,413,416],{"title":133,"path":411,"stem":412},"\u002Fdocs\u002Ftypegen\u002Fastro","docs\u002Ftypegen\u002Fastro",{"title":137,"path":414,"stem":415},"\u002Fdocs\u002Ftypegen\u002Fnextjs","docs\u002Ftypegen\u002Fnextjs",{"title":141,"path":417,"stem":418},"\u002Fdocs\u002Ftypegen\u002Fnuxt","docs\u002Ftypegen\u002Fnuxt",[420,450,460,478,556],{"title":5,"path":6,"stem":7,"children":421,"page":65},[422,424,426,428,430,432,434,436,438,440,442,444,446,448],{"title":10,"path":11,"stem":12,"icon":423},"i-lucide-sparkles",{"title":14,"path":15,"stem":16,"icon":425},"i-lucide-newspaper",{"title":18,"path":19,"stem":20,"icon":427},"i-lucide-terminal",{"title":22,"path":23,"stem":24,"icon":429},"i-lucide-layers",{"title":26,"path":27,"stem":28,"icon":431},"i-lucide-type",{"title":30,"path":31,"stem":32,"icon":433},"i-lucide-triangle-alert",{"title":34,"path":35,"stem":36,"icon":435},"i-lucide-image",{"title":38,"path":39,"stem":40,"icon":437},"i-lucide-map",{"title":42,"path":43,"stem":44,"icon":439},"i-lucide-file-text",{"title":46,"path":47,"stem":48,"icon":441},"i-lucide-sliders-horizontal",{"title":50,"path":51,"stem":52,"icon":443},"i-lucide-braces",{"title":54,"path":55,"stem":56,"icon":445},"i-lucide-wrench",{"title":58,"path":59,"stem":60,"icon":447},"i-lucide-shield-check",{"title":62,"path":63,"stem":64,"icon":449},"i-lucide-webhook",{"title":67,"path":68,"stem":69,"children":451,"page":65},[452,454,456,458],{"title":72,"path":73,"stem":74,"icon":453},"i-lucide-key-round",{"title":76,"path":77,"stem":78,"icon":455},"i-lucide-compass",{"title":80,"path":81,"stem":82,"icon":457},"i-lucide-rocket",{"title":84,"path":85,"stem":86,"icon":459},"i-lucide-pencil",{"title":88,"path":89,"stem":90,"children":461,"page":65},[462,464,466,468,470,472,474,476],{"title":93,"path":94,"stem":95,"icon":463},"i-lucide-layout-dashboard",{"title":97,"path":98,"stem":99,"icon":465},"i-lucide-package",{"title":101,"path":102,"stem":103,"icon":467},"i-lucide-git-branch",{"title":105,"path":106,"stem":107,"icon":469},"i-lucide-files",{"title":109,"path":110,"stem":111,"icon":471},"i-lucide-plug-zap",{"title":113,"path":114,"stem":115,"icon":473},"i-lucide-wand",{"title":117,"path":118,"stem":119,"icon":475},"i-lucide-users",{"title":121,"path":122,"stem":123,"icon":477},"i-lucide-pilcrow",{"title":125,"path":126,"stem":127,"children":479,"page":65},[480,481,482,484,486],{"title":38,"path":130,"stem":131,"icon":465},{"title":133,"path":134,"stem":135,"icon":457},{"title":137,"path":138,"stem":139,"icon":483},"i-lucide-triangle",{"title":141,"path":142,"stem":143,"icon":485},"i-lucide-hexagon",{"title":145,"path":146,"stem":147,"children":487,"page":65},[488,490,508,512,549],{"title":150,"path":151,"stem":152,"icon":489},null,{"title":154,"path":155,"stem":156,"children":491,"page":65},[492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507],{"title":159,"path":160,"stem":161,"icon":489},{"title":163,"path":164,"stem":165,"icon":489},{"title":167,"path":168,"stem":169,"icon":489},{"title":171,"path":172,"stem":173,"icon":489},{"title":175,"path":176,"stem":177,"icon":489},{"title":179,"path":180,"stem":181,"icon":489},{"title":183,"path":184,"stem":185,"icon":489},{"title":187,"path":188,"stem":189,"icon":489},{"title":191,"path":192,"stem":193,"icon":489},{"title":195,"path":196,"stem":197,"icon":489},{"title":199,"path":200,"stem":201,"icon":489},{"title":203,"path":204,"stem":205,"icon":489},{"title":207,"path":208,"stem":209,"icon":489},{"title":211,"path":212,"stem":213,"icon":489},{"title":215,"path":216,"stem":217,"icon":489},{"title":219,"path":220,"stem":221,"icon":489},{"title":223,"path":224,"stem":225,"children":509,"page":65},[510,511],{"title":228,"path":229,"stem":230,"icon":489},{"title":232,"path":233,"stem":234,"icon":489},{"title":236,"path":237,"stem":238,"children":513,"page":65},[514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548],{"title":241,"path":242,"stem":243,"icon":489},{"title":245,"path":246,"stem":247,"icon":489},{"title":249,"path":250,"stem":251,"icon":489},{"title":253,"path":254,"stem":255,"icon":489},{"title":257,"path":258,"stem":259,"icon":489},{"title":261,"path":262,"stem":263,"icon":489},{"title":265,"path":266,"stem":267,"icon":489},{"title":269,"path":270,"stem":271,"icon":489},{"title":273,"path":274,"stem":275,"icon":489},{"title":277,"path":278,"stem":279,"icon":489},{"title":281,"path":282,"stem":283,"icon":489},{"title":285,"path":286,"stem":287,"icon":489},{"title":289,"path":290,"stem":291,"icon":489},{"title":293,"path":294,"stem":295,"icon":489},{"title":297,"path":298,"stem":299,"icon":489},{"title":301,"path":302,"stem":303,"icon":489},{"title":305,"path":306,"stem":307,"icon":489},{"title":309,"path":310,"stem":311,"icon":489},{"title":313,"path":314,"stem":315,"icon":489},{"title":317,"path":318,"stem":319,"icon":489},{"title":321,"path":322,"stem":323,"icon":489},{"title":325,"path":326,"stem":327,"icon":489},{"title":329,"path":330,"stem":331,"icon":489},{"title":333,"path":334,"stem":335,"icon":489},{"title":337,"path":338,"stem":339,"icon":489},{"title":341,"path":342,"stem":343,"icon":489},{"title":345,"path":346,"stem":347,"icon":489},{"title":349,"path":350,"stem":351,"icon":489},{"title":353,"path":354,"stem":355,"icon":489},{"title":357,"path":358,"stem":359,"icon":489},{"title":361,"path":362,"stem":363,"icon":489},{"title":365,"path":366,"stem":367,"icon":489},{"title":369,"path":370,"stem":371,"icon":489},{"title":373,"path":374,"stem":375,"icon":489},{"title":377,"path":378,"stem":379,"icon":489},{"title":381,"path":382,"stem":383,"children":550,"page":65},[551,552,553,554,555],{"title":386,"path":387,"stem":388,"icon":489},{"title":390,"path":391,"stem":392,"icon":489},{"title":394,"path":395,"stem":396,"icon":489},{"title":398,"path":399,"stem":400,"icon":489},{"title":402,"path":403,"stem":404,"icon":489},{"title":406,"path":407,"stem":408,"children":557,"page":65},[558,559,560],{"title":133,"path":411,"stem":412,"icon":457},{"title":137,"path":414,"stem":415,"icon":483},{"title":141,"path":417,"stem":418,"icon":485},{"id":562,"title":10,"body":563,"description":2778,"extension":2779,"icon":423,"links":489,"meta":2780,"navigation":618,"path":11,"seo":2781,"stem":12,"__hash__":2782},"docs\u002Fdocs\u002Fapi\u002Fbest-practices.md",{"type":564,"value":565,"toc":2764},"minimark",[566,571,579,590,632,638,642,647,652,739,743,748,753,837,841,846,851,981,985,990,995,1032,1080,1084,1089,1094,1188,1192,1197,1205,1311,1315,1320,1325,1408,1412,1417,1422,1630,1634,1639,1644,2094,2097,2102,2107,2164,2169,2198,2203,2237,2242,2290,2292,2296,2301,2366,2371,2509,2514,2517,2576,2581,2696,2701,2704,2758,2760],[567,568,570],"h3",{"id":569},"_1-use-field-selection","1. Use Field Selection",[572,573,574,578],"p",{},[575,576,577],"strong",{},"Problem",": Fetching full page content when you only need title and excerpt wastes bandwidth.",[572,580,581,584,585,589],{},[575,582,583],{},"Solution",": Use ",[586,587,588],"code",{},"fields"," parameter:",[591,592,597],"pre",{"className":593,"code":594,"language":595,"meta":596,"style":596},"language-javascript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F Instead of this (returns all fields)\nconst pages = await fetch('\u002Fapi\u002Fv1\u002Fpages')\n\n\u002F\u002F Do this (returns only needed fields)\nconst pages = await fetch('\u002Fapi\u002Fv1\u002Fpages?fields=title,excerpt,publishDate')\n","javascript","",[586,598,599,607,613,620,626],{"__ignoreMap":596},[600,601,604],"span",{"class":602,"line":603},"line",1,[600,605,606],{},"\u002F\u002F Instead of this (returns all fields)\n",[600,608,610],{"class":602,"line":609},2,[600,611,612],{},"const pages = await fetch('\u002Fapi\u002Fv1\u002Fpages')\n",[600,614,616],{"class":602,"line":615},3,[600,617,619],{"emptyLinePlaceholder":618},true,"\n",[600,621,623],{"class":602,"line":622},4,[600,624,625],{},"\u002F\u002F Do this (returns only needed fields)\n",[600,627,629],{"class":602,"line":628},5,[600,630,631],{},"const pages = await fetch('\u002Fapi\u002Fv1\u002Fpages?fields=title,excerpt,publishDate')\n",[572,633,634,637],{},[575,635,636],{},"Impact",": Up to 90% reduction in payload size.",[567,639,641],{"id":640},"_2-implement-proper-caching","2. Implement Proper Caching",[572,643,644,646],{},[575,645,577],{},": Fetching same data repeatedly wastes API quota and slows down your app.",[572,648,649,651],{},[575,650,583],{},": Implement multi-layer caching:",[591,653,655],{"className":593,"code":654,"language":595,"meta":596,"style":596},"\u002F\u002F Layer 1: CDN (Cloudflare)\n\u002F\u002F Automatic, respect Cache-Control headers\n\n\u002F\u002F Layer 2: Server-side cache (for SSR)\nconst cachedPages = await redis.get('pages:all')\nif (cachedPages) return JSON.parse(cachedPages)\n\nconst pages = await fetchFromAPI('\u002Fapi\u002Fv1\u002Fpages')\nawait redis.set('pages:all', JSON.stringify(pages), 'EX', 60)\n\n\u002F\u002F Layer 3: Client-side cache (SWR, React Query)\nconst { data } = useSWR('\u002Fapi\u002Fv1\u002Fpages', fetcher, {\n  revalidateOnFocus: false,\n  dedupingInterval: 60000\n})\n",[586,656,657,662,667,671,676,681,687,692,698,704,709,715,721,727,733],{"__ignoreMap":596},[600,658,659],{"class":602,"line":603},[600,660,661],{},"\u002F\u002F Layer 1: CDN (Cloudflare)\n",[600,663,664],{"class":602,"line":609},[600,665,666],{},"\u002F\u002F Automatic, respect Cache-Control headers\n",[600,668,669],{"class":602,"line":615},[600,670,619],{"emptyLinePlaceholder":618},[600,672,673],{"class":602,"line":622},[600,674,675],{},"\u002F\u002F Layer 2: Server-side cache (for SSR)\n",[600,677,678],{"class":602,"line":628},[600,679,680],{},"const cachedPages = await redis.get('pages:all')\n",[600,682,684],{"class":602,"line":683},6,[600,685,686],{},"if (cachedPages) return JSON.parse(cachedPages)\n",[600,688,690],{"class":602,"line":689},7,[600,691,619],{"emptyLinePlaceholder":618},[600,693,695],{"class":602,"line":694},8,[600,696,697],{},"const pages = await fetchFromAPI('\u002Fapi\u002Fv1\u002Fpages')\n",[600,699,701],{"class":602,"line":700},9,[600,702,703],{},"await redis.set('pages:all', JSON.stringify(pages), 'EX', 60)\n",[600,705,707],{"class":602,"line":706},10,[600,708,619],{"emptyLinePlaceholder":618},[600,710,712],{"class":602,"line":711},11,[600,713,714],{},"\u002F\u002F Layer 3: Client-side cache (SWR, React Query)\n",[600,716,718],{"class":602,"line":717},12,[600,719,720],{},"const { data } = useSWR('\u002Fapi\u002Fv1\u002Fpages', fetcher, {\n",[600,722,724],{"class":602,"line":723},13,[600,725,726],{},"  revalidateOnFocus: false,\n",[600,728,730],{"class":602,"line":729},14,[600,731,732],{},"  dedupingInterval: 60000\n",[600,734,736],{"class":602,"line":735},15,[600,737,738],{},"})\n",[567,740,742],{"id":741},"_3-handle-redirects-for-seo","3. Handle Redirects for SEO",[572,744,745,747],{},[575,746,577],{},": Old slugs return 200 but SEO suffers without proper redirects.",[572,749,750,752],{},[575,751,583],{},": Implement framework-level redirects:",[591,754,756],{"className":593,"code":755,"language":595,"meta":596,"style":596},"\u002F\u002F Next.js\nexport async function getStaticProps({ params }) {\n  const response = await fetch(`\u002Fapi\u002Fv1\u002Fpages\u002F${params.slug}`)\n  const { data, redirect } = await response.json()\n\n  if (redirect) {\n    return {\n      redirect: {\n        destination: `\u002F${redirect.to}`,\n        permanent: true \u002F\u002F 301 redirect\n      }\n    }\n  }\n\n  return { props: { page: data } }\n}\n",[586,757,758,763,768,773,778,782,787,792,797,802,807,812,817,822,826,831],{"__ignoreMap":596},[600,759,760],{"class":602,"line":603},[600,761,762],{},"\u002F\u002F Next.js\n",[600,764,765],{"class":602,"line":609},[600,766,767],{},"export async function getStaticProps({ params }) {\n",[600,769,770],{"class":602,"line":615},[600,771,772],{},"  const response = await fetch(`\u002Fapi\u002Fv1\u002Fpages\u002F${params.slug}`)\n",[600,774,775],{"class":602,"line":622},[600,776,777],{},"  const { data, redirect } = await response.json()\n",[600,779,780],{"class":602,"line":628},[600,781,619],{"emptyLinePlaceholder":618},[600,783,784],{"class":602,"line":683},[600,785,786],{},"  if (redirect) {\n",[600,788,789],{"class":602,"line":689},[600,790,791],{},"    return {\n",[600,793,794],{"class":602,"line":694},[600,795,796],{},"      redirect: {\n",[600,798,799],{"class":602,"line":700},[600,800,801],{},"        destination: `\u002F${redirect.to}`,\n",[600,803,804],{"class":602,"line":706},[600,805,806],{},"        permanent: true \u002F\u002F 301 redirect\n",[600,808,809],{"class":602,"line":711},[600,810,811],{},"      }\n",[600,813,814],{"class":602,"line":717},[600,815,816],{},"    }\n",[600,818,819],{"class":602,"line":723},[600,820,821],{},"  }\n",[600,823,824],{"class":602,"line":729},[600,825,619],{"emptyLinePlaceholder":618},[600,827,828],{"class":602,"line":735},[600,829,830],{},"  return { props: { page: data } }\n",[600,832,834],{"class":602,"line":833},16,[600,835,836],{},"}\n",[567,838,840],{"id":839},"_4-implement-error-boundaries","4. Implement Error Boundaries",[572,842,843,845],{},[575,844,577],{},": API errors crash your entire app.",[572,847,848,850],{},[575,849,583],{},": Use error boundaries and fallbacks:",[591,852,854],{"className":593,"code":853,"language":595,"meta":596,"style":596},"async function fetchPage(slug) {\n  try {\n    const response = await fetch(`\u002Fapi\u002Fv1\u002Fpages\u002F${slug}`, {\n      headers: { 'X-API-Key': process.env.CMS_API_KEY }\n    })\n\n    if (response.status === 404) {\n      return { notFound: true }\n    }\n\n    if (response.status === 401) {\n      console.error('API key invalid')\n      return { error: 'Configuration error' }\n    }\n\n    if (!response.ok) {\n      throw new Error(`API error: ${response.status}`)\n    }\n\n    return await response.json()\n  } catch (error) {\n    console.error('Failed to fetch page:', error)\n    return { error: 'Failed to load content' }\n  }\n}\n",[586,855,856,861,866,871,876,881,885,890,895,899,903,908,913,918,922,926,931,937,942,947,953,959,965,971,976],{"__ignoreMap":596},[600,857,858],{"class":602,"line":603},[600,859,860],{},"async function fetchPage(slug) {\n",[600,862,863],{"class":602,"line":609},[600,864,865],{},"  try {\n",[600,867,868],{"class":602,"line":615},[600,869,870],{},"    const response = await fetch(`\u002Fapi\u002Fv1\u002Fpages\u002F${slug}`, {\n",[600,872,873],{"class":602,"line":622},[600,874,875],{},"      headers: { 'X-API-Key': process.env.CMS_API_KEY }\n",[600,877,878],{"class":602,"line":628},[600,879,880],{},"    })\n",[600,882,883],{"class":602,"line":683},[600,884,619],{"emptyLinePlaceholder":618},[600,886,887],{"class":602,"line":689},[600,888,889],{},"    if (response.status === 404) {\n",[600,891,892],{"class":602,"line":694},[600,893,894],{},"      return { notFound: true }\n",[600,896,897],{"class":602,"line":700},[600,898,816],{},[600,900,901],{"class":602,"line":706},[600,902,619],{"emptyLinePlaceholder":618},[600,904,905],{"class":602,"line":711},[600,906,907],{},"    if (response.status === 401) {\n",[600,909,910],{"class":602,"line":717},[600,911,912],{},"      console.error('API key invalid')\n",[600,914,915],{"class":602,"line":723},[600,916,917],{},"      return { error: 'Configuration error' }\n",[600,919,920],{"class":602,"line":729},[600,921,816],{},[600,923,924],{"class":602,"line":735},[600,925,619],{"emptyLinePlaceholder":618},[600,927,928],{"class":602,"line":833},[600,929,930],{},"    if (!response.ok) {\n",[600,932,934],{"class":602,"line":933},17,[600,935,936],{},"      throw new Error(`API error: ${response.status}`)\n",[600,938,940],{"class":602,"line":939},18,[600,941,816],{},[600,943,945],{"class":602,"line":944},19,[600,946,619],{"emptyLinePlaceholder":618},[600,948,950],{"class":602,"line":949},20,[600,951,952],{},"    return await response.json()\n",[600,954,956],{"class":602,"line":955},21,[600,957,958],{},"  } catch (error) {\n",[600,960,962],{"class":602,"line":961},22,[600,963,964],{},"    console.error('Failed to fetch page:', error)\n",[600,966,968],{"class":602,"line":967},23,[600,969,970],{},"    return { error: 'Failed to load content' }\n",[600,972,974],{"class":602,"line":973},24,[600,975,821],{},[600,977,979],{"class":602,"line":978},25,[600,980,836],{},[567,982,984],{"id":983},"_5-use-environment-variables","5. Use Environment Variables",[572,986,987,989],{},[575,988,577],{},": API keys hardcoded in source code are security risks.",[572,991,992,994],{},[575,993,583],{},": Use environment variables:",[591,996,1000],{"className":997,"code":998,"language":999,"meta":596,"style":596},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","# .env.local\nCMS_API_KEY=tento_pk_your_key_here\nCMS_API_BASE_URL=https:\u002F\u002Ftento-api.intelligentlending.co.uk\u002Fapi\u002Fv1\n","bash",[586,1001,1002,1008,1022],{"__ignoreMap":596},[600,1003,1004],{"class":602,"line":603},[600,1005,1007],{"class":1006},"sHwdD","# .env.local\n",[600,1009,1010,1014,1018],{"class":602,"line":609},[600,1011,1013],{"class":1012},"sTEyZ","CMS_API_KEY",[600,1015,1017],{"class":1016},"sMK4o","=",[600,1019,1021],{"class":1020},"sfazB","tento_pk_your_key_here\n",[600,1023,1024,1027,1029],{"class":602,"line":615},[600,1025,1026],{"class":1012},"CMS_API_BASE_URL",[600,1028,1017],{"class":1016},[600,1030,1031],{"class":1020},"https:\u002F\u002Ftento-api.intelligentlending.co.uk\u002Fapi\u002Fv1\n",[591,1033,1035],{"className":593,"code":1034,"language":595,"meta":596,"style":596},"\u002F\u002F lib\u002Fapi.js\nconst API_KEY = process.env.CMS_API_KEY\nconst BASE_URL = process.env.CMS_API_BASE_URL\n\nexport async function fetchPages() {\n  return fetch(`${BASE_URL}\u002Fpages`, {\n    headers: { 'X-API-Key': API_KEY }\n  })\n}\n",[586,1036,1037,1042,1047,1052,1056,1061,1066,1071,1076],{"__ignoreMap":596},[600,1038,1039],{"class":602,"line":603},[600,1040,1041],{},"\u002F\u002F lib\u002Fapi.js\n",[600,1043,1044],{"class":602,"line":609},[600,1045,1046],{},"const API_KEY = process.env.CMS_API_KEY\n",[600,1048,1049],{"class":602,"line":615},[600,1050,1051],{},"const BASE_URL = process.env.CMS_API_BASE_URL\n",[600,1053,1054],{"class":602,"line":622},[600,1055,619],{"emptyLinePlaceholder":618},[600,1057,1058],{"class":602,"line":628},[600,1059,1060],{},"export async function fetchPages() {\n",[600,1062,1063],{"class":602,"line":683},[600,1064,1065],{},"  return fetch(`${BASE_URL}\u002Fpages`, {\n",[600,1067,1068],{"class":602,"line":689},[600,1069,1070],{},"    headers: { 'X-API-Key': API_KEY }\n",[600,1072,1073],{"class":602,"line":694},[600,1074,1075],{},"  })\n",[600,1077,1078],{"class":602,"line":700},[600,1079,836],{},[567,1081,1083],{"id":1082},"_6-paginate-large-result-sets","6. Paginate Large Result Sets",[572,1085,1086,1088],{},[575,1087,577],{},": Fetching 1000 pages in one request times out.",[572,1090,1091,1093],{},[575,1092,583],{},": Use pagination:",[591,1095,1097],{"className":593,"code":1096,"language":595,"meta":596,"style":596},"async function fetchAllPages() {\n  const allPages = []\n  let page = 1\n  const limit = 100\n\n  while (true) {\n    const response = await fetch(\n      `\u002Fapi\u002Fv1\u002Fpages?page=${page}&limit=${limit}`\n    )\n    const { data, pagination } = await response.json()\n\n    allPages.push(...data)\n\n    if (pagination.page >= pagination.totalPages) break\n    page += 1\n  }\n\n  return allPages\n}\n",[586,1098,1099,1104,1109,1114,1119,1123,1128,1133,1138,1143,1148,1152,1157,1161,1166,1171,1175,1179,1184],{"__ignoreMap":596},[600,1100,1101],{"class":602,"line":603},[600,1102,1103],{},"async function fetchAllPages() {\n",[600,1105,1106],{"class":602,"line":609},[600,1107,1108],{},"  const allPages = []\n",[600,1110,1111],{"class":602,"line":615},[600,1112,1113],{},"  let page = 1\n",[600,1115,1116],{"class":602,"line":622},[600,1117,1118],{},"  const limit = 100\n",[600,1120,1121],{"class":602,"line":628},[600,1122,619],{"emptyLinePlaceholder":618},[600,1124,1125],{"class":602,"line":683},[600,1126,1127],{},"  while (true) {\n",[600,1129,1130],{"class":602,"line":689},[600,1131,1132],{},"    const response = await fetch(\n",[600,1134,1135],{"class":602,"line":694},[600,1136,1137],{},"      `\u002Fapi\u002Fv1\u002Fpages?page=${page}&limit=${limit}`\n",[600,1139,1140],{"class":602,"line":700},[600,1141,1142],{},"    )\n",[600,1144,1145],{"class":602,"line":706},[600,1146,1147],{},"    const { data, pagination } = await response.json()\n",[600,1149,1150],{"class":602,"line":711},[600,1151,619],{"emptyLinePlaceholder":618},[600,1153,1154],{"class":602,"line":717},[600,1155,1156],{},"    allPages.push(...data)\n",[600,1158,1159],{"class":602,"line":723},[600,1160,619],{"emptyLinePlaceholder":618},[600,1162,1163],{"class":602,"line":729},[600,1164,1165],{},"    if (pagination.page >= pagination.totalPages) break\n",[600,1167,1168],{"class":602,"line":735},[600,1169,1170],{},"    page += 1\n",[600,1172,1173],{"class":602,"line":833},[600,1174,821],{},[600,1176,1177],{"class":602,"line":933},[600,1178,619],{"emptyLinePlaceholder":618},[600,1180,1181],{"class":602,"line":939},[600,1182,1183],{},"  return allPages\n",[600,1185,1186],{"class":602,"line":944},[600,1187,836],{},[567,1189,1191],{"id":1190},"_7-use-conditional-requests","7. Use Conditional Requests",[572,1193,1194,1196],{},[575,1195,577],{},": Fetching unchanged content wastes bandwidth.",[572,1198,1199,584,1201,1204],{},[575,1200,583],{},[586,1202,1203],{},"If-None-Match"," with ETags:",[591,1206,1208],{"className":593,"code":1207,"language":595,"meta":596,"style":596},"let etag = null\n\nasync function fetchPageIfModified(slug) {\n  const headers = { 'X-API-Key': process.env.CMS_API_KEY }\n\n  if (etag) {\n    headers['If-None-Match'] = etag\n  }\n\n  const response = await fetch(`\u002Fapi\u002Fv1\u002Fpages\u002F${slug}`, { headers })\n\n  if (response.status === 304) {\n    \u002F\u002F Not modified, use cached version\n    return cachedPage\n  }\n\n  etag = response.headers.get('ETag')\n  const data = await response.json()\n  cachedPage = data\n\n  return data\n}\n",[586,1209,1210,1215,1219,1224,1229,1233,1238,1243,1247,1251,1256,1260,1265,1270,1275,1279,1283,1288,1293,1298,1302,1307],{"__ignoreMap":596},[600,1211,1212],{"class":602,"line":603},[600,1213,1214],{},"let etag = null\n",[600,1216,1217],{"class":602,"line":609},[600,1218,619],{"emptyLinePlaceholder":618},[600,1220,1221],{"class":602,"line":615},[600,1222,1223],{},"async function fetchPageIfModified(slug) {\n",[600,1225,1226],{"class":602,"line":622},[600,1227,1228],{},"  const headers = { 'X-API-Key': process.env.CMS_API_KEY }\n",[600,1230,1231],{"class":602,"line":628},[600,1232,619],{"emptyLinePlaceholder":618},[600,1234,1235],{"class":602,"line":683},[600,1236,1237],{},"  if (etag) {\n",[600,1239,1240],{"class":602,"line":689},[600,1241,1242],{},"    headers['If-None-Match'] = etag\n",[600,1244,1245],{"class":602,"line":694},[600,1246,821],{},[600,1248,1249],{"class":602,"line":700},[600,1250,619],{"emptyLinePlaceholder":618},[600,1252,1253],{"class":602,"line":706},[600,1254,1255],{},"  const response = await fetch(`\u002Fapi\u002Fv1\u002Fpages\u002F${slug}`, { headers })\n",[600,1257,1258],{"class":602,"line":711},[600,1259,619],{"emptyLinePlaceholder":618},[600,1261,1262],{"class":602,"line":717},[600,1263,1264],{},"  if (response.status === 304) {\n",[600,1266,1267],{"class":602,"line":723},[600,1268,1269],{},"    \u002F\u002F Not modified, use cached version\n",[600,1271,1272],{"class":602,"line":729},[600,1273,1274],{},"    return cachedPage\n",[600,1276,1277],{"class":602,"line":735},[600,1278,821],{},[600,1280,1281],{"class":602,"line":833},[600,1282,619],{"emptyLinePlaceholder":618},[600,1284,1285],{"class":602,"line":933},[600,1286,1287],{},"  etag = response.headers.get('ETag')\n",[600,1289,1290],{"class":602,"line":939},[600,1291,1292],{},"  const data = await response.json()\n",[600,1294,1295],{"class":602,"line":944},[600,1296,1297],{},"  cachedPage = data\n",[600,1299,1300],{"class":602,"line":949},[600,1301,619],{"emptyLinePlaceholder":618},[600,1303,1304],{"class":602,"line":955},[600,1305,1306],{},"  return data\n",[600,1308,1309],{"class":602,"line":961},[600,1310,836],{},[567,1312,1314],{"id":1313},"_8-handle-rate-limits-gracefully","8. Handle Rate Limits Gracefully",[572,1316,1317,1319],{},[575,1318,577],{},": Hitting rate limits stops your app from working.",[572,1321,1322,1324],{},[575,1323,583],{},": Implement retry with backoff:",[591,1326,1328],{"className":593,"code":1327,"language":595,"meta":596,"style":596},"async function fetchWithBackoff(url, options, maxRetries = 3) {\n  for (let attempt = 0; attempt \u003C maxRetries; attempt++) {\n    const response = await fetch(url, options)\n\n    if (response.status !== 429) {\n      return response\n    }\n\n    const retryAfter = parseInt(response.headers.get('Retry-After') || '1')\n    const backoffTime = Math.min(retryAfter * 1000, 2 ** attempt * 1000)\n\n    console.log(`Rate limited, retrying in ${backoffTime}ms`)\n    await new Promise(resolve => setTimeout(resolve, backoffTime))\n  }\n\n  throw new Error('Max retries exceeded')\n}\n",[586,1329,1330,1335,1340,1345,1349,1354,1359,1363,1367,1372,1377,1381,1386,1391,1395,1399,1404],{"__ignoreMap":596},[600,1331,1332],{"class":602,"line":603},[600,1333,1334],{},"async function fetchWithBackoff(url, options, maxRetries = 3) {\n",[600,1336,1337],{"class":602,"line":609},[600,1338,1339],{},"  for (let attempt = 0; attempt \u003C maxRetries; attempt++) {\n",[600,1341,1342],{"class":602,"line":615},[600,1343,1344],{},"    const response = await fetch(url, options)\n",[600,1346,1347],{"class":602,"line":622},[600,1348,619],{"emptyLinePlaceholder":618},[600,1350,1351],{"class":602,"line":628},[600,1352,1353],{},"    if (response.status !== 429) {\n",[600,1355,1356],{"class":602,"line":683},[600,1357,1358],{},"      return response\n",[600,1360,1361],{"class":602,"line":689},[600,1362,816],{},[600,1364,1365],{"class":602,"line":694},[600,1366,619],{"emptyLinePlaceholder":618},[600,1368,1369],{"class":602,"line":700},[600,1370,1371],{},"    const retryAfter = parseInt(response.headers.get('Retry-After') || '1')\n",[600,1373,1374],{"class":602,"line":706},[600,1375,1376],{},"    const backoffTime = Math.min(retryAfter * 1000, 2 ** attempt * 1000)\n",[600,1378,1379],{"class":602,"line":711},[600,1380,619],{"emptyLinePlaceholder":618},[600,1382,1383],{"class":602,"line":717},[600,1384,1385],{},"    console.log(`Rate limited, retrying in ${backoffTime}ms`)\n",[600,1387,1388],{"class":602,"line":723},[600,1389,1390],{},"    await new Promise(resolve => setTimeout(resolve, backoffTime))\n",[600,1392,1393],{"class":602,"line":729},[600,1394,821],{},[600,1396,1397],{"class":602,"line":735},[600,1398,619],{"emptyLinePlaceholder":618},[600,1400,1401],{"class":602,"line":833},[600,1402,1403],{},"  throw new Error('Max retries exceeded')\n",[600,1405,1406],{"class":602,"line":933},[600,1407,836],{},[567,1409,1411],{"id":1410},"_9-monitor-api-usage","9. Monitor API Usage",[572,1413,1414,1416],{},[575,1415,577],{},": You don't know when you're approaching rate limits.",[572,1418,1419,1421],{},[575,1420,583],{},": Track API usage:",[591,1423,1425],{"className":593,"code":1424,"language":595,"meta":596,"style":596},"class APIMonitor {\n  constructor() {\n    this.requests = []\n  }\n\n  async fetch(url, options) {\n    const start = Date.now()\n\n    try {\n      const response = await fetch(url, options)\n      const duration = Date.now() - start\n\n      this.requests.push({\n        url,\n        status: response.status,\n        duration,\n        timestamp: Date.now()\n      })\n\n      this.logStats()\n\n      return response\n    } catch (error) {\n      this.requests.push({\n        url,\n        status: 'error',\n        error: error.message,\n        timestamp: Date.now()\n      })\n      throw error\n    }\n  }\n\n  logStats() {\n    const lastMinute = this.requests.filter(\n      r => Date.now() - r.timestamp \u003C 60000\n    )\n\n    console.log(`API requests in last minute: ${lastMinute.length}\u002F100`)\n  }\n}\n",[586,1426,1427,1432,1437,1442,1446,1450,1455,1460,1464,1469,1474,1479,1483,1488,1493,1498,1503,1508,1513,1517,1522,1526,1530,1535,1539,1543,1549,1555,1560,1565,1571,1576,1581,1586,1592,1598,1604,1609,1614,1620,1625],{"__ignoreMap":596},[600,1428,1429],{"class":602,"line":603},[600,1430,1431],{},"class APIMonitor {\n",[600,1433,1434],{"class":602,"line":609},[600,1435,1436],{},"  constructor() {\n",[600,1438,1439],{"class":602,"line":615},[600,1440,1441],{},"    this.requests = []\n",[600,1443,1444],{"class":602,"line":622},[600,1445,821],{},[600,1447,1448],{"class":602,"line":628},[600,1449,619],{"emptyLinePlaceholder":618},[600,1451,1452],{"class":602,"line":683},[600,1453,1454],{},"  async fetch(url, options) {\n",[600,1456,1457],{"class":602,"line":689},[600,1458,1459],{},"    const start = Date.now()\n",[600,1461,1462],{"class":602,"line":694},[600,1463,619],{"emptyLinePlaceholder":618},[600,1465,1466],{"class":602,"line":700},[600,1467,1468],{},"    try {\n",[600,1470,1471],{"class":602,"line":706},[600,1472,1473],{},"      const response = await fetch(url, options)\n",[600,1475,1476],{"class":602,"line":711},[600,1477,1478],{},"      const duration = Date.now() - start\n",[600,1480,1481],{"class":602,"line":717},[600,1482,619],{"emptyLinePlaceholder":618},[600,1484,1485],{"class":602,"line":723},[600,1486,1487],{},"      this.requests.push({\n",[600,1489,1490],{"class":602,"line":729},[600,1491,1492],{},"        url,\n",[600,1494,1495],{"class":602,"line":735},[600,1496,1497],{},"        status: response.status,\n",[600,1499,1500],{"class":602,"line":833},[600,1501,1502],{},"        duration,\n",[600,1504,1505],{"class":602,"line":933},[600,1506,1507],{},"        timestamp: Date.now()\n",[600,1509,1510],{"class":602,"line":939},[600,1511,1512],{},"      })\n",[600,1514,1515],{"class":602,"line":944},[600,1516,619],{"emptyLinePlaceholder":618},[600,1518,1519],{"class":602,"line":949},[600,1520,1521],{},"      this.logStats()\n",[600,1523,1524],{"class":602,"line":955},[600,1525,619],{"emptyLinePlaceholder":618},[600,1527,1528],{"class":602,"line":961},[600,1529,1358],{},[600,1531,1532],{"class":602,"line":967},[600,1533,1534],{},"    } catch (error) {\n",[600,1536,1537],{"class":602,"line":973},[600,1538,1487],{},[600,1540,1541],{"class":602,"line":978},[600,1542,1492],{},[600,1544,1546],{"class":602,"line":1545},26,[600,1547,1548],{},"        status: 'error',\n",[600,1550,1552],{"class":602,"line":1551},27,[600,1553,1554],{},"        error: error.message,\n",[600,1556,1558],{"class":602,"line":1557},28,[600,1559,1507],{},[600,1561,1563],{"class":602,"line":1562},29,[600,1564,1512],{},[600,1566,1568],{"class":602,"line":1567},30,[600,1569,1570],{},"      throw error\n",[600,1572,1574],{"class":602,"line":1573},31,[600,1575,816],{},[600,1577,1579],{"class":602,"line":1578},32,[600,1580,821],{},[600,1582,1584],{"class":602,"line":1583},33,[600,1585,619],{"emptyLinePlaceholder":618},[600,1587,1589],{"class":602,"line":1588},34,[600,1590,1591],{},"  logStats() {\n",[600,1593,1595],{"class":602,"line":1594},35,[600,1596,1597],{},"    const lastMinute = this.requests.filter(\n",[600,1599,1601],{"class":602,"line":1600},36,[600,1602,1603],{},"      r => Date.now() - r.timestamp \u003C 60000\n",[600,1605,1607],{"class":602,"line":1606},37,[600,1608,1142],{},[600,1610,1612],{"class":602,"line":1611},38,[600,1613,619],{"emptyLinePlaceholder":618},[600,1615,1617],{"class":602,"line":1616},39,[600,1618,1619],{},"    console.log(`API requests in last minute: ${lastMinute.length}\u002F100`)\n",[600,1621,1623],{"class":602,"line":1622},40,[600,1624,821],{},[600,1626,1628],{"class":602,"line":1627},41,[600,1629,836],{},[567,1631,1633],{"id":1632},"_10-use-typescript-for-type-safety","10. Use TypeScript for Type Safety",[572,1635,1636,1638],{},[575,1637,577],{},": Runtime errors from incorrect API response handling.",[572,1640,1641,1643],{},[575,1642,583],{},": Define TypeScript interfaces:",[591,1645,1649],{"className":1646,"code":1647,"language":1648,"meta":596,"style":596},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","interface Page {\n  id: string\n  slug: string\n  type: string\n  fields: Record\u003Cstring, unknown>\n  publishedAt: string\n  updatedAt: string\n}\n\ninterface PageListResponse {\n  data: Page[]\n  pagination: {\n    total: number\n    page: number\n    limit: number\n    totalPages: number\n  }\n}\n\ninterface PageResponse {\n  data: Page\n  redirect: {\n    from: string\n    to: string\n    permanent: boolean\n  } | null\n}\n\nasync function fetchPages(): Promise\u003CPageListResponse> {\n  const response = await fetch('\u002Fapi\u002Fv1\u002Fpages', {\n    headers: { 'X-API-Key': process.env.CMS_API_KEY! }\n  })\n\n  if (!response.ok) {\n    throw new Error(`API error: ${response.status}`)\n  }\n\n  return response.json()\n}\n","typescript",[586,1650,1651,1664,1676,1685,1694,1719,1728,1737,1741,1745,1754,1766,1775,1785,1794,1803,1812,1816,1820,1824,1833,1842,1851,1860,1869,1879,1890,1894,1898,1926,1959,1998,2005,2009,2033,2067,2071,2075,2090],{"__ignoreMap":596},[600,1652,1653,1657,1661],{"class":602,"line":603},[600,1654,1656],{"class":1655},"spNyl","interface",[600,1658,1660],{"class":1659},"sBMFI"," Page",[600,1662,1663],{"class":1016}," {\n",[600,1665,1666,1670,1673],{"class":602,"line":609},[600,1667,1669],{"class":1668},"swJcz","  id",[600,1671,1672],{"class":1016},":",[600,1674,1675],{"class":1659}," string\n",[600,1677,1678,1681,1683],{"class":602,"line":615},[600,1679,1680],{"class":1668},"  slug",[600,1682,1672],{"class":1016},[600,1684,1675],{"class":1659},[600,1686,1687,1690,1692],{"class":602,"line":622},[600,1688,1689],{"class":1668},"  type",[600,1691,1672],{"class":1016},[600,1693,1675],{"class":1659},[600,1695,1696,1699,1701,1704,1707,1710,1713,1716],{"class":602,"line":628},[600,1697,1698],{"class":1668},"  fields",[600,1700,1672],{"class":1016},[600,1702,1703],{"class":1659}," Record",[600,1705,1706],{"class":1016},"\u003C",[600,1708,1709],{"class":1659},"string",[600,1711,1712],{"class":1016},",",[600,1714,1715],{"class":1659}," unknown",[600,1717,1718],{"class":1016},">\n",[600,1720,1721,1724,1726],{"class":602,"line":683},[600,1722,1723],{"class":1668},"  publishedAt",[600,1725,1672],{"class":1016},[600,1727,1675],{"class":1659},[600,1729,1730,1733,1735],{"class":602,"line":689},[600,1731,1732],{"class":1668},"  updatedAt",[600,1734,1672],{"class":1016},[600,1736,1675],{"class":1659},[600,1738,1739],{"class":602,"line":694},[600,1740,836],{"class":1016},[600,1742,1743],{"class":602,"line":700},[600,1744,619],{"emptyLinePlaceholder":618},[600,1746,1747,1749,1752],{"class":602,"line":706},[600,1748,1656],{"class":1655},[600,1750,1751],{"class":1659}," PageListResponse",[600,1753,1663],{"class":1016},[600,1755,1756,1759,1761,1763],{"class":602,"line":711},[600,1757,1758],{"class":1668},"  data",[600,1760,1672],{"class":1016},[600,1762,1660],{"class":1659},[600,1764,1765],{"class":1012},"[]\n",[600,1767,1768,1771,1773],{"class":602,"line":717},[600,1769,1770],{"class":1668},"  pagination",[600,1772,1672],{"class":1016},[600,1774,1663],{"class":1016},[600,1776,1777,1780,1782],{"class":602,"line":723},[600,1778,1779],{"class":1668},"    total",[600,1781,1672],{"class":1016},[600,1783,1784],{"class":1659}," number\n",[600,1786,1787,1790,1792],{"class":602,"line":729},[600,1788,1789],{"class":1668},"    page",[600,1791,1672],{"class":1016},[600,1793,1784],{"class":1659},[600,1795,1796,1799,1801],{"class":602,"line":735},[600,1797,1798],{"class":1668},"    limit",[600,1800,1672],{"class":1016},[600,1802,1784],{"class":1659},[600,1804,1805,1808,1810],{"class":602,"line":833},[600,1806,1807],{"class":1668},"    totalPages",[600,1809,1672],{"class":1016},[600,1811,1784],{"class":1659},[600,1813,1814],{"class":602,"line":933},[600,1815,821],{"class":1016},[600,1817,1818],{"class":602,"line":939},[600,1819,836],{"class":1016},[600,1821,1822],{"class":602,"line":944},[600,1823,619],{"emptyLinePlaceholder":618},[600,1825,1826,1828,1831],{"class":602,"line":949},[600,1827,1656],{"class":1655},[600,1829,1830],{"class":1659}," PageResponse",[600,1832,1663],{"class":1016},[600,1834,1835,1837,1839],{"class":602,"line":955},[600,1836,1758],{"class":1668},[600,1838,1672],{"class":1016},[600,1840,1841],{"class":1659}," Page\n",[600,1843,1844,1847,1849],{"class":602,"line":961},[600,1845,1846],{"class":1668},"  redirect",[600,1848,1672],{"class":1016},[600,1850,1663],{"class":1016},[600,1852,1853,1856,1858],{"class":602,"line":967},[600,1854,1855],{"class":1668},"    from",[600,1857,1672],{"class":1016},[600,1859,1675],{"class":1659},[600,1861,1862,1865,1867],{"class":602,"line":973},[600,1863,1864],{"class":1668},"    to",[600,1866,1672],{"class":1016},[600,1868,1675],{"class":1659},[600,1870,1871,1874,1876],{"class":602,"line":978},[600,1872,1873],{"class":1668},"    permanent",[600,1875,1672],{"class":1016},[600,1877,1878],{"class":1659}," boolean\n",[600,1880,1881,1884,1887],{"class":602,"line":1545},[600,1882,1883],{"class":1016},"  }",[600,1885,1886],{"class":1016}," |",[600,1888,1889],{"class":1659}," null\n",[600,1891,1892],{"class":602,"line":1551},[600,1893,836],{"class":1016},[600,1895,1896],{"class":602,"line":1557},[600,1897,619],{"emptyLinePlaceholder":618},[600,1899,1900,1903,1906,1910,1913,1916,1918,1921,1924],{"class":602,"line":1562},[600,1901,1902],{"class":1655},"async",[600,1904,1905],{"class":1655}," function",[600,1907,1909],{"class":1908},"s2Zo4"," fetchPages",[600,1911,1912],{"class":1016},"():",[600,1914,1915],{"class":1659}," Promise",[600,1917,1706],{"class":1016},[600,1919,1920],{"class":1659},"PageListResponse",[600,1922,1923],{"class":1016},">",[600,1925,1663],{"class":1016},[600,1927,1928,1931,1934,1937,1941,1944,1947,1950,1953,1955,1957],{"class":602,"line":1567},[600,1929,1930],{"class":1655},"  const",[600,1932,1933],{"class":1012}," response",[600,1935,1936],{"class":1016}," =",[600,1938,1940],{"class":1939},"s7zQu"," await",[600,1942,1943],{"class":1908}," fetch",[600,1945,1946],{"class":1668},"(",[600,1948,1949],{"class":1016},"'",[600,1951,1952],{"class":1020},"\u002Fapi\u002Fv1\u002Fpages",[600,1954,1949],{"class":1016},[600,1956,1712],{"class":1016},[600,1958,1663],{"class":1016},[600,1960,1961,1964,1966,1969,1972,1975,1977,1979,1982,1985,1988,1990,1992,1995],{"class":602,"line":1573},[600,1962,1963],{"class":1668},"    headers",[600,1965,1672],{"class":1016},[600,1967,1968],{"class":1016}," {",[600,1970,1971],{"class":1016}," '",[600,1973,1974],{"class":1668},"X-API-Key",[600,1976,1949],{"class":1016},[600,1978,1672],{"class":1016},[600,1980,1981],{"class":1012}," process",[600,1983,1984],{"class":1016},".",[600,1986,1987],{"class":1012},"env",[600,1989,1984],{"class":1016},[600,1991,1013],{"class":1012},[600,1993,1994],{"class":1016},"!",[600,1996,1997],{"class":1016}," }\n",[600,1999,2000,2002],{"class":602,"line":1578},[600,2001,1883],{"class":1016},[600,2003,2004],{"class":1668},")\n",[600,2006,2007],{"class":602,"line":1583},[600,2008,619],{"emptyLinePlaceholder":618},[600,2010,2011,2014,2017,2019,2022,2024,2027,2030],{"class":602,"line":1588},[600,2012,2013],{"class":1939},"  if",[600,2015,2016],{"class":1668}," (",[600,2018,1994],{"class":1016},[600,2020,2021],{"class":1012},"response",[600,2023,1984],{"class":1016},[600,2025,2026],{"class":1012},"ok",[600,2028,2029],{"class":1668},") ",[600,2031,2032],{"class":1016},"{\n",[600,2034,2035,2038,2041,2044,2046,2049,2052,2055,2057,2059,2062,2065],{"class":602,"line":1594},[600,2036,2037],{"class":1939},"    throw",[600,2039,2040],{"class":1016}," new",[600,2042,2043],{"class":1908}," Error",[600,2045,1946],{"class":1668},[600,2047,2048],{"class":1016},"`",[600,2050,2051],{"class":1020},"API error: ",[600,2053,2054],{"class":1016},"${",[600,2056,2021],{"class":1012},[600,2058,1984],{"class":1016},[600,2060,2061],{"class":1012},"status",[600,2063,2064],{"class":1016},"}`",[600,2066,2004],{"class":1668},[600,2068,2069],{"class":602,"line":1600},[600,2070,821],{"class":1016},[600,2072,2073],{"class":602,"line":1606},[600,2074,619],{"emptyLinePlaceholder":618},[600,2076,2077,2080,2082,2084,2087],{"class":602,"line":1611},[600,2078,2079],{"class":1939},"  return",[600,2081,1933],{"class":1012},[600,2083,1984],{"class":1016},[600,2085,2086],{"class":1908},"json",[600,2088,2089],{"class":1668},"()\n",[600,2091,2092],{"class":602,"line":1616},[600,2093,836],{"class":1016},[2095,2096],"hr",{},[2098,2099,2101],"h2",{"id":2100},"error-handling","Error handling",[572,2103,2104],{},[575,2105,2106],{},"Handle 401 Unauthorized:",[591,2108,2110],{"className":593,"code":2109,"language":595,"meta":596,"style":596},"const response = await fetch(url, {\n  headers: { 'X-API-Key': apiKey }\n})\n\nif (response.status === 401) {\n  \u002F\u002F API key invalid or expired\n  \u002F\u002F Check key in admin UI\n  \u002F\u002F Rotate to new key if expired\n  console.error('API key invalid or expired')\n  \u002F\u002F Show error to user or fail gracefully\n}\n",[586,2111,2112,2117,2122,2126,2130,2135,2140,2145,2150,2155,2160],{"__ignoreMap":596},[600,2113,2114],{"class":602,"line":603},[600,2115,2116],{},"const response = await fetch(url, {\n",[600,2118,2119],{"class":602,"line":609},[600,2120,2121],{},"  headers: { 'X-API-Key': apiKey }\n",[600,2123,2124],{"class":602,"line":615},[600,2125,738],{},[600,2127,2128],{"class":602,"line":622},[600,2129,619],{"emptyLinePlaceholder":618},[600,2131,2132],{"class":602,"line":628},[600,2133,2134],{},"if (response.status === 401) {\n",[600,2136,2137],{"class":602,"line":683},[600,2138,2139],{},"  \u002F\u002F API key invalid or expired\n",[600,2141,2142],{"class":602,"line":689},[600,2143,2144],{},"  \u002F\u002F Check key in admin UI\n",[600,2146,2147],{"class":602,"line":694},[600,2148,2149],{},"  \u002F\u002F Rotate to new key if expired\n",[600,2151,2152],{"class":602,"line":700},[600,2153,2154],{},"  console.error('API key invalid or expired')\n",[600,2156,2157],{"class":602,"line":706},[600,2158,2159],{},"  \u002F\u002F Show error to user or fail gracefully\n",[600,2161,2162],{"class":602,"line":711},[600,2163,836],{},[572,2165,2166],{},[575,2167,2168],{},"Handle 404 Not Found:",[591,2170,2172],{"className":593,"code":2171,"language":595,"meta":596,"style":596},"if (response.status === 404) {\n  \u002F\u002F Page doesn't exist or not published\n  \u002F\u002F Show 404 page to user\n  return { notFound: true }\n}\n",[586,2173,2174,2179,2184,2189,2194],{"__ignoreMap":596},[600,2175,2176],{"class":602,"line":603},[600,2177,2178],{},"if (response.status === 404) {\n",[600,2180,2181],{"class":602,"line":609},[600,2182,2183],{},"  \u002F\u002F Page doesn't exist or not published\n",[600,2185,2186],{"class":602,"line":615},[600,2187,2188],{},"  \u002F\u002F Show 404 page to user\n",[600,2190,2191],{"class":602,"line":622},[600,2192,2193],{},"  return { notFound: true }\n",[600,2195,2196],{"class":602,"line":628},[600,2197,836],{},[572,2199,2200],{},[575,2201,2202],{},"Handle 429 Rate Limited:",[591,2204,2206],{"className":593,"code":2205,"language":595,"meta":596,"style":596},"if (response.status === 429) {\n  const retryAfter = response.headers.get('Retry-After')\n  \u002F\u002F Wait and retry\n  await new Promise(resolve => setTimeout(resolve, retryAfter * 1000))\n  return fetch(url, options) \u002F\u002F Retry\n}\n",[586,2207,2208,2213,2218,2223,2228,2233],{"__ignoreMap":596},[600,2209,2210],{"class":602,"line":603},[600,2211,2212],{},"if (response.status === 429) {\n",[600,2214,2215],{"class":602,"line":609},[600,2216,2217],{},"  const retryAfter = response.headers.get('Retry-After')\n",[600,2219,2220],{"class":602,"line":615},[600,2221,2222],{},"  \u002F\u002F Wait and retry\n",[600,2224,2225],{"class":602,"line":622},[600,2226,2227],{},"  await new Promise(resolve => setTimeout(resolve, retryAfter * 1000))\n",[600,2229,2230],{"class":602,"line":628},[600,2231,2232],{},"  return fetch(url, options) \u002F\u002F Retry\n",[600,2234,2235],{"class":602,"line":683},[600,2236,836],{},[572,2238,2239],{},[575,2240,2241],{},"Handle 500 Internal Error:",[591,2243,2245],{"className":593,"code":2244,"language":595,"meta":596,"style":596},"if (response.status >= 500) {\n  \u002F\u002F Server error, implement retry with exponential backoff\n  for (let i = 0; i \u003C 3; i++) {\n    await new Promise(resolve => setTimeout(resolve, 2 ** i * 1000))\n    const retry = await fetch(url, options)\n    if (retry.ok) return retry\n  }\n  \u002F\u002F All retries failed, show error to user\n}\n",[586,2246,2247,2252,2257,2262,2267,2272,2277,2281,2286],{"__ignoreMap":596},[600,2248,2249],{"class":602,"line":603},[600,2250,2251],{},"if (response.status >= 500) {\n",[600,2253,2254],{"class":602,"line":609},[600,2255,2256],{},"  \u002F\u002F Server error, implement retry with exponential backoff\n",[600,2258,2259],{"class":602,"line":615},[600,2260,2261],{},"  for (let i = 0; i \u003C 3; i++) {\n",[600,2263,2264],{"class":602,"line":622},[600,2265,2266],{},"    await new Promise(resolve => setTimeout(resolve, 2 ** i * 1000))\n",[600,2268,2269],{"class":602,"line":628},[600,2270,2271],{},"    const retry = await fetch(url, options)\n",[600,2273,2274],{"class":602,"line":683},[600,2275,2276],{},"    if (retry.ok) return retry\n",[600,2278,2279],{"class":602,"line":689},[600,2280,821],{},[600,2282,2283],{"class":602,"line":694},[600,2284,2285],{},"  \u002F\u002F All retries failed, show error to user\n",[600,2287,2288],{"class":602,"line":700},[600,2289,836],{},[2095,2291],{},[2098,2293,2295],{"id":2294},"avoiding-rate-limits","Avoiding rate limits",[572,2297,2298],{},[575,2299,2300],{},"1. Implement Exponential Backoff",[591,2302,2304],{"className":593,"code":2303,"language":595,"meta":596,"style":596},"async function fetchWithRetry(url, options, maxRetries = 3) {\n  for (let i = 0; i \u003C maxRetries; i++) {\n    const response = await fetch(url, options)\n\n    if (response.status !== 429) {\n      return response\n    }\n\n    const retryAfter = response.headers.get('Retry-After') || 2 ** i\n    await new Promise(resolve => setTimeout(resolve, retryAfter * 1000))\n  }\n\n  throw new Error('Max retries exceeded')\n}\n",[586,2305,2306,2311,2316,2320,2324,2328,2332,2336,2340,2345,2350,2354,2358,2362],{"__ignoreMap":596},[600,2307,2308],{"class":602,"line":603},[600,2309,2310],{},"async function fetchWithRetry(url, options, maxRetries = 3) {\n",[600,2312,2313],{"class":602,"line":609},[600,2314,2315],{},"  for (let i = 0; i \u003C maxRetries; i++) {\n",[600,2317,2318],{"class":602,"line":615},[600,2319,1344],{},[600,2321,2322],{"class":602,"line":622},[600,2323,619],{"emptyLinePlaceholder":618},[600,2325,2326],{"class":602,"line":628},[600,2327,1353],{},[600,2329,2330],{"class":602,"line":683},[600,2331,1358],{},[600,2333,2334],{"class":602,"line":689},[600,2335,816],{},[600,2337,2338],{"class":602,"line":694},[600,2339,619],{"emptyLinePlaceholder":618},[600,2341,2342],{"class":602,"line":700},[600,2343,2344],{},"    const retryAfter = response.headers.get('Retry-After') || 2 ** i\n",[600,2346,2347],{"class":602,"line":706},[600,2348,2349],{},"    await new Promise(resolve => setTimeout(resolve, retryAfter * 1000))\n",[600,2351,2352],{"class":602,"line":711},[600,2353,821],{},[600,2355,2356],{"class":602,"line":717},[600,2357,619],{"emptyLinePlaceholder":618},[600,2359,2360],{"class":602,"line":723},[600,2361,1403],{},[600,2363,2364],{"class":602,"line":729},[600,2365,836],{},[572,2367,2368],{},[575,2369,2370],{},"2. Implement Request Queuing",[591,2372,2374],{"className":593,"code":2373,"language":595,"meta":596,"style":596},"class RateLimiter {\n  constructor(maxPerMinute = 100) {\n    this.maxPerMinute = maxPerMinute\n    this.queue = []\n    this.requests = []\n  }\n\n  async throttle() {\n    const now = Date.now()\n    this.requests = this.requests.filter(time => now - time \u003C 60000)\n\n    if (this.requests.length >= this.maxPerMinute) {\n      const oldestRequest = Math.min(...this.requests)\n      const waitTime = 60000 - (now - oldestRequest)\n      await new Promise(resolve => setTimeout(resolve, waitTime))\n    }\n\n    this.requests.push(Date.now())\n  }\n\n  async fetch(url, options) {\n    await this.throttle()\n    return fetch(url, options)\n  }\n}\n\n\u002F\u002F Usage\nconst limiter = new RateLimiter(100)\nconst response = await limiter.fetch(url, options)\n",[586,2375,2376,2381,2386,2391,2396,2400,2404,2408,2413,2418,2423,2427,2432,2437,2442,2447,2451,2455,2460,2464,2468,2472,2477,2482,2486,2490,2494,2499,2504],{"__ignoreMap":596},[600,2377,2378],{"class":602,"line":603},[600,2379,2380],{},"class RateLimiter {\n",[600,2382,2383],{"class":602,"line":609},[600,2384,2385],{},"  constructor(maxPerMinute = 100) {\n",[600,2387,2388],{"class":602,"line":615},[600,2389,2390],{},"    this.maxPerMinute = maxPerMinute\n",[600,2392,2393],{"class":602,"line":622},[600,2394,2395],{},"    this.queue = []\n",[600,2397,2398],{"class":602,"line":628},[600,2399,1441],{},[600,2401,2402],{"class":602,"line":683},[600,2403,821],{},[600,2405,2406],{"class":602,"line":689},[600,2407,619],{"emptyLinePlaceholder":618},[600,2409,2410],{"class":602,"line":694},[600,2411,2412],{},"  async throttle() {\n",[600,2414,2415],{"class":602,"line":700},[600,2416,2417],{},"    const now = Date.now()\n",[600,2419,2420],{"class":602,"line":706},[600,2421,2422],{},"    this.requests = this.requests.filter(time => now - time \u003C 60000)\n",[600,2424,2425],{"class":602,"line":711},[600,2426,619],{"emptyLinePlaceholder":618},[600,2428,2429],{"class":602,"line":717},[600,2430,2431],{},"    if (this.requests.length >= this.maxPerMinute) {\n",[600,2433,2434],{"class":602,"line":723},[600,2435,2436],{},"      const oldestRequest = Math.min(...this.requests)\n",[600,2438,2439],{"class":602,"line":729},[600,2440,2441],{},"      const waitTime = 60000 - (now - oldestRequest)\n",[600,2443,2444],{"class":602,"line":735},[600,2445,2446],{},"      await new Promise(resolve => setTimeout(resolve, waitTime))\n",[600,2448,2449],{"class":602,"line":833},[600,2450,816],{},[600,2452,2453],{"class":602,"line":933},[600,2454,619],{"emptyLinePlaceholder":618},[600,2456,2457],{"class":602,"line":939},[600,2458,2459],{},"    this.requests.push(Date.now())\n",[600,2461,2462],{"class":602,"line":944},[600,2463,821],{},[600,2465,2466],{"class":602,"line":949},[600,2467,619],{"emptyLinePlaceholder":618},[600,2469,2470],{"class":602,"line":955},[600,2471,1454],{},[600,2473,2474],{"class":602,"line":961},[600,2475,2476],{},"    await this.throttle()\n",[600,2478,2479],{"class":602,"line":967},[600,2480,2481],{},"    return fetch(url, options)\n",[600,2483,2484],{"class":602,"line":973},[600,2485,821],{},[600,2487,2488],{"class":602,"line":978},[600,2489,836],{},[600,2491,2492],{"class":602,"line":1545},[600,2493,619],{"emptyLinePlaceholder":618},[600,2495,2496],{"class":602,"line":1551},[600,2497,2498],{},"\u002F\u002F Usage\n",[600,2500,2501],{"class":602,"line":1557},[600,2502,2503],{},"const limiter = new RateLimiter(100)\n",[600,2505,2506],{"class":602,"line":1562},[600,2507,2508],{},"const response = await limiter.fetch(url, options)\n",[572,2510,2511],{},[575,2512,2513],{},"3. Use Field Selection",[572,2515,2516],{},"Reduce API calls by requesting only needed fields:",[591,2518,2520],{"className":997,"code":2519,"language":999,"meta":596,"style":596},"# Instead of multiple requests for different data\nGET \u002Fapi\u002Fv1\u002Fpages\u002Fpage1\nGET \u002Fapi\u002Fv1\u002Fpages\u002Fpage2\nGET \u002Fapi\u002Fv1\u002Fpages\u002Fpage3\n\n# Use list endpoint with field selection\nGET \u002Fapi\u002Fv1\u002Fpages?fields=title,excerpt&limit=100\n",[586,2521,2522,2527,2535,2542,2549,2553,2558],{"__ignoreMap":596},[600,2523,2524],{"class":602,"line":603},[600,2525,2526],{"class":1006},"# Instead of multiple requests for different data\n",[600,2528,2529,2532],{"class":602,"line":609},[600,2530,2531],{"class":1659},"GET",[600,2533,2534],{"class":1020}," \u002Fapi\u002Fv1\u002Fpages\u002Fpage1\n",[600,2536,2537,2539],{"class":602,"line":615},[600,2538,2531],{"class":1659},[600,2540,2541],{"class":1020}," \u002Fapi\u002Fv1\u002Fpages\u002Fpage2\n",[600,2543,2544,2546],{"class":602,"line":622},[600,2545,2531],{"class":1659},[600,2547,2548],{"class":1020}," \u002Fapi\u002Fv1\u002Fpages\u002Fpage3\n",[600,2550,2551],{"class":602,"line":628},[600,2552,619],{"emptyLinePlaceholder":618},[600,2554,2555],{"class":602,"line":683},[600,2556,2557],{"class":1006},"# Use list endpoint with field selection\n",[600,2559,2560,2562,2565,2568,2571,2573],{"class":602,"line":689},[600,2561,2531],{"class":1659},[600,2563,2564],{"class":1020}," \u002Fapi\u002Fv1\u002Fpages?fields=title,excerpt",[600,2566,2567],{"class":1016},"&",[600,2569,2570],{"class":1012},"limit",[600,2572,1017],{"class":1016},[600,2574,2575],{"class":1020},"100\n",[572,2577,2578],{},[575,2579,2580],{},"4. Implement Client-Side Caching",[591,2582,2584],{"className":593,"code":2583,"language":595,"meta":596,"style":596},"class CachedAPIClient {\n  constructor(apiKey, cacheTTL = 60000) {\n    this.apiKey = apiKey\n    this.cacheTTL = cacheTTL\n    this.cache = new Map()\n  }\n\n  async fetch(url) {\n    const cached = this.cache.get(url)\n\n    if (cached && Date.now() - cached.timestamp \u003C this.cacheTTL) {\n      return cached.data\n    }\n\n    const response = await fetch(url, {\n      headers: { 'X-API-Key': this.apiKey }\n    })\n\n    const data = await response.json()\n    this.cache.set(url, { data, timestamp: Date.now() })\n\n    return data\n  }\n}\n",[586,2585,2586,2591,2596,2601,2606,2611,2615,2619,2624,2629,2633,2638,2643,2647,2651,2656,2661,2665,2669,2674,2679,2683,2688,2692],{"__ignoreMap":596},[600,2587,2588],{"class":602,"line":603},[600,2589,2590],{},"class CachedAPIClient {\n",[600,2592,2593],{"class":602,"line":609},[600,2594,2595],{},"  constructor(apiKey, cacheTTL = 60000) {\n",[600,2597,2598],{"class":602,"line":615},[600,2599,2600],{},"    this.apiKey = apiKey\n",[600,2602,2603],{"class":602,"line":622},[600,2604,2605],{},"    this.cacheTTL = cacheTTL\n",[600,2607,2608],{"class":602,"line":628},[600,2609,2610],{},"    this.cache = new Map()\n",[600,2612,2613],{"class":602,"line":683},[600,2614,821],{},[600,2616,2617],{"class":602,"line":689},[600,2618,619],{"emptyLinePlaceholder":618},[600,2620,2621],{"class":602,"line":694},[600,2622,2623],{},"  async fetch(url) {\n",[600,2625,2626],{"class":602,"line":700},[600,2627,2628],{},"    const cached = this.cache.get(url)\n",[600,2630,2631],{"class":602,"line":706},[600,2632,619],{"emptyLinePlaceholder":618},[600,2634,2635],{"class":602,"line":711},[600,2636,2637],{},"    if (cached && Date.now() - cached.timestamp \u003C this.cacheTTL) {\n",[600,2639,2640],{"class":602,"line":717},[600,2641,2642],{},"      return cached.data\n",[600,2644,2645],{"class":602,"line":723},[600,2646,816],{},[600,2648,2649],{"class":602,"line":729},[600,2650,619],{"emptyLinePlaceholder":618},[600,2652,2653],{"class":602,"line":735},[600,2654,2655],{},"    const response = await fetch(url, {\n",[600,2657,2658],{"class":602,"line":833},[600,2659,2660],{},"      headers: { 'X-API-Key': this.apiKey }\n",[600,2662,2663],{"class":602,"line":933},[600,2664,880],{},[600,2666,2667],{"class":602,"line":939},[600,2668,619],{"emptyLinePlaceholder":618},[600,2670,2671],{"class":602,"line":944},[600,2672,2673],{},"    const data = await response.json()\n",[600,2675,2676],{"class":602,"line":949},[600,2677,2678],{},"    this.cache.set(url, { data, timestamp: Date.now() })\n",[600,2680,2681],{"class":602,"line":955},[600,2682,619],{"emptyLinePlaceholder":618},[600,2684,2685],{"class":602,"line":961},[600,2686,2687],{},"    return data\n",[600,2689,2690],{"class":602,"line":967},[600,2691,821],{},[600,2693,2694],{"class":602,"line":973},[600,2695,836],{},[572,2697,2698],{},[575,2699,2700],{},"5. Batch Operations",[572,2702,2703],{},"Instead of fetching pages one by one, use list endpoint:",[591,2705,2707],{"className":997,"code":2706,"language":999,"meta":596,"style":596},"# Bad: 10 individual requests\nGET \u002Fapi\u002Fv1\u002Fpages\u002Fpage1\nGET \u002Fapi\u002Fv1\u002Fpages\u002Fpage2\n...\nGET \u002Fapi\u002Fv1\u002Fpages\u002Fpage10\n\n# Good: 1 request with pagination\nGET \u002Fapi\u002Fv1\u002Fpages?limit=10\n",[586,2708,2709,2714,2720,2726,2731,2738,2742,2747],{"__ignoreMap":596},[600,2710,2711],{"class":602,"line":603},[600,2712,2713],{"class":1006},"# Bad: 10 individual requests\n",[600,2715,2716,2718],{"class":602,"line":609},[600,2717,2531],{"class":1659},[600,2719,2534],{"class":1020},[600,2721,2722,2724],{"class":602,"line":615},[600,2723,2531],{"class":1659},[600,2725,2541],{"class":1020},[600,2727,2728],{"class":602,"line":622},[600,2729,2730],{"class":1908},"...\n",[600,2732,2733,2735],{"class":602,"line":628},[600,2734,2531],{"class":1659},[600,2736,2737],{"class":1020}," \u002Fapi\u002Fv1\u002Fpages\u002Fpage10\n",[600,2739,2740],{"class":602,"line":683},[600,2741,619],{"emptyLinePlaceholder":618},[600,2743,2744],{"class":602,"line":689},[600,2745,2746],{"class":1006},"# Good: 1 request with pagination\n",[600,2748,2749,2751,2754],{"class":602,"line":694},[600,2750,2531],{"class":1659},[600,2752,2753],{"class":1020}," \u002Fapi\u002Fv1\u002Fpages?limit=",[600,2755,2757],{"class":2756},"sbssI","10\n",[2095,2759],{},[2761,2762,2763],"style",{},"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 .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}",{"title":596,"searchDepth":609,"depth":609,"links":2765},[2766,2767,2768,2769,2770,2771,2772,2773,2774,2775,2776,2777],{"id":569,"depth":615,"text":570},{"id":640,"depth":615,"text":641},{"id":741,"depth":615,"text":742},{"id":839,"depth":615,"text":840},{"id":983,"depth":615,"text":984},{"id":1082,"depth":615,"text":1083},{"id":1190,"depth":615,"text":1191},{"id":1313,"depth":615,"text":1314},{"id":1410,"depth":615,"text":1411},{"id":1632,"depth":615,"text":1633},{"id":2100,"depth":609,"text":2101},{"id":2294,"depth":609,"text":2295},"Field selection, caching, redirects, error boundaries, pagination and rate-limit backoff.","md",{},{"title":10,"description":2778},"BfYGFOeuDipXmu_hkIuYoKja96CqMhauE5KK9nlmuRU",[489,2784],{"title":14,"path":15,"stem":16,"description":2785,"children":-1},"Public read endpoints for blog posts, categories and tags.",1787919219934]