Documentation
MatteConnecting your apps
Updated
Matte is a provider: your other applications send it images. A Laravel app connects through the artisan-build/matte-client package, and Scalpels can do the wiring for any Laravel app you host on Laravel Cloud or Laravel Forge. Anything that is not a Laravel app calls the API directly; the client is a convenience, never a requirement.
Attach an app through Scalpels
Attaching is described in full in Attach to an existing app, including the preparation the Matte deployment needs and what each refusal means. For Matte specifically, attaching:
- mints a credential for that app on your Matte instance;
- writes
MATTE_URL(the Matte environment's base URL) andMATTE_TOKEN(the credential) into the app's Cloud environment or Forge.env, along withBFC_CLIENT_IDENTITY, the id of the connection Scalpels recorded; - opens a draft pull request on the app's repository, on a branch named
scalpels/connect-matte, that addsartisan-build/matte-clienttocomposer.jsonand the two variable names to.env.example, with the token left blank.
MATTE_URL is the base URL only. The client appends /v1/remove and /v1/jobs/... itself.
Scalpels writes no other Matte settings. Every other client setting has a working default. The pull request touches no .gitignore, because the client writes nothing into your repository.
Scalpels cannot regenerate composer.lock. Check out the branch, run the composer update command shown in the pull request, commit the lock file, then review, merge and deploy. Scalpels never merges it for you.
You do not need to run php artisan matte:install. That command prompts for a URL and a token and writes them to .env, which is exactly what attaching has already done.
Use the client
Once the package is installed and the two values are set, call Matte through the facade:
use ArtisanBuild\MatteClient\Facades\Matte;
use ArtisanBuild\MatteClient\Jobs\AwaitRemovalJob;
// Submit and return straight away with a handle.
$handle = Matte::remove($request->file('photo'), ['mode' => 'grabcut', 'preset' => 'quality']);
// Watch the job on your own queue. Fires MatteRemovalCompleted when it finishes.
AwaitRemovalJob::dispatch($handle->id());
// Or block until it is done and take the PNG bytes.
$png = $handle->result();
// Or, for a small image, convert inside this request.
$png = Matte::removeSync($smallImage);
The image can be a file path, raw image bytes, an SplFileInfo or an UploadedFile. Options are the same as the API's: mode, preset, model, edge_mode, iterations and margin.
The handle
Matte::remove() returns a JobHandle:
id()returns the job id.status()asks the server for the current status.wait($timeout)polls until the job isdone, and throws if it fails or the timeout passes. Without an argument it usesMATTE_POLL_TIMEOUT.result()waits, then returns the PNG bytes.
Matte::status($jobId) and Matte::result($jobId) do the same by job id.
wait() sleeps between polls, so calling it inside a web request or a queue job holds that process for as long as the conversion takes.
The completion event
AwaitRemovalJob runs on your app's own queue. It polls the job and then dispatches ArtisanBuild\MatteClient\Events\MatteRemovalCompleted, whose public fields are jobId, status, path and error. Listen for that event to carry on with your own work.
- If
MATTE_STORE_DISKis set, the job saves the PNG tomatte/<job-id>.pngon that disk and puts that path inpath. - If polling or the download throws, the job does not rethrow. It dispatches the event with a
failedstatus and the error message instead. - When the event reports
done, you can always fetch the bytes again withMatte::result($event->jobId).
Errors
The client throws ArtisanBuild\MatteClient\Exceptions\MatteException when MATTE_URL or MATTE_TOKEN is missing, when the image is not a supported type, when a job fails or times out, and when the server returns an unexpected status. The client does not retry on its own; decide retry behaviour in your app.
Verify the connection
Run one synchronous conversion in the connected app with a real image:
php artisan tinker --execute='$png = \ArtisanBuild\MatteClient\Facades\Matte::removeSync("/absolute/path/to/input.jpg"); file_put_contents(storage_path("app/matte-verify.png"), $png); dump(str_starts_with($png, "\x89PNG\r\n\x1a\n"), strlen($png));'
A working connection prints true followed by a positive byte count and writes storage/app/matte-verify.png. It uses the configured URL and credential without printing either.
A 401 here means the app is not holding a credential the Matte instance recognises. See Troubleshooting.
Apps Scalpels cannot attach
For a Laravel app hosted somewhere other than Laravel Cloud or Forge, mint a credential on the Matte instance as described in Using the API, then in the app run:
composer require artisan-build/matte-client
php artisan matte:install
matte:install prompts for the server URL and the credential, writes them to .env as MATTE_URL and MATTE_TOKEN, and publishes the client config. Run it in a terminal you control, because it asks for a secret.