[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"header-categories":3,"post-api-design-principles-developers-love":73,"parsed-post-3a9b5909-6957-489d-b39b-da65cea24d1f":146},{"success":4,"data":5},true,{"items":6,"pagination":70},[7,16,24,32,40,48,56,63],{"id":8,"name":9,"description":10,"parentId":11,"createdAt":12,"updatedAt":12,"parent":11,"children":13,"_count":14},"ai-future","AI & The Future","Artificial intelligence and emerging technology",null,"2026-07-24T06:02:45.990Z",[],{"posts":15},1,{"id":17,"name":18,"description":19,"parentId":11,"createdAt":20,"updatedAt":20,"parent":11,"children":21,"_count":22},"tools-productivity","Tools & Productivity","Developer tools and workflow optimization","2026-07-24T06:02:45.712Z",[],{"posts":23},7,{"id":25,"name":26,"description":27,"parentId":11,"createdAt":28,"updatedAt":28,"parent":11,"children":29,"_count":30},"career","Career & Growth","Professional development for developers","2026-07-24T06:02:45.486Z",[],{"posts":31},3,{"id":33,"name":34,"description":35,"parentId":11,"createdAt":36,"updatedAt":36,"parent":11,"children":37,"_count":38},"opinion","Opinion & Analysis","Industry analysis and technical opinions","2026-07-24T06:02:45.272Z",[],{"posts":39},6,{"id":41,"name":42,"description":43,"parentId":11,"createdAt":44,"updatedAt":44,"parent":11,"children":45,"_count":46},"tutorials","Tutorials","Step-by-step learning guides","2026-07-24T06:02:44.965Z",[],{"posts":47},21,{"id":49,"name":50,"description":51,"parentId":11,"createdAt":52,"updatedAt":52,"parent":11,"children":53,"_count":54},"software-engineering","Software Engineering","Best practices, patterns, and principles","2026-07-24T06:02:44.689Z",[],{"posts":55},24,{"id":57,"name":58,"description":59,"parentId":11,"createdAt":60,"updatedAt":60,"parent":11,"children":61,"_count":62},"devops-cloud","DevOps & Cloud","Infrastructure, deployment, and cloud computing","2026-07-24T06:02:44.453Z",[],{"posts":39},{"id":64,"name":65,"description":66,"parentId":11,"createdAt":67,"updatedAt":67,"parent":11,"children":68,"_count":69},"web-development","Web Development","Frontend and backend web development tutorials and guides","2026-07-24T06:02:44.169Z",[],{"posts":55},{"page":15,"limit":71,"total":71,"totalPages":15,"hasNext":72,"hasPrev":72},8,false,{"success":4,"data":74},{"id":75,"slug":76,"title":77,"excerpt":78,"content":79,"status":80,"visibility":81,"featuredImage":82,"canonicalUrl":11,"readingTime":83,"viewCount":84,"commentEnabled":4,"publishedAt":85,"scheduledAt":11,"createdAt":86,"updatedAt":87,"seoTitle":88,"seoDescription":78,"seoKeywords":11,"authorId":89,"author":90,"coAuthors":95,"tags":96,"categories":112,"comments":114,"_count":115,"relatedPosts":117},"3a9b5909-6957-489d-b39b-da65cea24d1f","api-design-principles-developers-love","API Design Principles: Building APIs Developers Love","Practical API design guidelines covering naming conventions, error handling, pagination, and versioning for RESTful services.","## APIs Are User Interfaces\n\nAn API is a UI for developers. The same principles apply: consistency, discoverability, and helpful error messages.\n\n## Naming Conventions\n\n```\n✅ GET    \u002Fapi\u002Fposts              — List posts\n✅ GET    \u002Fapi\u002Fposts\u002F:id          — Get a post\n✅ POST   \u002Fapi\u002Fposts              — Create a post\n✅ PATCH  \u002Fapi\u002Fposts\u002F:id          — Update a post\n✅ DELETE \u002Fapi\u002Fposts\u002F:id          — Delete a post\n\n❌ GET    \u002Fapi\u002FgetPost\u002F:id        — Don't use verbs in URLs\n❌ POST   \u002Fapi\u002Fposts\u002Fcreate       — The HTTP method IS the verb\n❌ GET    \u002Fapi\u002Fpost\u002F:id           — Use plural nouns\n```\n\n## Consistent Response Envelope\n\n```typescript\n\u002F\u002F Success response\n{\n  \"success\": true,\n  \"data\": { ... },\n  \"meta\": {\n    \"page\": 1,\n    \"limit\": 20,\n    \"total\": 156\n  }\n}\n\n\u002F\u002F Error response\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"VALIDATION_ERROR\",\n    \"message\": \"Invalid input\",\n    \"details\": [\n      { \"field\": \"email\", \"message\": \"Must be a valid email\" }\n    ]\n  }\n}\n```\n\n## Pagination\n\n```typescript\n\u002F\u002F Offset-based (simple, supports jumping to pages)\nGET \u002Fapi\u002Fposts?page=2&limit=20\n\n\u002F\u002F Cursor-based (better performance at scale)\nGET \u002Fapi\u002Fposts?cursor=abc123&limit=20\n```\n\n::callout{icon=\"i-lucide-book-open\" color=\"info\"}\nUse offset pagination for admin dashboards where users jump to specific pages. Use cursor pagination for infinite scroll feeds where performance matters.\n::\n\n## Filtering and Sorting\n\n```\nGET \u002Fapi\u002Fposts?status=published&sort=-publishedAt&tags=vue,nuxt\n```\n\nConvention: prefix with `-` for descending sort.\n\n## Error Handling\n\nReturn appropriate HTTP status codes:\n\n```typescript\n\u002F\u002F server\u002Futils\u002Ferrors.ts\nexport function notFound(resource: string) {\n  throw createError({\n    statusCode: 404,\n    message: `${resource} not found`,\n    data: { code: 'NOT_FOUND' },\n  })\n}\n\nexport function validationError(errors: ValidationError[]) {\n  throw createError({\n    statusCode: 422,\n    message: 'Validation failed',\n    data: { code: 'VALIDATION_ERROR', details: errors },\n  })\n}\n```\n\n## Versioning Strategy\n\nFor most APIs, URL versioning is simplest:\n\n```\n\u002Fapi\u002Fv1\u002Fposts\n\u002Fapi\u002Fv2\u002Fposts\n```\n\nBut consider: **do you actually need versioning?** For internal APIs (your own frontend), evolve the API in place and update both sides together.\n\n## Rate Limiting Headers\n\nAlways communicate limits:\n\n```\nX-RateLimit-Limit: 100\nX-RateLimit-Remaining: 87\nX-RateLimit-Reset: 1625097600\n```\n\n## Summary\n\nGood API design is: consistent naming, predictable responses, helpful errors, and clear documentation. Make it obvious, then make it fast.\n","published","public","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1580894894513-541e068a3e2b?w=1200&q=80",10,2088,"2026-06-25T06:03:20.636Z","2026-07-24T06:03:20.639Z","2026-07-28T17:11:12.669Z","API Design Principles: Building APIs Developers Love | BitBlog","fddb5d93-7a2c-4d86-a06a-fa32e73a01c6",{"email":91,"bio":92,"id":89,"name":93,"avatarUrl":94},"mbeahessilfieprince@gmail.com","Fullstack Software Developer ","Mbeah Essilfie","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F93322394?v=4",[],[97,102,107],{"id":98,"name":99,"color":100,"description":101},"nodejs","Node.js","#339933","JavaScript runtime built on V8",{"id":103,"name":104,"color":105,"description":106},"api-design","API Design","#009688","RESTful and GraphQL API patterns",{"id":108,"name":109,"color":110,"description":111},"architecture","Architecture","#795548","Software architecture patterns",[113],{"id":49,"name":50,"description":51},[],{"comments":116},0,[118,127,136],{"id":119,"slug":120,"title":121,"excerpt":122,"featuredImage":123,"viewCount":124,"readingTime":71,"publishedAt":125,"author":126},"2997028f-4d22-4eb7-9d86-894a54cb559a","building-type-safe-apis-nuxt3-prisma","Building Type-Safe APIs with Nuxt 3 and Prisma","Learn how to build end-to-end type-safe APIs using Nuxt 3 server routes and Prisma ORM for a seamless developer experience.","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1498050108023-c5249f4df085?w=1200&q=80",1922,"2026-07-23T06:02:46.910Z",{"id":89,"name":93,"avatarUrl":94},{"id":128,"slug":129,"title":130,"excerpt":131,"featuredImage":132,"viewCount":133,"readingTime":83,"publishedAt":134,"author":135},"da9e4553-8b0d-411e-b4ec-f9684017e163","mastering-tailwind-css-design-systems","Mastering Tailwind CSS: From Utility Classes to Design Systems","Go beyond basic utility classes and learn how to build cohesive, maintainable design systems with Tailwind CSS.","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1555066931-4365d14bab8c?w=1200&q=80",257,"2026-07-21T06:02:49.268Z",{"id":89,"name":93,"avatarUrl":94},{"id":137,"slug":138,"title":139,"excerpt":140,"featuredImage":141,"viewCount":142,"readingTime":143,"publishedAt":144,"author":145},"50add5fc-4026-4267-b917-7f71ea9e35b0","complete-guide-vue3-composables","The Complete Guide to Vue 3 Composables","Understand the power of Vue 3's Composition API through practical, real-world composable patterns that you can use today.","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1517694712202-14dd9538aa97?w=1200&q=80",990,12,"2026-07-19T06:02:51.753Z",{"id":89,"name":93,"avatarUrl":94},{"data":147,"body":149,"toc":343},{"title":148,"description":148},"",{"type":150,"children":151},"root",[152,161,167,173,185,191,202,208,216,227,233,242,255,261,266,274,280,285,294,307,313,318,327,333,338],{"type":153,"tag":154,"props":155,"children":157},"element","h2",{"id":156},"apis-are-user-interfaces",[158],{"type":159,"value":160},"text","APIs Are User Interfaces",{"type":153,"tag":162,"props":163,"children":164},"p",{},[165],{"type":159,"value":166},"An API is a UI for developers. The same principles apply: consistency, discoverability, and helpful error messages.",{"type":153,"tag":154,"props":168,"children":170},{"id":169},"naming-conventions",[171],{"type":159,"value":172},"Naming Conventions",{"type":153,"tag":174,"props":175,"children":179},"pre",{"className":176,"code":178,"language":159},[177],"language-text","✅ GET    \u002Fapi\u002Fposts              — List posts\n✅ GET    \u002Fapi\u002Fposts\u002F:id          — Get a post\n✅ POST   \u002Fapi\u002Fposts              — Create a post\n✅ PATCH  \u002Fapi\u002Fposts\u002F:id          — Update a post\n✅ DELETE \u002Fapi\u002Fposts\u002F:id          — Delete a post\n\n❌ GET    \u002Fapi\u002FgetPost\u002F:id        — Don't use verbs in URLs\n❌ POST   \u002Fapi\u002Fposts\u002Fcreate       — The HTTP method IS the verb\n❌ GET    \u002Fapi\u002Fpost\u002F:id           — Use plural nouns\n",[180],{"type":153,"tag":181,"props":182,"children":183},"code",{"__ignoreMap":148},[184],{"type":159,"value":178},{"type":153,"tag":154,"props":186,"children":188},{"id":187},"consistent-response-envelope",[189],{"type":159,"value":190},"Consistent Response Envelope",{"type":153,"tag":174,"props":192,"children":197},{"className":193,"code":194,"language":195,"meta":148,"style":196},"language-typescript","\u002F\u002F Success response\n{\n  \"success\": true,\n  \"data\": { ... },\n  \"meta\": {\n    \"page\": 1,\n    \"limit\": 20,\n    \"total\": 156\n  }\n}\n\n\u002F\u002F Error response\n{\n  \"success\": false,\n  \"error\": {\n    \"code\": \"VALIDATION_ERROR\",\n    \"message\": \"Invalid input\",\n    \"details\": [\n      { \"field\": \"email\", \"message\": \"Must be a valid email\" }\n    ]\n  }\n}\n","typescript","undefined",[198],{"type":153,"tag":181,"props":199,"children":200},{"__ignoreMap":148},[201],{"type":159,"value":194},{"type":153,"tag":154,"props":203,"children":205},{"id":204},"pagination",[206],{"type":159,"value":207},"Pagination",{"type":153,"tag":174,"props":209,"children":211},{"className":193,"code":210,"language":195,"meta":148,"style":196},"\u002F\u002F Offset-based (simple, supports jumping to pages)\nGET \u002Fapi\u002Fposts?page=2&limit=20\n\n\u002F\u002F Cursor-based (better performance at scale)\nGET \u002Fapi\u002Fposts?cursor=abc123&limit=20\n",[212],{"type":153,"tag":181,"props":213,"children":214},{"__ignoreMap":148},[215],{"type":159,"value":210},{"type":153,"tag":217,"props":218,"children":221},"callout",{"color":219,"icon":220},"info","i-lucide-book-open",[222],{"type":153,"tag":162,"props":223,"children":224},{},[225],{"type":159,"value":226},"Use offset pagination for admin dashboards where users jump to specific pages. Use cursor pagination for infinite scroll feeds where performance matters.",{"type":153,"tag":154,"props":228,"children":230},{"id":229},"filtering-and-sorting",[231],{"type":159,"value":232},"Filtering and Sorting",{"type":153,"tag":174,"props":234,"children":237},{"className":235,"code":236,"language":159},[177],"GET \u002Fapi\u002Fposts?status=published&sort=-publishedAt&tags=vue,nuxt\n",[238],{"type":153,"tag":181,"props":239,"children":240},{"__ignoreMap":148},[241],{"type":159,"value":236},{"type":153,"tag":162,"props":243,"children":244},{},[245,247,253],{"type":159,"value":246},"Convention: prefix with ",{"type":153,"tag":181,"props":248,"children":250},{"className":249},[],[251],{"type":159,"value":252},"-",{"type":159,"value":254}," for descending sort.",{"type":153,"tag":154,"props":256,"children":258},{"id":257},"error-handling",[259],{"type":159,"value":260},"Error Handling",{"type":153,"tag":162,"props":262,"children":263},{},[264],{"type":159,"value":265},"Return appropriate HTTP status codes:",{"type":153,"tag":174,"props":267,"children":269},{"className":193,"code":268,"language":195,"meta":148,"style":196},"\u002F\u002F server\u002Futils\u002Ferrors.ts\nexport function notFound(resource: string) {\n  throw createError({\n    statusCode: 404,\n    message: `${resource} not found`,\n    data: { code: 'NOT_FOUND' },\n  })\n}\n\nexport function validationError(errors: ValidationError[]) {\n  throw createError({\n    statusCode: 422,\n    message: 'Validation failed',\n    data: { code: 'VALIDATION_ERROR', details: errors },\n  })\n}\n",[270],{"type":153,"tag":181,"props":271,"children":272},{"__ignoreMap":148},[273],{"type":159,"value":268},{"type":153,"tag":154,"props":275,"children":277},{"id":276},"versioning-strategy",[278],{"type":159,"value":279},"Versioning Strategy",{"type":153,"tag":162,"props":281,"children":282},{},[283],{"type":159,"value":284},"For most APIs, URL versioning is simplest:",{"type":153,"tag":174,"props":286,"children":289},{"className":287,"code":288,"language":159},[177],"\u002Fapi\u002Fv1\u002Fposts\n\u002Fapi\u002Fv2\u002Fposts\n",[290],{"type":153,"tag":181,"props":291,"children":292},{"__ignoreMap":148},[293],{"type":159,"value":288},{"type":153,"tag":162,"props":295,"children":296},{},[297,299,305],{"type":159,"value":298},"But consider: ",{"type":153,"tag":300,"props":301,"children":302},"strong",{},[303],{"type":159,"value":304},"do you actually need versioning?",{"type":159,"value":306}," For internal APIs (your own frontend), evolve the API in place and update both sides together.",{"type":153,"tag":154,"props":308,"children":310},{"id":309},"rate-limiting-headers",[311],{"type":159,"value":312},"Rate Limiting Headers",{"type":153,"tag":162,"props":314,"children":315},{},[316],{"type":159,"value":317},"Always communicate limits:",{"type":153,"tag":174,"props":319,"children":322},{"className":320,"code":321,"language":159},[177],"X-RateLimit-Limit: 100\nX-RateLimit-Remaining: 87\nX-RateLimit-Reset: 1625097600\n",[323],{"type":153,"tag":181,"props":324,"children":325},{"__ignoreMap":148},[326],{"type":159,"value":321},{"type":153,"tag":154,"props":328,"children":330},{"id":329},"summary",[331],{"type":159,"value":332},"Summary",{"type":153,"tag":162,"props":334,"children":335},{},[336],{"type":159,"value":337},"Good API design is: consistent naming, predictable responses, helpful errors, and clear documentation. Make it obvious, then make it fast.",{"type":153,"tag":339,"props":340,"children":341},"style",{},[342],{"type":159,"value":148},{"title":148,"searchDepth":344,"depth":344,"links":345},2,[346,347,348,349,350,351,352,353,354],{"id":156,"depth":344,"text":160},{"id":169,"depth":344,"text":172},{"id":187,"depth":344,"text":190},{"id":204,"depth":344,"text":207},{"id":229,"depth":344,"text":232},{"id":257,"depth":344,"text":260},{"id":276,"depth":344,"text":279},{"id":309,"depth":344,"text":312},{"id":329,"depth":344,"text":332}]