[{"data":1,"prerenderedAt":750},["ShallowReactive",2],{"navigation_docs_id":3,"-id-docs-architecture-overview":62,"-id-docs-architecture-overview-surround":745},[4,9,26,37,51],{"title":5,"path":6,"stem":7,"icon":8},"Pendahuluan","\u002Fid\u002Fdocs\u002Fintroduction","id\u002Fdocs\u002F1.introduction","i-heroicons-book-open",{"title":10,"icon":11,"path":12,"stem":13,"children":14,"page":25},"Getting Started","i-heroicons-bolt","\u002Fid\u002Fdocs\u002Fgetting-started","id\u002Fdocs\u002F2.getting-started",[15,20],{"title":16,"path":17,"stem":18,"icon":19},"Instalasi","\u002Fid\u002Fdocs\u002Fgetting-started\u002Finstallation","id\u002Fdocs\u002F2.getting-started\u002Finstallation","i-heroicons-cloud-arrow-down",{"title":21,"path":22,"stem":23,"icon":24},"Struktur Project","\u002Fid\u002Fdocs\u002Fgetting-started\u002Fproject-structure","id\u002Fdocs\u002F2.getting-started\u002Fproject-structure","i-heroicons-folder",false,{"title":27,"icon":28,"path":29,"stem":30,"children":31,"page":25},"Architecture","i-heroicons-square-3-stack-3d","\u002Fid\u002Fdocs\u002Farchitecture","id\u002Fdocs\u002F3.architecture",[32],{"title":33,"path":34,"stem":35,"icon":36},"Arsitektur: Nuxt Layers","\u002Fid\u002Fdocs\u002Farchitecture\u002Foverview","id\u002Fdocs\u002F3.architecture\u002Foverview","i-heroicons-cpu-chip",{"title":38,"icon":39,"path":40,"stem":41,"children":42,"page":25},"Plugin System","i-heroicons-puzzle-piece","\u002Fid\u002Fdocs\u002Fplugin-system","id\u002Fdocs\u002F4.plugin-system",[43,46],{"title":38,"path":44,"stem":45,"icon":39},"\u002Fid\u002Fdocs\u002Fplugin-system\u002Fbasics","id\u002Fdocs\u002F4.plugin-system\u002Fbasics",{"title":47,"path":48,"stem":49,"icon":50},"Sistem Override","\u002Fid\u002Fdocs\u002Fplugin-system\u002Foverride-modes","id\u002Fdocs\u002F4.plugin-system\u002Foverride-modes","i-heroicons-arrow-path",{"title":52,"icon":53,"path":54,"stem":55,"children":56,"page":25},"Guides","i-heroicons-academic-cap","\u002Fid\u002Fdocs\u002Fguides","id\u002Fdocs\u002F5.guides",[57],{"title":58,"path":59,"stem":60,"icon":61},"Panduan Membuat Plugin","\u002Fid\u002Fdocs\u002Fguides\u002Fcreate-plugin","id\u002Fdocs\u002F5.guides\u002Fcreate-plugin","i-heroicons-command-line",{"id":63,"title":33,"body":64,"description":738,"extension":739,"links":740,"meta":741,"navigation":742,"path":34,"seo":743,"stem":35,"__hash__":744},"docs_id\u002Fid\u002Fdocs\u002F3.architecture\u002Foverview.md",{"type":65,"value":66,"toc":730},"minimark",[67,71,80,85,93,327,330,352,368,372,375,409,423,427,430,452,463,467,480,618,627,631,641,644,678,682,689,711,714,717,726],[68,69,33],"h1",{"id":70},"arsitektur-nuxt-layers",[72,73,74,75,79],"p",{},"Alkademi LMS Open Source dibangun sebagai ",[76,77,78],"strong",{},"modular monolith",". Semua fitur tetap berjalan sebagai satu aplikasi Nuxt, tetapi setiap domain fitur dipisah menjadi Nuxt Layer agar lebih mudah dirawat, diganti, atau diperluas.",[81,82,84],"h2",{"id":83},"komposisi-layer","Komposisi Layer",[72,86,87,88,92],{},"Komposisi layer utama berada di ",[89,90,91],"code",{},"nuxt.config.ts"," root:",[94,95,100],"pre",{"className":96,"code":97,"language":98,"meta":99,"style":99},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { resolve } from 'path'\nimport { getLayerDirs } from '.\u002Fshared\u002Futils\u002Flayers'\n\nconst rootDir = resolve(__dirname)\n\nexport default defineNuxtConfig({\n  extends: [\n    '.\u002Fweb',\n    ...getLayerDirs(rootDir, 'plugins'),\n    ...getLayerDirs(rootDir, 'cores')\n  ],\n  modules: ['@pinia\u002Fnuxt', '@nuxt\u002Fui']\n})\n","typescript","",[89,101,102,135,156,163,182,187,205,218,233,260,281,289,319],{"__ignoreMap":99},[103,104,107,111,115,119,122,125,128,132],"span",{"class":105,"line":106},"line",1,[103,108,110],{"class":109},"s7zQu","import",[103,112,114],{"class":113},"sMK4o"," {",[103,116,118],{"class":117},"sTEyZ"," resolve",[103,120,121],{"class":113}," }",[103,123,124],{"class":109}," from",[103,126,127],{"class":113}," '",[103,129,131],{"class":130},"sfazB","path",[103,133,134],{"class":113},"'\n",[103,136,138,140,142,145,147,149,151,154],{"class":105,"line":137},2,[103,139,110],{"class":109},[103,141,114],{"class":113},[103,143,144],{"class":117}," getLayerDirs",[103,146,121],{"class":113},[103,148,124],{"class":109},[103,150,127],{"class":113},[103,152,153],{"class":130},".\u002Fshared\u002Futils\u002Flayers",[103,155,134],{"class":113},[103,157,159],{"class":105,"line":158},3,[103,160,162],{"emptyLinePlaceholder":161},true,"\n",[103,164,166,170,173,176,179],{"class":105,"line":165},4,[103,167,169],{"class":168},"spNyl","const",[103,171,172],{"class":117}," rootDir ",[103,174,175],{"class":113},"=",[103,177,118],{"class":178},"s2Zo4",[103,180,181],{"class":117},"(__dirname)\n",[103,183,185],{"class":105,"line":184},5,[103,186,162],{"emptyLinePlaceholder":161},[103,188,190,193,196,199,202],{"class":105,"line":189},6,[103,191,192],{"class":109},"export",[103,194,195],{"class":109}," default",[103,197,198],{"class":178}," defineNuxtConfig",[103,200,201],{"class":117},"(",[103,203,204],{"class":113},"{\n",[103,206,208,212,215],{"class":105,"line":207},7,[103,209,211],{"class":210},"swJcz","  extends",[103,213,214],{"class":113},":",[103,216,217],{"class":117}," [\n",[103,219,221,224,227,230],{"class":105,"line":220},8,[103,222,223],{"class":113},"    '",[103,225,226],{"class":130},".\u002Fweb",[103,228,229],{"class":113},"'",[103,231,232],{"class":113},",\n",[103,234,236,239,242,245,248,250,253,255,258],{"class":105,"line":235},9,[103,237,238],{"class":113},"    ...",[103,240,241],{"class":178},"getLayerDirs",[103,243,244],{"class":117},"(rootDir",[103,246,247],{"class":113},",",[103,249,127],{"class":113},[103,251,252],{"class":130},"plugins",[103,254,229],{"class":113},[103,256,257],{"class":117},")",[103,259,232],{"class":113},[103,261,263,265,267,269,271,273,276,278],{"class":105,"line":262},10,[103,264,238],{"class":113},[103,266,241],{"class":178},[103,268,244],{"class":117},[103,270,247],{"class":113},[103,272,127],{"class":113},[103,274,275],{"class":130},"cores",[103,277,229],{"class":113},[103,279,280],{"class":117},")\n",[103,282,284,287],{"class":105,"line":283},11,[103,285,286],{"class":117},"  ]",[103,288,232],{"class":113},[103,290,292,295,297,300,302,305,307,309,311,314,316],{"class":105,"line":291},12,[103,293,294],{"class":210},"  modules",[103,296,214],{"class":113},[103,298,299],{"class":117}," [",[103,301,229],{"class":113},[103,303,304],{"class":130},"@pinia\u002Fnuxt",[103,306,229],{"class":113},[103,308,247],{"class":113},[103,310,127],{"class":113},[103,312,313],{"class":130},"@nuxt\u002Fui",[103,315,229],{"class":113},[103,317,318],{"class":117},"]\n",[103,320,322,325],{"class":105,"line":321},13,[103,323,324],{"class":113},"}",[103,326,280],{"class":117},[72,328,329],{},"Urutan aktual project adalah:",[331,332,333,339,346],"ol",{},[334,335,336,338],"li",{},[89,337,226],{}," untuk landing\u002Fpublic site.",[334,340,341,342,345],{},"Plugin aktif dari folder ",[89,343,344],{},"plugins\u002F",".",[334,347,348,349,345],{},"Core aktif dari folder ",[89,350,351],{},"cores\u002F",[72,353,354,355,358,359,361,362,364,365,367],{},"Layer tidak ditulis manual satu per satu. Fungsi ",[89,356,357],{},"getLayerDirs(rootDir, baseDir)"," memindai folder ",[89,360,344],{}," dan ",[89,363,351],{},", lalu hanya memasukkan folder yang memiliki ",[89,366,91],{}," dan config aktif.",[81,369,371],{"id":370},"auto-discovery-core","Auto-Discovery Core",[72,373,374],{},"Core dianggap aktif jika:",[376,377,378,385,390,395,403],"ul",{},[334,379,380,381,384],{},"foldernya berada di ",[89,382,383],{},"cores\u002F{core-id}",";",[334,386,387,388,384],{},"memiliki ",[89,389,91],{},[334,391,387,392,384],{},[89,393,394],{},"core.config.ts",[334,396,397,399,400,384],{},[89,398,394],{}," berisi ",[89,401,402],{},"enabled: true",[334,404,405,406,345],{},"core tersebut tidak sedang diganti oleh plugin aktif melalui ",[89,407,408],{},"replaces",[72,410,411,412,414,415,418,419,422],{},"Jika core tidak memiliki ",[89,413,394],{},", tidak memiliki flag ",[89,416,417],{},"enabled",", atau ",[89,420,421],{},"enabled: false",", layer tersebut dilewati.",[81,424,426],{"id":425},"auto-discovery-plugin","Auto-Discovery Plugin",[72,428,429],{},"Plugin dianggap aktif jika:",[376,431,432,437,441,446],{},[334,433,380,434,384],{},[89,435,436],{},"plugins\u002F{plugin-id}",[334,438,387,439,384],{},[89,440,91],{},[334,442,387,443,384],{},[89,444,445],{},"plugin.config.ts",[334,447,448,399,450,345],{},[89,449,445],{},[89,451,402],{},[72,453,454,455,458,459,462],{},"Plugin aktif juga dibaca untuk menentukan core yang diganti. Jika sebuah plugin memiliki ",[89,456,457],{},"replaces: ['program']",", core ",[89,460,461],{},"program"," tidak dimasukkan ke komposisi layer.",[81,464,466],{"id":465},"replacement-core","Replacement Core",[72,468,469,470,472,473,476,477,345],{},"Mekanisme replacement saat ini berbasis field ",[89,471,408],{},", bukan ",[89,474,475],{},"overrideMode"," atau ",[89,478,479],{},"targetCore",[94,481,483],{"className":96,"code":482,"language":98,"meta":99,"style":99},"export default {\n  enabled: true,\n  replaces: ['program'],\n  routes: [\n    {\n      key: 'custom-class',\n      path: '\u002Fdashboard\u002Fcustom-class',\n      icon: 'i-heroicons-sparkles',\n      label: 'Custom Class'\n    }\n  ]\n}\n",[89,484,485,494,507,527,536,541,557,573,589,603,608,613],{"__ignoreMap":99},[103,486,487,489,491],{"class":105,"line":106},[103,488,192],{"class":109},[103,490,195],{"class":109},[103,492,493],{"class":113}," {\n",[103,495,496,499,501,505],{"class":105,"line":137},[103,497,498],{"class":210},"  enabled",[103,500,214],{"class":113},[103,502,504],{"class":503},"sfNiH"," true",[103,506,232],{"class":113},[103,508,509,512,514,516,518,520,522,525],{"class":105,"line":158},[103,510,511],{"class":210},"  replaces",[103,513,214],{"class":113},[103,515,299],{"class":117},[103,517,229],{"class":113},[103,519,461],{"class":130},[103,521,229],{"class":113},[103,523,524],{"class":117},"]",[103,526,232],{"class":113},[103,528,529,532,534],{"class":105,"line":165},[103,530,531],{"class":210},"  routes",[103,533,214],{"class":113},[103,535,217],{"class":117},[103,537,538],{"class":105,"line":184},[103,539,540],{"class":113},"    {\n",[103,542,543,546,548,550,553,555],{"class":105,"line":189},[103,544,545],{"class":210},"      key",[103,547,214],{"class":113},[103,549,127],{"class":113},[103,551,552],{"class":130},"custom-class",[103,554,229],{"class":113},[103,556,232],{"class":113},[103,558,559,562,564,566,569,571],{"class":105,"line":207},[103,560,561],{"class":210},"      path",[103,563,214],{"class":113},[103,565,127],{"class":113},[103,567,568],{"class":130},"\u002Fdashboard\u002Fcustom-class",[103,570,229],{"class":113},[103,572,232],{"class":113},[103,574,575,578,580,582,585,587],{"class":105,"line":220},[103,576,577],{"class":210},"      icon",[103,579,214],{"class":113},[103,581,127],{"class":113},[103,583,584],{"class":130},"i-heroicons-sparkles",[103,586,229],{"class":113},[103,588,232],{"class":113},[103,590,591,594,596,598,601],{"class":105,"line":235},[103,592,593],{"class":210},"      label",[103,595,214],{"class":113},[103,597,127],{"class":113},[103,599,600],{"class":130},"Custom Class",[103,602,134],{"class":113},[103,604,605],{"class":105,"line":262},[103,606,607],{"class":113},"    }\n",[103,609,610],{"class":105,"line":283},[103,611,612],{"class":117},"  ]\n",[103,614,615],{"class":105,"line":291},[103,616,617],{"class":113},"}\n",[72,619,620,621,623,624,345],{},"Saat plugin di atas aktif, discovery akan melewati core ",[89,622,461],{},". Dengan cara ini plugin dapat mengambil alih fitur core tanpa mengubah source di ",[89,625,626],{},"cores\u002Fprogram",[81,628,630],{"id":629},"runtime-registry","Runtime Registry",[72,632,633,634,637,638,345],{},"Selain discovery build-time di ",[89,635,636],{},"shared\u002Futils\u002Flayers.ts",", aplikasi juga punya runtime registry di ",[89,639,640],{},"app\u002Fplugins\u002Fplugin-registry.ts",[72,642,643],{},"Registry ini:",[376,645,646,656,668,671],{},[334,647,648,649,652,653,384],{},"membaca semua ",[89,650,651],{},"plugins\u002F*\u002Fplugin.config.ts"," dengan ",[89,654,655],{},"import.meta.glob",[334,657,658,659,661,662,664,665,384],{},"memvalidasi field ",[89,660,417],{},", ",[89,663,408],{},", dan ",[89,666,667],{},"routes",[334,669,670],{},"hanya mendaftarkan plugin yang aktif;",[334,672,673,674,677],{},"menyediakan ",[89,675,676],{},"usePluginRegistry()"," untuk composable lain seperti sidebar.",[81,679,681],{"id":680},"sidebar-sebagai-bagian-arsitektur","Sidebar sebagai Bagian Arsitektur",[72,683,684,685,688],{},"Sidebar tidak ditulis statis di komponen. ",[89,686,687],{},"app\u002Fcomposables\u002FuseSidebarMenu.ts"," membangun menu dari:",[376,690,691,696,701,708],{},[334,692,693,695],{},[89,694,394],{}," untuk menu core;",[334,697,698,700],{},[89,699,445],{}," untuk menu plugin;",[334,702,703,704,707],{},"optional ",[89,705,706],{},"sidebar.ts"," dari core\u002Fplugin untuk menu dinamis;",[334,709,710],{},"daftar core yang diganti oleh plugin aktif.",[72,712,713],{},"Ini membuat route, plugin registry, dan navigasi dashboard tetap mengikuti konfigurasi feature.",[715,716],"hr",{},[72,718,719,720,725],{},"Pelajari lebih lanjut tentang ",[721,722,724],"a",{"href":723},"\u002Fplugin-system\u002Fbasics","Sistem Plugin"," untuk melihat bagaimana kustomisasi dilakukan.",[727,728,729],"style",{},"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 .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}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 .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}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 .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":99,"searchDepth":137,"depth":137,"links":731},[732,733,734,735,736,737],{"id":83,"depth":137,"text":84},{"id":370,"depth":137,"text":371},{"id":425,"depth":137,"text":426},{"id":465,"depth":137,"text":466},{"id":629,"depth":137,"text":630},{"id":680,"depth":137,"text":681},"Alkademi LMS Open Source dibangun sebagai modular monolith. Semua fitur tetap berjalan sebagai satu aplikasi Nuxt, tetapi setiap domain fitur dipisah menjadi Nuxt Layer agar lebih mudah dirawat, diganti, atau diperluas.","md",null,{},{"icon":36},{"title":33,"description":738},"MsNJDa8hiqARthMfi46PN_cESCVGOby38HAihWwii5M",[746,748],{"title":21,"path":22,"stem":23,"description":747,"icon":24,"children":-1},"Alkademi LMS Open Source menggunakan struktur modular monolith berbasis Nuxt Layers. Aplikasi utama tetap satu codebase dan satu proses build, tetapi fitur dipisah ke folder cores\u002F dan plugins\u002F.",{"title":38,"path":44,"stem":45,"description":749,"icon":39,"children":-1},"Plugin adalah Nuxt Layer tambahan yang ditempatkan di folder plugins\u002F. Plugin dipakai untuk menambah fitur baru, mengganti core tertentu, atau memperkaya navigasi tanpa mengubah source di cores\u002F.",1780026929747]