Never lose your precious resources again! A centralized resource link management platform that helps you organize, secure, and share your valuable links and knowledge with ease.
- Fast Create Flow: Add a resource with only a name and link; ownership comes from auth
- Private by Default: New resources are always created as private
- Edit Enrichment: Add description, tags, visibility, and update the URL on the edit page
- Intelligent Tagging: Organize resources with custom tags and predefined suggestions (on edit)
- Advanced Search: Find resources by name, description, or tags instantly
- Category Filtering: Browse resources by categories with visual icons
- Resource Editing: Full edit form prefilled with existing resource values
- Responsive Design: Beautiful, mobile-first interface with Tailwind CSS v4
- Live Preview: See how your resource will look while creating it
- Dual View Modes: Switch between grid and list views
- Smooth Animations: Engaging micro-interactions and transitions
- Loading States: Elegant loading screens and progress indicators
- Toast Notifications: Beautiful, non-intrusive user feedback
- Google OAuth Integration: Seamless login with your Google account
- Protected Routes: Secure access to private features with custom HOC
- Session Management: Cookie-based persistent authentication across browser sessions
- User Profile Management: Display user information and avatars
- Public Resource Discovery: Browse amazing resources shared by the community
- Resource Sharing: Make your resources public to help others learn
- Public Collections: Explore and share curated, ordered resource lists
- Collection Workflows: Optional per-item status labels (e.g. todo, done) on collections
- User Profiles: Track resource ownership and contributions via collection URLs (
/collections/:username/:slug)
- Installable: Add ResourceHub to your home screen (Android/desktop; iOS via Share β Add to Home Screen)
- Offline shell: Service worker caches static assets; dedicated
/offlinefallback page - Offline-aware writes: Mutations blocked with a clear toast when the network is unavailable
- Install prompt: In-app prompt for supported browsers
- Code Splitting: Lazy loading of components for optimal performance
- React Query: Server-state caching for collections and documents
- Hot Module Replacement: Fast development with Vite HMR
- ESLint Integration: Code quality assurance and formatting
- Docker Support: Containerized deployment ready
- Node.js 18.0 or higher (Docker image uses Node 24)
- npm or yarn package manager
- Backend API server running (see
resourceManager-backend) - Auth service for Google OAuth (
VITE_AUTH_URLβ external to this repo) - Docker (optional, for containerized deployment)
-
Clone the repository
git clone https://github.com/lakshay2425/resourceManager-frontend cd resourceManager-frontend -
Install dependencies
npm install # or yarn install -
Set up environment variables
Create a
.envfile in the root directory (not committed β see.gitignore):VITE_BACKEND_URL=http://localhost:3000/api VITE_AUTH_URL=http://localhost:5000/api VITE_FRONTEND_URL=http://localhost:5173 VITE_GOOGLE_CLIENT_ID=your_google_oauth_client_id.apps.googleusercontent.com VITE_DEV_MODE=true
There is no Vite dev proxy β the app calls these absolute URLs directly, so the backend must be reachable at
VITE_BACKEND_URL. -
Start the development server
npm run dev # or yarn dev -
Open your browser Navigate to
http://localhost:5173to see the application.
ResourceHub comes with a complete Docker setup for easy deployment:
# Build the Docker image
docker build -f Docker/Dockerfile -t resourcehub-frontend .# Run the container
docker run -p 3000:3000 resourcehub-frontendThe Dockerfile uses a multi-stage build process:
- Builder Stage: Installs dependencies and builds the application
- Production Stage: Creates a lightweight production container with serve
- Base Image: Node.js 24 Alpine (lightweight)
- Security: Runs as non-root user
- Port: Exposes port 3000
- Serve: Uses
servepackage to serve static files
- React 19.1: Latest React with hooks and concurrent features
- Vite 7.0: Lightning-fast build tool and development server
- React Router DOM v7: Client-side routing and navigation
- Tailwind CSS v4: Latest utility-first CSS framework with new features
- Lucide React: Beautiful, customizable SVG icons
- Custom Animations: Smooth transitions and micro-interactions
- Glassmorphism Design: Modern aesthetic with backdrop blur effects
- React Context API: Global state for authentication, loading, and online status
- TanStack React Query: Server state for collections and documents
- React Hook Form: Efficient form handling and validation
- Custom Hooks: OAuth, local storage, navigation, loading, SEO, offline guard, collections
- Google OAuth (@react-oauth/google): Secure authentication flow
- Axios: HTTP client for API requests with interceptors
- Protected Routes: Route-level security implementation
- Cookie-based Sessions: Persistent authentication
- React Hot Toast: Beautiful toast notifications
- ESLint v9: Latest code linting and formatting
- Lazy Loading: Code-splitting with offline chunk fallback
- Suspense: React Suspense for loading states
- vite-plugin-pwa: Service worker and web app manifest
src/
βββ api/ # API client modules
β βββ collectionsApi.js # Collections CRUD and item mutations
β βββ documentApi.js # Document / MinIO upload APIs
β βββ usersApi.js # User profile helpers
βββ components/ # Reusable UI components
β βββ collections/ # Collection cards, modals, item rows
β βββ HomePage/ # Landing page sections
β βββ BookmarkCard.jsx
β βββ Footer.jsx
β βββ InstallPrompt.jsx # PWA install prompt
β βββ LoadingBar.jsx
β βββ LoadingScreen.jsx
β βββ Navbar.jsx
β βββ OfflineBanner.jsx
β βββ ResourceCard.jsx
β βββ RouteErrorBoundary.jsx
βββ context/
β βββ AuthContext.jsx
β βββ LoadingContext.jsx
β βββ OnlineStatusContext.jsx
βββ hooks/
β βββ useCollections.js # React Query hooks for collections
β βββ useDocuments.js
β βββ useGoogleOAuth.js
β βββ useLocalStorage.js
β βββ useLoading.js
β βββ useNavigation.js
β βββ useOfflineGuard.js
β βββ usePageSeo.js # Per-route SEO meta tags
βββ pages/
β βββ Home.jsx
β βββ Resources.jsx
β βββ publicResources.jsx
β βββ CreateResource.jsx
β βββ EditResource.jsx
β βββ BookmarkResources.jsx
β βββ DocumentManagement.jsx
β βββ MyCollections.jsx
β βββ PublicCollections.jsx
β βββ CreateCollection.jsx
β βββ CollectionDetail.jsx
β βββ Offline.jsx
β βββ NotFound.jsx
βββ utilis/
β βββ Axios.jsx # Axios instance + offline write guard
β βββ seo.js # Meta tags, JSON-LD, canonical URLs
β βββ collectionErrors.js # Collection API error messages
β βββ resourceErrors.js # Duplicate resource (409) helpers
β βββ networkStatus.js
β βββ idempotency.js
β βββ lazyWithOfflineFallback.js
β βββ renderProtectedRoute.jsx
βββ App.jsx
βββ main.jsx
βββ index.css
public/
βββ resourceManagerLogo.png
βββ health # Docker / load-balancer health check (JSON)
βββ llm.txt # LLM / AI crawler site summary
βββ robots.txt # Search engine crawl rules
βββ sitemap.xml # Static public URL sitemap
βββ offline.html # PWA offline fallback
Docker/
βββ Dockerfile
Manages global authentication state and user session with cookie verification:
const { isAuthenticated, gmail, setIsAuthenticated, isLoading } = useContext(AuthContext);Manages application loading states:
const { isLoading, setIsLoading } = useContext(LoadingContext);Secure routes that require authentication with custom protection logic:
<Route
path="/resources"
element={
<RenderProtectedRoute
condition={isAuthenticated === true}
renderPage={<Resources />}
fallback="/"
errorMessage="You need to login to access this page"
/>
}
/>Create and edit use separate page components (not one shared form):
| Page | Route | Component | Fields |
|---|---|---|---|
| Create | /createResource |
CreateResource.jsx |
name, link only |
| Edit | /edit/:id |
EditResource.jsx |
name, description, tags, status, sourceLink (prefilled) |
- Create:
POST /resourceswith{ name, link }β noemailin body (owner from auth cookie); server always creates asprivate - Edit:
PATCH /resources/:idwith{ updatedFields: { ... } }β usesourceLink(notlink) for URL updates - Delete resources with confirmation modals
- Filter and search (handles missing description / empty tags)
- Tag-based organization on the edit flow
// CREATE β CreateResource.jsx
// POST /api/resources
{ name: string /* min 5 */, link: string /* valid URL β stored as sourceLink */ }
// UPDATE β EditResource.jsx
// PATCH /api/resources/:id
{
updatedFields: {
name?: string, // min 5
description?: string, // min 10 when present
tags?: string[],
status?: "public" | "private",
sourceLink?: string // valid URL
}
}Field name trap: create uses link; GET responses and PATCH use sourceLink.
The backend rejects duplicate resources for the same user with the same name + URL. Affected flows:
| Flow | Endpoint | UX on 409 |
|---|---|---|
| Create | POST /resources |
Inline banner on form; no error toast |
| Edit | PATCH /resources/:id |
Inline banner; loading toast dismissed |
| Collection create-and-add | POST .../items/create-and-add |
Inline banner in modal |
Shared helpers live in src/utilis/resourceErrors.js. Other error statuses keep existing toast/inline behavior.
| Route | Auth | Description |
|---|---|---|
/ |
Public | Landing page |
/publicResources |
Public | Community resources |
/collections/public |
Public | Browse public collections |
/collections/:username/:slug |
Public* | Collection detail (*private collections get noindex) |
/resources |
Required | My resources |
/createResource |
Required | Create resource (name + link) |
/edit/:id |
Required | Edit resource |
/bookmarks |
Required | Saved bookmarks |
/documents |
Required | Document management |
/collections |
Required | My collections |
/collections/new |
Required | Create collection |
/offline |
Public | PWA offline fallback |
Seamless authentication flow with error handling:
const { handleGoogleLogin } = useGoogleAuth();ResourceHub uses a modern, glassmorphism-inspired design with:
- Color Palette: Purple and blue gradients with clean whites and glass effects
- Typography: Bold headings with readable body text using system fonts
- Spacing: Generous whitespace and consistent padding following 8px grid
- Animations: Subtle hover effects, smooth transitions, and micro-interactions
- Responsive: Mobile-first design with breakpoint optimization
- Accessibility: Focus states and keyboard navigation support
ResourceHub ships with first-class SEO for public pages and blocks indexing of authenticated areas.
| Route | Page | Meta tags |
|---|---|---|
/ |
Landing | Title, description, Open Graph, Twitter Card, WebSite JSON-LD |
/publicResources |
Community resources | Per-page title & description |
/collections/public |
Public collections browse | Per-page title & description |
/collections/:username/:slug |
Public collection detail | Dynamic title, description, CollectionPage JSON-LD; noindex when private |
Per-route metadata is applied at runtime via usePageSeo (src/hooks/usePageSeo.js) and src/utilis/seo.js.
Set VITE_FRONTEND_URL in .env so runtime canonical URLs, Open Graph links, and JSON-LD match your deployment domain. Static files in public/ (sitemap.xml, robots.txt, llm.txt) ship with the production domain https://resources.lakshaymahajan.com β update them when deploying to a different hostname.
| File | URL | Purpose |
|---|---|---|
sitemap.xml |
/sitemap.xml |
Static sitemap for public landing pages |
robots.txt |
/robots.txt |
Crawl rules; links sitemap and llm.txt |
llm.txt |
/llm.txt |
Machine-readable site summary for LLM crawlers (llmstxt.org) |
health |
/health |
JSON health check for Docker / probes |
offline.html |
/offline.html |
PWA offline fallback (precached by service worker) |
- Allowed:
/,/publicResources,/collections/public,/collections/*/*(public collection detail) - Disallowed:
/resources,/bookmarks,/createResource,/edit/,/documents,/collections/new,/collections(owner list),/offline - LLM crawlers:
GPTBot,ChatGPT-User, andClaude-Webmay read/llm.txtand public indexable routes - Sitemap: declared at bottom of
robots.txt
Dynamic public collection URLs are discoverable via on-page links and client-side meta tags; add them to sitemap.xml manually or via a build-time script if you need full sitemap coverage.
Search engines that execute JavaScript will read updated <title>, meta, and JSON-LD after navigation. The base tags in index.html provide a fallback for the home page before hydration.
| Variable | Description | Example (local dev) |
|---|---|---|
VITE_BACKEND_URL |
Backend API base URL | http://localhost:3000/api |
VITE_AUTH_URL |
Authentication service URL | http://localhost:5000/api |
VITE_FRONTEND_URL |
Frontend URL (SEO, canonical) | http://localhost:5173 |
VITE_GOOGLE_CLIENT_ID |
Google OAuth client ID | your-client-id.apps.googleusercontent.com |
VITE_DEV_MODE |
Development mode flag | true |
The project uses Vite with optimized settings for:
- Fast HMR: Hot Module Replacement for instant updates
- Code Splitting: Automatic chunking for optimal loading
- Production Builds: Minification and optimization
- Modern Syntax: ES2020+ with modern browser support
- Tailwind Integration: Built-in Tailwind CSS plugin
- Modern ESLint: Uses flat config format
- React Rules: React hooks and refresh plugins
- Custom Rules: Unused vars handling with pattern matching
- Browser Globals: Configured for browser environment
Dedicated create form β not the edit form reused with empty values:
- Fields: Resource name + URL (
link) only - Validation: Name β₯ 5 characters; link must be a valid URL
- Privacy: Always created as private (no visibility picker on create)
- Ownership: Taken from the auth cookie β do not send
emailin the body - Live Preview: Shows name/link preview marked as private
- Success State: Navigate to My Resources or create another
- Enrich later: Description, tags, and public/private are set on the edit page
Separate full form, opened with existing resource values via router state:
- Prefills name, description, tags, status, and
sourceLink - Client validation aligned with backend PATCH rules
- Maps the URL field to
sourceLinkin the PATCH body - Optional description (min 10 characters when provided)
- Visibility toggle and tag management
- My Collections (
/collections): List and manage your collections - Create Collection (
/collections/new): Name, slug, visibility, optional status labels - Public browse (
/collections/public): Discover community collections - Collection detail (
/collections/:username/:slug): Ordered items, drag reorder (owner), add existing or create-and-add resources - Idempotency: Collection mutations use idempotency keys to safely retry writes
- Smart Search: Search across names, descriptions, and tags (safe when description/tags are missing)
- Category Filtering: Filter by resource categories with visual indicators
- Sorting Options: Sort by date, alphabetically, or relevance
- View Modes: Toggle between grid and list views with animations
- Empty-field resilience: Placeholders when description is missing; empty tags treated as
[]
- Responsive Design: Optimized for mobile, tablet, and desktop
- Loading States: Skeleton screens and elegant loading animations
- Error Handling: Friendly error messages with recovery options; duplicate resources (409) shown inline on forms
- Toast Notifications: Non-intrusive feedback for success and non-form errors
- Keyboard Navigation: Full keyboard accessibility support
- Lazy Loading: Components loaded on demand
- Image Optimization: Optimized images and lazy loading
- Bundle Splitting: Automatic code splitting by routes
- Caching: HTTP caching for API requests
npm run build
# or
yarn buildnpm run preview
# or
yarn previewnpm install -g vercel
vercel --prodnpm install -g netlify-cli
npm run build
netlify deploy --prod --dir=dist# Build and run with Docker
docker build -f Docker/Dockerfile -t resourcehub-frontend .
docker run -p 3000:3000 resourcehub-frontendFor production deployment, ensure:
- Environment Variables: Set all required production URLs
- SSL/HTTPS: Configure HTTPS for secure authentication
- CORS: Configure backend CORS for your domain
- OAuth: Update Google OAuth settings with production domains
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow the existing code style and conventions
- Write meaningful commit messages following conventional commits
- Test your changes thoroughly across different devices
- Update documentation when needed
- Run
npm run lintbefore submitting (note: some pre-existing lint warnings may remain)
- Use functional components with hooks
- Prefer named exports over default exports
- Use descriptive variable and function names
- Keep components small and focused
- Extract reusable logic into custom hooks
| Script | Description |
|---|---|
npm run dev |
Start development server |
npm run build |
Build for production |
npm run preview |
Preview production build |
npm run lint |
Run ESLint |
OAuth not working:
- Check if
VITE_GOOGLE_CLIENT_IDis correctly set - Ensure OAuth is configured in Google Console with correct redirect URIs
- The auth service at
VITE_AUTH_URLis external to this repo β local login may not complete without it - Verify that you're using HTTPS in production
- Check browser console for OAuth errors
API requests failing:
- Verify backend server is running and accessible
- Check if
VITE_BACKEND_URLandVITE_AUTH_URLpoint to correct endpoints - Look for CORS errors in browser console
- Ensure cookies are being sent with
withCredentials: true
Build errors:
- Clear
node_modulesand reinstall dependencies - Ensure all environment variables are set correctly
- Check for any TypeScript errors if using TypeScript
- Verify that all imports are correct
Docker issues:
- Ensure Docker is running
- Check if port 3000 is available
- Verify the Dockerfile path is correct
- Check Docker logs for specific error messages
Loading/Authentication issues:
- Clear browser cookies and local storage
- Check network requests for authentication endpoints
- Verify backend authentication service is running
- Ensure proper session cookie configuration
- Route Protection: HOC-based route protection
- Session Validation: Server-side session verification
- CSRF Protection: Cookie-based session security
- Input Validation: Form validation on both client and server
- Context Menu Disabled: Right-click and key shortcuts disabled in production
- Lighthouse Score: 90+ across all metrics
- First Contentful Paint: < 1.5s
- Time to Interactive: < 3s
- Bundle Size: Optimized chunks under 500KB
- Core Web Vitals: Meets Google's recommended thresholds
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with β€οΈ for the developer community
- Icons by Lucide
- Styled with Tailwind CSS
- Powered by React and Vite
- Authentication via Google OAuth
- Deployed with Docker
ResourceHub - Your centralized resource management platform! π
For questions, support, or contributions, please:
- π§ Email: lakshay12290@gmail.com
- π Issues: Open an issue on GitHub
- π¬ Discussion: Start a GitHub Discussion
Never lose your precious resources again!