AI-powered image generator supporting Google Gemini and Fal Nano Banana 2. Supports image generation from text prompts and image modification with reference images (Gemini).
- πΌοΈ Image generation from text descriptions
- π¨ Image modification using reference images
- π Style transfer - Apply artistic styles to your images
- π Quality control - Generate in 1K, 2K or 4K
- π― Multiple formats - Supports local paths, URLs and Base64
- πΎ Auto-save with unique hash per prompt
npm install genmixYou can also add GenMix as a skill for AI agentic development:
npx skills add https://github.com/clasen/GenMix --skill genmixCreate a .env file in your project root:
GEMINI_API_KEY=your_api_key_here
FAL_API_KEY=your_fal_api_key_hereGEMINI_API_KEY is used with provider gemini and FAL_API_KEY is used with provider fal.
GenMix shines when combining multiple images with specific instructions using its intuitive chainable API:
import { GeminiGenerator } from 'genmix';
const generator = new GeminiGenerator();
const result = await generator
.pro() // Use the Pro model for best results
.addReference('./person.jpg', 'Use this person as the main subject')
.addReference('./background.jpg', 'Use this as the background setting')
.generate('A photo of the person standing in the background setting, cinematic lighting');
await generator.save({ filename: 'composite-result' });import { GeminiGenerator, FalGenerator } from 'genmix';
const gemini = new GeminiGenerator({ apiKey: process.env.GEMINI_API_KEY });
const fal = new FalGenerator({ apiKey: process.env.FAL_API_KEY });
await gemini.flash().generate('A cinematic portrait with dramatic lighting');
await fal.generate('A cinematic portrait with dramatic lighting', {
numberOfImages: 1,
quality: '1K',
aspectRatio: '1:1'
});Fal models available in this integration:
flash(orbanana2) ->fal-ai/nano-banana-2/edit(image-to-image editing)pro(orbanana-pro) ->fal-ai/nano-banana-pro/edit(image-to-image editing)
You can easily switch between the Pro and Flash models using chainable methods:
import { GeminiGenerator } from 'genmix';
const generator = new GeminiGenerator();
// Use the Pro model
await generator
.pro()
.generate('A highly detailed portrait of a cat');
// Switch to the Flash model
await generator
.flash()
.generate('A quick sketch of a dog');import { GeminiGenerator } from 'genmix';
const generator = new GeminiGenerator();
// Generate an image
const result = await generator.generate(
'A futuristic city with flying cars, cyberpunk style',
{
numberOfImages: 1,
quality: '2K',
aspectRatio: '16:9'
}
);
// Save images
const savedPaths = await generator.save({ directory: './output' });
console.log('Images saved:', savedPaths);// Modify an existing image
const result = await generator.generate(
'Transform this image to have sunset lighting with warm orange tones',
{
referenceImage: './my-image.png', // Local path
quality: '2K',
numberOfImages: 1
}
);
const savedPaths = await generator.save({ directory: './output' });const result = await generator.generate(
'Convert this photo into a watercolor painting',
{
referenceImage: 'https://example.com/image.jpg', // URL
quality: '1K'
}
);
generator.save({ directory: './output' });new GeminiGenerator({
apiKey: string, // Your Google API key (required)
modelId: string // Model to use (optional, default: 'gemini-3-pro-image-preview')
})new FalGenerator({
apiKey: string, // Your Fal API key (required)
modelId: string // Optional: FalGenerator.MODELS.BANANA_2 or BANANA_PRO_EDIT
})generator.pro() // Switches to the gemini-3-pro-image-preview model
generator.flash() // Switches to the gemini-3.1-flash-image-preview modelBoth methods are chainable and return the generator instance.
Fal generator model methods:
fal.banana2() // fal-ai/nano-banana-2/edit (image editing)
fal.bananaPro() // fal-ai/nano-banana-pro/edit (image editing)
fal.pro() // alias of bananaPro()
fal.flash() // alias of banana2()You can also use chainable methods to add one or multiple reference images before calling generate():
generator.addReference(image, description) // Adds a reference image (path, URL, Buffer)
generator.clearReferences() // Removes all queued reference imagesFor fal (flash and pro), references can be URL, data URI, local file path, or Buffer.
await generator.generate(prompt, options)Parameters:
| Option | Type | Description | Default |
|---|---|---|---|
prompt |
string | Description of what you want to generate | - |
options.referenceImage |
string/Buffer | Reference image (path, URL, Base64, Buffer) | - |
options.numberOfImages |
number | Number of images to generate | 1 |
options.quality |
string | Quality: '1K', '2K', '4K' | - |
options.aspectRatio |
string | Aspect ratio: '1:1', '16:9', '4:3', etc. | - |
options.width |
number | Final output width in pixels (requires height) |
- |
options.height |
number | Final output height in pixels (requires width) |
- |
await generator.save(options)Parameters:
| Option | Type | Description | Default |
|---|---|---|---|
options.directory |
string | Target directory path to save images | '.' |
options.filename |
string | Custom filename (without extension). If not provided, uses hash-based filename | - |
options.extension |
string | File format: 'jpg', 'png', 'webp', 'avif', 'tiff' | 'jpg' |
Examples:
// Save to specific directory with auto-generated filename (jpg by default)
await generator.save({ directory: './output' });
// Save as PNG
await generator.save({ directory: './output', extension: 'png' });
// Save to specific directory with custom filename
await generator.save({ directory: './output', filename: 'my-image' });
// Save as WebP with custom filename
await generator.save({ directory: './output', filename: 'my-image', extension: 'webp' });
// Save to current directory with custom filename
await generator.save({ filename: 'my-image' });
// Save to current directory with auto-generated filename (jpg)
await generator.save();You can request high generation quality and still force an exact final output size directly in generate():
const generator = new GeminiGenerator();
await generator.generate('App icon, flat minimal style', {
quality: '4K', // generation quality (independent)
width: 400,
height: 400
});
// width/height resize is automatically applied on save()
await generator.save({ filename: 'icon-400x400', extension: 'png' });If you also pass aspectRatio, it must match the ratio derived from width/height.
Note:
- When multiple images are generated and a custom filename is provided, they will be saved as
filename_0.jpg,filename_1.jpg, etc. - The method uses Sharp for image conversion, supporting high-quality format conversion
const result = await generator.generate(
'Transform this photo into a Van Gogh style painting with visible brush strokes',
{
referenceImage: './photo.jpg',
quality: '4K'
}
);const result = await generator.generate(
'Change the lighting to dramatic studio lighting with strong shadows',
{
referenceImage: './portrait.png',
quality: '2K'
}
);const result = await generator.generate(
'Add dramatic clouds and enhance colors',
{
referenceImage: './landscape.jpg',
numberOfImages: 3,
quality: '1K'
}
);
// Generates 3 variations of the same modificationimport fs from 'fs';
const imageBuffer = fs.readFileSync('./image.png');
const result = await generator.generate(
'Make this image look cinematic',
{
referenceImage: imageBuffer
}
);GenMix accepts reference images in multiple formats:
- Local file path:
'./image.png' - URL:
'https://example.com/image.jpg' - Data URI:
'data:image/png;base64,iVBORw0KG...' - Buffer:
Buffer.from(...)
Supported image formats: PNG, JPEG, GIF, WEBP
try {
const result = await generator.generate(prompt, options);
if (result.images && result.images.length > 0) {
const paths = generator.save({ directory: './output' });
console.log('Success!', paths);
} else {
console.log('No images generated');
}
} catch (error) {
console.error('Error:', error.message);
// Common errors:
// - 'API Key is required'
// - 'Failed to read reference image file'
// - 'Failed to download reference image from URL'
// - 'Gemini API Error: ...'
}genmix/
βββ generators/
β βββ BaseGenerator.js # Base class with utilities
β βββ GeminiGenerator.js # Gemini API implementation
β βββ FalGenerator.js # Fal Nano Banana 2 implementation
βββ demo/
β βββ example.js # Basic examples
β βββ example-translation.js # Translate image
βββ index.js # Entry point
βββ README.md
-
Clear Prompts: Be specific about what you want
// β Good 'Add dramatic sunset lighting with orange and pink tones in the sky' // β Vague 'Make it better'
-
Appropriate Quality:
1K: Quick tests2K: General use4K: High quality (slower)
-
Image Size: Reference images between 512x512 and 2048x2048 work best
-
Result Caching: Images are automatically saved with unique hash based on the prompt
Install GenMix globally to use it from the command line:
npm install -g genmixIf no API key is available, the CLI asks for it on first use and saves it to:
~/.genmix/config.json
You can set or update it explicitly anytime:
genmix --configAPI key resolution order in CLI:
- Provider-specific environment variable (
GEMINI_API_KEYorFAL_API_KEY) - Saved config (
~/.genmix/config.json) usinggeminiApiKey/apiKeyorfalApiKey - Interactive prompt (then persisted)
# Show help
genmix --help
# Generate from prompt
genmix "A futuristic city with flying cars, cyberpunk style"
# Generate multiple images
genmix "A cozy cabin in winter" -n 2 -q 2K -r 16:9 -m flash
# Use Fal Nano Banana 2 edit (flash) with reference
genmix "Restyle this room with warm sunset mood" --provider fal -m flash --ref "./room.jpg" -n 2 -q 2K -r 16:9
# Use Fal Nano Banana Pro (edit) with reference
genmix "make this scene cinematic" --provider fal -m banana-pro --ref "https://example.com/input.png"--output accepts either:
- a directory path, or
- a full output file path (including filename + extension)
# Save to a directory (auto-generated hash filename)
genmix "Watercolor fox logo" --output ./output
# Save to exact file path and filename
genmix "Watercolor fox logo" --output ./output/logo-fox.pngYou can ask the model for high generation quality (for example 4K) and still force a final exact output size.
When you pass target dimensions, GenMix CLI:
- Derives the generation ratio automatically (for example
400x400->1:1,1920x1080->16:9) - Generates using your selected quality (
1K,2K, or4K) - Resizes the final image to the exact dimensions you requested
# Ask for 4K quality, deliver exact 400x400 output
genmix "app icon, flat minimal style" -q 4K --width 400 --height 400 --output ./output/icon.pngIf you also pass --ratio, it must match the derived ratio from the target size.
Use --ref <path:text> to add reference images with optional guidance text:
# Reference path only
genmix "Restyle this room" --ref ./room.jpg
# Reference path + description
genmix "Restyle this room" --ref "./room.jpg:keep composition and camera angle"
# Multiple references with descriptions
genmix "Create product ad scene" \
--ref "./product.png:use as main subject" \
--ref "./bg.jpg:use as background mood"
# References for fal models (URL, data URI, or local path)
genmix "Edit this image for a magazine look" \
--provider fal -m flash \
--ref "./photo.png"-n, --number <N> Number of images (default: 1)
-q, --quality <1K|2K|4K> Image quality (default: 1K)
-p, --provider <gemini|fal> Provider (default: gemini)
-r, --ratio <ratio> Aspect ratio (default: 1:1 for gemini, auto for fal)
-m, --model <...> gemini: pro|flash (default: flash)
fal: pro|flash (aliases: banana-pro|banana2|2, default: flash)
-o, --output <path> Output directory or full output file path
-f, --format <format> Output format when output is a directory (default: jpg)
--width <px> Final output width in pixels (requires --height)
--height <px> Final output height in pixels (requires --width)
--ref <path[:text]> Reference image (path/URL/data URI); for URL descriptions use URL::description
--no-sharp Save raw model bytes without Sharp conversion (disables resizing)
--config Set/update persisted API key
--help Show help
- Code Examples
- Google Gemini API Documentation
- Fal Nano Banana 2 Edit Documentation
- Fal Nano Banana Pro Edit Documentation
MIT
Contributions are welcome! Please open an issue or pull request.