A modern web application for uploading, managing, and sharing digital images. Built with React, TypeScript, and Tailwind CSS, featuring dark/light theme support, adaptive image modals, private share groups, and download analytics. Powered by a REST API backend with Cloudinary storage.
π https://ui-pixel-vault.vercel.app
- JWT-based registration and login
- Password visibility toggle
- Password strength meter on registration
- Protected routes with automatic redirect
-
Drag-and-drop or file picker β upload up to 30 images at once (5MB max per file)
-
Client-side validation (MIME type, file size, count)
-
Thumbnail grid with auto-extracted dimensions and per-file size
-
Per-file status badges: queued / uploading / success / failed
-
Per-file upload progress plus an overall progress bar
-
Partial-failure handling: successful uploads are preserved even if some files fail
-
Retry controls β retry a single failed upload or all failed uploads at once
-
Bounded concurrency (3 parallel uploads) for responsive UX on slow networks
-
Grid selection & reordering: include/exclude individual uploaded images and reorder them with β / β controls before saving β ordered numbering badges show the final save order
-
Shared metadata (title, description, keywords, privacy) applied to every saved image
-
Cloud storage via Cloudinary
- Two grid modes: masonry and uniform grid
- Full-text search by title or keywords
- Pagination with page navigation β pagination only affects the returned data, not the counts
- My Library tab shows accurate
All / Public / Privatecounts driven by the API'stotalCount,publicCount, andprivateCountfor the current search and scope - Privacy badges (π Private / π Public) on library cards
- Public Gallery β browse all public images shared by users
- My Library β view only your own uploads with privacy filters (All / Public / Private)
A single adaptive modal used everywhere an image is opened β My Library, Public Gallery, and Group Detail.
-
Adaptive layout β side-by-side info panel for portrait images on desktop, stacked layout (title β image β details) for landscape/mobile
-
Fullscreen view β click the image or the maximize icon to enter cursor-zoom fullscreen; press
Escor click anywhere to exit -
Body-scroll lock β opening the modal locks the underlying page; only the modal content scrolls
-
Single scroll container β image and metadata scroll together so long info panels never desync from the picture
-
Metadata β dimensions, file size, upload date, keyword chips, full image URL with copy-to-clipboard
-
Quick actions β Copy URL, Open in new tab, Download
-
Owner controls β inline edit (title / description / keywords / privacy toggle) and delete-with-confirmation, hidden when viewing outside your own library
-
Group context β when opened from a Share Group, the Download button routes through the audited group-download endpoint instead of a direct link, and owner-only edit/delete are suppressed
-
Edit title, description, and keywords inline
-
Toggle privacy between public and private
-
Delete images with confirmation dialog
-
Bulk actions in My Library: select multiple images, then make Public/Private, add to a Share Group, or Delete in one click
The Share Groups hub lets you privately share selected images with specific people.
- Three tabs β
Owned(groups you created),Joined(groups you've accepted into),Invites(pending / accepted / rejected) - Create group β name max 10 chars, unique per owner, enforced both client-side and server-side
- Group cards β show role (Owner / Member), member count, image count, and a quick Open action
- Owner-only controls β inline Rename and Delete on each owned group card
- Invite management β pending invites display Accept / Reject buttons, accepted invites jump straight into the group
- Pending-invite badge on the Groups nav link keeps unread invites visible across the app
The dedicated workspace for a single share group, with three tabs whose visibility depends on your role.
Images tab (owner + members)
- Searchable, paginated grid of shared images (counts reflect the full matched set, not just the current page)
- Click any image to open it in the shared
ImageDetailModal(in group-download mode) - Per-image Download button records the download in the backend audit log and streams the file as a blob
- Owner-only multi-select with a sticky action bar to bulk-remove images from the group
- Owner-only βAdd Imagesβ dialog β searches your library, supports multi-select with pagination, and adds picks to the group in one call
Members tab (owner + members)
- List of members with avatar initials, name, email, and a colored status pill (Pending / Accepted / Rejected)
- Owner-only remove button per row (works for both members and pending invites)
- Owner-only Invite dialog with debounced
/user/searchautocomplete β pick from suggestions or type a raw email; multiple invites at once via chip input
Analytics tab (owner only)
- Stat cards: Total Downloads, Unique Users, Top Image
- Top Images grid with thumbnails and per-image download counts
- Paginated Download History table β who downloaded what, when
-
Hero banner with avatar displaying user initials
-
View account info and upload statistics
-
Edit profile (first name, last name, gender)
-
Change password with real-time strength indicator
-
Quick-action grid: Edit Profile, Change Password, Upload, My Library, Share Groups
- Toggle between dark and light themes from the navbar
- Preference persisted in localStorage
- Full design-token support for both modes
- Mobile-friendly layout across all pages
- Accessible UI components via shadcn/ui
| Layer | Technology |
|---|---|
| Framework | React 18 + TypeScript |
| Build Tool | Vite |
| Styling | Tailwind CSS |
| UI Components | shadcn/ui |
| Routing | React Router v6 |
| HTTP Client | Axios |
| State | TanStack React Query |
| Notifications | Sonner |
| Icons | Lucide React |
| Backend | REST API on Render |
| Storage | Cloudinary |
git clone https://github.com/Ajay-Maury/Pixel-Vault.git
cd Pixel-Vault
npm installCreate a .env file:
VITE_BASE_URL= <Backend Service URL>The backend service for this application is available here: π https://github.com/Ajay-Maury/Pixel-Vault-Backend
Refer to the backend repository's README for the full list of REST endpoints, request/response shapes, and authentication details. The frontend wraps every backend endpoint in src/lib/api.ts.
npm run devOpen http://localhost:5173.
src/
βββ components/
β βββ ui/ # shadcn/ui components
β βββ ImageDetailModal.tsx # Adaptive image modal (fullscreen, edit, group-download mode)
β βββ Navbar.tsx # Global nav with Groups link + pending-invite badge
β βββ NavLink.tsx
β βββ ThemeProvider.tsx # Dark/light mode context
βββ hooks/
β βββ use-mobile.tsx
β βββ use-toast.ts
βββ lib/
β βββ api.ts # Axios client + typed wrappers for every backend endpoint
β βββ auth.ts # Token + userId helpers
β βββ utils.ts
βββ pages/
β βββ Index.tsx # Landing / home page
β βββ Gallery.tsx # Public gallery + My Library (with bulk actions)
β βββ Groups.tsx # Share Groups: Owned / Joined / Invites tabs
β βββ GroupDetail.tsx # Per-group Images / Members / Analytics tabs
β βββ Login.tsx
β βββ Register.tsx
β βββ Upload.tsx # Batch upload with progress, retry, reordering
β βββ Profile.tsx # Account hub w/ quick-action grid incl. Share Groups
β βββ NotFound.tsx
βββ App.tsx # Routes (incl. /groups and /groups/:id under RequireAuth)
βββ main.tsx
βββ index.css # Design tokens (light + dark)
Contributions welcome! Open issues or pull requests for improvements. For major changes, discuss in an issue first.
MIT β see LICENSE for details.