[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"header-categories":3,"post-monorepos-turborepo-managing-packages":73,"parsed-post-1437766b-f895-4382-9d67-2525941643d9":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":71,"viewCount":83,"commentEnabled":4,"publishedAt":84,"scheduledAt":11,"createdAt":85,"updatedAt":86,"seoTitle":87,"seoDescription":78,"seoKeywords":11,"authorId":88,"author":89,"coAuthors":94,"tags":95,"categories":111,"comments":114,"_count":115,"relatedPosts":117},"1437766b-f895-4382-9d67-2525941643d9","monorepos-turborepo-managing-packages","Monorepos with Turborepo: Managing Multiple Packages","Set up a productive monorepo with Turborepo for shared UI libraries, APIs, and apps with smart caching and task orchestration.","## Why Monorepos?\n\nWhen you have a shared UI library, a web app, a mobile app, and an API — all using the same types and utilities — a monorepo keeps everything in sync.\n\n## Setup with Turborepo\n\n```bash\nnpx create-turbo@latest my-monorepo\n```\n\nStructure:\n\n```\nmy-monorepo\u002F\n├── apps\u002F\n│   ├── web\u002F          ← Nuxt app\n│   ├── api\u002F          ← API server\n│   └── docs\u002F         ← Documentation site\n├── packages\u002F\n│   ├── ui\u002F           ← Shared component library\n│   ├── config\u002F       ← Shared ESLint, Tailwind configs\n│   ├── database\u002F     ← Prisma schema & client\n│   └── types\u002F        ← Shared TypeScript types\n├── turbo.json\n├── package.json\n└── pnpm-workspace.yaml\n```\n\n## Workspace Configuration\n\n```yaml\n# pnpm-workspace.yaml\npackages:\n  - \"apps\u002F*\"\n  - \"packages\u002F*\"\n```\n\n```json\n\u002F\u002F turbo.json\n{\n  \"tasks\": {\n    \"build\": {\n      \"dependsOn\": [\"^build\"],\n      \"outputs\": [\".output\u002F**\", \"dist\u002F**\"]\n    },\n    \"dev\": {\n      \"cache\": false,\n      \"persistent\": true\n    },\n    \"test\": {\n      \"dependsOn\": [\"^build\"]\n    },\n    \"lint\": {}\n  }\n}\n```\n\n## Shared Packages\n\n```json\n\u002F\u002F packages\u002Fui\u002Fpackage.json\n{\n  \"name\": \"@myorg\u002Fui\",\n  \"exports\": {\n    \".\": \".\u002Fsrc\u002Findex.ts\",\n    \".\u002FButton\": \".\u002Fsrc\u002FButton.vue\"\n  }\n}\n```\n\nConsuming in an app:\n\n```json\n\u002F\u002F apps\u002Fweb\u002Fpackage.json\n{\n  \"dependencies\": {\n    \"@myorg\u002Fui\": \"workspace:*\",\n    \"@myorg\u002Ftypes\": \"workspace:*\"\n  }\n}\n```\n\n::callout{icon=\"i-lucide-link\" color=\"primary\"}\n`workspace:*` tells pnpm to always use the local version. Changes to the shared package are immediately available in all consuming apps — no publishing needed.\n::\n\n## Task Caching\n\nTurborepo's killer feature: if inputs haven't changed, skip the task entirely:\n\n```bash\n$ turbo build\n\n Tasks:    4 successful, 4 total\n Cached:   3 cached, 4 total\n Time:     1.2s (3 cached)\n```\n\nEnable remote caching for team-wide sharing:\n\n```bash\nturbo login\nturbo link\n```\n\nNow builds cached by one developer are reused by the entire team and CI.\n\n## Shared Configuration\n\n```typescript\n\u002F\u002F packages\u002Fconfig\u002Ftailwind.config.ts\nimport type { Config } from 'tailwindcss'\n\nexport default {\n  theme: {\n    extend: {\n      colors: { brand: { 500: '#3b82f6' } },\n    },\n  },\n} satisfies Config\n```\n\n```typescript\n\u002F\u002F apps\u002Fweb\u002Ftailwind.config.ts\nimport baseConfig from '@myorg\u002Fconfig\u002Ftailwind'\n\nexport default {\n  presets: [baseConfig],\n  content: ['.\u002Fapp\u002F**\u002F*.vue', '..\u002F..\u002Fpackages\u002Fui\u002Fsrc\u002F**\u002F*.vue'],\n}\n```\n\n## When a Monorepo Makes Sense\n\n✅ Multiple apps sharing code\n✅ Atomic changes across packages (update types + UI + app in one PR)\n✅ Team working across multiple packages\n\n❌ Unrelated projects that happen to live together\n❌ Teams that rarely collaborate\n❌ When build times become unmanageable\n\nStart with a monorepo if you foresee shared code. Splitting later is harder than starting unified.\n","published","public","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1555066931-4365d14bab8c?w=1200&q=80",2102,"2026-04-22T06:04:35.999Z","2026-07-24T06:04:36.002Z","2026-07-28T12:22:17.023Z","Monorepos with Turborepo: Managing Multiple Packages | BitBlog","fddb5d93-7a2c-4d86-a06a-fa32e73a01c6",{"email":90,"bio":91,"id":88,"name":92,"avatarUrl":93},"mbeahessilfieprince@gmail.com","Fullstack Software Developer ","Mbeah Essilfie","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F93322394?v=4",[],[96,101,106],{"id":97,"name":98,"color":99,"description":100},"typescript","TypeScript","#3178c6","Typed superset of JavaScript",{"id":102,"name":103,"color":104,"description":105},"devops","DevOps","#ff6c37","Development and Operations",{"id":107,"name":108,"color":109,"description":110},"architecture","Architecture","#795548","Software architecture patterns",[112,113],{"id":49,"name":50,"description":51},{"id":17,"name":18,"description":19},[],{"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",1920,"2026-07-23T06:02:46.910Z",{"id":88,"name":92,"avatarUrl":93},{"id":128,"slug":129,"title":130,"excerpt":131,"featuredImage":82,"viewCount":132,"readingTime":133,"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.",256,10,"2026-07-21T06:02:49.268Z",{"id":88,"name":92,"avatarUrl":93},{"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",989,12,"2026-07-19T06:02:51.753Z",{"id":88,"name":92,"avatarUrl":93},{"data":147,"body":149,"toc":357},{"title":148,"description":148},"",{"type":150,"children":151},"root",[152,161,167,173,186,191,201,207,217,227,233,241,246,254,271,277,282,290,295,303,308,314,323,331,337,342,347,352],{"type":153,"tag":154,"props":155,"children":157},"element","h2",{"id":156},"why-monorepos",[158],{"type":159,"value":160},"text","Why Monorepos?",{"type":153,"tag":162,"props":163,"children":164},"p",{},[165],{"type":159,"value":166},"When you have a shared UI library, a web app, a mobile app, and an API — all using the same types and utilities — a monorepo keeps everything in sync.",{"type":153,"tag":154,"props":168,"children":170},{"id":169},"setup-with-turborepo",[171],{"type":159,"value":172},"Setup with Turborepo",{"type":153,"tag":174,"props":175,"children":180},"pre",{"className":176,"code":177,"language":178,"meta":148,"style":179},"language-bash","npx create-turbo@latest my-monorepo\n","bash","undefined",[181],{"type":153,"tag":182,"props":183,"children":184},"code",{"__ignoreMap":148},[185],{"type":159,"value":177},{"type":153,"tag":162,"props":187,"children":188},{},[189],{"type":159,"value":190},"Structure:",{"type":153,"tag":174,"props":192,"children":196},{"className":193,"code":195,"language":159},[194],"language-text","my-monorepo\u002F\n├── apps\u002F\n│   ├── web\u002F          ← Nuxt app\n│   ├── api\u002F          ← API server\n│   └── docs\u002F         ← Documentation site\n├── packages\u002F\n│   ├── ui\u002F           ← Shared component library\n│   ├── config\u002F       ← Shared ESLint, Tailwind configs\n│   ├── database\u002F     ← Prisma schema & client\n│   └── types\u002F        ← Shared TypeScript types\n├── turbo.json\n├── package.json\n└── pnpm-workspace.yaml\n",[197],{"type":153,"tag":182,"props":198,"children":199},{"__ignoreMap":148},[200],{"type":159,"value":195},{"type":153,"tag":154,"props":202,"children":204},{"id":203},"workspace-configuration",[205],{"type":159,"value":206},"Workspace Configuration",{"type":153,"tag":174,"props":208,"children":212},{"className":209,"code":210,"language":211,"meta":148,"style":179},"language-yaml","# pnpm-workspace.yaml\npackages:\n  - \"apps\u002F*\"\n  - \"packages\u002F*\"\n","yaml",[213],{"type":153,"tag":182,"props":214,"children":215},{"__ignoreMap":148},[216],{"type":159,"value":210},{"type":153,"tag":174,"props":218,"children":222},{"className":219,"code":220,"language":221,"meta":148,"style":179},"language-json","\u002F\u002F turbo.json\n{\n  \"tasks\": {\n    \"build\": {\n      \"dependsOn\": [\"^build\"],\n      \"outputs\": [\".output\u002F**\", \"dist\u002F**\"]\n    },\n    \"dev\": {\n      \"cache\": false,\n      \"persistent\": true\n    },\n    \"test\": {\n      \"dependsOn\": [\"^build\"]\n    },\n    \"lint\": {}\n  }\n}\n","json",[223],{"type":153,"tag":182,"props":224,"children":225},{"__ignoreMap":148},[226],{"type":159,"value":220},{"type":153,"tag":154,"props":228,"children":230},{"id":229},"shared-packages",[231],{"type":159,"value":232},"Shared Packages",{"type":153,"tag":174,"props":234,"children":236},{"className":219,"code":235,"language":221,"meta":148,"style":179},"\u002F\u002F packages\u002Fui\u002Fpackage.json\n{\n  \"name\": \"@myorg\u002Fui\",\n  \"exports\": {\n    \".\": \".\u002Fsrc\u002Findex.ts\",\n    \".\u002FButton\": \".\u002Fsrc\u002FButton.vue\"\n  }\n}\n",[237],{"type":153,"tag":182,"props":238,"children":239},{"__ignoreMap":148},[240],{"type":159,"value":235},{"type":153,"tag":162,"props":242,"children":243},{},[244],{"type":159,"value":245},"Consuming in an app:",{"type":153,"tag":174,"props":247,"children":249},{"className":219,"code":248,"language":221,"meta":148,"style":179},"\u002F\u002F apps\u002Fweb\u002Fpackage.json\n{\n  \"dependencies\": {\n    \"@myorg\u002Fui\": \"workspace:*\",\n    \"@myorg\u002Ftypes\": \"workspace:*\"\n  }\n}\n",[250],{"type":153,"tag":182,"props":251,"children":252},{"__ignoreMap":148},[253],{"type":159,"value":248},{"type":153,"tag":255,"props":256,"children":259},"callout",{"color":257,"icon":258},"primary","i-lucide-link",[260],{"type":153,"tag":162,"props":261,"children":262},{},[263,269],{"type":153,"tag":182,"props":264,"children":266},{"className":265},[],[267],{"type":159,"value":268},"workspace:*",{"type":159,"value":270}," tells pnpm to always use the local version. Changes to the shared package are immediately available in all consuming apps — no publishing needed.",{"type":153,"tag":154,"props":272,"children":274},{"id":273},"task-caching",[275],{"type":159,"value":276},"Task Caching",{"type":153,"tag":162,"props":278,"children":279},{},[280],{"type":159,"value":281},"Turborepo's killer feature: if inputs haven't changed, skip the task entirely:",{"type":153,"tag":174,"props":283,"children":285},{"className":176,"code":284,"language":178,"meta":148,"style":179},"$ turbo build\n\n Tasks:    4 successful, 4 total\n Cached:   3 cached, 4 total\n Time:     1.2s (3 cached)\n",[286],{"type":153,"tag":182,"props":287,"children":288},{"__ignoreMap":148},[289],{"type":159,"value":284},{"type":153,"tag":162,"props":291,"children":292},{},[293],{"type":159,"value":294},"Enable remote caching for team-wide sharing:",{"type":153,"tag":174,"props":296,"children":298},{"className":176,"code":297,"language":178,"meta":148,"style":179},"turbo login\nturbo link\n",[299],{"type":153,"tag":182,"props":300,"children":301},{"__ignoreMap":148},[302],{"type":159,"value":297},{"type":153,"tag":162,"props":304,"children":305},{},[306],{"type":159,"value":307},"Now builds cached by one developer are reused by the entire team and CI.",{"type":153,"tag":154,"props":309,"children":311},{"id":310},"shared-configuration",[312],{"type":159,"value":313},"Shared Configuration",{"type":153,"tag":174,"props":315,"children":318},{"className":316,"code":317,"language":97,"meta":148,"style":179},"language-typescript","\u002F\u002F packages\u002Fconfig\u002Ftailwind.config.ts\nimport type { Config } from 'tailwindcss'\n\nexport default {\n  theme: {\n    extend: {\n      colors: { brand: { 500: '#3b82f6' } },\n    },\n  },\n} satisfies Config\n",[319],{"type":153,"tag":182,"props":320,"children":321},{"__ignoreMap":148},[322],{"type":159,"value":317},{"type":153,"tag":174,"props":324,"children":326},{"className":316,"code":325,"language":97,"meta":148,"style":179},"\u002F\u002F apps\u002Fweb\u002Ftailwind.config.ts\nimport baseConfig from '@myorg\u002Fconfig\u002Ftailwind'\n\nexport default {\n  presets: [baseConfig],\n  content: ['.\u002Fapp\u002F**\u002F*.vue', '..\u002F..\u002Fpackages\u002Fui\u002Fsrc\u002F**\u002F*.vue'],\n}\n",[327],{"type":153,"tag":182,"props":328,"children":329},{"__ignoreMap":148},[330],{"type":159,"value":325},{"type":153,"tag":154,"props":332,"children":334},{"id":333},"when-a-monorepo-makes-sense",[335],{"type":159,"value":336},"When a Monorepo Makes Sense",{"type":153,"tag":162,"props":338,"children":339},{},[340],{"type":159,"value":341},"✅ Multiple apps sharing code\n✅ Atomic changes across packages (update types + UI + app in one PR)\n✅ Team working across multiple packages",{"type":153,"tag":162,"props":343,"children":344},{},[345],{"type":159,"value":346},"❌ Unrelated projects that happen to live together\n❌ Teams that rarely collaborate\n❌ When build times become unmanageable",{"type":153,"tag":162,"props":348,"children":349},{},[350],{"type":159,"value":351},"Start with a monorepo if you foresee shared code. Splitting later is harder than starting unified.",{"type":153,"tag":353,"props":354,"children":355},"style",{},[356],{"type":159,"value":148},{"title":148,"searchDepth":358,"depth":358,"links":359},2,[360,361,362,363,364,365,366],{"id":156,"depth":358,"text":160},{"id":169,"depth":358,"text":172},{"id":203,"depth":358,"text":206},{"id":229,"depth":358,"text":232},{"id":273,"depth":358,"text":276},{"id":310,"depth":358,"text":313},{"id":333,"depth":358,"text":336}]