Skip to main content

AssetLibrary

Generic content asset upload, security inspection, R2 storage, presigned URLs, and image lightbox UI

Status​

KeyValue
Layerfoundation
TierL0
Statuswip
Version0.1.0
PriceFree (free)
CategoryContent

Overview​

AssetLibrary is a foundation plugin for storing and reusing images, uploaded audio, PDFs, and attachments across SaaS/Tenant boundaries. It validates MIME, extension, and file signatures before storage, supports private/public R2 disks, and resolves private assets through presigned URLs. It also provides reusable Blade partials for full-screen image lightbox previews.

Image Lightbox UI​

SaaS screens that need full-size image inspection should use the shared AssetLibrary partial.

Render the lightbox dialog once near the page root. Do not place it inside another <dialog>, because nested dialogs can behave inconsistently across browsers.

@include('asset-library::components.image-lightbox')
<figure class="relative overflow-hidden rounded-md border bg-white">
<img class="max-h-72 w-full object-contain"
src="{{ $imageUrl }}"
alt="{{ $imageTitle }}">

@include('asset-library::components.zoom-button', [
'imageSrc' => $imageUrl,
'imageTitle' => $imageTitle,
])
</figure>

For upload previews where img.src is set by JavaScript, add data-asset-image-lightbox-scope to the wrapper and omit imageSrc.

<div class="relative" data-asset-image-lightbox-scope>
<img data-preview-image alt="Upload preview image">

@include('asset-library::components.zoom-button', [
'label' => 'Open preview image',
])
</div>

The lightbox opens as a full-screen dialog. On mobile, users can use browser-native pinch zoom and scrolling.

Public / Private Policy​

Decide the public/private visibility policy before implementing uploads. If the business model is unclear, the AI should ask the user before implementation. The default is private.

Asset typeRecommended visibility
Files tied to users, customers, permissions, payments, or learning historyprivate
Original uploads, internal review assets, user-specific attachmentsprivate
Files whose image URL itself must be shared externallypublic
SEO/OG, landing, brand, and public content imagespublic

Private presigned URLs expire. Page sharing can work because the application can issue a new URL on each request, but long-lived direct image sharing requires a public/CDN/custom domain URL.

Three Access Patterns​

PatternSecurity meaningSuitable examplesCaution
Public domain URLAnyone who knows the object key can access itscripture.how color meaning images, public content, SEO/OG imagesOnce the URL is shared, access does not expire
Public bucket + random keyBucket listing is unavailable, so the object is hard to find without the URLLow-sensitivity content assets where accidental exposure is acceptableThis is path obscurity, not authorization. If the URL leaks through logs, referer headers, or sharing, it remains accessible
Private bucket + temporary URLAccess is granted through an expiring URL after application-side authorizationUser files, customer materials, payment/learning/personal dataNot suitable for long-lived direct image sharing

For scripture.how, where the content is public learning material and direct image sharing is expected, operating with one public bucket is acceptable. If original user uploads, customer-private materials, or permission-bound assets are added later, do not mix them into the public bucket; use a private bucket or explicit access control.

Demos​


View on Plugin Store: store.codebase.how/plugins/asset-library