> ## Documentation Index
> Fetch the complete documentation index at: https://flex-fields.bjanczak.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Examples target Filament 5. Verify optional dependencies before configuring integrations.
> Upload transfer completion, permanent storage and record acceptance are separate milestones. Native and Spatie image conversions retain the original.

# Use Media OS without a form

> Guide your AI assistant to use FLEX Media OS directly in Laravel services, controllers, commands and jobs, with disk storage or Spatie.

**Media OS can run directly in your PHP application.** A controller, service,
command or job can store files, create image variants and use staging without
rendering `FlexFileUpload` or a Filament form.

The shipped AI skill includes a dedicated `references/media-os.md` guide for this
workflow. Component discovery describes rendered controls; it is not the service
API reference.

## Choose the right entry point

| Requirement | API | Read first |
| - | - | - |
| Store a local file, stream or bytes | `FlexMedia::store()` | [Storage API](https://flex-fields.bjanczak.com/docs/media-os-api.md) |
| Inspect, verify, sign a URL or delete an owned object | `FlexMedia::os()` | [Policies and receipts](https://flex-fields.bjanczak.com/docs/media-os-api.md) |
| Store an original and synchronous variants | `FlexMedia::images()->store()` | [Image conversions](https://flex-fields.bjanczak.com/docs/media-os-images.md) |
| Generate variants in a worker | `FlexMedia::queuedImages()` | [Background processing](https://flex-fields.bjanczak.com/docs/media-os-images.md#background-conversions) |
| Receive a file before its final record is accepted | `FlexMedia::staging()` | [Staging and confirmation](https://flex-fields.bjanczak.com/docs/media-os-lifecycle.md) |
| Store in a Spatie collection | `MediaWrite` with the `spatie` adapter | [Spatie setup and storage](https://flex-fields.bjanczak.com/docs/media-os-spatie.md) |
| Build your own capture interface | Public browser helpers plus the server API | [Browser integration](https://flex-fields.bjanczak.com/docs/media-os-browser.md) |

## Minimal service-level storage

This example uses a trusted, existing local file and a configured private Laravel
disk. It can run inside your application service; it creates no form field.

```php theme={"theme":{"light":"github-light","dark":"github-dark"}}
use Bjanczak\FilamentFlexFields\Support\Media\FlexMedia;
use Bjanczak\FilamentFlexFields\Support\Media\Data\MediaPolicy;
use Bjanczak\FilamentFlexFields\Support\Media\Data\MediaWrite;
use Bjanczak\FilamentFlexFields\Support\Media\Sources\MediaSource;

$receipt = FlexMedia::store(
    MediaSource::path(storage_path('app/imports/contract.pdf'), 'contract.pdf'),
    new MediaWrite(
        disk: 'local',
        directory: 'contracts',
        policy: new MediaPolicy(
            maxBytes: 10 * 1024 * 1024,
            mimeTypes: ['application/pdf'],
            visibility: 'private',
        ),
    ),
);

// Persist the owned reference using your application's model and save flow.
$disk = $receipt->disk;
$path = $receipt->path;
```

Permanent storage inspects the actual content against the policy. Your application
still authorizes the operation and persists its own record reference. The receipt
does not automatically create a gallery row or grant permission to read the file.

For a normal HTTP request, validate the `UploadedFile` and use its valid local
path with `MediaSource::path()`. `MediaSource::upload()` specifically accepts a
Livewire temporary upload. See the [HTTP request example](https://flex-fields.bjanczak.com/docs/media-os-api.md#http-request-upload).

## Give the assistant a complete task

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
Use the installed FLEX Media OS directly in our Laravel import service, without
adding a Filament field or browser interface. Read the standalone Media OS skill
reference and storage API first.

Import an authorized local PDF to our configured private disk. Apply MIME and
size policy, persist the returned disk/path and required metadata in our existing
document model, and provide an authorized expiring URL where supported.
Keep our record policies. Explain the database-versus-storage failure handling.
Verify accepted and rejected content, persisted references and private URL failure.
```

## Images and Spatie

For disk-backed images, define named `ImageConversion` variants and choose
synchronous or queued processing. Retain the returned bundle/receipt information
needed by your application. A queued variant may not exist yet; configure a
fallback and a worker with supported encoders.

For Spatie, use the adapter with a persisted `HasMedia` model and `SpatieOptions`.
Keep Spatie's collections, conversions and queue configuration. An extra table
for every conversion is not normally required. The [Spatie guide](https://flex-fields.bjanczak.com/docs/media-os-spatie.md)
shows direct service storage as well as field integration.

## When storage happens before the record save

Use staging when the workflow needs it. Stage, promote and confirm are distinct
operations; confirmation belongs after the durable record reference commits.
A database rollback does not roll back disk/S3 writes. Derive lease ownership
from trusted server context and follow the documented recovery contract for
ambiguous outcomes.

Read [temporary uploads and recovery](https://flex-fields.bjanczak.com/docs/media-os-lifecycle.md) before implementing
this flow. Do not copy an upload field's completion hook into a service that does
not mount that field.

Pure server-side storage needs no browser asset initialization. A custom capture
interface has a separate browser lifecycle and still needs server validation.

## Existing related gallery tables

For ordinary same-connection `hasMany` galleries, inspect `HasManyMediaCollection`,
`MediaRelationColumns` and `MediaRelationSnapshot`. The
[related gallery guide](https://flex-fields.bjanczak.com/docs/media-os-relations.md) covers explicit model columns,
authorization and new-file admission, unique disk/path ownership, locked revision
baselines, transaction/rollback, order and detach. `sync()` maps originals into
SQL; it does not upload files, accept stages, convert or delete physical objects.
Keep the mounted field's native/custom commit-aware acceptance contract.
Spatie remains a separate integration. Do not invent a disk uploader
`relationship()` option or treat a revision as authorization.

## Check the deployment configuration

Ask the assistant to run `fff:media:doctor` with the profile matching the actual
workflow. Use `--queued` with the selected connection, queue and job timeout for
native background conversions, and `--custom-encoder` when the application supplies
its own encoder. The [diagnostic report](https://flex-fields.bjanczak.com/docs/media-os-diagnostics.md) does not execute
extension factories or modify storage. Treat `unverified` findings as checks still
required; a valid configuration is not proof of a running worker or a successful
upload/save/reopen workflow.

For explicitly approved infrastructure checks, `fff:media:probe --write` can
exercise a named `--disk`, named `--lock-store` and requested `--format` values.
It creates synthetic diagnostic data and invokes the selected backend adapters.
Do not run it as a read-only inspection or select production targets without the
operator's authorization. Its [active probe report](https://flex-fields.bjanczak.com/docs/media-os-diagnostics.md#active-probes)
states what was exercised, any failed cleanup and the remaining deployment checks.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.