# joelfrens/fts architecture

> Architecture diagram of the GitHub repository joelfrens/fts, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-29). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/joelfrens/fts
- Repository: https://github.com/joelfrens/fts

## Overview

FTS is a Laravel image-upload and storage application with local and Azure backends. A browser user submits an image through the Vue upload UI to the API; the route dispatches to the controller, which delegates processing, storage, and audit-row creation to the upload service. Image processing validates and resizes before storage; driver selection is bound by the service provider. The README documents these flows and capabilities; edges for unsampled subsystems are omitted where their runtime wiring is not evidenced.

Main entry points: [`app/Services/ImageUploadService.php`](https://github.com/joelfrens/fts/blob/main/app/Services/ImageUploadService.php) (Upload orchestration), [`app/Contracts/ImageStorageInterface.php`](https://github.com/joelfrens/fts/blob/main/app/Contracts/ImageStorageInterface.php) (Storage contract), [`app/Data/StoredImage.php`](https://github.com/joelfrens/fts/blob/main/app/Data/StoredImage.php) (Stored image DTO), [`app/Providers/AppServiceProvider.php`](https://github.com/joelfrens/fts/blob/main/app/Providers/AppServiceProvider.php) (Driver binding)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_client["Upload client"]
  node_upload_ui["Upload UI<br/>[ImageUpload.vue]"]
end

subgraph group_http["HTTP entry"]
  node_api_route["Images API route<br/>[api.php]"]
  node_app_boot["Laravel routing<br/>[app.php]"]
  node_controller["Image controller"]
  node_request["Upload validation"]
  node_web_middleware["Inertia middleware"]
  node_user_model["User model<br/>[User.php]"]
  node_user_factory["User factory<br/>[UserFactory.php]"]
end

subgraph group_image["Image workflow"]
  node_upload_service["Upload orchestration"]
  node_processor["Image processor<br/>[ImageProcessor.php]"]
  node_processing_options["Resize options"]
  node_processed_image["Processed image DTO<br/>[ProcessedImage.php]"]
  node_uploaded_image["Upload result DTO<br/>[UploadedImage.php]"]
  node_image_record["Image audit model<br/>[Image.php]"]
end

subgraph group_storage["Storage backends"]
  node_storage_port["Storage contract"]
  node_stored_image["Stored image DTO<br/>[StoredImage.php]"]
  node_driver_enum["Storage driver enum<br/>[StorageDriver.php]"]
  node_provider["Driver binding"]
  node_local_storage["Local storage"]
  node_azure_storage["Azure storage"]
end

node_user(("Browser user"))
node_azure_blob[("Azure Blob Storage")]
node_images_db[("Images database")]

node_user -->|"submits image"| node_upload_ui
node_upload_ui -->|"posts upload"| node_api_route
node_app_boot -->|"loads route"| node_api_route
node_api_route -->|"dispatches to"| node_controller
node_controller -->|"validates with"| node_request
node_controller -->|"delegates upload"| node_upload_service
node_upload_service -->|"processes with"| node_processor
node_upload_service -->|"sets limits"| node_processing_options
node_processor -->|"returns image"| node_processed_image
node_upload_service -->|"stores through"| node_storage_port
node_storage_port -->|"returns metadata"| node_stored_image
node_upload_service -->|"creates audit row"| node_image_record
node_upload_service -->|"returns result"| node_uploaded_image
node_upload_service -->|"gets image URL"| node_storage_port
node_provider -->|"binds contract"| node_storage_port
node_provider -->|"selects driver"| node_local_storage
node_provider -->|"selects driver"| node_azure_storage
node_local_storage -->|"returns metadata"| node_stored_image
node_azure_storage -->|"returns metadata"| node_stored_image
node_azure_storage -->|"uploads blob"| node_azure_blob
node_image_record -->|"casts driver"| node_driver_enum
node_stored_image -->|"records driver"| node_driver_enum
node_web_middleware -->|"registered in"| node_app_boot
node_user_factory -->|"creates users"| node_user_model

click node_upload_ui "https://github.com/joelfrens/fts/blob/main/resources/js/pages/ImageUpload.vue"
click node_api_route "https://github.com/joelfrens/fts/blob/main/routes/api.php"
click node_app_boot "https://github.com/joelfrens/fts/blob/main/bootstrap/app.php"
click node_controller "https://github.com/joelfrens/fts/blob/main/app/Http/Controllers/ImageController.php"
click node_request "https://github.com/joelfrens/fts/blob/main/app/Http/Requests/StoreImageRequest.php"
click node_upload_service "https://github.com/joelfrens/fts/blob/main/app/Services/ImageUploadService.php"
click node_processor "https://github.com/joelfrens/fts/blob/main/app/Services/ImageProcessor.php"
click node_processing_options "https://github.com/joelfrens/fts/blob/main/app/Data/ImageProcessingOptions.php"
click node_processed_image "https://github.com/joelfrens/fts/blob/main/app/Data/ProcessedImage.php"
click node_uploaded_image "https://github.com/joelfrens/fts/blob/main/app/Data/UploadedImage.php"
click node_image_record "https://github.com/joelfrens/fts/blob/main/app/Models/Image.php"
click node_storage_port "https://github.com/joelfrens/fts/blob/main/app/Contracts/ImageStorageInterface.php"
click node_stored_image "https://github.com/joelfrens/fts/blob/main/app/Data/StoredImage.php"
click node_driver_enum "https://github.com/joelfrens/fts/blob/main/app/Enums/StorageDriver.php"
click node_provider "https://github.com/joelfrens/fts/blob/main/app/Providers/AppServiceProvider.php"
click node_local_storage "https://github.com/joelfrens/fts/blob/main/app/Services/Storage/LocalImageStorage.php"
click node_azure_storage "https://github.com/joelfrens/fts/blob/main/app/Services/Storage/AzureImageStorage.php"
click node_web_middleware "https://github.com/joelfrens/fts/blob/main/app/Http/Middleware/HandleInertiaRequests.php"
click node_user_model "https://github.com/joelfrens/fts/blob/main/app/Models/User.php"
click node_user_factory "https://github.com/joelfrens/fts/blob/main/database/factories/UserFactory.php"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_upload_ui,node_user toneBlue
class node_api_route,node_app_boot,node_controller,node_request,node_web_middleware,node_user_model,node_user_factory,node_azure_blob,node_images_db toneAmber
class node_upload_service,node_processor,node_processing_options,node_processed_image,node_uploaded_image,node_image_record toneMint
class node_storage_port,node_stored_image,node_driver_enum,node_provider,node_local_storage,node_azure_storage toneRose
```

## Components

### Upload client

- [Upload UI](https://github.com/joelfrens/fts/blob/main/resources/js/pages/ImageUpload.vue): `resources/js/pages/ImageUpload.vue`

### HTTP entry

- [Images API route](https://github.com/joelfrens/fts/blob/main/routes/api.php): `routes/api.php`
- [Laravel routing](https://github.com/joelfrens/fts/blob/main/bootstrap/app.php): `bootstrap/app.php`
- [Image controller](https://github.com/joelfrens/fts/blob/main/app/Http/Controllers/ImageController.php): `app/Http/Controllers/ImageController.php`
- [Upload validation](https://github.com/joelfrens/fts/blob/main/app/Http/Requests/StoreImageRequest.php): `app/Http/Requests/StoreImageRequest.php`
- [Inertia middleware](https://github.com/joelfrens/fts/blob/main/app/Http/Middleware/HandleInertiaRequests.php): `app/Http/Middleware/HandleInertiaRequests.php`
- [User model](https://github.com/joelfrens/fts/blob/main/app/Models/User.php): `app/Models/User.php`
- [User factory](https://github.com/joelfrens/fts/blob/main/database/factories/UserFactory.php): `database/factories/UserFactory.php`

### Image workflow

- [Upload orchestration](https://github.com/joelfrens/fts/blob/main/app/Services/ImageUploadService.php): `app/Services/ImageUploadService.php`
- [Image processor](https://github.com/joelfrens/fts/blob/main/app/Services/ImageProcessor.php): `app/Services/ImageProcessor.php`
- [Resize options](https://github.com/joelfrens/fts/blob/main/app/Data/ImageProcessingOptions.php): `app/Data/ImageProcessingOptions.php`
- [Processed image DTO](https://github.com/joelfrens/fts/blob/main/app/Data/ProcessedImage.php): `app/Data/ProcessedImage.php`
- [Upload result DTO](https://github.com/joelfrens/fts/blob/main/app/Data/UploadedImage.php): `app/Data/UploadedImage.php`
- [Image audit model](https://github.com/joelfrens/fts/blob/main/app/Models/Image.php): `app/Models/Image.php`

### Storage backends

- [Storage contract](https://github.com/joelfrens/fts/blob/main/app/Contracts/ImageStorageInterface.php): `app/Contracts/ImageStorageInterface.php`
- [Stored image DTO](https://github.com/joelfrens/fts/blob/main/app/Data/StoredImage.php): `app/Data/StoredImage.php`
- [Storage driver enum](https://github.com/joelfrens/fts/blob/main/app/Enums/StorageDriver.php): `app/Enums/StorageDriver.php`
- [Driver binding](https://github.com/joelfrens/fts/blob/main/app/Providers/AppServiceProvider.php): `app/Providers/AppServiceProvider.php`
- [Local storage](https://github.com/joelfrens/fts/blob/main/app/Services/Storage/LocalImageStorage.php): `app/Services/Storage/LocalImageStorage.php`
- [Azure storage](https://github.com/joelfrens/fts/blob/main/app/Services/Storage/AzureImageStorage.php): `app/Services/Storage/AzureImageStorage.php`

### Other components

- **Browser user**
- **Azure Blob Storage**
- **Images database**

## Connections

- Browser user → Upload UI: submits image (evidence: `README.md`)
- Upload UI → Images API route: posts upload (evidence: `README.md`)
- Laravel routing → Images API route: loads route (evidence: `bootstrap/app.php`)
- Images API route → Image controller: dispatches to (evidence: `routes/api.php`)
- Image controller → Upload validation: validates with (evidence: `app/Http/Controllers/ImageController.php`)
- Image controller → Upload orchestration: delegates upload (evidence: `app/Http/Controllers/ImageController.php`)
- Upload orchestration → Image processor: processes with (evidence: `app/Services/ImageUploadService.php`)
- Upload orchestration → Resize options: sets limits (evidence: `app/Services/ImageUploadService.php`)
- Image processor → Processed image DTO: returns image (evidence: `app/Services/ImageProcessor.php`)
- Upload orchestration → Storage contract: stores through (evidence: `app/Services/ImageUploadService.php`)
- Storage contract → Stored image DTO: returns metadata (evidence: `app/Contracts/ImageStorageInterface.php`)
- Upload orchestration → Image audit model: creates audit row (evidence: `README.md`)
- Upload orchestration → Upload result DTO: returns result (evidence: `app/Services/ImageUploadService.php`)
- Upload orchestration → Storage contract: gets image URL (evidence: `app/Services/ImageUploadService.php`)
- Driver binding → Storage contract: binds contract (evidence: `app/Providers/AppServiceProvider.php`)
- Driver binding → Local storage: selects driver (evidence: `app/Providers/AppServiceProvider.php`)
- Driver binding → Azure storage: selects driver (evidence: `app/Providers/AppServiceProvider.php`)
- Local storage → Stored image DTO: returns metadata (evidence: `app/Services/Storage/LocalImageStorage.php`)
- Azure storage → Stored image DTO: returns metadata (evidence: `app/Services/Storage/AzureImageStorage.php`)
- Azure storage → Azure Blob Storage: uploads blob (evidence: `app/Services/Storage/AzureImageStorage.php`)
- Image audit model → Storage driver enum: casts driver (evidence: `app/Models/Image.php`)
- Stored image DTO → Storage driver enum: records driver (evidence: `app/Data/StoredImage.php`)
- Inertia middleware → Laravel routing: registered in (evidence: `bootstrap/app.php`)
- User factory → User model: creates users (evidence: `database/factories/UserFactory.php`)
