A minimalist, web-based link storage and collaboration app built with React.js, TypeScript, and Firebase.
- User Authentication - Secure login and signup with Firebase Auth
- Vault Management - Create, edit, and delete vaults (link containers)
- Link Management - Add, edit, and delete links within vaults
- Real-time Sync - Live data synchronization with Firebase Firestore
- Theme System - Light/dark mode with persistent storage
- Email Invitations - Send vault invitations to users by email
- Permission Management - View, comment, and edit permissions
- Collaborator Management - Add, remove, and manage vault collaborators
- Share Links - Generate shareable links with expiration and usage limits
- Notifications - Real-time notification system for invitations and updates
- Search Functionality - Search across vaults, links, titles, descriptions, and URLs
- Responsive Design - Mobile-first design that works on all devices
- Loading States - Skeleton loaders and loading indicators
- Copy to Clipboard - Quick copy functionality for links
- Frontend: React 18, TypeScript, Vite
- Styling: Classic CSS , Tailwind CSS, PostCSS
- Backend: Firebase (Authentication + Firestore)
- Icons: Lucide React
- Routing: React Router DOM
- State Management: React Context API
- Node.js (v16 or higher)
- npm or yarn
- Firebase project
- Clone the repository:
git clone https://github.com/samirrhashimov/blink.git
cd blink-app- Install dependencies:
npm install-
Set up Firebase:
- Create a new Firebase project at Firebase Console
- Enable Authentication and Firestore
- Copy your Firebase config and update
src/firebase/config.ts
-
Start the development server:
npm run dev- Open http://localhost:5173 in your browser
- Create a Firebase project
- Enable Authentication (Email/Password)
- Enable Firestore Database
- Set up Firestore security rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read: if request.auth != null;
allow create: if request.auth != null;
allow update, delete: if request.auth != null && request.auth.uid == userId;
}
match /vaults/{vaultId} {
allow create: if request.auth != null && request.resource.data.ownerId == request.auth.uid;
allow read: if request.auth != null &&
(resource.data.ownerId == request.auth.uid ||
request.auth.uid in resource.data.authorizedUsers);
allow delete: if request.auth != null && resource.data.ownerId == request.auth.uid;
allow update: if request.auth != null &&
(resource.data.ownerId == request.auth.uid ||
request.auth.uid in resource.data.authorizedUsers ||
request.auth.uid in request.resource.data.authorizedUsers);
}
match /shareInvites/{inviteId} {
allow read, write: if request.auth != null;
}
match /vaultPermissions/{permissionId} {
allow read, write: if request.auth != null;
}
match /shareLinks/{linkId} {
allow read, write: if request.auth != null;
}
match /notifications/{notificationId} {
allow create: if request.auth != null;
allow read, update, delete: if request.auth != null && resource.data.userId == request.auth.uid;
}
}
}npm run dev- Start development servernpm run build- Build for productionnpm run preview- Preview production buildnpm run lint- Run ESLint
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
If you discover a security vulnerability in the project, do not open a public issue.
Instead, submit a private report through the Security advisories section.
This project is licensed under the APGLv3 License. For more details, see the LICENSE file.
For issues and questions, please open an issue on GitHub.