diff --git a/Modules/Documentation/Config/config.php b/Modules/Documentation/Config/config.php
new file mode 100644
index 00000000..262e77ad
--- /dev/null
+++ b/Modules/Documentation/Config/config.php
@@ -0,0 +1,33 @@
+ 'Documentation',
+ 'storage_disk' => env('DOCUMENTATION_DISK', 'public'),
+ 'upload_path' => env('DOCUMENTATION_UPLOAD_PATH', 'documentation'),
+ 'max_upload_kb' => (int) env('DOCUMENTATION_MAX_UPLOAD_KB', 20480),
+ 'max_markdown_import_bytes' => (int) env('DOCUMENTATION_MAX_MARKDOWN_IMPORT_BYTES', 1048576),
+ 'import_markdown_attachments' => true,
+ 'allowed_upload_mimes' => [
+ 'pdf',
+ 'doc',
+ 'docx',
+ 'xls',
+ 'xlsx',
+ 'ppt',
+ 'pptx',
+ 'txt',
+ 'csv',
+ 'md',
+ 'markdown',
+ 'png',
+ 'jpg',
+ 'jpeg',
+ 'webp',
+ 'zip',
+ ],
+ 'statuses' => [
+ 'draft' => 'Draft',
+ 'published' => 'Published',
+ 'archived' => 'Archived',
+ ],
+];
diff --git a/Modules/Documentation/Database/Migrations/2026_06_15_000000_create_documentation_tables.php b/Modules/Documentation/Database/Migrations/2026_06_15_000000_create_documentation_tables.php
new file mode 100644
index 00000000..9438b1b4
--- /dev/null
+++ b/Modules/Documentation/Database/Migrations/2026_06_15_000000_create_documentation_tables.php
@@ -0,0 +1,79 @@
+id();
+ $table->string('name', 150);
+ $table->string('slug', 180)->unique();
+ $table->string('icon', 80)->nullable();
+ $table->string('colour', 32)->default('blue');
+ $table->text('description')->nullable();
+ $table->unsignedInteger('sort_order')->default(0)->index();
+ $table->boolean('is_active')->default(true)->index();
+ $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
+ $table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();
+ $table->timestamps();
+ });
+ }
+
+ if (! Schema::hasTable('documentation_documents')) {
+ Schema::create('documentation_documents', function (Blueprint $table): void {
+ $table->id();
+ $table->foreignId('documentation_category_id')->nullable()->constrained('documentation_categories')->nullOnDelete();
+ $table->string('title', 220);
+ $table->string('slug', 240)->unique();
+ $table->string('summary', 500)->nullable();
+ $table->longText('body')->nullable();
+ $table->string('status', 40)->default('draft')->index();
+ $table->boolean('is_featured')->default(false)->index();
+ $table->string('version', 50)->default('1.0.0');
+ $table->string('reference', 100)->nullable()->index();
+ $table->string('attachment_disk')->nullable();
+ $table->string('attachment_path')->nullable();
+ $table->string('attachment_name')->nullable();
+ $table->string('attachment_mime')->nullable();
+ $table->unsignedBigInteger('attachment_size')->nullable();
+ $table->timestamp('published_at')->nullable()->index();
+ $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
+ $table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();
+ $table->timestamps();
+ $table->softDeletes();
+ });
+ }
+
+ if (! Schema::hasTable('documentation_attachments')) {
+ Schema::create('documentation_attachments', function (Blueprint $table): void {
+ $table->id();
+ $table->foreignId('documentation_document_id')->constrained('documentation_documents')->cascadeOnDelete();
+ $table->string('disk')->default('public');
+ $table->string('path');
+ $table->string('original_name');
+ $table->string('mime_type')->nullable();
+ $table->unsignedBigInteger('size')->nullable();
+ $table->foreignId('uploaded_by')->nullable()->constrained('users')->nullOnDelete();
+ $table->timestamps();
+ });
+ }
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('documentation_attachments');
+ Schema::dropIfExists('documentation_documents');
+ Schema::dropIfExists('documentation_categories');
+ }
+};
diff --git a/Modules/Documentation/Providers/DocumentationServiceProvider.php b/Modules/Documentation/Providers/DocumentationServiceProvider.php
new file mode 100644
index 00000000..e709a8d5
--- /dev/null
+++ b/Modules/Documentation/Providers/DocumentationServiceProvider.php
@@ -0,0 +1,58 @@
+app->register(RouteServiceProvider::class);
+
+ $this->mergeConfigFrom(
+ module_path('Documentation', 'Config/config.php'),
+ 'documentation'
+ );
+ }
+
+ /**
+ * Bootstrap module services.
+ */
+ public function boot(): void
+ {
+ $this->registerViews();
+ $this->loadMigrationsFrom(module_path('Documentation', 'Database/Migrations'));
+ }
+
+ /**
+ * Register module views and anonymous components.
+ */
+ private function registerViews(): void
+ {
+ $sourcePath = module_path('Documentation', 'Resources/views');
+ $overridePath = resource_path('views/modules/documentation');
+
+ $this->publishes([
+ $sourcePath => $overridePath,
+ ], ['views', 'documentation-module-views']);
+
+ $paths = [$sourcePath];
+
+ foreach (Config::get('view.paths', []) as $path) {
+ if (is_dir($path.'/modules/documentation')) {
+ array_unshift($paths, $path.'/modules/documentation');
+ }
+ }
+
+ $this->loadViewsFrom($paths, 'documentation');
+ Blade::anonymousComponentPath($sourcePath.'/components', 'documentation');
+ }
+}
diff --git a/Modules/Documentation/Resources/views/layouts/master.blade.php b/Modules/Documentation/Resources/views/layouts/master.blade.php
index 269b689a..efa01c52 100644
--- a/Modules/Documentation/Resources/views/layouts/master.blade.php
+++ b/Modules/Documentation/Resources/views/layouts/master.blade.php
@@ -1,10 +1,6 @@
-
-
-
-
-
- {{ trim($__env->yieldContent('title', 'Documentation')) }} - {{ config('app.name', 'Laravel') }}
-
-
-
-
- @yield('content')
-
-
-
-
+
+
+
diff --git a/Modules/Documentation/Routes/api.php b/Modules/Documentation/Routes/api.php
new file mode 100644
index 00000000..119a57a4
--- /dev/null
+++ b/Modules/Documentation/Routes/api.php
@@ -0,0 +1,12 @@
+prefix('documentation')
+ ->name('api.documentation.')
+ ->group(function (): void {
+ // Reserved for tenant-aware documentation API endpoints.
+ });
diff --git a/Modules/Documentation/Routes/web.php b/Modules/Documentation/Routes/web.php
new file mode 100644
index 00000000..06c60802
--- /dev/null
+++ b/Modules/Documentation/Routes/web.php
@@ -0,0 +1,27 @@
+prefix('documentation')
+ ->name('documentation.')
+ ->group(function (): void {
+ Route::get('/', [DocumentationController::class, 'index'])->name('index');
+
+ Route::get('/documents', [DocumentationController::class, 'index'])->name('documents.index');
+ Route::get('/documents/create', [DocumentationController::class, 'create'])->name('documents.create');
+ Route::post('/documents', [DocumentationController::class, 'store'])->name('documents.store');
+ Route::get('/documents/{document}', [DocumentationController::class, 'show'])->name('documents.show');
+ Route::get('/documents/{document}/edit', [DocumentationController::class, 'edit'])->name('documents.edit');
+ Route::put('/documents/{document}', [DocumentationController::class, 'update'])->name('documents.update');
+ Route::delete('/documents/{document}', [DocumentationController::class, 'destroy'])->name('documents.destroy');
+ Route::get('/documents/{document}/download', [DocumentationController::class, 'download'])->name('documents.download');
+ Route::get('/documents/{document}/attachments/{attachment}/download', [DocumentationController::class, 'downloadAttachment'])->name('documents.attachments.download');
+ Route::delete('/documents/{document}/attachments/{attachment}', [DocumentationController::class, 'destroyAttachment'])->name('documents.attachments.destroy');
+
+ Route::resource('categories', DocumentationCategoryController::class)->except(['show']);
+ });
diff --git a/Modules/Documentation/changelog.yaml b/Modules/Documentation/changelog.yaml
index 194163ab..f22bc63d 100644
--- a/Modules/Documentation/changelog.yaml
+++ b/Modules/Documentation/changelog.yaml
@@ -1,26 +1,12 @@
-- version: 1.5.0
+1.6.1:
date: 2026-06-15
changes:
- - Updated the Documentation module visual theme to match the WMS/Helpdesk slate-blue shell, zinc cards, dark-mode surfaces, blue primary actions, emerald success states, red danger states, and amber warnings.
- - Reworked the Documentation hero to use the same professional gradient/header pattern as the Helpdesk workflow screens.
+ - Added missing Documentation RouteServiceProvider so Composer package discovery and artisan commands can boot cleanly.
-version: 1.4.0
-date: 2026-06-15
-changes:
- - Added professional documentation dashboard and document CRUD.
- - Added document categories with status, ordering, colour, and icon support.
- - Added migrations, Eloquent models, form requests, routes, and feature coverage.
- - Added self-contained Abbott-style module views with accessible responsive styling.
- - Added Markdown upload processing for .md files with safe rendered HTML preview.
- - Added Markdown import coverage and styling for headings, code blocks, tables, and blockquotes.
- - Added multiple supporting attachments per document with upload, download, removal, storage cleanup, and tests.
- - Added a free built-in Markdown editor toolbar with controls for headings, bold, italic, quotes, lists, links, inline code, fenced code blocks, and tables.
- - Added WMS Support sidebar integration for Documentation, New Document, and Categories links using the existing sidebar colour scheme and active-state conventions.
- - Added a root documentation.index route while preserving documentation.documents.index for CRUD navigation.
- - Fixed module composer metadata and synced module.json version.
-
-- version: 1.4.1
- date: 2026-06-15
- changes:
- - Fixed sidebar integration so Documentation is rendered directly under the existing Support menu when Documentation routes exist.
- - Added direct replacement Blade block for the current WMS app shell.
+releases:
+ - version: 1.6.1
+ date: 2026-06-15
+ changes:
+ - Fixed missing DocumentationCategoryController binding failure for documentation category routes.
+ - Added explicit DocumentationServiceProvider, route files, config, and guarded migrations so the module registers cleanly in nwidart/laravel-modules.
+ - Preserved WMS shell styling and Documentation CRUD/Markdown/attachment functionality.
diff --git a/Modules/Documentation/module.json b/Modules/Documentation/module.json
index 62d05952..221462b1 100644
--- a/Modules/Documentation/module.json
+++ b/Modules/Documentation/module.json
@@ -1,8 +1,8 @@
{
"name": "Documentation",
"alias": "documentation",
- "version": "1.5.0",
- "description": "Professional document management and knowledge-base module with categories, CRUD, publishing, Markdown editing/import support, code blocks, attachments, and WMS Support navigation integration.",
+ "version": "1.6.1",
+ "description": "Professional document management and knowledge-base module with WMS shell styling, categories, CRUD, publishing, Markdown editing/import support, code blocks, attachments, and Support navigation integration.",
"keywords": [
"documentation",
"documents",