MySplash is a modern image gallery application built with the Unsplash API. Users can search for photos, save their favorites, and view them in detail.
Live: MySplash on Vercel
- 🔍 Image Search — Search for any topic using the Unsplash API
- 📸 Masonry Grid — Beautiful responsive masonry layout
- ❤️ Liked Images — Add/remove images from favorites (persisted in LocalStorage)
- 🔎 Image Details — Dedicated page for each image with zoom support
- ⬇️ Download — Download images directly
- 🌙 Dark / Light Mode — Theme switcher
- 🔐 Authentication — Sign up and sign in via Email/Password or Google (Firebase Auth)
- 📱 Fully Responsive — Works seamlessly on mobile and desktop
- 🔄 Load More — Paginated image loading with a "Load More" button
| Technology | Purpose |
|---|---|
| React 19 | UI framework |
| Vite | Build tool |
| React Router v7 | Client-side routing |
| Material UI (MUI v6) | UI components and styling |
| Firebase v11 | Authentication |
| Unsplash API | Image source |
| react-responsive-masonry | Masonry grid layout |
| react-toastify | Toast notifications |
| styled-components | Additional styling |
my-splash/
├── public/
│ └── unsplash.svg
├── src/
│ ├── assets/
│ ├── components/
│ │ ├── Navbar.jsx # Navigation bar
│ │ ├── Footer.jsx # Footer
│ │ ├── Search.jsx # Search form
│ │ ├── Images.jsx # Image card component
│ │ ├── FormInput.jsx # Text input component
│ │ ├── ProtectedRoutes.jsx # Route guard
│ │ └── ErrorBoundry.jsx # Error boundary
│ ├── context/
│ │ └── GlobalContext.jsx # Global state (useReducer)
│ ├── firebase/
│ │ └── firebaseConfig.js # Firebase configuration
│ ├── hooks/
│ │ ├── useGlobalContext.js # Context hook
│ │ ├── useFetch.js # Data fetching hook
│ │ ├── useLogin.js # Login hook
│ │ └── useRegister.jsx # Registration hook
│ ├── layout/
│ │ └── RootLayout.jsx # Root layout
│ ├── pages/
│ │ ├── home/Home.jsx # Home page
│ │ ├── about/About.jsx # About page
│ │ ├── contact/Contact.jsx # Contact page
│ │ ├── login/Login.jsx # Login page
│ │ ├── register/Register.jsx # Register page
│ │ ├── likedImages/LikedImages.jsx # Favorites page
│ │ ├── ImageInfo.jsx # Image detail page
│ │ └── error/ErrorPage.jsx # Error page
│ ├── App.jsx # Root component + routing
│ ├── main.jsx # Entry point
│ └── index.css # Global styles
├── index.html
├── vite.config.js
├── package.json
└── .gitignore
- Node.js
>= 20 - npm or yarn
- Unsplash Developer account
- Firebase project
git clone https://github.com/abeekofficial/my-splash.git
cd my-splashnpm installCreate a .env file in the project root:
VITE_UNSPLASH_URL=https://api.unsplash.com/search/photos
VITE_UNSPLASH_URL_ID=https://api.unsplash.com/photos/
VITE_UNSPLASH_KEY=your_unsplash_access_keyGet your Unsplash API key: Register at unsplash.com/developers and create a new application.
Update src/firebase/firebaseConfig.js with your Firebase project credentials:
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_AUTH_DOMAIN",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_STORAGE_BUCKET",
messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
appId: "YOUR_APP_ID",
};Create a Firebase project: Go to console.firebase.google.com, then enable Email/Password and Google providers under Authentication.
npm run devThe app will be available at http://localhost:5173.
npm run dev # Start the development server
npm run build # Build for production
npm run preview # Preview the production build
npm run lint # Run ESLint| Route | Page | Description |
|---|---|---|
/ |
Home | Search images and masonry gallery |
/about |
About | Information about the project |
/contact |
Contact | Contact form and map |
/likedImages |
Liked Images | Your saved favorite images |
/imageInfo/:id |
Image Detail | Full image view with zoom |
/login |
Login | Sign in to your account |
/register |
Register | Create a new account |
Managed with GlobalContext + useReducer:
likedImages— list of favorited images (persisted in LocalStorage)user— current authenticated user (Firebase Auth)isExpanded— image zoom state
- Firebase Authentication is used for all auth flows
ProtectedRoutescomponent guards private routesonAuthStateChangedkeeps auth state in sync- Unauthenticated users are automatically redirected to
/login
useFetch custom hook handles all API calls with AbortController for safe cleanup, plus loading and error states.
- Fork the repository
- Create a new branch:
git checkout -b feature/your-feature - Commit your changes:
git commit -m 'Add new feature' - Push to the branch:
git push origin feature/your-feature - Open a Pull Request
This project is distributed under the MIT License.
Abeek — mysplash-abeek.vercel.app
- GitHub: @abeekofficial
- LinkedIn: abeekofficial
- Twitter: @abeekofficial
⭐ If you like this project, give it a star on GitHub!