A collaborative calendar web application built with React, TypeScript, Vite, Tailwind CSS, and Firebase.
Before setting up the project, make sure you have the following installed on your machine:
- Node.js (v18 or higher) — Download here
- Git — Download here
- A Firebase account — Sign up here
To verify your installations, run:
node -v
git --versiongit clone https://github.com/NathanKim16/SyncedCalendar
cd SyncedCalendarnpm i- Go to console.firebase.google.com
- Click "Add Project" and follow the setup steps
- Once created, click the web icon
</>to register a web app - Copy the
firebaseConfigobject provided
- In the Firebase console, go to Build → Authentication
- Click "Get Started"
- Under Sign-in method, enable Email/Password
- Go to Build → Firestore Database
- Click "Create Database"
- Choose "Start in test mode" for development
- Select a region and click Done
In the Firebase console, go to Firestore → Rules and paste the following:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth.uid == userId;
}
match /calendars/{calendarId} {
allow read, write: if request.auth != null;
}
match /events/{eventId} {
allow read: if request.auth != null;
allow write: if request.auth.uid == resource.data.created_by;
}
match /memberships/{membershipId} {
allow read, write: if request.auth != null;
}
match /rsvps/{rsvpId} {
allow read: if request.auth != null;
allow write: if request.auth.uid == resource.data.user_id;
}
}
}
Create a .env file in the project root (same level as package.json):
VITE_FIREBASE_API_KEY=your_api_key
VITE_FIREBASE_AUTH_DOMAIN=your_auth_domain
VITE_FIREBASE_DATABASE_URL=your_database_url
VITE_FIREBASE_PROJECT_ID=your_project_id
VITE_FIREBASE_STORAGE_BUCKET=your_storage_bucket
VITE_FIREBASE_MESSAGING_SENDER_ID=your_messaging_sender_id
VITE_FIREBASE_APP_ID=your_app_id
VITE_FIREBASE_MEASUREMENT_ID=your_measurement_id
Replace each value with the corresponding value from your Firebase firebaseConfig object.
npm run devThe app will be available at http://localhost:5173 by default.
npm run buildThe production build will be output to the dist/ folder.
SyncedCalendar/
├── public/ # Static assets
├── src/
│ ├── assets/ # Images and icons
│ ├── components/ # React components
│ │ ├── CalendarApp.jsx # Main calendar component
│ │ ├── navbar.tsx # Navigation and sidebar
│ │ └── Login.tsx # Authentication page
│ ├── context/
│ │ └── auth/
│ │ └── index.jsx # Firebase Auth context
│ ├── firebase/
│ │ └── auth.ts # Firebase Auth helper functions
│ ├── services/
│ │ ├── firestoreService.ts # Firestore CRUD functions
│ │ └── CodeInvite.js # Calendar invite code logic
│ ├── firebase.ts # Firebase initialization
│ ├── App.tsx # Root component and routing
│ ├── main.tsx # Entry point
│ └── App.css # Global styles
├── .env # Environment variables (not committed)
├── .gitignore
├── package.json
├── tailwind.config.js
├── tsconfig.json
└── vite.config.ts
| Command | Description |
|---|---|
npm run dev |
Start the development server |
npm run build |
Build for production |
npm run preview |
Preview the production build locally |
npm run lint |
Run ESLint |
The app uses the following Firestore collections:
| Collection | Description |
|---|---|
users |
User profiles and display names |
calendars |
Calendar documents with name, color, and owner |
memberships |
Links users to calendars with a role (owner, admin, user) |
events |
Calendar events with time, title, and color |
rsvps |
User RSVPs for events with optional notes |
Each calendar has an invite code which is the last 5 characters of its Firestore document ID, visible at the bottom of the Members panel. Share this code with others so they can join via "Join with a Code" in the sidebar.