create-cloudinary-react 1.0.0-beta.14 → 1.0.0-beta.16
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 +21 -0
- package/cli.js +25 -6
- package/package.json +1 -1
- package/templates/.cursorrules.template +1 -1
- package/templates/README.md.template +3 -6
- package/templates/src/App.css.template +1 -1
- package/templates/src/App.tsx.template +33 -13
- package/templates/vite.config.ts.template +5 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
# [1.0.0-beta.16](https://github.com/cloudinary-devs/create-cloudinary-react/compare/v1.0.0-beta.15...v1.0.0-beta.16) (2026-02-11)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* add copy on click ([a4ecf5d](https://github.com/cloudinary-devs/create-cloudinary-react/commit/a4ecf5d1d1478d854683a115735fa71f7fb50cea))
|
|
7
|
+
* complete the sentance ([d6c68dd](https://github.com/cloudinary-devs/create-cloudinary-react/commit/d6c68ddc213fbc18771f26840f33edb805950799))
|
|
8
|
+
* remove upload question ([fbf01ae](https://github.com/cloudinary-devs/create-cloudinary-react/commit/fbf01ae696e158cab48feb053a3515bb21453fdd))
|
|
9
|
+
|
|
10
|
+
# [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)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* use correct CLAUDE.md convention for Claude Code ([07a8a08](https://github.com/cloudinary-devs/create-cloudinary-react/commit/07a8a085686b160387388464a722d90c09cb6805))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **analytics:** add CLI feature detection for React SDK ([4dfe495](https://github.com/cloudinary-devs/create-cloudinary-react/commit/4dfe4957bf615e9df08afe729e4f024c02d1cc7f))
|
|
21
|
+
|
|
1
22
|
# [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
23
|
|
|
3
24
|
|
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
|
-
|
|
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:
|
|
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, '.
|
|
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
|
|
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
|
@@ -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
|
-
-
|
|
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
|
-
{{
|
|
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
|
-
|
|
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
|
|
|
@@ -23,8 +25,13 @@ function App() {
|
|
|
23
25
|
alert(`Upload failed: ${error.message}`);
|
|
24
26
|
};
|
|
25
27
|
|
|
28
|
+
const copyPrompt = (e: React.MouseEvent<HTMLLIElement>) => {
|
|
29
|
+
const text = e.currentTarget.textContent ?? '';
|
|
30
|
+
void navigator.clipboard.writeText(text);
|
|
31
|
+
};
|
|
32
|
+
|
|
26
33
|
// Display uploaded image if available, otherwise show a sample
|
|
27
|
-
const imageId = uploadedImageId || 'samples/
|
|
34
|
+
const imageId = uploadedImageId || 'samples/people/bicycle';
|
|
28
35
|
|
|
29
36
|
const displayImage = cld
|
|
30
37
|
.image(imageId)
|
|
@@ -38,14 +45,16 @@ function App() {
|
|
|
38
45
|
<h1>Cloudinary React + Vite</h1>
|
|
39
46
|
<p>This is a ready-to-use development environment with Cloudinary integration.</p>
|
|
40
47
|
|
|
41
|
-
|
|
42
|
-
<
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
{hasUploadPreset && (
|
|
49
|
+
<div className="upload-section">
|
|
50
|
+
<h2>Upload an Image</h2>
|
|
51
|
+
<UploadWidget
|
|
52
|
+
onUploadSuccess={handleUploadSuccess}
|
|
53
|
+
onUploadError={handleUploadError}
|
|
54
|
+
buttonText="Upload Image"
|
|
55
|
+
/>
|
|
56
|
+
</div>
|
|
57
|
+
)}
|
|
49
58
|
|
|
50
59
|
<div className="image-section">
|
|
51
60
|
<h2>Display Image</h2>
|
|
@@ -66,9 +75,20 @@ function App() {
|
|
|
66
75
|
<strong>Copy and paste</strong> one of these prompts into your AI assistant:
|
|
67
76
|
</p>
|
|
68
77
|
<ul className="prompts-list">
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
{hasUploadPreset ? (
|
|
79
|
+
<>
|
|
80
|
+
<li onClick={copyPrompt} title="Click to copy">Create an image gallery with lazy loading and responsive images</li>
|
|
81
|
+
<li onClick={copyPrompt} title="Click to copy">Create a video player that plays a Cloudinary video</li>
|
|
82
|
+
<li onClick={copyPrompt} title="Click to copy">Add image overlays with text or logos</li>
|
|
83
|
+
</>
|
|
84
|
+
) : (
|
|
85
|
+
<>
|
|
86
|
+
<li onClick={copyPrompt} title="Click to copy">Let's try uploading — help me add an upload preset and upload widget</li>
|
|
87
|
+
<li onClick={copyPrompt} title="Click to copy">Create an image gallery with lazy loading and responsive images</li>
|
|
88
|
+
<li onClick={copyPrompt} title="Click to copy">Create a video player that plays a Cloudinary video</li>
|
|
89
|
+
<li onClick={copyPrompt} title="Click to copy">Add image overlays with text or logos</li>
|
|
90
|
+
</>
|
|
91
|
+
)}
|
|
72
92
|
</ul>
|
|
73
93
|
</div>
|
|
74
94
|
</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
|
})
|