boilercraft 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +171 -0
  3. package/bin/boilercraft.js +110 -0
  4. package/cli/app.js +596 -0
  5. package/cli/ui.js +356 -0
  6. package/docs/STACK_ENGINE.md +93 -0
  7. package/docs/assets/cli-create.svg +52 -0
  8. package/docs/assets/cli-menu.svg +47 -0
  9. package/docs/stacks/dotnet-core.md +69 -0
  10. package/docs/stacks/laravel-vue.md +46 -0
  11. package/docs/stacks/nextjs.md +58 -0
  12. package/docs/stacks/node-express.md +58 -0
  13. package/docs/stacks/raw-php.md +130 -0
  14. package/main.js +82 -0
  15. package/package.json +86 -0
  16. package/public/index.html +721 -0
  17. package/public/logo.png +17 -0
  18. package/public/logo.svg +17 -0
  19. package/server.js +84 -0
  20. package/services/componentGenerator.js +195 -0
  21. package/services/engine/scaffoldEngine.js +517 -0
  22. package/services/engine/toolInstaller.js +232 -0
  23. package/services/engine/versionCatalog.js +115 -0
  24. package/services/generate.js +46 -0
  25. package/services/projectGenerator.js +686 -0
  26. package/services/readmeGenerator.js +221 -0
  27. package/services/themeGenerator.js +150 -0
  28. package/services/versionResolver.js +176 -0
  29. package/stacks/dotnet-core/overlays/api/Controllers/ProductsController.cs +33 -0
  30. package/stacks/dotnet-core/overlays/api/Program.cs +33 -0
  31. package/stacks/dotnet-core/overlays/api/wwwroot/index.html +38 -0
  32. package/stacks/dotnet-core/overlays/api-auth/Controllers/AuthController.cs +87 -0
  33. package/stacks/dotnet-core/overlays/common/Data/ApplicationDbContext.cs +25 -0
  34. package/stacks/dotnet-core/overlays/common/Models/Product.cs +19 -0
  35. package/stacks/dotnet-core/overlays/mvc/Controllers/ProductsController.cs +84 -0
  36. package/stacks/dotnet-core/overlays/mvc/Views/Home/Index.cshtml +23 -0
  37. package/stacks/dotnet-core/overlays/mvc/Views/Products/Create.cshtml +16 -0
  38. package/stacks/dotnet-core/overlays/mvc/Views/Products/Delete.cshtml +16 -0
  39. package/stacks/dotnet-core/overlays/mvc/Views/Products/Edit.cshtml +17 -0
  40. package/stacks/dotnet-core/overlays/mvc/Views/Products/Index.cshtml +46 -0
  41. package/stacks/dotnet-core/overlays/mvc/Views/Products/_Form.cshtml +19 -0
  42. package/stacks/dotnet-core/overlays/mvc-auth/Controllers/AccountController.cs +98 -0
  43. package/stacks/dotnet-core/overlays/mvc-auth/Models/AppUser.cs +48 -0
  44. package/stacks/dotnet-core/overlays/mvc-auth/Views/Account/Login.cshtml +35 -0
  45. package/stacks/dotnet-core/overlays/mvc-auth/Views/Account/Register.cshtml +41 -0
  46. package/stacks/dotnet-core/overlays/mvc-auth/Views/Shared/_AuthNav.cshtml +22 -0
  47. package/stacks/dotnet-core/snippets/packages-auth.xml +4 -0
  48. package/stacks/dotnet-core/snippets/packages-common.xml +5 -0
  49. package/stacks/dotnet-core/snippets/packages-ef.xml +4 -0
  50. package/stacks/dotnet-core/snippets/packages-mssql.xml +4 -0
  51. package/stacks/dotnet-core/snippets/packages-mysql.xml +4 -0
  52. package/stacks/dotnet-core/snippets/packages-swagger.xml +4 -0
  53. package/stacks/dotnet-core/stack.json +426 -0
  54. package/stacks/laravel/overlays/auth/app/Http/Controllers/Api/AuthController.php +67 -0
  55. package/stacks/laravel/overlays/common/app/Http/Controllers/BoilerCraftController.php +14 -0
  56. package/stacks/laravel/overlays/common/resources/views/boilercraft.blade.php +36 -0
  57. package/stacks/laravel/overlays/inertia-common/resources/views/app.blade.php +15 -0
  58. package/stacks/laravel/overlays/inertia-react/resources/js/Pages/Welcome.jsx +18 -0
  59. package/stacks/laravel/overlays/inertia-react/resources/js/app.jsx +13 -0
  60. package/stacks/laravel/overlays/inertia-vue/resources/js/Pages/Welcome.vue +23 -0
  61. package/stacks/laravel/overlays/inertia-vue/resources/js/app.js +13 -0
  62. package/stacks/laravel/snippets/api-routes.php +9 -0
  63. package/stacks/laravel/snippets/web-routes-inertia.php +7 -0
  64. package/stacks/laravel/snippets/web-routes.php +4 -0
  65. package/stacks/laravel/stack.json +477 -0
  66. package/stacks/nextjs/overlays/auth/src/lib/auth.js +36 -0
  67. package/stacks/nextjs/overlays/auth-app/src/app/api/auth/login/route.js +11 -0
  68. package/stacks/nextjs/overlays/auth-app/src/app/api/auth/register/route.js +14 -0
  69. package/stacks/nextjs/overlays/auth-pages/src/pages/api/auth/login.js +14 -0
  70. package/stacks/nextjs/overlays/auth-pages/src/pages/api/auth/register.js +17 -0
  71. package/stacks/nextjs/overlays/common/.env.example +3 -0
  72. package/stacks/nextjs/overlays/common/.env.local +3 -0
  73. package/stacks/nextjs/overlays/db/mongodb/src/lib/db.js +12 -0
  74. package/stacks/nextjs/overlays/db/mssql/src/lib/db.js +17 -0
  75. package/stacks/nextjs/overlays/db/mysql/src/lib/db.js +13 -0
  76. package/stacks/nextjs/overlays/router-app/src/app/api/health/route.js +10 -0
  77. package/stacks/nextjs/overlays/router-app/src/app/layout.js +16 -0
  78. package/stacks/nextjs/overlays/router-app/src/app/page.js +19 -0
  79. package/stacks/nextjs/overlays/router-pages/src/pages/_app.js +7 -0
  80. package/stacks/nextjs/overlays/router-pages/src/pages/_document.js +13 -0
  81. package/stacks/nextjs/overlays/router-pages/src/pages/api/health.js +8 -0
  82. package/stacks/nextjs/overlays/router-pages/src/pages/index.js +27 -0
  83. package/stacks/nextjs/stack.json +257 -0
  84. package/stacks/node-express/overlays/auth/src/controllers/authController.js +53 -0
  85. package/stacks/node-express/overlays/auth/src/middlewares/auth.js +36 -0
  86. package/stacks/node-express/overlays/auth/src/routes/authRoutes.js +16 -0
  87. package/stacks/node-express/overlays/common/.env.example +5 -0
  88. package/stacks/node-express/overlays/common/public/index.html +31 -0
  89. package/stacks/node-express/overlays/common/src/server.js +32 -0
  90. package/stacks/node-express/overlays/db/mongodb/src/db.js +13 -0
  91. package/stacks/node-express/overlays/db/mssql/src/db.js +22 -0
  92. package/stacks/node-express/overlays/db/mysql/src/db.js +22 -0
  93. package/stacks/node-express/stack.json +165 -0
  94. package/templates/dotnet-bootstrap-mssql/Controllers/AuthController.cs +74 -0
  95. package/templates/dotnet-bootstrap-mssql/Controllers/ProductsController.cs +33 -0
  96. package/templates/dotnet-bootstrap-mssql/Data/ApplicationDbContext.cs +24 -0
  97. package/templates/dotnet-bootstrap-mssql/Models/Product.cs +10 -0
  98. package/templates/dotnet-core/Controllers/AuthController.cs +74 -0
  99. package/templates/laravel-full/app/Http/Controllers/AuthController.php +79 -0
  100. package/templates/laravel-full/app/Http/Controllers/HomeController.php +22 -0
  101. package/templates/laravel-full/app/Models/User.php +49 -0
  102. package/templates/laravel-full/artisan +22 -0
  103. package/templates/laravel-full/bootstrap/app.php +21 -0
  104. package/templates/laravel-full/config/database.php +54 -0
  105. package/templates/laravel-full/database/migrations/2024_01_01_000001_create_users_table.php +27 -0
  106. package/templates/laravel-full/public/index.php +17 -0
  107. package/templates/laravel-full/resources/css/app.css +3 -0
  108. package/templates/laravel-full/resources/js/Pages/Home.vue +76 -0
  109. package/templates/laravel-full/resources/js/app.js +21 -0
  110. package/templates/laravel-full/resources/js/bootstrap.js +3 -0
  111. package/templates/laravel-full/resources/views/app.blade.php +15 -0
  112. package/templates/laravel-full/routes/api.php +8 -0
  113. package/templates/laravel-full/routes/console.php +7 -0
  114. package/templates/laravel-full/routes/web.php +24 -0
  115. package/templates/laravel-full/tailwind.config.js +12 -0
  116. package/templates/laravel-full/vite.config.js +20 -0
  117. package/templates/laravel-vue/app/Http/Controllers/Auth/AuthenticatedSessionController.php +43 -0
  118. package/templates/laravel-vue-mysql/app/Http/Controllers/HomeController.php +25 -0
  119. package/templates/laravel-vue-mysql/resources/js/Pages/Home.vue +70 -0
  120. package/templates/nextjs/src/app/api/auth/login/route.js +28 -0
  121. package/templates/nextjs-mongodb/src/app/api/health/route.js +17 -0
  122. package/templates/nextjs-mongodb/src/lib/mongodb.js +18 -0
  123. package/templates/nextjs-mssql/src/app/api/health/route.js +24 -0
  124. package/templates/nextjs-mssql/src/lib/mssql.js +38 -0
  125. package/templates/node-express/src/controllers/authController.js +53 -0
  126. package/templates/node-express/src/middlewares/auth.js +36 -0
  127. package/templates/node-express/src/routes/authRoutes.js +16 -0
  128. package/templates/node-mongodb/src/controllers/userController.js +30 -0
  129. package/templates/node-mongodb/src/middlewares/errorHandler.js +8 -0
  130. package/templates/node-mongodb/src/models/User.js +23 -0
  131. package/templates/node-mongodb/src/routes/api.js +9 -0
  132. package/templates/raw-php-mysql/app/Controllers/AuthController.php +73 -0
  133. package/templates/raw-php-mysql/app/Controllers/HomeController.php +65 -0
  134. package/templates/raw-php-mysql/app/Models/User.php +60 -0
  135. package/templates/raw-php-mysql/app/Views/404.php +15 -0
  136. package/templates/raw-php-mysql/app/Views/auth/login.php +66 -0
  137. package/templates/raw-php-mysql/app/Views/auth/register.php +71 -0
  138. package/templates/raw-php-mysql/app/Views/dashboard.php +50 -0
  139. package/templates/raw-php-mysql/app/Views/home.php +83 -0
  140. package/templates/raw-php-mysql/config/Auth.php +62 -0
  141. package/templates/raw-php-mysql/config/Database.php +100 -0
  142. package/templates/raw-php-mysql/config/Env.php +30 -0
  143. package/templates/raw-php-mysql/config/Middleware.php +53 -0
  144. package/templates/raw-php-mysql/config/QueryBuilder.php +109 -0
  145. package/templates/raw-php-mysql/config/Router.php +33 -0
  146. package/templates/raw-php-mysql/public/index.php +57 -0
@@ -0,0 +1,76 @@
1
+ <script setup>
2
+ import { ref } from 'vue';
3
+
4
+ defineProps({
5
+ appName: String,
6
+ description: String,
7
+ author: String,
8
+ framework: String,
9
+ frontend: String,
10
+ database: String
11
+ });
12
+
13
+ const isModalOpen = ref(false);
14
+ const isDrawerOpen = ref(false);
15
+ </script>
16
+
17
+ <template>
18
+ <div class="min-h-screen bg-slate-50 text-slate-900 p-8">
19
+ <div class="max-w-4xl mx-auto text-center">
20
+ <div class="w-16 h-16 rounded-2xl bg-sky-600 text-white text-3xl font-extrabold flex items-center justify-center mx-auto mb-4 shadow-md">
21
+ {{ appName ? appName.charAt(0) : 'L' }}
22
+ </div>
23
+
24
+ <h1 class="text-4xl font-extrabold mb-2 tracking-tight text-slate-900">{{ appName }}</h1>
25
+ <p class="text-lg text-slate-600 mb-6">{{ description }}</p>
26
+
27
+ <div class="inline-flex items-center gap-3 px-4 py-2 rounded-full bg-white border border-slate-200 text-sm font-semibold mb-8 shadow-sm">
28
+ <span class="text-red-500 font-bold">🔴 {{ framework }}</span>
29
+ <span>•</span>
30
+ <span class="text-emerald-600 font-bold">🟢 {{ frontend }}</span>
31
+ <span>•</span>
32
+ <span class="text-sky-600 font-bold">🗄️ {{ database.toUpperCase() }}</span>
33
+ </div>
34
+
35
+ <!-- Action Buttons -->
36
+ <div class="flex gap-4 justify-center mb-8">
37
+ <button @click="isModalOpen = true" class="px-5 py-2.5 rounded-lg bg-sky-600 text-white font-semibold hover:bg-sky-700 transition">
38
+ Open Demo Modal
39
+ </button>
40
+ <button @click="isDrawerOpen = true" class="px-5 py-2.5 rounded-lg border border-slate-300 bg-white font-semibold hover:bg-slate-100 transition">
41
+ Open Offcanvas Drawer
42
+ </button>
43
+ </div>
44
+
45
+ <!-- System Architecture Details -->
46
+ <div class="p-6 rounded-xl bg-white border border-slate-200 text-left shadow-sm">
47
+ <h3 class="text-lg font-bold mb-3">Included Architecture:</h3>
48
+ <ul class="space-y-2 text-sm text-slate-600">
49
+ <li class="flex items-center gap-2">✓ <strong>Artisan CLI:</strong> Full <code>php artisan</code> support included.</li>
50
+ <li class="flex items-center gap-2">✓ <strong>Database:</strong> Native Eloquent ORM & Migrations configured for {{ database.toUpperCase() }}.</li>
51
+ <li class="flex items-center gap-2">✓ <strong>Frontend:</strong> Vue 3 Composition API with Inertia.js & Vite HMR.</li>
52
+ <li class="flex items-center gap-2">✓ <strong>Maintainer:</strong> Built with BoilerCraft by {{ author }}.</li>
53
+ </ul>
54
+ </div>
55
+ </div>
56
+
57
+ <!-- Modal Dialog -->
58
+ <div v-if="isModalOpen" class="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-xs">
59
+ <div class="bg-white border border-slate-200 p-6 rounded-xl max-w-md w-full shadow-2xl">
60
+ <h3 class="text-lg font-bold mb-2">Action Modal</h3>
61
+ <p class="text-sm text-slate-600 mb-4">This Vue component is pre-wired and ready for your forms.</p>
62
+ <button @click="isModalOpen = false" class="w-full py-2 bg-sky-600 text-white rounded-lg font-semibold hover:bg-sky-700">Close</button>
63
+ </div>
64
+ </div>
65
+
66
+ <!-- Offcanvas Drawer -->
67
+ <div v-if="isDrawerOpen" class="fixed inset-0 z-50 bg-black/30" @click="isDrawerOpen = false"></div>
68
+ <div :class="['fixed top-0 left-0 bottom-0 w-80 bg-white border-r border-slate-200 p-6 z-50 transition-transform duration-300', isDrawerOpen ? 'translate-x-0' : '-translate-x-full']">
69
+ <div class="flex justify-between items-center mb-6">
70
+ <h4 class="font-bold">Navigation Drawer</h4>
71
+ <button @click="isDrawerOpen = false" class="text-xl">&times;</button>
72
+ </div>
73
+ <p class="text-sm text-slate-600">Vue 3 offcanvas drawer with clean responsive layout.</p>
74
+ </div>
75
+ </div>
76
+ </template>
@@ -0,0 +1,21 @@
1
+ import './bootstrap';
2
+ import '../css/app.css';
3
+
4
+ import { createApp, h } from 'vue';
5
+ import { createInertiaApp } from '@inertiajs/vue3';
6
+ import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
7
+
8
+ const appName = import.meta.env.VITE_APP_NAME || '{{APP_TITLE}}';
9
+
10
+ createInertiaApp({
11
+ title: (title) => `${title} - ${appName}`,
12
+ resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
13
+ setup({ el, App, props, plugin }) {
14
+ return createApp({ render: () => h(App, props) })
15
+ .use(plugin)
16
+ .mount(el);
17
+ },
18
+ progress: {
19
+ color: '#0284c7',
20
+ },
21
+ });
@@ -0,0 +1,3 @@
1
+ import axios from 'axios';
2
+ window.axios = axios;
3
+ window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title inertia>{{ config('app.name', 'Laravel') }}</title>
7
+
8
+ <!-- Scripts -->
9
+ @vite(['resources/js/app.js', 'resources/css/app.css'])
10
+ @inertiaHead
11
+ </head>
12
+ <body class="font-sans antialiased bg-slate-50 text-slate-900">
13
+ @inertia
14
+ </body>
15
+ </html>
@@ -0,0 +1,8 @@
1
+ <?php
2
+
3
+ use Illuminate\Http\Request;
4
+ use Illuminate\Support\Facades\Route;
5
+
6
+ Route::get('/user', function (Request $request) {
7
+ return $request->user();
8
+ })->middleware('auth:sanctum');
@@ -0,0 +1,7 @@
1
+ <?php
2
+
3
+ use Illuminate\Support\Facades\Artisan;
4
+
5
+ Artisan::command('inspire', function () {
6
+ $this->comment("Build remarkable apps with BoilerCraft by ARG RABBI.");
7
+ })->purpose('Display an inspiring quote');
@@ -0,0 +1,24 @@
1
+ <?php
2
+
3
+ use Illuminate\Support\Facades\Route;
4
+ use Inertia\Inertia;
5
+ use App\Http\Controllers\HomeController;
6
+ use App\Http\Controllers\AuthController;
7
+
8
+ Route::get('/', [HomeController::class, 'index']);
9
+
10
+ // Authentication Routes
11
+ Route::post('/login', [AuthController::class, 'login'])->name('login');
12
+ Route::post('/register', [AuthController::class, 'register'])->name('register');
13
+ Route::post('/logout', [AuthController::class, 'logout'])->name('logout');
14
+
15
+ Route::get('/health', function () {
16
+ return response()->json([
17
+ 'status' => 'online',
18
+ 'app' => '{{APP_TITLE}}',
19
+ 'framework' => 'Laravel',
20
+ 'php' => PHP_VERSION,
21
+ 'timestamp' => now()
22
+ ]);
23
+ });
24
+
@@ -0,0 +1,12 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ export default {
3
+ content: [
4
+ "./resources/**/*.blade.php",
5
+ "./resources/**/*.js",
6
+ "./resources/**/*.vue",
7
+ ],
8
+ theme: {
9
+ extend: {},
10
+ },
11
+ plugins: [],
12
+ }
@@ -0,0 +1,20 @@
1
+ import { defineConfig } from 'vite';
2
+ import laravel from 'laravel-vite-plugin';
3
+ import vue from '@vitejs/plugin-vue';
4
+
5
+ export default defineConfig({
6
+ plugins: [
7
+ laravel({
8
+ input: ['resources/css/app.css', 'resources/js/app.js'],
9
+ refresh: true,
10
+ }),
11
+ vue({
12
+ template: {
13
+ transformAssetUrls: {
14
+ base: null,
15
+ includeAbsolute: false,
16
+ },
17
+ },
18
+ }),
19
+ ],
20
+ });
@@ -0,0 +1,43 @@
1
+ <?php
2
+ namespace App\Http\Controllers\Auth;
3
+
4
+ use App\Http\Controllers\Controller;
5
+ use Illuminate\Http\Request;
6
+ use Illuminate\Support\Facades\Auth;
7
+ use Inertia\Inertia;
8
+ use Inertia\Response;
9
+
10
+ class AuthenticatedSessionController extends Controller
11
+ {
12
+ public function create(): Response
13
+ {
14
+ return Inertia::render('Auth/Login', [
15
+ 'status' => session('status'),
16
+ ]);
17
+ }
18
+
19
+ public function store(Request $request)
20
+ {
21
+ $credentials = $request->validate([
22
+ 'email' => ['required', 'email'],
23
+ 'password' => ['required'],
24
+ ]);
25
+
26
+ if (Auth::attempt($credentials)) {
27
+ $request->session()->regenerate();
28
+ return redirect()->intended('/dashboard');
29
+ }
30
+
31
+ return back()->withErrors([
32
+ 'email' => 'The provided credentials do not match our records.',
33
+ ]);
34
+ }
35
+
36
+ public function destroy(Request $request)
37
+ {
38
+ Auth::guard('web')->logout();
39
+ $request->session()->invalidate();
40
+ $request->session()->regenerateToken();
41
+ return redirect('/');
42
+ }
43
+ }
@@ -0,0 +1,25 @@
1
+ <?php
2
+ namespace App\Http\Controllers;
3
+
4
+ use Illuminate\Http\Request;
5
+ use Inertia\Inertia;
6
+ use Inertia\Response;
7
+
8
+ class HomeController extends Controller
9
+ {
10
+ public function index(): Response
11
+ {
12
+ return Inertia::render('Home', [
13
+ 'appName' => '{{APP_TITLE}}',
14
+ 'description' => '{{APP_DESC}}',
15
+ 'author' => '{{AUTHOR}}',
16
+ 'database' => 'MySQL',
17
+ 'features' => [
18
+ 'Laravel 11 Enterprise Framework',
19
+ 'Vue 3 Composition API & Vite',
20
+ 'Tailwind CSS & Theme Switcher',
21
+ 'MySQL Eloquent ORM'
22
+ ]
23
+ ]);
24
+ }
25
+ }
@@ -0,0 +1,70 @@
1
+ <script setup>
2
+ import { ref } from 'vue';
3
+
4
+ defineProps({
5
+ appName: String,
6
+ description: String,
7
+ author: String,
8
+ features: Array
9
+ });
10
+
11
+ const isModalOpen = ref(false);
12
+ const isDrawerOpen = ref(false);
13
+ </script>
14
+
15
+ <template>
16
+ <div class="min-h-screen bg-[var(--color-bg)] text-[var(--color-text)] p-8">
17
+ <div class="max-w-4xl mx-auto text-center">
18
+ <div class="w-16 h-16 rounded-2xl bg-[var(--color-primary)] text-white text-3xl font-extrabold flex items-center justify-center mx-auto mb-4 shadow-lg shadow-[var(--color-primary)]/20">
19
+ {{ appName ? appName.charAt(0) : 'L' }}
20
+ </div>
21
+
22
+ <h1 class="text-4xl font-extrabold mb-2 tracking-tight">{{ appName }}</h1>
23
+ <p class="text-lg text-[var(--color-text-muted)] mb-6">{{ description }}</p>
24
+
25
+ <div class="inline-flex items-center gap-2 px-4 py-1.5 rounded-full bg-[var(--color-surface)] border border-[var(--color-border)] text-sm font-semibold mb-8">
26
+ <span>Laravel 11 + Vue 3 + MySQL</span>
27
+ <span class="text-[var(--color-primary)] font-bold">● Active</span>
28
+ </div>
29
+
30
+ <!-- Action Buttons for Modal and Drawer -->
31
+ <div class="flex gap-4 justify-center mb-8">
32
+ <button @click="isModalOpen = true" class="px-5 py-2.5 rounded-xl bg-[var(--color-primary)] text-white font-semibold hover:opacity-90 transition">
33
+ Open Demo Modal
34
+ </button>
35
+ <button @click="isDrawerOpen = true" class="px-5 py-2.5 rounded-xl border border-[var(--color-border)] bg-[var(--color-surface)] font-semibold hover:bg-[var(--color-surface-hover)] transition">
36
+ Open Offcanvas Drawer
37
+ </button>
38
+ </div>
39
+
40
+ <!-- Feature Card -->
41
+ <div class="p-6 rounded-2xl bg-[var(--color-surface)] border border-[var(--color-border)] text-left shadow-xl">
42
+ <h3 class="text-lg font-bold mb-4">Included Architectures:</h3>
43
+ <ul class="space-y-2">
44
+ <li v-for="(feat, idx) in features" :key="idx" class="flex items-center gap-2 text-sm text-[var(--color-text-muted)]">
45
+ <span class="text-emerald-500 font-bold">✓</span> {{ feat }}
46
+ </li>
47
+ </ul>
48
+ </div>
49
+ </div>
50
+
51
+ <!-- Modal Component -->
52
+ <div v-if="isModalOpen" class="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm">
53
+ <div class="bg-[var(--color-surface)] border border-[var(--color-border)] p-6 rounded-2xl max-w-md w-full shadow-2xl">
54
+ <h3 class="text-lg font-bold mb-2">Enterprise Modal</h3>
55
+ <p class="text-sm text-[var(--color-text-muted)] mb-4">This Vue modal component is pre-wired to BoilerCraft design tokens.</p>
56
+ <button @click="isModalOpen = false" class="w-full py-2 bg-[var(--color-primary)] text-white rounded-lg font-semibold">Close</button>
57
+ </div>
58
+ </div>
59
+
60
+ <!-- Drawer Component -->
61
+ <div v-if="isDrawerOpen" class="fixed inset-0 z-50 bg-black/40" @click="isDrawerOpen = false"></div>
62
+ <div :class="['fixed top-0 left-0 bottom-0 w-80 bg-[var(--color-surface)] border-r border-[var(--color-border)] p-6 z-50 transition-transform duration-300', isDrawerOpen ? 'translate-x-0' : '-translate-x-full']">
63
+ <div class="flex justify-between items-center mb-6">
64
+ <h4 class="font-bold">Navigation Drawer</h4>
65
+ <button @click="isDrawerOpen = false" class="text-xl">&times;</button>
66
+ </div>
67
+ <p class="text-sm text-[var(--color-text-muted)]">Vue 3 composition offcanvas drawer ready for your menu links.</p>
68
+ </div>
69
+ </div>
70
+ </template>
@@ -0,0 +1,28 @@
1
+ import { NextResponse } from 'next/server';
2
+
3
+ export async function POST(request) {
4
+ try {
5
+ const body = await request.json();
6
+ const { email, password } = body;
7
+
8
+ if (email === 'admin@example.com' && password === 'admin123') {
9
+ return NextResponse.json({
10
+ success: true,
11
+ user: { id: 1, name: 'Admin User', email, role: 'admin' },
12
+ token: 'mock_jwt_token_admin'
13
+ });
14
+ }
15
+
16
+ if (email && password) {
17
+ return NextResponse.json({
18
+ success: true,
19
+ user: { id: 2, name: 'Regular User', email, role: 'user' },
20
+ token: 'mock_jwt_token_user'
21
+ });
22
+ }
23
+
24
+ return NextResponse.json({ success: false, error: 'Invalid credentials' }, { status: 401 });
25
+ } catch (error) {
26
+ return NextResponse.json({ success: false, error: error.message }, { status: 500 });
27
+ }
28
+ }
@@ -0,0 +1,17 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { connectToDatabase } from '@/lib/mongodb';
3
+
4
+ export async function GET() {
5
+ try {
6
+ await connectToDatabase();
7
+ return NextResponse.json({
8
+ status: 'online',
9
+ stack: 'Next.js App Router',
10
+ database: 'MongoDB (Mongoose)',
11
+ appName: '{{APP_TITLE}}',
12
+ author: '{{AUTHOR}}'
13
+ });
14
+ } catch (error) {
15
+ return NextResponse.json({ success: false, error: error.message }, { status: 500 });
16
+ }
17
+ }
@@ -0,0 +1,18 @@
1
+ const mongoose = require('mongoose');
2
+
3
+ let isConnected = false;
4
+
5
+ export async function connectToDatabase() {
6
+ if (isConnected) {
7
+ return;
8
+ }
9
+ const uri = process.env.MONGODB_URI || 'mongodb://127.0.0.1:27017/{{PROJECT_NAME}}';
10
+ try {
11
+ const db = await mongoose.connect(uri);
12
+ isConnected = db.connections[0].readyState;
13
+ console.log('⚡ Connected to MongoDB (Next.js App Router)');
14
+ } catch (err) {
15
+ console.error('MongoDB connection error:', err);
16
+ throw err;
17
+ }
18
+ }
@@ -0,0 +1,24 @@
1
+ import { NextResponse } from 'next/server';
2
+ import { getMssqlPool } from '@/lib/mssql';
3
+
4
+ export async function GET() {
5
+ try {
6
+ const pool = await getMssqlPool();
7
+ const result = await pool.request().query('SELECT @@VERSION as version, GETDATE() as currentTime');
8
+
9
+ return NextResponse.json({
10
+ status: 'online',
11
+ stack: 'Next.js App Router',
12
+ database: 'Microsoft SQL Server (MSSQL)',
13
+ appName: '{{APP_TITLE}}',
14
+ author: '{{AUTHOR}}',
15
+ dbInfo: result.recordset[0]
16
+ });
17
+ } catch (error) {
18
+ return NextResponse.json({
19
+ status: 'database_unreachable_or_offline',
20
+ stack: 'Next.js App Router + MSSQL',
21
+ message: error.message
22
+ }, { status: 500 });
23
+ }
24
+ }
@@ -0,0 +1,38 @@
1
+ import sql from 'mssql';
2
+
3
+ const sqlConfig = {
4
+ user: process.env.DB_USER || 'sa',
5
+ password: process.env.DB_PASSWORD || 'YourStrong@Password',
6
+ database: process.env.DB_NAME || '{{PROJECT_NAME}}',
7
+ server: process.env.DB_HOST || 'localhost',
8
+ port: parseInt(process.env.DB_PORT || '1433'),
9
+ pool: {
10
+ max: 10,
11
+ min: 0,
12
+ idleTimeoutMillis: 30000
13
+ },
14
+ options: {
15
+ encrypt: false, // Set to true for Azure
16
+ trustServerCertificate: true
17
+ }
18
+ };
19
+
20
+ let poolPromise = null;
21
+
22
+ export async function getMssqlPool() {
23
+ if (!poolPromise) {
24
+ poolPromise = sql.connect(sqlConfig)
25
+ .then(pool => {
26
+ console.log('⚡ Connected to MSSQL Server (Next.js App Router)');
27
+ return pool;
28
+ })
29
+ .catch(err => {
30
+ poolPromise = null;
31
+ console.error('Database connection failed:', err);
32
+ throw err;
33
+ });
34
+ }
35
+ return poolPromise;
36
+ }
37
+
38
+ export { sql };
@@ -0,0 +1,53 @@
1
+ const bcrypt = require('bcryptjs');
2
+ const jwt = require('jsonwebtoken');
3
+ const { JWT_SECRET } = require('../middlewares/auth');
4
+
5
+ // In-memory or dynamic model fallback
6
+ let usersTable = [];
7
+
8
+ exports.register = async (req, res) => {
9
+ const { name, email, password, role = 'user' } = req.body;
10
+ if (!name || !email || !password) {
11
+ return res.status(400).json({ success: false, error: 'Name, email, and password required.' });
12
+ }
13
+
14
+ const existing = usersTable.find(u => u.email === email);
15
+ if (existing) {
16
+ return res.status(409).json({ success: false, error: 'User already exists.' });
17
+ }
18
+
19
+ const hashedPassword = await bcrypt.hash(password, 10);
20
+ const newUser = { id: usersTable.length + 1, name, email, password: hashedPassword, role };
21
+ usersTable.push(newUser);
22
+
23
+ const token = jwt.sign({ id: newUser.id, name: newUser.name, email: newUser.email, role: newUser.role }, JWT_SECRET, { expiresIn: '7d' });
24
+
25
+ res.status(201).json({
26
+ success: true,
27
+ message: 'User registered successfully',
28
+ token,
29
+ user: { id: newUser.id, name: newUser.name, email: newUser.email, role: newUser.role }
30
+ });
31
+ };
32
+
33
+ exports.login = async (req, res) => {
34
+ const { email, password } = req.body;
35
+ const user = usersTable.find(u => u.email === email);
36
+
37
+ if (!user || !(await bcrypt.compare(password, user.password))) {
38
+ return res.status(401).json({ success: false, error: 'Invalid credentials.' });
39
+ }
40
+
41
+ const token = jwt.sign({ id: user.id, name: user.name, email: user.email, role: user.role }, JWT_SECRET, { expiresIn: '7d' });
42
+
43
+ res.json({
44
+ success: true,
45
+ message: 'Login successful',
46
+ token,
47
+ user: { id: user.id, name: user.name, email: user.email, role: user.role }
48
+ });
49
+ };
50
+
51
+ exports.getProfile = (req, res) => {
52
+ res.json({ success: true, user: req.user });
53
+ };
@@ -0,0 +1,36 @@
1
+ const jwt = require('jsonwebtoken');
2
+
3
+ const JWT_SECRET = process.env.JWT_SECRET || 'super_secret_jwt_key_boiler_craft_2026';
4
+
5
+ function auth(req, res, next) {
6
+ const authHeader = req.headers['authorization'];
7
+ const token = authHeader && authHeader.split(' ')[1];
8
+
9
+ if (!token) {
10
+ return res.status(401).json({ success: false, error: 'Access denied. No token provided.' });
11
+ }
12
+
13
+ try {
14
+ const decoded = jwt.verify(token, JWT_SECRET);
15
+ req.user = decoded;
16
+ next();
17
+ } catch (err) {
18
+ return res.status(403).json({ success: false, error: 'Invalid or expired token.' });
19
+ }
20
+ }
21
+
22
+ function role(allowedRoles = []) {
23
+ if (typeof allowedRoles === 'string') allowedRoles = [allowedRoles];
24
+
25
+ return (req, res, next) => {
26
+ if (!req.user) {
27
+ return res.status(401).json({ success: false, error: 'Unauthenticated.' });
28
+ }
29
+ if (!allowedRoles.includes(req.user.role)) {
30
+ return res.status(403).json({ success: false, error: 'Forbidden. Insufficient permissions.' });
31
+ }
32
+ next();
33
+ };
34
+ }
35
+
36
+ module.exports = { auth, role, JWT_SECRET };
@@ -0,0 +1,16 @@
1
+ const express = require('express');
2
+ const router = express.Router();
3
+ const { register, login, getProfile } = require('../controllers/authController');
4
+ const { auth, role } = require('../middlewares/auth');
5
+
6
+ // Public
7
+ router.post('/register', register);
8
+ router.post('/login', login);
9
+
10
+ // Protected Routes
11
+ router.get('/profile', auth, getProfile);
12
+ router.get('/admin', auth, role('admin'), (req, res) => {
13
+ res.json({ success: true, message: 'Welcome to Admin Authorized Area!', user: req.user });
14
+ });
15
+
16
+ module.exports = router;
@@ -0,0 +1,30 @@
1
+ const User = require('../models/User');
2
+
3
+ exports.getHealth = async (req, res) => {
4
+ res.json({
5
+ status: 'online',
6
+ app: '{{APP_TITLE}}',
7
+ description: '{{APP_DESC}}',
8
+ author: '{{AUTHOR}}',
9
+ database: 'MongoDB connected via Mongoose',
10
+ timestamp: new Date().toISOString()
11
+ });
12
+ };
13
+
14
+ exports.getUsers = async (req, res, next) => {
15
+ try {
16
+ const users = await User.find().sort({ createdAt: -1 }).limit(20);
17
+ res.json({ success: true, count: users.length, data: users });
18
+ } catch (err) {
19
+ next(err);
20
+ }
21
+ };
22
+
23
+ exports.createUser = async (req, res, next) => {
24
+ try {
25
+ const user = await User.create(req.body);
26
+ res.status(201).json({ success: true, data: user });
27
+ } catch (err) {
28
+ next(err);
29
+ }
30
+ };
@@ -0,0 +1,8 @@
1
+ module.exports = (err, req, res, next) => {
2
+ console.error('[Error Logger]:', err);
3
+ const status = err.statusCode || 500;
4
+ res.status(status).json({
5
+ success: false,
6
+ error: err.message || 'Internal Server Error'
7
+ });
8
+ };
@@ -0,0 +1,23 @@
1
+ const mongoose = require('mongoose');
2
+
3
+ const UserSchema = new mongoose.Schema({
4
+ name: {
5
+ type: String,
6
+ required: [true, 'Name is required'],
7
+ trim: true
8
+ },
9
+ email: {
10
+ type: String,
11
+ required: [true, 'Email is required'],
12
+ unique: true,
13
+ lowercase: true,
14
+ trim: true
15
+ },
16
+ role: {
17
+ type: String,
18
+ enum: ['user', 'admin'],
19
+ default: 'user'
20
+ }
21
+ }, { timestamps: true });
22
+
23
+ module.exports = mongoose.model('User', UserSchema);
@@ -0,0 +1,9 @@
1
+ const express = require('express');
2
+ const router = express.Router();
3
+ const { getHealth, getUsers, createUser } = require('../controllers/userController');
4
+
5
+ router.get('/health', getHealth);
6
+ router.get('/users', getUsers);
7
+ router.post('/users', createUser);
8
+
9
+ module.exports = router;