A modern web app to search, save, and manage high-quality images using the Unsplash API. Users can sign in, search for images, and save/delete their favorite images securely in a PostgreSQL database powered by Neon and managed via Drizzle ORM.
🔗 https://image-finder-ecru-phi.vercel.app
- 🔍 Search millions of images from Unsplash
- ✅ User authentication via Auth.js
- 💾 Save your favorite images to your profile
- ❌ Delete saved images anytime
- 🧩 Built with Next.js 14 App Router, TypeScript, Tailwind CSS
- 🐘 Database: Neon (PostgreSQL) + Drizzle ORM
- ☁️ Hosted on Vercel
❗ This app uses Google OAuth for login and is currently in testing mode.
Only 2 specific test Gmail accounts (added manually in the Google Cloud Console) are allowed to log in during this phase.
If you are not one of the approved test users, you'll encounter a "This app is not verified" error from Google.
This limitation is due to Google’s policy of allowing a maximum of 100 users in OAuth testing mode unless the app undergoes OAuth verification.
| Frontend | Backend / DB |
|---|---|
| Next.js 14 | Next.js App Router |
| TypeScript | Neon PostgreSQL |
| Tailwind CSS | Drizzle ORM |
| Auth.js (NextAuth) | REST API Routes |
| Home Page | Search Results | Saved Images |
|---|---|---|
![]() |
![]() |
![]() |
app/
├── layout.tsx # Main layout file
├── SearchInput.tsx # Input box for searching images
├── ImageGrid.tsx # Component to display search results
├── SavedImages.tsx # Component to show user's saved images
│
├── (root)/ # Root folder (if part of app directory routing)
│ ├── SavedImage/ # Page or component folder
│ └── Dashboard/ # Dashboard page or component
│
├── Components/ # UI and layout components
│ └── UserAvatar.tsx
│
├── context/ # Context providers
│ └── SessionContext.tsx
│
├── db/ # Database configuration and schema
│ ├── index.ts # DB connection setup
│ └── schema.ts # DB schema (e.g., for saved images)
│
├── api/ # API route handlers
│ ├── search/route.ts # Fetch images from Unsplash API
│ ├── saveUser/route.ts # Save image to the database
│ ├── delete/route.ts # Delete image from the database
│ └── auth/[...nextauth].ts # NextAuth.js authentication config
│
├── action/ # Server actions
│ ├── SignIn.ts
│ ├── logout.ts
│ └── show.ts
├──drizzle/
├── auth.ts # auth integration or utility
├── drizzle.config.ts # Drizzle configuration
git clone https://github.com/your-username/image-finder-app.git
cd image-finder-appnpm installCreate a .env.local file and configure the following:
# Unsplash
UNSPLASH_ACCESS_KEY=your_unsplash_api_key
# Auth.js (Google Provider)
AUTH_SECRET=your_auth_secret
AUTH_PROVIDER_CLIENT_ID=your_client_id
AUTH_PROVIDER_CLIENT_SECRET=your_client_secret
# Database (Neon)
DATABASE_URL=your_neon_database_urlnpx drizzle-kit pushnpm run devVisit http://localhost:3000.
- User (id, name, email)
- SavedImage (id, userId, url, description, createdAt)
This project uses Auth.js (formerly NextAuth.js) for secure authentication.
- Social login via Google
- JWT-based session management
- Only pre-approved Gmail users can log in in testing mode
This project is licensed under the MIT License.
- 📷 Unsplash – Free image API
- 🔐 Auth.js – Authentication framework
- 🧪 Drizzle ORM – Type-safe PostgreSQL ORM
- 🐘 Neon – Serverless PostgreSQL
- ⚡ Next.js – Fullstack React Framework
- 🎨 Tailwind CSS – Utility-first CSS framework


