Architecture: Nuxt Layers
Architecture: Nuxt Layers
Alkademi LMS Open Source is built as a modular monolith. Every feature still runs inside one Nuxt application, but each domain feature is isolated as a Nuxt Layer so it can be maintained, replaced, or extended more easily.
Layer Composition
The main layer composition lives in the root nuxt.config.ts:
import { resolve } from 'path'
import { getLayerDirs } from './shared/utils/layers'
const rootDir = resolve(__dirname)
export default defineNuxtConfig({
extends: [
'./web',
...getLayerDirs(rootDir, 'plugins'),
...getLayerDirs(rootDir, 'cores')
],
modules: ['@pinia/nuxt', '@nuxt/ui']
})
The actual project order is:
./webfor the landing/public site.- Active plugins from
plugins/. - Active cores from
cores/.
Layers are not listed manually one by one. getLayerDirs(rootDir, baseDir) scans the plugins/ and cores/ folders, then only includes folders with nuxt.config.ts and an enabled config.
Core Auto-Discovery
A core is active when:
- it is located at
cores/{core-id}; - it has
nuxt.config.ts; - it has
core.config.ts; core.config.tscontainsenabled: true;- the core is not replaced by an active plugin through
replaces.
If a core does not have core.config.ts, does not have an enabled flag, or has enabled: false, the layer is skipped.
Plugin Auto-Discovery
A plugin is active when:
- it is located at
plugins/{plugin-id}; - it has
nuxt.config.ts; - it has
plugin.config.ts; plugin.config.tscontainsenabled: true.
Active plugins are also read to determine replaced cores. If a plugin has replaces: ['program'], the program core is not included in the layer composition.
Core Replacement
The current replacement mechanism is based on the replaces field, not overrideMode or targetCore.
export default {
enabled: true,
replaces: ['program'],
routes: [
{
key: 'custom-class',
path: '/dashboard/custom-class',
icon: 'i-heroicons-sparkles',
label: 'Custom Class'
}
]
}
When this plugin is active, discovery skips the program core. This lets a plugin take over a core feature without changing source files under cores/program.
Runtime Registry
In addition to build-time discovery in shared/utils/layers.ts, the app has a runtime registry in app/plugins/plugin-registry.ts.
The registry:
- reads all
plugins/*/plugin.config.tsfiles withimport.meta.glob; - validates
enabled,replaces, androutes; - only registers enabled plugins;
- exposes
usePluginRegistry()for other composables such as the sidebar.
Sidebar in the Architecture
The sidebar is not hardcoded in the component. app/composables/useSidebarMenu.ts builds menu items from:
core.config.tsfor core menus;plugin.config.tsfor plugin menus;- optional
sidebar.tsfiles from cores/plugins for dynamic menus; - the list of cores replaced by active plugins.
This keeps routes, plugin registry, and dashboard navigation aligned with feature configuration.
Learn more about the Plugin System to see how customization is done.
Project Structure
Alkademi LMS Open Source uses a Nuxt Layers based modular monolith structure. The application is still one codebase and one build, but features are separated into cores/ and plugins/.
Plugin System
A plugin is an additional Nuxt Layer placed under plugins/. Plugins are used to add new features, replace selected cores, or enrich navigation without changing source files under cores/.
