create-cloudinary-react 1.0.0-beta.14 → 1.0.0-beta.15

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/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ # [1.0.0-beta.15](https://github.com/cloudinary-devs/create-cloudinary-react/compare/v1.0.0-beta.14...v1.0.0-beta.15) (2026-02-10)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * use correct CLAUDE.md convention for Claude Code ([07a8a08](https://github.com/cloudinary-devs/create-cloudinary-react/commit/07a8a085686b160387388464a722d90c09cb6805))
7
+
8
+
9
+ ### Features
10
+
11
+ * **analytics:** add CLI feature detection for React SDK ([4dfe495](https://github.com/cloudinary-devs/create-cloudinary-react/commit/4dfe4957bf615e9df08afe729e4f024c02d1cc7f))
12
+
1
13
  # [1.0.0-beta.14](https://github.com/cloudinary-devs/create-cloudinary-react/compare/v1.0.0-beta.13...v1.0.0-beta.14) (2026-02-04)
2
14
 
3
15
 
package/cli.js CHANGED
@@ -72,7 +72,7 @@ async function main() {
72
72
  console.log(chalk.cyan.bold('\n🚀 Cloudinary React + Vite\n'));
73
73
  console.log(chalk.gray('💡 Need a Cloudinary account? Sign up for free: https://cloudinary.com/users/register/free\n'));
74
74
 
75
- answers = await inquirer.prompt([
75
+ const questions = [
76
76
  {
77
77
  type: 'input',
78
78
  name: 'projectName',
@@ -135,7 +135,9 @@ async function main() {
135
135
  {
136
136
  type: 'checkbox',
137
137
  name: 'aiTools',
138
- message: 'Which AI coding assistant(s) are you using? (Select all that apply)',
138
+ message:
139
+ 'Which AI coding assistant(s) are you using? (Select all that apply)\n' +
140
+ chalk.gray(' We’ll add local instruction files so your assistant knows Cloudinary patterns.\n'),
139
141
  choices: [
140
142
  { name: 'Cursor', value: 'cursor' },
141
143
  { name: 'GitHub Copilot', value: 'copilot' },
@@ -157,7 +159,9 @@ async function main() {
157
159
  default: false,
158
160
  when: (answers) => answers.installDeps,
159
161
  },
160
- ]);
162
+ ];
163
+
164
+ answers = await inquirer.prompt(questions);
161
165
  }
162
166
 
163
167
  const { projectName, cloudName, uploadPreset, aiTools, installDeps, startDev } = answers;
@@ -183,6 +187,9 @@ async function main() {
183
187
  PROJECT_NAME: projectName,
184
188
  CLOUD_NAME: cloudName,
185
189
  UPLOAD_PRESET: uploadPreset || '',
190
+ UPLOAD_PRESET_ENV_LINE: uploadPreset
191
+ ? `- \`VITE_CLOUDINARY_UPLOAD_PRESET\`: ${uploadPreset}`
192
+ : '- `VITE_CLOUDINARY_UPLOAD_PRESET`: (not set - add one for uploads)',
186
193
  };
187
194
 
188
195
  // Function to copy template file
@@ -247,8 +254,7 @@ async function main() {
247
254
  }
248
255
 
249
256
  if (aiTools.includes('claude')) {
250
- writeFileSync(join(projectPath, '.claude'), aiRulesContent);
251
- writeFileSync(join(projectPath, 'claude.md'), aiRulesContent);
257
+ writeFileSync(join(projectPath, 'CLAUDE.md'), aiRulesContent);
252
258
  }
253
259
 
254
260
  if (aiTools.includes('generic')) {
@@ -279,6 +285,18 @@ async function main() {
279
285
 
280
286
  console.log(chalk.green('✅ Project created successfully!\n'));
281
287
 
288
+ if (aiTools && aiTools.length > 0) {
289
+ console.log(chalk.cyan('📋 AI assistant files created:'));
290
+ if (aiTools.includes('cursor')) console.log(chalk.gray(' • Cursor: .cursorrules'));
291
+ if (aiTools.includes('copilot')) console.log(chalk.gray(' • GitHub Copilot: .github/copilot-instructions.md'));
292
+ if (aiTools.includes('claude')) console.log(chalk.gray(' • Claude: CLAUDE.md'));
293
+ if (aiTools.includes('generic')) console.log(chalk.gray(' • Generic: AI_INSTRUCTIONS.md, PROMPT.md'));
294
+ if (aiTools.includes('cursor') || aiTools.includes('claude')) {
295
+ console.log(chalk.gray(' • MCP (Cursor/Claude): .cursor/mcp.json'));
296
+ }
297
+ console.log('');
298
+ }
299
+
282
300
  if (!answers.hasUploadPreset) {
283
301
  console.log(chalk.yellow('\n📝 Note: Upload preset not configured'));
284
302
  console.log(chalk.gray(' • Transformations will work with sample images'));
@@ -287,7 +305,8 @@ async function main() {
287
305
  console.log(chalk.cyan(' 1. Go to https://console.cloudinary.com/app/settings/upload/presets'));
288
306
  console.log(chalk.cyan(' 2. Click "Add upload preset"'));
289
307
  console.log(chalk.cyan(' 3. Set it to "Unsigned" mode'));
290
- console.log(chalk.cyan(' 4. Add the preset name to your .env file\n'));
308
+ console.log(chalk.cyan(' 4. Add the preset name to your .env file'));
309
+ console.log(chalk.cyan(' 5. Save the file and restart the dev server so it loads correctly\n'));
291
310
  }
292
311
 
293
312
  if (installDeps) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-cloudinary-react",
3
- "version": "1.0.0-beta.14",
3
+ "version": "1.0.0-beta.15",
4
4
  "description": "Scaffold a Cloudinary React + Vite + TypeScript project with interactive setup",
5
5
  "type": "module",
6
6
  "bin": {
@@ -30,7 +30,7 @@ If the user is **not** using the create-cloudinary-react CLI and only has these
30
30
  Create a `.env` file in the project root with **Vite prefix** (required for client access):
31
31
  - `VITE_CLOUDINARY_CLOUD_NAME=your_cloud_name` (required)
32
32
  - `VITE_CLOUDINARY_UPLOAD_PRESET=your_unsigned_preset_name` (optional; required for unsigned upload widget)
33
- - Restart the dev server after adding or changing `.env`. Use `import.meta.env.VITE_*` in code, not `process.env`.
33
+ - Save the `.env` file after editing it, then restart the dev server so changes load correctly. Use `import.meta.env.VITE_*` in code, not `process.env`.
34
34
 
35
35
  **2. Reusable Cloudinary instance (config)**
36
36
  Create a config file (e.g. `src/cloudinary/config.ts`) so the rest of the app can use a single `cld` instance:
@@ -18,11 +18,7 @@ This project uses Cloudinary for image management. If you don't have a Cloudinar
18
18
 
19
19
  Your `.env` file has been pre-configured with:
20
20
  - `VITE_CLOUDINARY_CLOUD_NAME`: {{CLOUD_NAME}}
21
- {{#UPLOAD_PRESET}}
22
- - `VITE_CLOUDINARY_UPLOAD_PRESET`: {{UPLOAD_PRESET}}
23
- {{/UPLOAD_PRESET}}
24
- {{^UPLOAD_PRESET}}
25
- - `VITE_CLOUDINARY_UPLOAD_PRESET`: (not set - required for uploads)
21
+ {{UPLOAD_PRESET_ENV_LINE}}
26
22
 
27
23
  **Note**: Transformations work without an upload preset (using sample images). Uploads require an unsigned upload preset.
28
24
 
@@ -31,7 +27,8 @@ To create an unsigned upload preset:
31
27
  2. Click "Add upload preset"
32
28
  3. Set it to "Unsigned" mode
33
29
  4. Add the preset name to your `.env` file
34
- {{/UPLOAD_PRESET}}
30
+ 5. **Save** the `.env` file and restart the dev server so the new values load correctly.
31
+
35
32
 
36
33
  ## AI Assistant Support
37
34
 
@@ -5,11 +5,13 @@ import { format, quality } from '@cloudinary/url-gen/actions/delivery';
5
5
  import { auto } from '@cloudinary/url-gen/qualifiers/format';
6
6
  import { auto as autoQuality } from '@cloudinary/url-gen/qualifiers/quality';
7
7
  import { autoGravity } from '@cloudinary/url-gen/qualifiers/gravity';
8
- import { cld } from './cloudinary/config';
8
+ import { cld, uploadPreset } from './cloudinary/config';
9
9
  import { UploadWidget } from './cloudinary/UploadWidget';
10
10
  import type { CloudinaryUploadResult } from './cloudinary/UploadWidget';
11
11
  import './App.css';
12
12
 
13
+ const hasUploadPreset = Boolean(uploadPreset);
14
+
13
15
  function App() {
14
16
  const [uploadedImageId, setUploadedImageId] = useState<string | null>(null);
15
17
 
@@ -24,7 +26,7 @@ function App() {
24
26
  };
25
27
 
26
28
  // Display uploaded image if available, otherwise show a sample
27
- const imageId = uploadedImageId || 'samples/cloudinary-icon';
29
+ const imageId = uploadedImageId || 'samples/people/bicycle';
28
30
 
29
31
  const displayImage = cld
30
32
  .image(imageId)
@@ -38,14 +40,16 @@ function App() {
38
40
  <h1>Cloudinary React + Vite</h1>
39
41
  <p>This is a ready-to-use development environment with Cloudinary integration.</p>
40
42
 
41
- <div className="upload-section">
42
- <h2>Upload an Image</h2>
43
- <UploadWidget
44
- onUploadSuccess={handleUploadSuccess}
45
- onUploadError={handleUploadError}
46
- buttonText="Upload Image"
47
- />
48
- </div>
43
+ {hasUploadPreset && (
44
+ <div className="upload-section">
45
+ <h2>Upload an Image</h2>
46
+ <UploadWidget
47
+ onUploadSuccess={handleUploadSuccess}
48
+ onUploadError={handleUploadError}
49
+ buttonText="Upload Image"
50
+ />
51
+ </div>
52
+ )}
49
53
 
50
54
  <div className="image-section">
51
55
  <h2>Display Image</h2>
@@ -66,9 +70,21 @@ function App() {
66
70
  <strong>Copy and paste</strong> one of these prompts into your AI assistant:
67
71
  </p>
68
72
  <ul className="prompts-list">
69
- <li>Create an image gallery with lazy loading and responsive</li>
70
- <li>Create a video player that plays a Cloudinary video</li>
71
- <li>Add image overlays with text or logos</li>
73
+ {hasUploadPreset ? (
74
+ <>
75
+ <li>Upload an image to my account</li>
76
+ <li>Create an image gallery with lazy loading and responsive images</li>
77
+ <li>Create a video player that plays a Cloudinary video</li>
78
+ <li>Add image overlays with text or logos</li>
79
+ </>
80
+ ) : (
81
+ <>
82
+ <li>Let&apos;s try uploading — help me add an upload preset and upload widget</li>
83
+ <li>Create an image gallery with lazy loading and responsive</li>
84
+ <li>Create a video player that plays a Cloudinary video</li>
85
+ <li>Add image overlays with text or logos</li>
86
+ </>
87
+ )}
72
88
  </ul>
73
89
  </div>
74
90
  </main>
@@ -4,4 +4,9 @@ import react from '@vitejs/plugin-react'
4
4
  // https://vite.dev/config/
5
5
  export default defineConfig({
6
6
  plugins: [react()],
7
+ define: {
8
+ // Analytics: Mark this project as created via create-cloudinary-react CLI
9
+ 'process.env.CLOUDINARY_SOURCE': '"cli"',
10
+ 'process.env.CLD_CLI': '"true"',
11
+ },
7
12
  })