Skip to content

Commit 1a8f623

Browse files
committed
Add ai logo generation.
1 parent 3db7aa1 commit 1a8f623

File tree

4 files changed

+104
-0
lines changed

4 files changed

+104
-0
lines changed

BACKLOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Backlog
2+
3+
---
4+
## Feature name
5+
Generate a logo with AI.
6+
7+
### Description
8+
Ask the user to provide a prompt that will be used for logo generation with AI as a final step before the last step in the cli init process.
9+
---

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@
44

55
### Features
66

7+
- Implement AI logo generation using Google Gemini.
8+
79
### Fixes
810

11+
- Fix error handling in `lib/ai.ts` to avoid local exception catching and improve reliability.
12+
-
913
## [0.1.18] - 2026-01-13
1014

1115
### Miscellaneous

init.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { promptInput, promptSelect } from "./lib/prompt.ts";
1414
import { degitRepoToDir } from "./lib/degit.ts";
1515
import { replacePlaceholdersInRepo } from "./lib/replace.ts";
1616
import { isValidProjectName, slugifyProjectName } from "./lib/validate.ts";
17+
import { generateLogo } from "./lib/ai.ts";
1718

1819
export async function initCommand() {
1920
console.log(magenta(bold(`
@@ -80,6 +81,20 @@ export async function initCommand() {
8081
);
8182
const phone = promptInput("📞 Phone number (optional)", "+46 7182387123");
8283

84+
// Logo generation prompt
85+
console.log(cyan(bold("\n🎨 AI Logo Generation")));
86+
const logoPrompt = promptInput(
87+
"✨ Enter a prompt for your logo (optional, leave empty to skip)",
88+
"",
89+
);
90+
91+
let geminiApiKey = "";
92+
if (logoPrompt) {
93+
geminiApiKey = promptInput("🔑 Enter your Google Gemini API key", "", {
94+
required: true,
95+
});
96+
}
97+
8398
const meta = {
8499
projectname: projectname.trim(),
85100
shortname: shortname.trim(),
@@ -369,6 +384,14 @@ export async function initCommand() {
369384
}
370385
}
371386

387+
// ------------------------
388+
// Step 4: AI Logo Generation (if prompt and key provided)
389+
// ------------------------
390+
if (logoPrompt && geminiApiKey) {
391+
console.log("");
392+
await generateLogo(logoPrompt, geminiApiKey, destDir);
393+
}
394+
372395
console.log(
373396
green(bold(`\n🎉 Project successfully generated in: ${meta.projectname}`)),
374397
);

lib/ai.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { startSpinner } from "./ui.ts";
2+
import { join } from "@std/path";
3+
import { ensureDir } from "@std/fs";
4+
5+
/**
6+
* Generates a logo using Google's Gemini AI (Imagen model)
7+
*/
8+
export async function generateLogo(
9+
prompt: string,
10+
apiKey: string,
11+
destDir: string,
12+
): Promise<string | null> {
13+
const spinner = startSpinner("🎨 Generating logo with AI...");
14+
15+
try {
16+
// Note: Using imagen-3.0-generate-001 model via Gemini API
17+
const url = `https://generativelanguage.googleapis.com/v1beta/models/imagen-3.0-generate-001:predict?key=${apiKey}`;
18+
19+
const response = await fetch(url, {
20+
method: "POST",
21+
headers: {
22+
"Content-Type": "application/json",
23+
},
24+
body: JSON.stringify({
25+
instances: [
26+
{
27+
prompt: prompt,
28+
},
29+
],
30+
parameters: {
31+
sampleCount: 1,
32+
aspectRatio: "1:1",
33+
outputMimeType: "image/png",
34+
},
35+
}),
36+
});
37+
38+
if (!response.ok) {
39+
const errorData = await response.json().catch(() => ({}));
40+
const errorMessage = errorData.error?.message || `API request failed with status ${response.status}`;
41+
spinner.stop(false);
42+
console.log(` ⚠️ Failed to generate logo: ${errorMessage}`);
43+
return null;
44+
}
45+
46+
const data = await response.json();
47+
const base64Image = data.predictions?.[0]?.bytesBase64Encoded;
48+
49+
if (!base64Image) {
50+
spinner.stop(false);
51+
console.log(" ⚠️ Failed to generate logo: No image data received from AI.");
52+
return null;
53+
}
54+
55+
const imageBuffer = Uint8Array.from(atob(base64Image), (c) => c.charCodeAt(0));
56+
const publicDir = join(destDir, "public");
57+
await ensureDir(publicDir);
58+
const logoPath = join(publicDir, "logo.png");
59+
await Deno.writeFile(logoPath, imageBuffer);
60+
61+
spinner.stop(true);
62+
return logoPath;
63+
} catch (err) {
64+
spinner.stop(false);
65+
console.log(` ⚠️ An unexpected error occurred: ${err instanceof Error ? err.message : String(err)}`);
66+
return null;
67+
}
68+
}

0 commit comments

Comments
 (0)