noxsi / laravel-gemininano
A Repo / SDK for Gemini Nano
Installs: 2
Dependents: 0
Suggesters: 0
Security: 0
Stars: 1
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/noxsi/laravel-gemininano
Requires
- php: ^8.4.0
- illuminate/filesystem: ^12.41
- illuminate/http: ^12.41
- illuminate/support: ^12.41
Requires (Dev)
- laravel/pint: ^1.24.0
- orchestra/testbench: ^10.8
- peckphp/peck: ^0.1.3
- pestphp/pest: ^4.1
- pestphp/pest-plugin-type-coverage: ^4.0
- phpstan/phpstan: ^2.1.26
- phpunit/phpunit: ^12.4.4
- rector/rector: ^2.1.7
- symfony/var-dumper: ^7.3.3
README
GeminiNano Laravel is an elegant Laravel SDK for generating images with Google Gemini (e.g. gemini-2.5-flash-image).
It wraps the official Gemini REST API in a clean, resource-based, Laravel-friendly API and can automatically:
- return Base64 image data, or
- store images on your Laravel filesystem and return a public URL – all controlled via config.
Under the hood it calls:
POST https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContentwith a text prompt and extracts the inline base64 image data.
✨ Features
- Modern architecture – clean
Client::factory()->make()API - Resource-based – separate
images()resource for image generation - Laravel integration – service provider + facade out of the box
- Config-driven storage
- store images via Laravel’s filesystem and return URLs
- or return raw Base64 directly (for APIs, tests, etc.)
- Type-safe responses with dedicated response classes
- Framework-first DX – built for Laravel 10/11/12 and PHP 8.2+
📦 Installation
Install the package via Composer:
composer require noxsi/laravel-gemininano
For local development using a path repository, point your Laravel app’s
composer.jsonto your package directory and then run the command above.
⚙️ Configuration
Publish the config file:
php artisan vendor:publish --provider="Noxsi\GeminiNano\GeminiNanoServiceProvider" --tag="config"
This will create config/gemininano.php.
.env
Add your Gemini API configuration:
GEMINI_NANO_URL=https://generativelanguage.googleapis.com GEMINI_NANO_KEY=your-gemini-api-key GEMINI_NANO_MODEL=gemini-2.5-flash-image GEMINI_NANO_TIMEOUT=60 # Image handling GEMINI_NANO_STORE=true # true = store in filesystem, false = return base64 GEMINI_NANO_DISK=public # Laravel filesystem disk GEMINI_NANO_PATH=gemininano # directory inside the disk
Config file overview
return [ 'base_url' => env('GEMINI_NANO_URL', 'https://generativelanguage.googleapis.com'), 'api_key' => env('GEMINI_NANO_KEY'), 'model' => env('GEMINI_NANO_MODEL', 'gemini-2.5-flash-image'), 'timeout' => (int) env('GEMINI_NANO_TIMEOUT', 60), 'store' => (bool) env('GEMINI_NANO_STORE', true), 'disk' => env('GEMINI_NANO_DISK', 'public'), 'path' => env('GEMINI_NANO_PATH', 'gemininano'), ];
🚀 Usage
You can use the package either via the client or the facade.
1. Basic usage with the Facade
use Noxsi\GeminiNano\Facades\GeminiNano; // Facade alias // Generate an image from a text prompt $response = GeminiNano::images()->generate( 'Create a picture of a nano banana dish in a fancy restaurant with a Gemini theme' ); // Depending on config: // - GEMINI_NANO_STORE=true -> result() returns a URL (stored via filesystem) // - GEMINI_NANO_STORE=false -> result() returns a base64 string $result = $response->result(); return response()->json([ 'image' => $result, ]);
2. Using the Client directly (DI-friendly)
use Noxsi\GeminiNano\Client; class BananaController { public function __construct( private Client $gemini, ) {} public function __invoke() { $response = $this->gemini ->images() ->generate('A futuristic nano banana in a Gemini-themed lab'); return [ 'image' => $response->result(), ]; } }
🧠 How the image pipeline works
When you call:
$response = GeminiNano::images()->generate('Your prompt here');
the package:
-
Builds a request body compatible with the official Gemini API:
{ "contents": [ { "parts": [ { "text": "Your prompt here" } ] } ] } -
Sends a
POSTrequest to:https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContentwith headers:
x-goog-api-key: <your-api-key>Content-Type: application/json
-
Extracts the base64-encoded image data from the response:
candidates[0].content.parts[*].inlineData.data- (also supports snake_case
inline_data.datafor safety)
-
Wraps everything in a
GenerateResponseobject. -
When you call
->result():-
If
config('gemininano.store') === true
→ the package decodes the base64 string, stores it as a.pngviaStorage::disk(...), and returns the public URL. -
If
config('gemininano.store') === false
→ it simply returns the raw base64 string.
-
You can always access the raw data:
$base64 = $response->base64(); // raw base64 image data $raw = $response->raw(); // full decoded Gemini JSON response
🎛 Advanced usage
Passing extra options to Gemini
You can pass additional options like generationConfig, safetySettings, etc. They are merged into the root payload:
$options = [ 'generationConfig' => [ 'temperature' => 0.7, ], 'safetySettings' => [ // ... ], ]; $response = GeminiNano::images()->generate( 'A neon-lit banana robot in a Gemini-branded bar', options: $options, ); $image = $response->result();
Using an input image (multimodal / inline_data)
You can optionally send an input image along with your text prompt.
Internally this builds a payload like:
{
"contents": [
{
"parts": [
{
"inline_data": {
"mime_type": "image/jpeg",
"data": "BASE64_ENCODED_IMAGE"
}
},
{
"text": "Caption this image."
}
]
}
]
}
Example:
use Noxsi\GeminiNano\Facades\GeminiNano; $imagePath = storage_path('app/public/example.jpg'); $response = GeminiNano::images()->generate( prompt: 'Caption this image.', imagePath: $imagePath, imageMimeType: 'image/jpeg', // optional, will be auto-detected if null ); $result = $response->result(); // URL or base64 depending on config
Note:
imagePathmust point to a readable image file. The package will base64-encode the file and send it asinline_datato the Gemini API.
Returning base64 for an API endpoint
For API scenarios where you don’t want to store anything:
GEMINI_NANO_STORE=false
Then in your controller:
$response = GeminiNano::images()->generate('Minimalist banana icon, flat design'); return response()->json([ 'image_base64' => $response->result(), // now base64 ]);
🧪 Testing
If you are testing within your Laravel app that uses the package, you can mock the HTTP layer as usual:
use Illuminate\Support\Facades\Http; use Noxsi\GeminiNano\Facades\GeminiNano; test('it generates an image via gemini nano', function () { Http::fake([ 'https://generativelanguage.googleapis.com/*' => Http::response([ 'candidates' => [ [ 'content' => [ 'parts' => [ [ 'inlineData' => [ 'data' => base64_encode('dummy-image-binary'), ], ], ], ], ], ], ], 200), ]); $response = GeminiNano::images()->generate('Test prompt'); expect($response->base64())->toBe(base64_encode('dummy-image-binary')); });
If you’re testing the package itself, you can use Pest; the package is designed to run in a standard Laravel test environment.
🧱 Requirements
- PHP 8.2+
- Laravel 10.x, 11.x, 12.x
ext-mbstringext-json- A valid Google Gemini API key
🔧 Local development (using a path repository)
If you’re developing this package locally, you can hook it into a test Laravel application via a path repository:
In your Laravel app’s composer.json:
"repositories": [ { "type": "path", "url": "../laravel-gemininano", "options": { "symlink": true } } ]
Then:
composer require noxsi/laravel-gemininano:*@dev
Any changes you make in the package directory will be reflected in your Laravel app (after composer dump-autoload when adding/removing classes).
📜 Changelog
All notable changes to this package will be documented in the CHANGELOG.md file.
🤝 Contributing
Pull requests are welcome!
If you plan something bigger (new resources, breaking changes, etc.), open an issue first to discuss your idea.
Steps:
- Fork the repo
- Create your feature branch:
git checkout -b feature/my-awesome-feature - Run tests & formatter:
composer test/composer lint - Commit your changes and open a PR
📄 License
This package is open-sourced software licensed under the MIT license.