Slice · AI prompt
ONE button opens a dialog: gallery (colours/gradients/textures), upload, paste URL, Unsplash search. Set any image — wallpaper, cover, profile header. Props-driven, no backend lock-in.
# Install `image-picker` — Image Picker — one-button image/wallpaper chooser (gallery · upload · link · Unsplash · reposition)
> ONE button opens a dialog: gallery (colours/gradients/textures), upload, paste URL, Unsplash search. Set any image — wallpaper, cover, profile header. Props-driven, no backend lock-in.
📚 Knowledge base : https://resource.rahmanef.com/llms.txt
📦 Slice detail : https://resource.rahmanef.com/slices/image-picker
🧠 JSON catalog : https://resource.rahmanef.com/api/knowledge?slice=image-picker
🔗 Source : https://github.com/rahmanef63/resource-site/tree/main/frontend/slices/image-picker
## 1. Install
```bash
npx rahman-resources add image-picker
# alias: npx rr add image-picker
```
The CLI copies `frontend/slices/image-picker/` into your project + augments `.env.example` + installs npm deps automatically. Run it from your project root.
## 2. What it ships
- shadcn primitives: `dialog`, `button`, `input`
- env vars:
- `UNSPLASH_ACCESS_KEY` (server) — Server-side only (e.g. on the /api/unsplash route). Without it the Unsplash tab falls back to the curated set.
## 3. Wire it up
Run `npx rr add image-picker`. The headline component is `<ImagePickerButton label="Change image" onChange={(img)=>save(img)} onUpload={…} searchUnsplash={…} />` — ONE button that opens the 4-tab dialog (gallery / upload / link / Unsplash). For a reposition-able cover/hero band use `<ImageBanner image={value} onChange={save} resolvedUrl={…} onUpload={…} searchUnsplash={…} />` (also passable to notion-shell's `<NotionPage coverSlot={…} />`). Inject the backend: `onUpload` = the `files` slice's useFileUpload().upload (returns a FileRef); resolve upload images for display with `resolvedUrl` = files useFileUrl(parseFileRef(imageRef(parseImage(value))).storageId). `searchUnsplash` = `unsplashSearchVia('/api/unsplash')` — add a server route that proxies api.unsplash.com with UNSPLASH_ACCESS_KEY (never expose the key client-side). Ships a curated Unsplash + gallery fallback so it works with zero wiring. ImageValue = { type, value, positionY?, metadata? }; parseImage handles legacy string values.
## Rules of engagement
- shadcn-only UI primitives. No raw `<button>` / `<dialog>` / native date or file inputs.
- 200-line hard cap per source file (extract neighbours when over).
- All Convex queries hit an index (`.withIndex(...)`); never bare `.collect()`.
- Public mutations/queries declare `args:` validators + authz.
- Full ruleset: https://resource.rahmanef.com/best-practice
The agent will fetch /llms.txt for the full ruleset and use /api/knowledge for the JSON catalog.