create-nara 1.0.0 → 1.0.3
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.
- package/dist/template.js +29 -8
- package/package.json +1 -1
- package/templates/svelte/env.example +17 -0
- package/templates/svelte/env.production.example +17 -0
- package/templates/svelte/resources/js/app.ts +1 -0
- package/templates/svelte/resources/js/index.css +76 -0
- package/templates/svelte/tailwind.config.js +120 -0
- package/templates/svelte/vite.config.ts +2 -1
- /package/templates/base/{.env.example → env.example} +0 -0
package/dist/template.js
CHANGED
|
@@ -11,12 +11,6 @@ export async function setupProject(options) {
|
|
|
11
11
|
}
|
|
12
12
|
// 1. Copy base template (shared files like .gitignore, tsconfig, etc)
|
|
13
13
|
copyDir(path.join(templatesDir, 'base'), targetDir);
|
|
14
|
-
// Rename gitignore.template to .gitignore (npm doesn't include dotfiles)
|
|
15
|
-
const gitignoreTemplate = path.join(targetDir, 'gitignore.template');
|
|
16
|
-
const gitignoreDest = path.join(targetDir, '.gitignore');
|
|
17
|
-
if (fs.existsSync(gitignoreTemplate)) {
|
|
18
|
-
fs.renameSync(gitignoreTemplate, gitignoreDest);
|
|
19
|
-
}
|
|
20
14
|
// 2. Copy mode-specific template
|
|
21
15
|
const modeTemplateDir = path.join(templatesDir, mode);
|
|
22
16
|
if (fs.existsSync(modeTemplateDir)) {
|
|
@@ -30,7 +24,32 @@ export async function setupProject(options) {
|
|
|
30
24
|
copyDir(featureDir, targetDir);
|
|
31
25
|
}
|
|
32
26
|
}
|
|
33
|
-
// 4.
|
|
27
|
+
// 4. Rename dotfiles (npm doesn't include them by default)
|
|
28
|
+
// Must happen AFTER all templates are copied
|
|
29
|
+
const gitignoreTemplate = path.join(targetDir, 'gitignore.template');
|
|
30
|
+
const gitignoreDest = path.join(targetDir, '.gitignore');
|
|
31
|
+
if (fs.existsSync(gitignoreTemplate)) {
|
|
32
|
+
fs.renameSync(gitignoreTemplate, gitignoreDest);
|
|
33
|
+
}
|
|
34
|
+
// Rename env files
|
|
35
|
+
const envFiles = [
|
|
36
|
+
{ src: 'env.example', dest: '.env.example' },
|
|
37
|
+
{ src: 'env.production.example', dest: '.env.production.example' }
|
|
38
|
+
];
|
|
39
|
+
for (const envFile of envFiles) {
|
|
40
|
+
const envSrc = path.join(targetDir, envFile.src);
|
|
41
|
+
const envDest = path.join(targetDir, envFile.dest);
|
|
42
|
+
if (fs.existsSync(envSrc)) {
|
|
43
|
+
fs.renameSync(envSrc, envDest);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Copy .env.example to .env for development convenience
|
|
47
|
+
const envExample = path.join(targetDir, '.env.example');
|
|
48
|
+
const envFile = path.join(targetDir, '.env');
|
|
49
|
+
if (fs.existsSync(envExample)) {
|
|
50
|
+
fs.copyFileSync(envExample, envFile);
|
|
51
|
+
}
|
|
52
|
+
// 5. Ensure required directories exist
|
|
34
53
|
fs.mkdirSync(path.join(targetDir, 'app/controllers'), { recursive: true });
|
|
35
54
|
fs.mkdirSync(path.join(targetDir, 'app/models'), { recursive: true });
|
|
36
55
|
// Create database directory if db feature is selected
|
|
@@ -41,7 +60,7 @@ export async function setupProject(options) {
|
|
|
41
60
|
if (features.includes('uploads')) {
|
|
42
61
|
fs.mkdirSync(path.join(targetDir, 'uploads'), { recursive: true });
|
|
43
62
|
}
|
|
44
|
-
//
|
|
63
|
+
// 6. Generate package.json (dynamic content)
|
|
45
64
|
const pkg = createPackageJson(projectName, mode, features);
|
|
46
65
|
fs.writeFileSync(path.join(targetDir, 'package.json'), JSON.stringify(pkg, null, 2));
|
|
47
66
|
}
|
|
@@ -74,6 +93,8 @@ function createPackageJson(name, mode, features) {
|
|
|
74
93
|
pkg.devDependencies['vite'] = '^6.0.0';
|
|
75
94
|
pkg.devDependencies['@sveltejs/vite-plugin-svelte'] = '^5.0.0';
|
|
76
95
|
pkg.devDependencies['concurrently'] = '^9.0.0';
|
|
96
|
+
pkg.devDependencies['tailwindcss'] = '^4.0.0';
|
|
97
|
+
pkg.devDependencies['@tailwindcss/vite'] = '^4.0.0';
|
|
77
98
|
}
|
|
78
99
|
else if (mode === 'vue') {
|
|
79
100
|
pkg.dependencies['@nara-web/inertia-vue'] = '^1.0.0';
|
package/package.json
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Application
|
|
2
|
+
PORT=3000
|
|
3
|
+
NODE_ENV=development
|
|
4
|
+
APP_URL=http://localhost:3000
|
|
5
|
+
APP_KEY=change-me-to-random-string
|
|
6
|
+
|
|
7
|
+
# Database
|
|
8
|
+
DB_CONNECTION=sqlite
|
|
9
|
+
DB_DATABASE=./database/dev.sqlite3
|
|
10
|
+
|
|
11
|
+
# Authentication (if auth feature enabled)
|
|
12
|
+
JWT_SECRET=change-me-to-random-jwt-secret
|
|
13
|
+
JWT_EXPIRES_IN=7d
|
|
14
|
+
|
|
15
|
+
# Session
|
|
16
|
+
SESSION_SECRET=change-me-to-random-session-secret
|
|
17
|
+
SESSION_NAME=nara_session
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Application
|
|
2
|
+
PORT=3000
|
|
3
|
+
NODE_ENV=production
|
|
4
|
+
APP_URL=https://your-domain.com
|
|
5
|
+
APP_KEY=generate-a-strong-random-key-here
|
|
6
|
+
|
|
7
|
+
# Database
|
|
8
|
+
DB_CONNECTION=sqlite
|
|
9
|
+
DB_DATABASE=./database/prod.sqlite3
|
|
10
|
+
|
|
11
|
+
# Authentication (if auth feature enabled)
|
|
12
|
+
JWT_SECRET=generate-a-strong-jwt-secret-here
|
|
13
|
+
JWT_EXPIRES_IN=7d
|
|
14
|
+
|
|
15
|
+
# Session
|
|
16
|
+
SESSION_SECRET=generate-a-strong-session-secret-here
|
|
17
|
+
SESSION_NAME=nara_session
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
@import url('https://rsms.me/inter/inter.css');
|
|
2
|
+
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,600;0,700;1,400&display=swap');
|
|
3
|
+
@tailwind base;
|
|
4
|
+
@tailwind components;
|
|
5
|
+
@tailwind utilities;
|
|
6
|
+
|
|
7
|
+
@layer base {
|
|
8
|
+
html {
|
|
9
|
+
font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
body::-webkit-scrollbar {
|
|
13
|
+
width: 4px;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
body::-webkit-scrollbar-track {
|
|
17
|
+
background: transparent;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
body::-webkit-scrollbar-thumb {
|
|
21
|
+
background-color: theme('colors.primary.500');
|
|
22
|
+
border-radius: 3px;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@layer components {
|
|
27
|
+
.card-hover {
|
|
28
|
+
@apply transition-all duration-300 hover:shadow-soft hover:-translate-y-1;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.nav-link {
|
|
32
|
+
@apply px-4 py-2 text-gray-600 dark:text-gray-200 hover:text-gray-900 hover:bg-gray-100 rounded-lg transition-colors duration-300;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.nav-link.active {
|
|
36
|
+
@apply bg-primary-50 dark:bg-gray-800 text-primary-600;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.gradient-text {
|
|
40
|
+
@apply bg-clip-text text-transparent bg-gradient-to-r from-primary-600 to-primary-400;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.btn-primary {
|
|
44
|
+
@apply bg-primary-600 text-white px-4 py-2 rounded-lg hover:bg-primary-700
|
|
45
|
+
transition-all duration-300 active:bg-primary-800
|
|
46
|
+
disabled:opacity-50 disabled:cursor-not-allowed
|
|
47
|
+
focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.btn-secondary {
|
|
51
|
+
@apply bg-white text-gray-900 px-4 py-2 rounded-lg border border-gray-300
|
|
52
|
+
hover:bg-gray-50 transition-all duration-300 active:bg-gray-100
|
|
53
|
+
disabled:opacity-50 disabled:cursor-not-allowed
|
|
54
|
+
focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.btn-danger {
|
|
58
|
+
@apply bg-danger-600 text-white px-4 py-2 rounded-lg hover:bg-danger-700
|
|
59
|
+
transition-all duration-300 active:bg-danger-800
|
|
60
|
+
disabled:opacity-50 disabled:cursor-not-allowed
|
|
61
|
+
focus:outline-none focus:ring-2 focus:ring-danger-500 focus:ring-offset-2;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.card {
|
|
65
|
+
@apply bg-white rounded-xl shadow-soft p-6 transition-all duration-300
|
|
66
|
+
shadow-lg hover:shadow-xl hover:-translate-y-0.5;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.bg-surface {
|
|
70
|
+
@apply bg-surface-light dark:bg-surface-dark;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.bg-surface-card {
|
|
74
|
+
@apply bg-surface-card-light dark:bg-surface-card-dark;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/** @type {import('tailwindcss').Config} */
|
|
2
|
+
export default {
|
|
3
|
+
content: [
|
|
4
|
+
"./resources/**/*.{svelte,html,js,ts}",
|
|
5
|
+
],
|
|
6
|
+
darkMode: 'class',
|
|
7
|
+
theme: {
|
|
8
|
+
extend: {
|
|
9
|
+
fontFamily: {
|
|
10
|
+
sans: ['Inter var', 'Inter', 'system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'Helvetica Neue', 'Arial', 'sans-serif'],
|
|
11
|
+
serif: ['Playfair Display', 'Georgia', 'Cambria', 'Times New Roman', 'Times', 'serif'],
|
|
12
|
+
},
|
|
13
|
+
colors: {
|
|
14
|
+
primary: {
|
|
15
|
+
50: '#ecfdf5',
|
|
16
|
+
100: '#d1fae5',
|
|
17
|
+
200: '#a7f3d0',
|
|
18
|
+
300: '#6ee7b7',
|
|
19
|
+
400: '#34d399',
|
|
20
|
+
500: '#10b981',
|
|
21
|
+
600: '#059669',
|
|
22
|
+
700: '#047857',
|
|
23
|
+
800: '#065f46',
|
|
24
|
+
900: '#064e3b',
|
|
25
|
+
950: '#022c22',
|
|
26
|
+
},
|
|
27
|
+
secondary: {
|
|
28
|
+
50: '#fffbeb',
|
|
29
|
+
100: '#fef3c7',
|
|
30
|
+
200: '#fde68a',
|
|
31
|
+
300: '#fcd34d',
|
|
32
|
+
400: '#fbbf24',
|
|
33
|
+
500: '#f59e0b',
|
|
34
|
+
600: '#d97706',
|
|
35
|
+
700: '#b45309',
|
|
36
|
+
800: '#92400e',
|
|
37
|
+
900: '#78350f',
|
|
38
|
+
950: '#451a03',
|
|
39
|
+
},
|
|
40
|
+
accent: {
|
|
41
|
+
50: '#faf5ff',
|
|
42
|
+
100: '#f3e8ff',
|
|
43
|
+
200: '#e9d5ff',
|
|
44
|
+
300: '#d8b4fe',
|
|
45
|
+
400: '#c084fc',
|
|
46
|
+
500: '#a855f7',
|
|
47
|
+
600: '#9333ea',
|
|
48
|
+
700: '#7c3aed',
|
|
49
|
+
800: '#6b21a8',
|
|
50
|
+
900: '#581c87',
|
|
51
|
+
950: '#3b0764',
|
|
52
|
+
},
|
|
53
|
+
info: {
|
|
54
|
+
50: '#ecfeff',
|
|
55
|
+
100: '#cffafe',
|
|
56
|
+
200: '#a5f3fc',
|
|
57
|
+
300: '#67e8f9',
|
|
58
|
+
400: '#22d3ee',
|
|
59
|
+
500: '#06b6d4',
|
|
60
|
+
600: '#0891b2',
|
|
61
|
+
700: '#0e7490',
|
|
62
|
+
800: '#155e75',
|
|
63
|
+
900: '#164e63',
|
|
64
|
+
950: '#083344',
|
|
65
|
+
},
|
|
66
|
+
warning: {
|
|
67
|
+
50: '#fff7ed',
|
|
68
|
+
100: '#ffedd5',
|
|
69
|
+
200: '#fed7aa',
|
|
70
|
+
300: '#fdba74',
|
|
71
|
+
400: '#fb923c',
|
|
72
|
+
500: '#f97316',
|
|
73
|
+
600: '#ea580c',
|
|
74
|
+
700: '#c2410c',
|
|
75
|
+
800: '#9a3412',
|
|
76
|
+
900: '#7c2d12',
|
|
77
|
+
950: '#431407',
|
|
78
|
+
},
|
|
79
|
+
danger: {
|
|
80
|
+
50: '#fef2f2',
|
|
81
|
+
100: '#fee2e2',
|
|
82
|
+
200: '#fecaca',
|
|
83
|
+
300: '#fca5a5',
|
|
84
|
+
400: '#f87171',
|
|
85
|
+
500: '#ef4444',
|
|
86
|
+
600: '#dc2626',
|
|
87
|
+
700: '#b91c1c',
|
|
88
|
+
800: '#991b1b',
|
|
89
|
+
900: '#7f1d1d',
|
|
90
|
+
950: '#450a0a',
|
|
91
|
+
},
|
|
92
|
+
success: {
|
|
93
|
+
50: '#ecfdf5',
|
|
94
|
+
100: '#d1fae5',
|
|
95
|
+
200: '#a7f3d0',
|
|
96
|
+
300: '#6ee7b7',
|
|
97
|
+
400: '#34d399',
|
|
98
|
+
500: '#10b981',
|
|
99
|
+
600: '#059669',
|
|
100
|
+
700: '#047857',
|
|
101
|
+
800: '#065f46',
|
|
102
|
+
900: '#064e3b',
|
|
103
|
+
950: '#022c22',
|
|
104
|
+
},
|
|
105
|
+
surface: {
|
|
106
|
+
light: '#f8f8f8',
|
|
107
|
+
dark: '#0a0a0a',
|
|
108
|
+
card: {
|
|
109
|
+
light: '#f1f5f9',
|
|
110
|
+
dark: '#0f0f0f',
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
boxShadow: {
|
|
115
|
+
'soft': '0 2px 15px -3px rgba(0, 0, 0, 0.07), 0 10px 20px -2px rgba(0, 0, 0, 0.04)',
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
plugins: [],
|
|
120
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { defineConfig } from 'vite';
|
|
2
2
|
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
|
3
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
3
4
|
import path from 'path';
|
|
4
5
|
|
|
5
6
|
export default defineConfig({
|
|
6
|
-
plugins: [svelte()],
|
|
7
|
+
plugins: [svelte(), tailwindcss()],
|
|
7
8
|
resolve: {
|
|
8
9
|
alias: {
|
|
9
10
|
'@': path.resolve(__dirname, './resources/js')
|
|
File without changes
|