Skip to content

Commit e839d5c

Browse files
committed
Add README visual abstract and generation script
1 parent 1797151 commit e839d5c

4 files changed

Lines changed: 125 additions & 18 deletions

File tree

README.md

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,13 @@ Web2Comics is a Chrome extension that:
99
- shows the result in a comic viewer side panel
1010
- saves history and exports a single composite comic image
1111

12-
## Quick Try (60 Seconds)
12+
## Visual Abstract
1313

14-
1. Download the latest release ZIP from the `Releases` page.
15-
2. Load it in Chrome via `chrome://extensions` -> `Load unpacked`.
16-
3. Enable and pin `Web2Comics` from the Extensions (puzzle) menu.
17-
4. Open the extension, configure a `Google Gemini` API key in `Options -> Providers`.
18-
5. Open any article, click `Create Comic`, and generate a 3-panel summary.
14+
![Web2Comics visual abstract](docs/visual-abstract-gemini.png)
1915

2016
## Install (Easy ZIP Method)
2117

22-
### Option A: Download Release ZIP (recommended for non-developers)
18+
### Install From Release ZIP (recommended)
2319

2420
Release links:
2521
- Releases page: https://github.com/ApartsinProjects/Web2Comics/releases
@@ -34,20 +30,11 @@ Release links:
3430
7. Select the extracted folder that contains `manifest.json` (for example `Web2Comics-v1.0.1`).
3531
8. In `chrome://extensions`, confirm the `Web2Comics` card is enabled (toggle ON).
3632
9. Open the Chrome Extensions menu (puzzle icon), find `Web2Comics`, and click the pin icon to show it in the toolbar.
37-
10. Web2Comics will open the Options page on first install so you can configure providers.
33+
10. Open the extension and configure a `Google Gemini` API key in `Options -> Providers` (recommended first-run setup).
34+
11. Open any article, click `Create Comic`, and generate a 3-panel summary.
3835

3936
Note: `Code -> Download ZIP` downloads the full source repository (tests/scripts/docs included). Use the release asset ZIP for installation.
4037

41-
### Option B: Clone the repo (developer workflow)
42-
43-
```powershell
44-
git clone https://github.com/ApartsinProjects/Web2Comics.git
45-
cd Web2Comics
46-
```
47-
48-
Then load it in Chrome using the same `chrome://extensions` -> `Load unpacked` steps above.
49-
After loading, confirm the extension is enabled and pin `Web2Comics` from the Extensions (puzzle) menu so the toolbar icon is visible.
50-
5138
## What You Can Do
5239

5340
- Generate comics from articles, docs, blog posts, and reference pages

docs/visual-abstract-gemini.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"generatedAt": "2026-02-26T08:08:04.874Z",
3+
"provider": "gemini",
4+
"model": "gemini-2.0-flash-exp-image-generation",
5+
"prompt": "Create a polished visual abstract hero image for a Chrome extension named Web2Comics. Wide banner composition, clean modern flat illustration, friendly and professional. Show a left-to-right workflow with 4 stages: 1) a web page/article in a browser tab, 2) an AI processing/storyboard stage (robot/AI spark icon), 3) comic strip panels being generated, 4) a side panel viewer and an exported PNG image. Use bright colors, strong contrast, white or very light background, subtle gradients. No logos from other companies. No watermarks. No tiny unreadable text. If text is included, keep it minimal and legible: \"Web Page\", \"AI\", \"Comic\", \"Export\". Style should feel inviting for a README visual abstract. 16:9 landscape.",
6+
"mimeType": "image/png",
7+
"textParts": [
8+
"I will generate a wide, 16:9 visual abstract hero image for the Chrome extension \"Web2Comics\". The illustration will use a clean, modern flat style with bright colors and strong contrast against a white background with subtle gradients. It will depict a left-to-right workflow in four stages: first, a simplified web page displayed in a browser tab labeled \"Web Page\"; second, an abstract AI processing or storyboard stage represented by a friendly robot icon emitting a spark, labeled \"AI\"; third, comic strip panels in the process of being generated; and fourth, a side panel viewer displaying a completed comic strip next to an exported PNG image icon, labeled \"Comic\" above the viewer and \"Export\" above the PNG icon.\n\n"
9+
]
10+
}

docs/visual-abstract-gemini.png

341 KB
Loading
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
4+
function loadLocalEnvFile() {
5+
const envPath = path.resolve(__dirname, '../.env.e2e.local');
6+
if (!fs.existsSync(envPath)) return;
7+
const lines = fs.readFileSync(envPath, 'utf8').split(/\r?\n/);
8+
for (const rawLine of lines) {
9+
const line = rawLine.trim();
10+
if (!line || line.startsWith('#')) continue;
11+
const eq = line.indexOf('=');
12+
if (eq <= 0) continue;
13+
const key = line.slice(0, eq).trim();
14+
const value = line.slice(eq + 1).trim();
15+
process.env[key] = value;
16+
}
17+
}
18+
19+
loadLocalEnvFile();
20+
21+
const GEMINI_API_KEY = process.env.GEMINI_API_KEY || '';
22+
const MODEL = process.env.GEMINI_IMAGE_MODEL || 'gemini-2.0-flash-exp-image-generation';
23+
24+
if (!GEMINI_API_KEY) {
25+
console.error('GEMINI_API_KEY missing (.env.e2e.local)');
26+
process.exit(1);
27+
}
28+
29+
const prompt = [
30+
'Create a polished visual abstract hero image for a Chrome extension named Web2Comics.',
31+
'Wide banner composition, clean modern flat illustration, friendly and professional.',
32+
'Show a left-to-right workflow with 4 stages:',
33+
'1) a web page/article in a browser tab,',
34+
'2) an AI processing/storyboard stage (robot/AI spark icon),',
35+
'3) comic strip panels being generated,',
36+
'4) a side panel viewer and an exported PNG image.',
37+
'Use bright colors, strong contrast, white or very light background, subtle gradients.',
38+
'No logos from other companies. No watermarks. No tiny unreadable text.',
39+
'If text is included, keep it minimal and legible: "Web Page", "AI", "Comic", "Export".',
40+
'Style should feel inviting for a README visual abstract.',
41+
'16:9 landscape.'
42+
].join(' ');
43+
44+
async function main() {
45+
const url = `https://generativelanguage.googleapis.com/v1beta/models/${MODEL}:generateContent?key=${GEMINI_API_KEY}`;
46+
const res = await fetch(url, {
47+
method: 'POST',
48+
headers: { 'Content-Type': 'application/json' },
49+
body: JSON.stringify({
50+
contents: [{ parts: [{ text: prompt }] }],
51+
generationConfig: {
52+
responseModalities: ['image', 'text'],
53+
maxOutputTokens: 1024
54+
}
55+
})
56+
});
57+
58+
const raw = await res.text();
59+
let json = null;
60+
try {
61+
json = raw ? JSON.parse(raw) : null;
62+
} catch (_) {}
63+
64+
if (!res.ok) {
65+
console.error(`Gemini request failed: ${res.status}`);
66+
console.error(raw.slice(0, 2000));
67+
process.exit(1);
68+
}
69+
70+
const parts = json?.candidates?.[0]?.content?.parts || [];
71+
const imagePart = parts.find((p) => p?.inlineData?.data);
72+
if (!imagePart) {
73+
console.error('No image returned by Gemini.');
74+
console.error(JSON.stringify(json, null, 2).slice(0, 4000));
75+
process.exit(1);
76+
}
77+
78+
const mimeType = imagePart.inlineData?.mimeType || 'image/png';
79+
const ext = mimeType.includes('jpeg') ? 'jpg' : 'png';
80+
const outDir = path.resolve(__dirname, '../docs');
81+
fs.mkdirSync(outDir, { recursive: true });
82+
83+
const outImage = path.join(outDir, `visual-abstract-gemini.${ext}`);
84+
fs.writeFileSync(outImage, Buffer.from(imagePart.inlineData.data, 'base64'));
85+
86+
const outMeta = path.join(outDir, 'visual-abstract-gemini.json');
87+
fs.writeFileSync(
88+
outMeta,
89+
JSON.stringify(
90+
{
91+
generatedAt: new Date().toISOString(),
92+
provider: 'gemini',
93+
model: MODEL,
94+
prompt,
95+
mimeType,
96+
textParts: parts.filter((p) => p?.text).map((p) => p.text)
97+
},
98+
null,
99+
2
100+
)
101+
);
102+
103+
console.log(`Saved image: ${path.relative(path.resolve(__dirname, '..'), outImage)}`);
104+
console.log(`Saved metadata: ${path.relative(path.resolve(__dirname, '..'), outMeta)}`);
105+
}
106+
107+
main().catch((error) => {
108+
console.error(error);
109+
process.exit(1);
110+
});

0 commit comments

Comments
 (0)