[{"data":1,"prerenderedAt":454},["ShallowReactive",2],{"navigation_docs_id":3,"-id-docs-getting-started-project-structure":62,"-id-docs-getting-started-project-structure-surround":449},[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":21,"body":64,"description":442,"extension":443,"links":444,"meta":445,"navigation":446,"path":22,"seo":447,"stem":23,"__hash__":448},"docs_id\u002Fid\u002Fdocs\u002F2.getting-started\u002Fproject-structure.md",{"type":65,"value":66,"toc":437},"minimark",[67,71,89,99,104,107,160,166,352,356,367,393,396,402,406,422,425,433],[68,69,21],"h1",{"id":70},"struktur-project",[72,73,74,75,79,80,84,85,88],"p",{},"Alkademi LMS Open Source menggunakan struktur ",[76,77,78],"strong",{},"modular monolith"," berbasis Nuxt Layers. Aplikasi utama tetap satu codebase dan satu proses build, tetapi fitur dipisah ke folder ",[81,82,83],"code",{},"cores\u002F"," dan ",[81,86,87],{},"plugins\u002F",".",[90,91,97],"pre",{"className":92,"code":94,"language":95,"meta":96},[93],"language-text","lms-opensource\u002F\n|-- app\u002F                    # Komponen, layout, composable, dan plugin Nuxt global\n|   |-- components\u002F          # AppHeader, AppSidebar, dan komponen global lain\n|   |-- composables\u002F         # Composable aplikasi, termasuk generator sidebar\n|   |-- layouts\u002F             # Layout default dan landing\n|   `-- plugins\u002F             # Plugin Nuxt tingkat aplikasi, termasuk plugin registry\n|-- cores\u002F                  # Fitur bawaan LMS\n|   |-- kelas\u002F\n|   |   |-- components\u002F\n|   |   |-- pages\u002F\n|   |   |-- server\u002Fapi\u002F\n|   |   |-- stores\u002F\n|   |   |-- types\u002F\n|   |   |-- core.config.ts\n|   |   `-- nuxt.config.ts\n|   |-- assignment\u002F\n|   |-- form\u002F\n|   |-- program\u002F\n|   |-- pustaka\u002F\n|   |-- studio\u002F\n|   `-- uikit\u002F\n|-- plugins\u002F                # Plugin kustom atau ekstensi\n|   `-- custom-class\u002F\n|       |-- components\u002F\n|       |-- pages\u002F\n|       |-- server\u002Fapi\u002F\n|       |-- plugin.config.ts\n|       |-- sidebar.ts\n|       `-- nuxt.config.ts\n|-- shared\u002F                 # Type dan utility bersama\n|   |-- types\u002F\n|   `-- utils\u002Flayers.ts\n|-- web\u002F                    # Layer landing\u002Fpublic site\n|-- public\u002F                 # Static assets\n|-- nuxt.config.ts          # Komposisi layer utama\n`-- package.json\n","text","",[81,98,94],{"__ignoreMap":96},[100,101,103],"h2",{"id":102},"folder-core","Folder Core",[72,105,106],{},"Setiap core feature adalah Nuxt Layer mandiri. Core yang aktif harus memiliki:",[108,109,110,120,134,143],"ul",{},[111,112,113,116,117,88],"li",{},[81,114,115],{},"nuxt.config.ts",": membuat folder tersebut dapat dimasukkan ke array ",[81,118,119],{},"extends",[111,121,122,125,126,129,130,133],{},[81,123,124],{},"core.config.ts",": menentukan ",[81,127,128],{},"enabled"," dan daftar ",[81,131,132],{},"routes"," untuk sidebar.",[111,135,136,139,140,88],{},[81,137,138],{},"pages\u002F",": halaman fitur. Contoh ",[81,141,142],{},"cores\u002Fkelas\u002Fpages\u002Fdashboard\u002Fkelas\u002Findex.vue",[111,144,145,148,149,148,152,155,156,159],{},[81,146,147],{},"components\u002F",", ",[81,150,151],{},"stores\u002F",[81,153,154],{},"server\u002Fapi\u002F",", dan ",[81,157,158],{},"types\u002F",": dipakai sesuai kebutuhan fitur.",[72,161,162,163,165],{},"Contoh ",[81,164,124],{},":",[90,167,171],{"className":168,"code":169,"language":170,"meta":96,"style":96},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import type { FeatureConfig } from '..\u002F..\u002Fshared\u002Ftypes\u002Ffeature'\n\nexport default {\n  enabled: true,\n  routes: [\n    {\n      key: 'kelas',\n      path: '\u002Fdashboard\u002Fkelas',\n      icon: 'i-heroicons-academic-cap',\n      label: 'Kelas'\n    }\n  ]\n} satisfies FeatureConfig\n","typescript",[81,172,173,209,216,228,244,255,261,279,296,312,327,333,339],{"__ignoreMap":96},[174,175,178,182,185,189,193,196,199,202,206],"span",{"class":176,"line":177},"line",1,[174,179,181],{"class":180},"s7zQu","import",[174,183,184],{"class":180}," type",[174,186,188],{"class":187},"sMK4o"," {",[174,190,192],{"class":191},"sTEyZ"," FeatureConfig",[174,194,195],{"class":187}," }",[174,197,198],{"class":180}," from",[174,200,201],{"class":187}," '",[174,203,205],{"class":204},"sfazB","..\u002F..\u002Fshared\u002Ftypes\u002Ffeature",[174,207,208],{"class":187},"'\n",[174,210,212],{"class":176,"line":211},2,[174,213,215],{"emptyLinePlaceholder":214},true,"\n",[174,217,219,222,225],{"class":176,"line":218},3,[174,220,221],{"class":180},"export",[174,223,224],{"class":180}," default",[174,226,227],{"class":187}," {\n",[174,229,231,235,237,241],{"class":176,"line":230},4,[174,232,234],{"class":233},"swJcz","  enabled",[174,236,165],{"class":187},[174,238,240],{"class":239},"sfNiH"," true",[174,242,243],{"class":187},",\n",[174,245,247,250,252],{"class":176,"line":246},5,[174,248,249],{"class":233},"  routes",[174,251,165],{"class":187},[174,253,254],{"class":191}," [\n",[174,256,258],{"class":176,"line":257},6,[174,259,260],{"class":187},"    {\n",[174,262,264,267,269,271,274,277],{"class":176,"line":263},7,[174,265,266],{"class":233},"      key",[174,268,165],{"class":187},[174,270,201],{"class":187},[174,272,273],{"class":204},"kelas",[174,275,276],{"class":187},"'",[174,278,243],{"class":187},[174,280,282,285,287,289,292,294],{"class":176,"line":281},8,[174,283,284],{"class":233},"      path",[174,286,165],{"class":187},[174,288,201],{"class":187},[174,290,291],{"class":204},"\u002Fdashboard\u002Fkelas",[174,293,276],{"class":187},[174,295,243],{"class":187},[174,297,299,302,304,306,308,310],{"class":176,"line":298},9,[174,300,301],{"class":233},"      icon",[174,303,165],{"class":187},[174,305,201],{"class":187},[174,307,53],{"class":204},[174,309,276],{"class":187},[174,311,243],{"class":187},[174,313,315,318,320,322,325],{"class":176,"line":314},10,[174,316,317],{"class":233},"      label",[174,319,165],{"class":187},[174,321,201],{"class":187},[174,323,324],{"class":204},"Kelas",[174,326,208],{"class":187},[174,328,330],{"class":176,"line":329},11,[174,331,332],{"class":187},"    }\n",[174,334,336],{"class":176,"line":335},12,[174,337,338],{"class":191},"  ]\n",[174,340,342,345,348],{"class":176,"line":341},13,[174,343,344],{"class":187},"}",[174,346,347],{"class":180}," satisfies",[174,349,351],{"class":350},"sBMFI"," FeatureConfig\n",[100,353,355],{"id":354},"folder-plugin","Folder Plugin",[72,357,358,359,362,363,366],{},"Plugin juga Nuxt Layer, tetapi memakai ",[81,360,361],{},"plugin.config.ts",". Saat ",[81,364,365],{},"enabled: true",", plugin akan:",[108,368,369,372,375,381,387],{},[111,370,371],{},"dimasukkan ke komposisi Nuxt Layer;",[111,373,374],{},"didaftarkan di runtime plugin registry;",[111,376,377,378,380],{},"menambahkan route ke sidebar dari field ",[81,379,132],{},";",[111,382,383,384,380],{},"bisa mengganti core tertentu lewat field ",[81,385,386],{},"replaces",[111,388,389,390,88],{},"bisa memperkaya sidebar lewat file ",[81,391,392],{},"sidebar.ts",[72,394,395],{},"Contoh struktur plugin minimal:",[90,397,400],{"className":398,"code":399,"language":95,"meta":96},[93],"plugins\u002Fmy-plugin\u002F\n|-- pages\u002F\n|   `-- dashboard\u002Fmy-plugin\u002Findex.vue\n|-- plugin.config.ts\n`-- nuxt.config.ts\n",[81,401,399],{"__ignoreMap":96},[100,403,405],{"id":404},"shared-types-dan-discovery","Shared Types dan Discovery",[72,407,408,409,412,413,416,417,84,419,421],{},"Kontrak core, plugin, dan sidebar berada di ",[81,410,411],{},"shared\u002Ftypes\u002F",". Proses auto-discovery layer berada di ",[81,414,415],{},"shared\u002Futils\u002Flayers.ts","; file ini membaca ",[81,418,124],{},[81,420,361],{}," untuk menentukan layer mana yang aktif.",[423,424],"hr",{},[72,426,427,428,88],{},"Selanjutnya, mari pelajari lebih dalam mengenai ",[429,430,432],"a",{"href":431},"\u002Farchitecture\u002Foverview","Arsitektur Layers",[434,435,436],"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 .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}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);}",{"title":96,"searchDepth":211,"depth":211,"links":438},[439,440,441],{"id":102,"depth":211,"text":103},{"id":354,"depth":211,"text":355},{"id":404,"depth":211,"text":405},"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.","md",null,{},{"icon":24},{"title":21,"description":442},"jB6UlkCv6jp-Tqhb0KO0ktmntQ21VEM9Zcaeh2az3i0",[450,452],{"title":16,"path":17,"stem":18,"description":451,"icon":19,"children":-1},"Ikuti langkah-langkah di bawah ini untuk memasang Alkademi LMS Open Source di lingkungan lokal Anda.",{"title":33,"path":34,"stem":35,"description":453,"icon":36,"children":-1},"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.",1780026929371]