Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Assetpicker Laravel Package

netresearch/assetpicker

Netresearch AssetPicker is a TYPO3 CMS extension that adds a backend asset picker for selecting files from the File Abstraction Layer. Editors can browse and choose assets for TCA fields via a wizard, making file selection in records and content simpler and more consistent.

Deep Wiki
Context7

Getting Started

  1. Install the frontend package alongside your Laravel app's existing toolchain:

    npm install netresearch/assetpicker
    

    It is a Vue 3 component, not a Laravel package — there is no service provider or Composer entry. Treat it as a UI dependency of your Vite build.

  2. Read the adapter contract first. Before writing any integration code, open the package's adapter interface (usually src/adapters/ and an AdapterInterface or similar type definition). Every workflow below hinges on it: the picker UI is generic, and all provider behavior (listing, searching, uploading, URL resolution) is delegated to an adapter. If the README is thin, the shipped GitHub/Google Drive adapters are your best documentation — they are working reference implementations.

  3. Start with the bundled GitHub adapter in a throwaway route. Mount the picker on a plain Blade page with a hardcoded test repo. This validates your Vite config, component import, CSS, and event wiring before you introduce auth complexity:

    <div id="assetpicker"></div>
    @vite(['resources/js/assetpicker.js'])
    
  4. First real use case: a media/image field in an admin form. Replace a plain <input type="file"> with the picker so editors browse a Drive folder or GitHub repo and select an existing asset. The picker emits a selection event; you store the returned URL/path string in a normal Eloquent column. This is the lowest-risk, highest-value integration and doesn't require upload support.

Implementation Patterns

Token brokering through Laravel controllers. Never ship provider credentials in your JS bundle. The picker's adapters that hit remote APIs need tokens; issue short-lived, scoped tokens from a Laravel endpoint and pass them into the component as props. For GitHub, a fine-grained PAT or a GitHub App installation token minted server-side. For Google Drive, this is non-negotiable — you need an OAuth flow, and the standard shape is: Laravel handles the redirect/callback, stores the refresh token encrypted per user, and exposes a GET /api/drive-token route that returns a fresh access token to the frontend just before mounting.

Write a thin custom adapter rather than fighting a bundled one. The pluggable layer exists precisely so you can wrap your own storage. A typical Laravel-side adapter implements list, search, and getUrl against your own /api/assets endpoints, returning the package's normalized file shape. Benefits: authorization lives in Laravel policies, you get pagination and filtering for free via Eloquent, and you're not coupling the picker to a third-party API's quirks. Use the bundled providers only when the assets genuinely live in those systems.

Mounting in Inertia vs. Blade. In Inertia, render the picker inside a page component and pass adapter config through page props — this is the cleanest path and keeps state in Vue. In Blade, mount with createApp on a dedicated element and pass config via a data- attribute containing @json($config); keep the mounting script tiny and isolated so it doesn't collide with any other Vue instance on the page.

Handle selection as a two-step: pick, then persist. Treat the picker as returning a descriptor ({ id, url, name, mime, size }), not a finished upload. On the select callback, POST that descriptor to a Laravel endpoint that validates it (allowlist of hosts/MIME types) and writes your assets record. This keeps the picker stateless and makes the same component reusable for "attach existing" and "replace asset" flows.

Multi-tenant config injection. Because config is just props, you can vary it per user or team: each tenant's Drive folder ID, each repo's branch, or a different adapter entirely. Resolve this in a Laravel controller and hand it down, rather than branching inside Vue.

Testing without the network. Build a stub adapter backed by an in-memory array of fixtures and register it in your test environment. You get deterministic component tests (Vitest/Cypress) and can exercise selection and error states without OAuth tokens or rate limits.

Gotchas and Tips

  • CORS will bite you before anything else. Browser-side calls to GitHub and Google APIs from localhost:5173 or your app domain need the right origins and, for Drive, the right OAuth consent scopes. If listings come back empty, check the Network tab for preflight failures before suspecting the adapter.
  • Google Drive access tokens expire in ~1 hour. Do not cache them in the frontend. Fetch a fresh one on mount and again on 401 — build a retry-once interceptor or editors will hit silent failures mid-session.
  • Signed/expiring asset URLs. GitHub raw URLs and Drive download links can be short-lived or require auth headers. If thumbnails work but the final <img src> breaks for end users, you're storing a protected URL. Download through a Laravel proxy route and store your own stable path instead.
  • Pin the version. At ~22 stars this is a small, actively-iterating package; the adapter interface and event payloads may shift between minors. Commit a lockfile entry and re-read the changelog on upgrade. Add a thin wrapper component of your own so a breaking change touches one file, not fifty.
  • The adapter interface is your extension point, not the UI. Attempting to restyle or override internals is fragile; customizing behavior by swapping the adapter is supported and stable. If you need slot/component overrides, verify they're documented before relying on them.
  • Debounce search yourself. If the adapter's search maps to a Laravel endpoint, the picker may call it on every keystroke. Guard with a debounce and cancel in-flight requests, or add a minimum-length check server-side.
  • Debugging checklist, in order: (1) is the adapter receiving the config object you think it is — console.log at construction; (2) are requests leaving the browser at all (Network tab) or failing before dispatch; (3) is the response shape normalized to what the picker expects — a 200 with an unexpected array shape renders as an empty list with no error; (4) is the component emitting select before your listener is attached (mount race in Blade). Add an explicit error/empty state to the picker wrapper so adapter failures surface instead of looking like "no files."
  • Vite/CSS: the component ships styles; make sure your @vite entry imports them and that Tailwind (if used) isn't purging classes inside node_modules — configure content to include the package path or you'll get an unstyled grid.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin