Skip to content

Commit fecbe87

Browse files
strausrcursoragent
andcommitted
Improve CLI and templates: README env default, conditional upload widget, AI prompt context, save .env note
- README: default upload preset line when none supplied; add step to save .env and restart - App: hide upload widget when no upload preset; conditional AI prompts (try uploading vs add preset) - App: default display image to samples/landscapes/beach-boat - CLI: explain AI assistant question (local instruction files); list created files per selection after create - CLI: remove edit/review step and 'no data sent' line per feedback - .cursorrules: save .env then restart for changes to load Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 0ac7fdc commit fecbe87

File tree

5 files changed

+59
-26
lines changed

5 files changed

+59
-26
lines changed

cli.js

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ async function main() {
7272
console.log(chalk.cyan.bold('\n🚀 Cloudinary React + Vite\n'));
7373
console.log(chalk.gray('💡 Need a Cloudinary account? Sign up for free: https://cloudinary.com/users/register/free\n'));
7474

75-
answers = await inquirer.prompt([
75+
const questions = [
7676
{
7777
type: 'input',
7878
name: 'projectName',
@@ -135,7 +135,9 @@ async function main() {
135135
{
136136
type: 'checkbox',
137137
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'),
139141
choices: [
140142
{ name: 'Cursor', value: 'cursor' },
141143
{ name: 'GitHub Copilot', value: 'copilot' },
@@ -157,7 +159,9 @@ async function main() {
157159
default: false,
158160
when: (answers) => answers.installDeps,
159161
},
160-
]);
162+
];
163+
164+
answers = await inquirer.prompt(questions);
161165
}
162166

163167
const { projectName, cloudName, uploadPreset, aiTools, installDeps, startDev } = answers;
@@ -183,6 +187,9 @@ async function main() {
183187
PROJECT_NAME: projectName,
184188
CLOUD_NAME: cloudName,
185189
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)',
186193
};
187194

188195
// Function to copy template file
@@ -278,6 +285,18 @@ async function main() {
278285

279286
console.log(chalk.green('✅ Project created successfully!\n'));
280287

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+
281300
if (!answers.hasUploadPreset) {
282301
console.log(chalk.yellow('\n📝 Note: Upload preset not configured'));
283302
console.log(chalk.gray(' • Transformations will work with sample images'));
@@ -286,7 +305,8 @@ async function main() {
286305
console.log(chalk.cyan(' 1. Go to https://console.cloudinary.com/app/settings/upload/presets'));
287306
console.log(chalk.cyan(' 2. Click "Add upload preset"'));
288307
console.log(chalk.cyan(' 3. Set it to "Unsigned" mode'));
289-
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'));
290310
}
291311

292312
if (installDeps) {

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

templates/.cursorrules.template

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ If the user is **not** using the create-cloudinary-react CLI and only has these
3030
Create a `.env` file in the project root with **Vite prefix** (required for client access):
3131
- `VITE_CLOUDINARY_CLOUD_NAME=your_cloud_name` (required)
3232
- `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`.
3434

3535
**2. Reusable Cloudinary instance (config)**
3636
Create a config file (e.g. `src/cloudinary/config.ts`) so the rest of the app can use a single `cld` instance:

templates/README.md.template

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,7 @@ This project uses Cloudinary for image management. If you don't have a Cloudinar
1818

1919
Your `.env` file has been pre-configured with:
2020
- `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}}
2622

2723
**Note**: Transformations work without an upload preset (using sample images). Uploads require an unsigned upload preset.
2824

@@ -31,7 +27,8 @@ To create an unsigned upload preset:
3127
2. Click "Add upload preset"
3228
3. Set it to "Unsigned" mode
3329
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+
3532

3633
## AI Assistant Support
3734

templates/src/App.tsx.template

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import { format, quality } from '@cloudinary/url-gen/actions/delivery';
55
import { auto } from '@cloudinary/url-gen/qualifiers/format';
66
import { auto as autoQuality } from '@cloudinary/url-gen/qualifiers/quality';
77
import { autoGravity } from '@cloudinary/url-gen/qualifiers/gravity';
8-
import { cld } from './cloudinary/config';
8+
import { cld, uploadPreset } from './cloudinary/config';
99
import { UploadWidget } from './cloudinary/UploadWidget';
1010
import type { CloudinaryUploadResult } from './cloudinary/UploadWidget';
1111
import './App.css';
1212

13+
const hasUploadPreset = Boolean(uploadPreset);
14+
1315
function App() {
1416
const [uploadedImageId, setUploadedImageId] = useState<string | null>(null);
1517

@@ -24,7 +26,7 @@ function App() {
2426
};
2527

2628
// Display uploaded image if available, otherwise show a sample
27-
const imageId = uploadedImageId || 'samples/cloudinary-icon';
29+
const imageId = uploadedImageId || 'samples/people/bicycle';
2830

2931
const displayImage = cld
3032
.image(imageId)
@@ -38,14 +40,16 @@ function App() {
3840
<h1>Cloudinary React + Vite</h1>
3941
<p>This is a ready-to-use development environment with Cloudinary integration.</p>
4042

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+
)}
4953

5054
<div className="image-section">
5155
<h2>Display Image</h2>
@@ -66,9 +70,21 @@ function App() {
6670
<strong>Copy and paste</strong> one of these prompts into your AI assistant:
6771
</p>
6872
<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+
)}
7288
</ul>
7389
</div>
7490
</main>

0 commit comments

Comments
 (0)