🏗️ Monorepo Architecture

Rekomendasi #5 — Turborepo Setup for Consolidated Projects | Generated 27 Maret 2026

Turbo
Build System
~12
Apps in Monorepo
3
Shared Packages
~70%
Build Time Saved

📊 Why Monorepo?

Setelah consolidation (93 → ~20 projects), semua apps bisa di-manage dalam satu repository menggunakan Turborepo. Ini memberikan:

⚡

Incremental Builds

Turborepo hanya rebuild apps yang berubah. Deploy 1 app tanpa rebuild semua 20.

📦

Shared Packages

UI components, utilities, dan configs shared across apps — zero duplication.

🔄

Single Source of Truth

Satu repo, satu PR workflow, satu CI/CD pipeline. Easier code review & maintenance.

🚀

Remote Caching

Vercel Remote Cache gratis — build artifacts di-cache, tim lain langsung pakai tanpa rebuild.

📁 Monorepo Structure

ibnu-workspace/
├── turbo.json                    # Turborepo config
├── package.json                  # Root workspace config
├── vercel.json                   # Global Vercel settings
│
├── apps/                          # All deployable applications
│   ├── superapp/                  # app.heyibnu.com (merged from 15 projects)
│   │   ├── package.json
│   │   ├── vercel.json
│   │   └── src/
│   │       ├── index.html
│   │       └── modules/           # life, pro, skill, business, etc.
│   │
│   ├── superapp-gov/              # superapp.bangkim.com (merged from 7 projects)
│   │   ├── package.json
│   │   └── src/
│   │
│   ├── gov-dashboard/             # dashboard.bangkim.com
│   │   ├── package.json
│   │   └── src/
│   │
│   ├── gov-data/                  # data.bangkim.com
│   │   ├── package.json
│   │   └── src/
│   │
│   ├── finance/                   # finance.heyibnu.com (merged from 8 projects)
│   │   ├── package.json
│   │   └── src/
│   │
│   ├── ai-hub/                    # ai.heyibnu.com
│   │   ├── package.json
│   │   └── src/
│   │
│   ├── tech-toolkit/              # tools.heyibnu.com
│   │   ├── package.json
│   │   └── src/
│   │
│   ├── learning/                  # learning.heyibnu.com (merged from 9 projects)
│   │   ├── package.json
│   │   └── src/
│   │
│   ├── career/                    # career.heyibnu.com
│   │   ├── package.json
│   │   └── src/
│   │
│   ├── productivity/              # productivity.heyibnu.com
│   │   ├── package.json
│   │   └── src/
│   │
│   ├── portfolio/                 # heyibnu.com
│   │   ├── package.json
│   │   └── src/
│   │
│   └── hub/                       # hub.heyibnu.com
│       ├── package.json
│       └── src/
│
├── packages/                      # Shared packages
│   ├── ui/                        # Shared UI components (nav, theme, cards)
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── nav.js
│   │   │   ├── theme.js
│   │   │   ├── card.js
│   │   │   └── index.js
│   │   └── styles/
│   │       └── base.css
│   │
│   ├── utils/                     # Shared utilities (fetch, auth, storage)
│   │   ├── package.json
│   │   └── src/
│   │       ├── api.js
│   │       ├── storage.js
│   │       └── helpers.js
│   │
│   └── config/                    # Shared configs (ESLint, Prettier, TypeScript)
│       ├── eslint-config/
│       ├── prettier-config/
│       └── tsconfig/
│
└── .github/
    └── workflows/
        └── ci.yml                 # GitHub Actions CI with Turborepo

⚙️ Key Configuration Files

turbo.json

{
  "$schema": "https://turbo.build/schema.json",
  "globalDependencies": ["**/.env"],
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**", ".next/**", "!.next/cache/**"],
      "cache": true
    },
    "dev": {
      "persistent": true,
      "cache": false
    },
    "lint": {
      "dependsOn": ["^build"],
      "cache": true
    },
    "deploy": {
      "dependsOn": ["build", "lint"],
      "cache": false
    }
  }
}

Root package.json

{
  "name": "ibnu-workspace",
  "private": true,
  "workspaces": ["apps/*", "packages/*"],
  "scripts": {
    "build": "turbo run build",
    "dev": "turbo run dev",
    "lint": "turbo run lint",
    "build:superapp": "turbo run build --filter=superapp",
    "build:gov": "turbo run build --filter=superapp-gov --filter=gov-dashboard --filter=gov-data",
    "deploy:all": "turbo run deploy"
  },
  "devDependencies": {
    "turbo": "^2.3.0"
  }
}

Per-App vercel.json (Example: superapp)

{
  "buildCommand": "cd ../.. && npx turbo run build --filter=superapp",
  "outputDirectory": "dist",
  "installCommand": "npm install",
  "framework": null
}

🔧 Vercel Multi-Project Deployment

Setiap app di monorepo bisa deploy ke Vercel project terpisah dengan domain sendiri:

AppVercel ProjectDomainRoot Directory
superappsuperapp-mainapp.heyibnu.comapps/superapp
superapp-govsuperappgovsuperapp.bangkim.comapps/superapp-gov
gov-dashboarddashboard-monitoringdashboard.bangkim.comapps/gov-dashboard
gov-datadatabangkimdata.bangkim.comapps/gov-data
financefinancefinance.heyibnu.comapps/finance
ai-hubllmaiai.heyibnu.comapps/ai-hub
tech-toolkitkoleksiapitools.heyibnu.comapps/tech-toolkit
learningibnu-learning-journeylearning.heyibnu.comapps/learning
careercareer-jobcareer.heyibnu.comapps/career
productivityproductivityproductivity.heyibnu.comapps/productivity
portfolioibnu-portfolioheyibnu.comapps/portfolio
hubibnu-hubhub.heyibnu.comapps/hub

📦 Shared Package: @ibnu/ui

// packages/ui/src/nav.js
// Shared navigation component used by ALL apps

export function createNav(config) {
  const nav = document.createElement('nav');
  nav.className = 'ibnu-nav';
  nav.innerHTML = `
    <div class="nav-brand">
      <a href="${config.homeUrl || '/'}">${config.title}</a>
    </div>
    <div class="nav-links">
      ${config.links.map(l =>
        \`<a href="\${l.url}" class="\${l.active ? 'active' : ''}">\${l.label}</a>\`
      ).join('')}
    </div>
    <div class="nav-hub">
      <a href="https://hub.heyibnu.com">🔗 Hub</a>
    </div>
  `;
  return nav;
}

// packages/ui/src/theme.js
// Unified dark theme applied across all apps

export const theme = {
  bg: '#0a0a0a', surface: '#141414', border: '#2a2a2a',
  text: '#f5f5f5', muted: '#a0a0a0', accent: '#3b82f6',
  success: '#22c55e', error: '#ef4444', warn: '#eab308'
};

export function injectTheme() {
  const style = document.createElement('style');
  style.textContent = Object.entries(theme)
    .map(([k,v]) => `--${k}:${v}`).join(';');
  document.head.appendChild(style);
}

🚀 Implementation Steps

1

Initialize Turborepo Workspace

Create new repo ibnu-workspace, install Turborepo, setup workspace structure dengan apps/ dan packages/ directories.

2

Create Shared Packages

Build @ibnu/ui (nav, theme, cards), @ibnu/utils (API helpers, storage), @ibnu/config (ESLint, Prettier, TypeScript configs).

3

Migrate Consolidated Apps

Move each of the ~12 consolidated apps into apps/ directory. Update imports to use shared packages. Verify builds pass.

4

Configure Vercel Projects

Update each Vercel project's root directory setting to point to its app directory. Setup build commands with Turborepo filter.

5

Enable Remote Caching

Link Turborepo to Vercel for remote cache. Build artifacts cached & shared — subsequent builds ~70% faster.

6

Setup CI/CD

GitHub Actions workflow with turbo run build --filter=...[HEAD^1] — only CI affected apps on each push.

📈 Performance Comparison

MetricBefore (93 repos)After MonorepoImprovement
Cold Build (all)N/A (separate repos)~3 minOne command
Incremental BuildAlways full rebuild~30s (changed only)~70% faster
Shared Code UpdatesCopy-paste to 93 repos1 change, auto-propagate~99% less effort
Dependency Management93 package.jsons1 root + 12 apps~87% fewer
CI Pipeline93 separate pipelines1 smart pipelineUnified
Code ConsistencyNo enforcementShared lint/format100% consistent

🔗 Dependencies

PrerequisiteStatusNotes
Rekomendasi #2: Consolidation📋 Plan CompleteMust complete consolidation before monorepo migration
Rekomendasi #4: Domain Strategy✅ DoneDomains already mapped — monorepo preserves these
Rekomendasi #8: Framework Standardization⏳ ParallelCan migrate to Next.js during monorepo setup

Monorepo Architecture Plan v1.0 — Generated by Claude for Subkhan Ibnu Aji — 27 Maret 2026

Part of Vercel & GitHub Infrastructure Audit Series