@digitalygo/create-diggocms-app 0.1.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.
- package/README.md +152 -0
- package/bin/cli.js +392 -0
- package/package.json +44 -0
- package/templates/full/.env.local.example +13 -0
- package/templates/full/README.md +101 -0
- package/templates/full/app/[...slug]/page.tsx +115 -0
- package/templates/full/app/globals.css +187 -0
- package/templates/full/app/layout.tsx +25 -0
- package/templates/full/app/page.tsx +6 -0
- package/templates/full/components/DiggoProvider.tsx +15 -0
- package/templates/full/components/ExtendedCard.tsx +15 -0
- package/templates/full/components/ExtendedImage.tsx +16 -0
- package/templates/full/components/ExtendedMenuContainer.tsx +10 -0
- package/templates/full/components/ExtendedMenuItem.tsx +22 -0
- package/templates/full/components/ExtendedRichtext.tsx +15 -0
- package/templates/full/components/ExtendedSubtitle.tsx +10 -0
- package/templates/full/components/ExtendedTitle.tsx +10 -0
- package/templates/full/components/server-components.ts +8 -0
- package/templates/full/lib/data-fetching.ts +205 -0
- package/templates/full/lib/diggo-config.ts +48 -0
- package/templates/full/next-env.d.ts +2 -0
- package/templates/full/next.config.ts +7 -0
- package/templates/full/package.json +25 -0
- package/templates/full/tsconfig.json +23 -0
- package/templates/minimal/.env.local.example +13 -0
- package/templates/minimal/README.md +67 -0
- package/templates/minimal/app/[...slug]/page.tsx +56 -0
- package/templates/minimal/app/globals.css +11 -0
- package/templates/minimal/app/layout.tsx +22 -0
- package/templates/minimal/app/page.tsx +6 -0
- package/templates/minimal/components/DiggoProvider.tsx +15 -0
- package/templates/minimal/lib/data-fetching.ts +59 -0
- package/templates/minimal/lib/diggo-config.ts +35 -0
- package/templates/minimal/next-env.d.ts +2 -0
- package/templates/minimal/next.config.ts +7 -0
- package/templates/minimal/package.json +25 -0
- package/templates/minimal/tsconfig.json +23 -0
- package/templates/with-mock/.env.local.example +13 -0
- package/templates/with-mock/README.md +128 -0
- package/templates/with-mock/app/[...slug]/page.tsx +115 -0
- package/templates/with-mock/app/globals.css +187 -0
- package/templates/with-mock/app/layout.tsx +25 -0
- package/templates/with-mock/app/page.tsx +6 -0
- package/templates/with-mock/components/DiggoProvider.tsx +15 -0
- package/templates/with-mock/components/ExtendedCard.tsx +15 -0
- package/templates/with-mock/components/ExtendedImage.tsx +16 -0
- package/templates/with-mock/components/ExtendedMenuContainer.tsx +10 -0
- package/templates/with-mock/components/ExtendedMenuItem.tsx +22 -0
- package/templates/with-mock/components/ExtendedRichtext.tsx +15 -0
- package/templates/with-mock/components/ExtendedSubtitle.tsx +10 -0
- package/templates/with-mock/components/ExtendedTitle.tsx +10 -0
- package/templates/with-mock/components/server-components.ts +8 -0
- package/templates/with-mock/fixtures/collection.json +28 -0
- package/templates/with-mock/fixtures/menu.json +29 -0
- package/templates/with-mock/fixtures/pages/chi-siamo.json +37 -0
- package/templates/with-mock/fixtures/pages/contatti.json +33 -0
- package/templates/with-mock/fixtures/pages/home.json +62 -0
- package/templates/with-mock/fixtures/pages/index.json +17 -0
- package/templates/with-mock/lib/data-fetching.ts +205 -0
- package/templates/with-mock/lib/diggo-config.ts +48 -0
- package/templates/with-mock/next-env.d.ts +2 -0
- package/templates/with-mock/next.config.ts +7 -0
- package/templates/with-mock/package.json +27 -0
- package/templates/with-mock/scripts/mock-server.ts +231 -0
- package/templates/with-mock/tsconfig.json +23 -0
package/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Create DiggoCMS App
|
|
2
|
+
|
|
3
|
+
A CLI tool to scaffold new DiggoCMS projects with Next.js and the DiggoCMS SDK.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
### With npx (no installation required)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx create-diggocms-app@latest
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### With bun
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
bun x create-diggocms-app
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Global installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install -g create-diggocms-app
|
|
23
|
+
create-diggocms-app
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Interactive Setup
|
|
27
|
+
|
|
28
|
+
The CLI will guide you through the setup process:
|
|
29
|
+
|
|
30
|
+
1. **Project name** - Name of your new project directory
|
|
31
|
+
2. **Template** - Choose from:
|
|
32
|
+
- `full` - Complete setup with all extended components (recommended)
|
|
33
|
+
- `with-mock` - Full setup + mock API server + sample fixtures
|
|
34
|
+
- `minimal` - Basic setup, add components yourself
|
|
35
|
+
3. **Package manager** - Choose your preferred package manager (bun, npm, yarn, pnpm)
|
|
36
|
+
|
|
37
|
+
## Templates
|
|
38
|
+
|
|
39
|
+
### Minimal
|
|
40
|
+
|
|
41
|
+
A bare-bones setup with just the SDK installed. You'll need to:
|
|
42
|
+
- Create your own extended components
|
|
43
|
+
- Configure the SDK manually
|
|
44
|
+
- Set up data fetching
|
|
45
|
+
|
|
46
|
+
Best for: Experienced developers who want full control.
|
|
47
|
+
|
|
48
|
+
### Full
|
|
49
|
+
|
|
50
|
+
Complete setup including:
|
|
51
|
+
- All extended components (Title, Subtitle, Image, Richtext, Card)
|
|
52
|
+
- Navigation components with dropdown support
|
|
53
|
+
- Dynamic routing with `[...slug]`
|
|
54
|
+
- Data fetching helpers
|
|
55
|
+
- Error handling and mock indicators
|
|
56
|
+
- Ready-to-use styles
|
|
57
|
+
|
|
58
|
+
Best for: Most users starting a new project.
|
|
59
|
+
|
|
60
|
+
### With Mock
|
|
61
|
+
|
|
62
|
+
Everything from the full template, plus:
|
|
63
|
+
- Standalone mock API server (`scripts/mock-server.ts`)
|
|
64
|
+
- Sample fixtures (pages, menu, collection)
|
|
65
|
+
- Scripts: `mock:api` and `dev:mock`
|
|
66
|
+
- Pre-configured `.env.local` for mock mode
|
|
67
|
+
|
|
68
|
+
Best for: Developing without a real CMS API, testing, or learning.
|
|
69
|
+
|
|
70
|
+
## Project Structure
|
|
71
|
+
|
|
72
|
+
After scaffolding, your project will have this structure:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
my-app/
|
|
76
|
+
├── app/ # Next.js app router
|
|
77
|
+
│ ├── [...slug]/ # Dynamic routes
|
|
78
|
+
│ ├── layout.tsx
|
|
79
|
+
│ ├── page.tsx
|
|
80
|
+
│ └── globals.css
|
|
81
|
+
├── components/ # React components
|
|
82
|
+
│ ├── DiggoProvider.tsx
|
|
83
|
+
│ ├── server-components.ts
|
|
84
|
+
│ └── Extended*.tsx
|
|
85
|
+
├── lib/ # Utilities
|
|
86
|
+
│ ├── diggo-config.ts
|
|
87
|
+
│ └── data-fetching.ts
|
|
88
|
+
├── fixtures/ # Mock data (with-mock only)
|
|
89
|
+
├── scripts/ # Mock server (with-mock only)
|
|
90
|
+
├── .env.local.example
|
|
91
|
+
├── next.config.ts
|
|
92
|
+
├── package.json
|
|
93
|
+
├── tsconfig.json
|
|
94
|
+
└── README.md
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Environment Variables
|
|
98
|
+
|
|
99
|
+
Copy `.env.local.example` to `.env.local` and configure:
|
|
100
|
+
|
|
101
|
+
```env
|
|
102
|
+
# Use real CMS API
|
|
103
|
+
BASE_URL=https://your-cms-api.com
|
|
104
|
+
MOCK=0
|
|
105
|
+
|
|
106
|
+
# Or use mock mode
|
|
107
|
+
MOCK=1
|
|
108
|
+
MOCK_API_URL=http://localhost:3001
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Requirements
|
|
112
|
+
|
|
113
|
+
- Node.js >= 18.0.0 or Bun >= 1.1.0
|
|
114
|
+
- A DiggoCMS API endpoint (or use mock mode)
|
|
115
|
+
|
|
116
|
+
## Options
|
|
117
|
+
|
|
118
|
+
You can also pass the project name as an argument:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
npx create-diggocms-app@latest my-project
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
This skips the project name prompt and uses `my-project` directly.
|
|
125
|
+
|
|
126
|
+
## Troubleshooting
|
|
127
|
+
|
|
128
|
+
### Permission denied
|
|
129
|
+
|
|
130
|
+
If you get a permission error, try:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
npx create-diggocms-app@latest --use-npm
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Or use a Node version manager like nvm/fnm.
|
|
137
|
+
|
|
138
|
+
### Port already in use
|
|
139
|
+
|
|
140
|
+
If the mock API server fails to start due to port conflicts, set a different port:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
PORT=3002 bun run mock:api
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Contributing
|
|
147
|
+
|
|
148
|
+
This CLI is part of the DiggoCMS SDK monorepo. See the main repository for contribution guidelines.
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
MIT © DigitalyGo Team
|
package/bin/cli.js
ADDED
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Create DiggoCMS App - CLI tool to scaffold new DiggoCMS projects
|
|
4
|
+
* Inspired by create-next-app and create-vite
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createRequire } from 'module';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import { dirname, join } from 'path';
|
|
10
|
+
import { cp, mkdir, readFile, writeFile, access, stat } from 'fs/promises';
|
|
11
|
+
import { execSync } from 'child_process';
|
|
12
|
+
import process from 'process';
|
|
13
|
+
import prompts from 'prompts';
|
|
14
|
+
import {
|
|
15
|
+
cyan,
|
|
16
|
+
green,
|
|
17
|
+
red,
|
|
18
|
+
yellow,
|
|
19
|
+
blue,
|
|
20
|
+
magenta,
|
|
21
|
+
lightGray,
|
|
22
|
+
dim,
|
|
23
|
+
} from 'kolorist';
|
|
24
|
+
|
|
25
|
+
const require = createRequire(import.meta.url);
|
|
26
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
27
|
+
const __dirname = dirname(__filename);
|
|
28
|
+
|
|
29
|
+
const TEMPLATES = ['minimal', 'full', 'with-mock'];
|
|
30
|
+
const PACKAGE_MANAGERS = ['bun', 'npm', 'yarn', 'pnpm'];
|
|
31
|
+
|
|
32
|
+
const DEFAULT_PROJECT_NAME = 'my-diggocms-app';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Validates project name (no spaces, special chars, etc.)
|
|
36
|
+
* @param {string} name
|
|
37
|
+
* @returns {string | true} Error message or true if valid
|
|
38
|
+
*/
|
|
39
|
+
function validateProjectName(name) {
|
|
40
|
+
if (!name || name.trim().length === 0) {
|
|
41
|
+
return 'Project name is required';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (name.trim().includes(' ')) {
|
|
45
|
+
return 'Project name cannot contain spaces';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (!/^[a-z0-9-_]+$/i.test(name)) {
|
|
49
|
+
return 'Project name can only contain letters, numbers, hyphens, and underscores';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Checks if directory exists and is not empty
|
|
57
|
+
* @param {string} dir
|
|
58
|
+
* @returns {Promise<boolean>}
|
|
59
|
+
*/
|
|
60
|
+
async function isDirectoryEmpty(dir) {
|
|
61
|
+
try {
|
|
62
|
+
const stats = await stat(dir);
|
|
63
|
+
if (!stats.isDirectory()) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
const files = await readdir(dir);
|
|
67
|
+
return files.length === 0;
|
|
68
|
+
} catch {
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Checks if a command exists
|
|
75
|
+
* @param {string} cmd
|
|
76
|
+
* @returns {boolean}
|
|
77
|
+
*/
|
|
78
|
+
function commandExists(cmd) {
|
|
79
|
+
try {
|
|
80
|
+
execSync(`${cmd} --version`, { stdio: 'ignore' });
|
|
81
|
+
return true;
|
|
82
|
+
} catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Gets the version of Node.js or Bun
|
|
89
|
+
* @param {string} runtime
|
|
90
|
+
* @returns {string | null}
|
|
91
|
+
*/
|
|
92
|
+
function getRuntimeVersion(runtime) {
|
|
93
|
+
try {
|
|
94
|
+
const version = execSync(`${runtime} --version`, { encoding: 'utf-8' }).trim();
|
|
95
|
+
return version;
|
|
96
|
+
} catch {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Checks version requirements
|
|
103
|
+
* @returns {{ node: string | null, bun: string | null }}
|
|
104
|
+
*/
|
|
105
|
+
function checkRuntimeVersions() {
|
|
106
|
+
return {
|
|
107
|
+
node: getRuntimeVersion('node'),
|
|
108
|
+
bun: getRuntimeVersion('bun'),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Copies template files to target directory
|
|
114
|
+
* @param {string} template
|
|
115
|
+
* @param {string} targetDir
|
|
116
|
+
*/
|
|
117
|
+
async function copyTemplate(template, targetDir) {
|
|
118
|
+
const templateDir = join(__dirname, '..', 'templates', template);
|
|
119
|
+
|
|
120
|
+
async function copyRecursive(src, dest) {
|
|
121
|
+
const entries = await readdir(src, { withFileTypes: true });
|
|
122
|
+
|
|
123
|
+
for (const entry of entries) {
|
|
124
|
+
const srcPath = join(src, entry.name);
|
|
125
|
+
const destPath = join(dest, entry.name);
|
|
126
|
+
|
|
127
|
+
if (entry.isDirectory()) {
|
|
128
|
+
await mkdir(destPath, { recursive: true });
|
|
129
|
+
await copyRecursive(srcPath, destPath);
|
|
130
|
+
} else {
|
|
131
|
+
await cp(srcPath, destPath);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
await copyRecursive(templateDir, targetDir);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Updates package.json with project name
|
|
141
|
+
* @param {string} targetDir
|
|
142
|
+
* @param {string} projectName
|
|
143
|
+
*/
|
|
144
|
+
async function updatePackageJson(targetDir, projectName) {
|
|
145
|
+
const packageJsonPath = join(targetDir, 'package.json');
|
|
146
|
+
const content = await readFile(packageJsonPath, 'utf-8');
|
|
147
|
+
const packageJson = JSON.parse(content);
|
|
148
|
+
|
|
149
|
+
packageJson.name = projectName;
|
|
150
|
+
|
|
151
|
+
await writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Installs dependencies using specified package manager
|
|
156
|
+
* @param {string} packageManager
|
|
157
|
+
* @param {string} cwd
|
|
158
|
+
*/
|
|
159
|
+
function installDependencies(packageManager, cwd) {
|
|
160
|
+
const installCmd = {
|
|
161
|
+
bun: 'bun install',
|
|
162
|
+
npm: 'npm install',
|
|
163
|
+
yarn: 'yarn',
|
|
164
|
+
pnpm: 'pnpm install',
|
|
165
|
+
}[packageManager];
|
|
166
|
+
|
|
167
|
+
console.log(dim(`\nInstalling dependencies with ${packageManager}...`));
|
|
168
|
+
execSync(installCmd, { cwd, stdio: 'inherit' });
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Initializes git repository
|
|
173
|
+
* @param {string} cwd
|
|
174
|
+
*/
|
|
175
|
+
function initGit(cwd) {
|
|
176
|
+
try {
|
|
177
|
+
execSync('git init', { cwd, stdio: 'ignore' });
|
|
178
|
+
execSync('git add .', { cwd, stdio: 'ignore' });
|
|
179
|
+
execSync('git commit -m "Initial commit from create-diggocms-app"', {
|
|
180
|
+
cwd,
|
|
181
|
+
stdio: 'ignore',
|
|
182
|
+
});
|
|
183
|
+
return true;
|
|
184
|
+
} catch {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Shows the final success message with next steps
|
|
191
|
+
* @param {string} projectName
|
|
192
|
+
* @param {string} targetDir
|
|
193
|
+
* @param {string} packageManager
|
|
194
|
+
* @param {string} template
|
|
195
|
+
*/
|
|
196
|
+
function showSuccessMessage(projectName, targetDir, packageManager, template) {
|
|
197
|
+
const runCmd = {
|
|
198
|
+
bun: 'bun run',
|
|
199
|
+
npm: 'npm run',
|
|
200
|
+
yarn: 'yarn',
|
|
201
|
+
pnpm: 'pnpm',
|
|
202
|
+
}[packageManager];
|
|
203
|
+
|
|
204
|
+
console.log(`\n${green('✔')} Successfully created ${cyan(projectName)}`);
|
|
205
|
+
console.log(`\n${lightGray('Next steps:')}`);
|
|
206
|
+
console.log(` ${cyan('cd')} ${projectName}`);
|
|
207
|
+
|
|
208
|
+
if (template === 'with-mock') {
|
|
209
|
+
console.log(` ${cyan(`${runCmd} mock:api`)} ${dim('# Start the mock API server')}`);
|
|
210
|
+
console.log(` ${cyan(`${runCmd} dev`)} ${dim('# Start the Next.js dev server (in another terminal)')}`);
|
|
211
|
+
console.log(`\n${yellow('Or run both together:')}`);
|
|
212
|
+
console.log(` ${cyan(`${runCmd} dev:mock`)} ${dim('# Start mock API and dev server concurrently')}`);
|
|
213
|
+
} else {
|
|
214
|
+
console.log(` ${cyan(`${runCmd} dev`)} ${dim('# Start the development server')}`);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
console.log(`\n${lightGray('Before you start:')}`);
|
|
218
|
+
console.log(` ${dim('• Copy')} .env.local.example ${dim('to')} .env.local`);
|
|
219
|
+
console.log(` ${dim('• Configure your')} BASE_URL ${dim('or set')} MOCK=1`);
|
|
220
|
+
|
|
221
|
+
if (template === 'minimal') {
|
|
222
|
+
console.log(`\n${yellow('Note:')} This is a minimal template. You'll need to:`);
|
|
223
|
+
console.log(` ${dim('• Create your extended components in')} components/`);
|
|
224
|
+
console.log(` ${dim('• Configure the SDK in')} lib/diggo-config.ts`);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
console.log(`\n${blue('Happy coding with DiggoCMS!')} ${magenta('🚀')}\n`);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Main CLI function
|
|
232
|
+
*/
|
|
233
|
+
async function main() {
|
|
234
|
+
console.log(`\n${cyan('◆')} ${bold('DiggoCMS')} ${lightGray('– Create a new CMS-powered app')}\n`);
|
|
235
|
+
|
|
236
|
+
// Check runtime versions
|
|
237
|
+
const versions = checkRuntimeVersions();
|
|
238
|
+
|
|
239
|
+
if (!versions.node && !versions.bun) {
|
|
240
|
+
console.error(red('Error: Neither Node.js nor Bun found. Please install one of them.'));
|
|
241
|
+
process.exit(1);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Get project name from command line or prompt
|
|
245
|
+
let projectName = process.argv[2];
|
|
246
|
+
|
|
247
|
+
if (!projectName) {
|
|
248
|
+
const response = await prompts({
|
|
249
|
+
type: 'text',
|
|
250
|
+
name: 'projectName',
|
|
251
|
+
message: 'Project name:',
|
|
252
|
+
initial: DEFAULT_PROJECT_NAME,
|
|
253
|
+
validate: validateProjectName,
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
if (!response.projectName) {
|
|
257
|
+
console.log(red('\nAborted.'));
|
|
258
|
+
process.exit(1);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
projectName = response.projectName;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const validation = validateProjectName(projectName);
|
|
265
|
+
if (validation !== true) {
|
|
266
|
+
console.error(red(`Error: ${validation}`));
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Check if directory exists
|
|
271
|
+
const targetDir = join(process.cwd(), projectName);
|
|
272
|
+
|
|
273
|
+
try {
|
|
274
|
+
await access(targetDir);
|
|
275
|
+
const dirStats = await stat(targetDir);
|
|
276
|
+
|
|
277
|
+
if (dirStats.isDirectory()) {
|
|
278
|
+
const files = await readdir(targetDir);
|
|
279
|
+
if (files.length > 0) {
|
|
280
|
+
const { overwrite } = await prompts({
|
|
281
|
+
type: 'confirm',
|
|
282
|
+
name: 'overwrite',
|
|
283
|
+
message: `Directory "${projectName}" is not empty. Remove existing files and continue?`,
|
|
284
|
+
initial: false,
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
if (!overwrite) {
|
|
288
|
+
console.log(red('\nAborted.'));
|
|
289
|
+
process.exit(1);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Remove directory contents
|
|
293
|
+
for (const file of files) {
|
|
294
|
+
const filePath = join(targetDir, file);
|
|
295
|
+
await rm(filePath, { recursive: true, force: true });
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
} catch {
|
|
300
|
+
// Directory doesn't exist, create it
|
|
301
|
+
await mkdir(targetDir, { recursive: true });
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Choose template
|
|
305
|
+
const { template } = await prompts({
|
|
306
|
+
type: 'select',
|
|
307
|
+
name: 'template',
|
|
308
|
+
message: 'Choose a template:',
|
|
309
|
+
choices: [
|
|
310
|
+
{ title: green('full'), value: 'full', description: 'Complete setup with all components' },
|
|
311
|
+
{ title: blue('with-mock'), value: 'with-mock', description: 'Full setup + mock API server' },
|
|
312
|
+
{ title: yellow('minimal'), value: 'minimal', description: 'Basic setup, add components yourself' },
|
|
313
|
+
],
|
|
314
|
+
initial: 0,
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
if (!template) {
|
|
318
|
+
console.log(red('\nAborted.'));
|
|
319
|
+
process.exit(1);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Choose package manager
|
|
323
|
+
const availableManagers = PACKAGE_MANAGERS.filter(commandExists);
|
|
324
|
+
const defaultManager = availableManagers.includes('bun') ? 'bun' : 'npm';
|
|
325
|
+
|
|
326
|
+
const { packageManager } = await prompts({
|
|
327
|
+
type: 'select',
|
|
328
|
+
name: 'packageManager',
|
|
329
|
+
message: 'Choose a package manager:',
|
|
330
|
+
choices: PACKAGE_MANAGERS.map((pm) => ({
|
|
331
|
+
title: pm + (pm === defaultManager ? dim(' (default)') : ''),
|
|
332
|
+
value: pm,
|
|
333
|
+
disabled: !availableManagers.includes(pm),
|
|
334
|
+
})),
|
|
335
|
+
initial: PACKAGE_MANAGERS.indexOf(defaultManager),
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
if (!packageManager) {
|
|
339
|
+
console.log(red('\nAborted.'));
|
|
340
|
+
process.exit(1);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Scaffold project
|
|
344
|
+
console.log(dim(`\nScaffolding project in ${targetDir}...`));
|
|
345
|
+
|
|
346
|
+
try {
|
|
347
|
+
// Copy template
|
|
348
|
+
await copyTemplate(template, targetDir);
|
|
349
|
+
|
|
350
|
+
// Update package.json
|
|
351
|
+
await updatePackageJson(targetDir, projectName);
|
|
352
|
+
|
|
353
|
+
// Initialize git
|
|
354
|
+
const gitInitialized = initGit(targetDir);
|
|
355
|
+
|
|
356
|
+
// Install dependencies
|
|
357
|
+
installDependencies(packageManager, targetDir);
|
|
358
|
+
|
|
359
|
+
// Show success message
|
|
360
|
+
showSuccessMessage(projectName, targetDir, packageManager, template);
|
|
361
|
+
|
|
362
|
+
if (gitInitialized) {
|
|
363
|
+
console.log(`${green('✔')} Git repository initialized\n`);
|
|
364
|
+
}
|
|
365
|
+
} catch (error) {
|
|
366
|
+
console.error(red('\nError scaffolding project:'));
|
|
367
|
+
console.error(error.message);
|
|
368
|
+
process.exit(1);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Helper functions
|
|
373
|
+
function bold(str) {
|
|
374
|
+
return `\x1b[1m${str}\x1b[0m`;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
async function readdir(path, options) {
|
|
378
|
+
const fs = await import('fs/promises');
|
|
379
|
+
return fs.readdir(path, options);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
async function rm(path, options) {
|
|
383
|
+
const fs = await import('fs/promises');
|
|
384
|
+
return fs.rm(path, options);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Run main function
|
|
388
|
+
main().catch((error) => {
|
|
389
|
+
console.error(red('\nUnexpected error:'));
|
|
390
|
+
console.error(error);
|
|
391
|
+
process.exit(1);
|
|
392
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@digitalygo/create-diggocms-app",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI tool to scaffold a new DiggoCMS project",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-diggocms-app": "./bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"files": ["bin", "templates"],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"prepublishOnly": "echo 'No build step needed'"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"prompts": "^2.4.2",
|
|
15
|
+
"kolorist": "^1.8.0"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"cms",
|
|
19
|
+
"headless-cms",
|
|
20
|
+
"react",
|
|
21
|
+
"nextjs",
|
|
22
|
+
"cli",
|
|
23
|
+
"scaffold",
|
|
24
|
+
"generator",
|
|
25
|
+
"diggo"
|
|
26
|
+
],
|
|
27
|
+
"author": "DigitalyGo Team <team@digitalygo.com>",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/digitalygo/diggocms-sdk.git",
|
|
32
|
+
"directory": "packages/create-diggocms-app"
|
|
33
|
+
},
|
|
34
|
+
"bugs": {
|
|
35
|
+
"url": "https://github.com/digitalygo/diggocms-sdk/issues"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/digitalygo/diggocms-sdk/tree/main/packages/create-diggocms-app#readme",
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18.0.0"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# DiggoCMS Environment Configuration
|
|
2
|
+
# Copy this file to .env.local and update the values
|
|
3
|
+
|
|
4
|
+
# CMS API Configuration
|
|
5
|
+
# Set your DiggoCMS API base URL
|
|
6
|
+
BASE_URL=https://your-cms-api.com
|
|
7
|
+
|
|
8
|
+
# Mock Mode
|
|
9
|
+
# Set to 1 to use local mock data instead of a real API
|
|
10
|
+
MOCK=0
|
|
11
|
+
|
|
12
|
+
# Mock API URL (only used when MOCK=1)
|
|
13
|
+
MOCK_API_URL=http://localhost:3001
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# My DiggoCMS App
|
|
2
|
+
|
|
3
|
+
A complete DiggoCMS application built with Next.js and the DiggoCMS SDK.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Dynamic routing with `[...slug]` pattern
|
|
8
|
+
- Extended components (Title, Subtitle, Image, Richtext, Card)
|
|
9
|
+
- Navigation with dropdown support
|
|
10
|
+
- Mock mode for development
|
|
11
|
+
- Error handling and loading states
|
|
12
|
+
|
|
13
|
+
## Getting Started
|
|
14
|
+
|
|
15
|
+
1. Copy `.env.local.example` to `.env.local` and configure:
|
|
16
|
+
```bash
|
|
17
|
+
cp .env.local.example .env.local
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
2. Install dependencies:
|
|
21
|
+
```bash
|
|
22
|
+
npm install
|
|
23
|
+
# or
|
|
24
|
+
bun install
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
3. Run the development server:
|
|
28
|
+
```bash
|
|
29
|
+
npm run dev
|
|
30
|
+
# or
|
|
31
|
+
bun run dev
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
4. Open [http://localhost:3000](http://localhost:3000) in your browser.
|
|
35
|
+
|
|
36
|
+
## Configuration
|
|
37
|
+
|
|
38
|
+
### Using a Real CMS API
|
|
39
|
+
|
|
40
|
+
Set your CMS API base URL:
|
|
41
|
+
```env
|
|
42
|
+
BASE_URL=https://your-cms-api.com
|
|
43
|
+
MOCK=0
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Using Mock Mode
|
|
47
|
+
|
|
48
|
+
Enable mock mode for development without a real API:
|
|
49
|
+
```env
|
|
50
|
+
MOCK=1
|
|
51
|
+
MOCK_API_URL=http://localhost:3001
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Project Structure
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
app/ # Next.js app router
|
|
58
|
+
├── [...slug]/ # Dynamic catch-all route
|
|
59
|
+
├── layout.tsx # Root layout with DiggoProvider
|
|
60
|
+
├── page.tsx # Home redirect
|
|
61
|
+
└── globals.css # Global styles
|
|
62
|
+
|
|
63
|
+
components/ # React components
|
|
64
|
+
├── DiggoProvider.tsx # SDK provider wrapper
|
|
65
|
+
├── server-components.ts # Server-safe component exports
|
|
66
|
+
├── ExtendedTitle.tsx
|
|
67
|
+
├── ExtendedSubtitle.tsx
|
|
68
|
+
├── ExtendedImage.tsx
|
|
69
|
+
├── ExtendedRichtext.tsx
|
|
70
|
+
├── ExtendedCard.tsx
|
|
71
|
+
├── ExtendedMenuItem.tsx
|
|
72
|
+
└── ExtendedMenuContainer.tsx
|
|
73
|
+
|
|
74
|
+
lib/ # Utility functions
|
|
75
|
+
├── diggo-config.ts # SDK configuration
|
|
76
|
+
└── data-fetching.ts # Data fetching helpers
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Extended Components
|
|
80
|
+
|
|
81
|
+
This template includes extended versions of all base components:
|
|
82
|
+
|
|
83
|
+
- **ExtendedTitle** - Styled H1 heading
|
|
84
|
+
- **ExtendedSubtitle** - Styled H2 heading
|
|
85
|
+
- **ExtendedImage** - Responsive image with shadow
|
|
86
|
+
- **ExtendedRichtext** - HTML content renderer
|
|
87
|
+
- **ExtendedCard** - Card layout with title, subtitle, content
|
|
88
|
+
- **ExtendedMenuItem** - Navigation item with active state
|
|
89
|
+
- **ExtendedMenuContainer** - Navigation wrapper
|
|
90
|
+
|
|
91
|
+
## Customization
|
|
92
|
+
|
|
93
|
+
1. Edit styles in `app/globals.css`
|
|
94
|
+
2. Modify components in `components/`
|
|
95
|
+
3. Update configuration in `lib/diggo-config.ts`
|
|
96
|
+
4. Add more data fetching functions in `lib/data-fetching.ts`
|
|
97
|
+
|
|
98
|
+
## Documentation
|
|
99
|
+
|
|
100
|
+
- [DiggoCMS SDK Documentation](https://github.com/digitalygo/diggocms-sdk)
|
|
101
|
+
- [Next.js Documentation](https://nextjs.org/docs)
|