A responsive photo search & discovery app built with Vue 3, Vuetify, and the Unsplash API.
- Search thousands of Unsplash photos, with live (debounced) search-as-you-type
- Browse a default feed sorted by Latest or Popular
- Filters — orientation (landscape / portrait / square) and color, while searching
- Masonry grid layout, responsive from mobile to desktop
- Lightbox viewer with keyboard navigation (arrow keys, Esc), photographer attribution, and description
- Favorites — save photos locally (per-browser, via
localStorage) - Download button that follows the Unsplash API's required download-tracking flow
- Dark / light theme toggle, persisted across visits
- Infinite scroll with a "Load more" fallback
- Friendly error and empty states (including Unsplash rate-limit messaging)
npm install
cp .env.example .envThen edit .env and add your own Unsplash Access Key:
-
Go to https://unsplash.com/oauth/applications and create an application (or use an existing one).
-
Copy its Access Key.
-
Paste it into
.env:VITE_PHOTO_LIBRARY=your_access_key_here
.env is git-ignored — never commit your real key. The demo Unsplash tier is
rate-limited to 50 requests/hour; apply for production access on the Unsplash
dashboard to raise that limit.
npm run devnpm run build
npm run preview # preview the production build locally- Vue 3 (
<script setup>, Composition API) - Vuetify 3 for UI components/theming, tree-shaken via
vite-plugin-vuetify - unsplash-js as the API client
- Vite for tooling
src/
components/ UI components (header, search bar, grid, card, lightbox)
composables/ usePhotoSearch (search/pagination), useFavorites (localStorage)
services/ Unsplash API client + attribution/download helpers
App.vue Top-level layout and state wiring
Per the Unsplash API Guidelines, this app:
- Attributes each photographer and Unsplash itself with
utm_source/utm_mediumtagged links - Triggers a download-tracking request (
photos.trackDownload) before serving a download
VS Code + Vue (Official) (and disable Vetur).