Multi-User School Planning Screen
Build a shared weekly planner with Firebase Authentication and real-time sync
What You Will Build
A shared planning screen where multiple students within a business school can view and manage their weekly schedule. Each user sees their own tasks and can also see classmates' availability — making group project coordination easy.
Key Concepts
- Authentication — Who is using the app? (Firebase Auth)
- Multi-user data — Each user has their own events, but the schedule is shared
- Real-time sync — Changes appear instantly for all connected users (Firestore)
Prerequisites
- Completed Practical Work 2, Exercises 1–4 (Next.js project running locally)
- A Google account (for Firebase console access)
This exercise is optional and designed for students who finish the main practical work early or want an extra challenge. It can also be completed as homework.
Set Up Firebase
Firebase is Google's platform for building apps without managing servers. It provides authentication, a real-time database, and hosting — all with a generous free tier.
Create a Firebase Project
- Go to console.firebase.google.com and sign in with your Google account
- Click "Create a project" and name it
school-planner - Disable Google Analytics (not needed for this exercise) and click Create
- Once created, click the Web icon (
</>) to register a web app - Name it
school-planner-weband click Register app - Copy the Firebase config object — you will need it in the next step
The config object looks like this. Keep it handy — you will paste it into your code soon:
const firebaseConfig = {
apiKey: "AIza...",
authDomain: "school-planner-xxxxx.firebaseapp.com",
projectId: "school-planner-xxxxx",
storageBucket: "school-planner-xxxxx.appspot.com",
messagingSenderId: "123456789",
appId: "1:123456789:web:abc123"
};
Enable Authentication
- In the Firebase console sidebar, go to Build → Authentication
- Click Get Started
- Enable Email/Password as a sign-in provider
- Optionally enable Google sign-in for a smoother experience
Enable Firestore Database
- Go to Build → Firestore Database
- Click Create database
- Select Start in test mode (allows all reads/writes for 30 days — fine for learning)
- Choose the closest region (e.g.,
europe-west1) and click Enable
Checkpoint: You have a Firebase project with Authentication (Email/Password) and Firestore both enabled.
Install & Configure Firebase SDK
Install the Firebase JavaScript SDK in your Next.js project and create a configuration file.
Install the Package
In your project terminal:
npm install firebase
Create the Config File
Ask Antigravity to generate the Firebase configuration:
Create a file src/lib/firebase.ts that:
- Initializes Firebase with my config (below)
- Exports the auth instance (getAuth)
- Exports the Firestore database instance (getFirestore)
- Uses a check to avoid initializing twice
Here is my Firebase config:
[paste your config object here]
The generated file should look something like this:
import { initializeApp, getApps } from 'firebase/app';
import { getAuth } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';
const firebaseConfig = {
apiKey: "your-api-key",
authDomain: "your-project.firebaseapp.com",
projectId: "your-project-id",
storageBucket: "your-project.appspot.com",
messagingSenderId: "123456789",
appId: "your-app-id"
};
const app = getApps().length === 0
? initializeApp(firebaseConfig)
: getApps()[0];
export const auth = getAuth(app);
export const db = getFirestore(app);
Note: In a production app, you would store these keys in environment variables (.env.local). For this exercise, putting them directly in the file is acceptable — Firebase API keys are safe to expose in frontend code (they are restricted by security rules, not by secrecy).
Checkpoint: src/lib/firebase.ts exists and exports auth and db. Your project still compiles without errors.
Build the Auth Screen
Create a login and signup page so each student can create an account and sign in.
Create the Auth Page
Ask Antigravity:
Create an auth page at src/app/auth/page.tsx with:
- A toggle between "Sign In" and "Sign Up" modes
- Email input field (required)
- Password input field (required, min 6 characters)
- A submit button that calls Firebase Auth:
- Sign Up: createUserWithEmailAndPassword
- Sign In: signInWithEmailAndPassword
- Display error messages below the form if login fails
(e.g., "wrong password", "email already in use")
- On successful sign-in, redirect to /planning
- Optional: a "Sign in with Google" button using
signInWithPopup and GoogleAuthProvider
Use Tailwind CSS for styling.
Import auth from "@/lib/firebase".
Test the Auth Page
- Navigate to
http://localhost:3000/auth - Create a new account with any email and password
- Check the Firebase console → Authentication → Users — your new user should appear
- Sign out and sign back in to verify login works
Tip: Use simple test emails like alice@school.com and bob@school.com — Firebase does not verify email addresses in test mode.
Checkpoint: You can create an account and sign in. The user appears in the Firebase Authentication console.
Create the Auth Context
You need a way to know which user is logged in from any page in the app. A React Context provides this.
What is a Context?
Think of it as a global variable that any component can read. Instead of passing the user object through every page manually, the context makes it available everywhere.
Generate the Auth Context
Ask Antigravity:
Create an AuthProvider context at
src/context/AuthContext.tsx that:
- Uses Firebase onAuthStateChanged to track the
currently signed-in user
- Provides: user object, loading boolean, signOut
function
- Exports a useAuth() hook for easy access
Then wrap the app with AuthProvider in
src/app/layout.tsx (the provider must be a client
component with "use client").
If loading is true, show a spinner or "Loading..."
Add Route Protection
Ask Antigravity to protect the planning page:
In src/app/planning/page.tsx (or a layout), check if
the user is logged in using the useAuth() hook.
If not logged in, redirect to /auth.
If logged in, show the page content.
Add a Sign Out Button
Add a sign-out button to the navigation bar that calls signOut(auth) and redirects to /auth.
Checkpoint: Visiting /planning when not logged in redirects to /auth. After signing in, you can access the planning page. The sign-out button works.
Build the Planning Screen
This is the main feature — a weekly calendar grid where all students in a school can manage their schedule together.
The Data Model
Before building the UI, understand how data is organized in Firestore:
schools (collection)
└── my-school (document)
└── events (sub-collection)
├── event1: { userId, userName, title,
│ day, startHour, endHour,
│ color, type }
├── event2: { ... }
└── event3: { ... }
Each event belongs to a user (userId) but is visible to everyone in the school.
Generate the Planning Page
Ask Antigravity to build the complete planning view:
Create a planning page at src/app/planning/page.tsx:
LAYOUT:
- A weekly calendar grid showing Monday to Friday
- Time slots from 8:00 to 18:00 (one row per hour)
- Each cell represents one hour on one day
- A header row with day names
ADDING EVENTS:
- Clicking an empty cell opens a modal/dialog with:
- Title (text input)
- Type (select: class / study / group-project / free)
- Start hour and end hour (select dropdowns)
- On submit, save to Firestore:
Collection path: schools/my-school/events
Fields: userId, userName (from auth), title, day,
startHour, endHour, color (based on type), type
DISPLAYING EVENTS:
- Events appear as colored blocks on the grid
- Color by type: purple=class, cyan=study,
emerald=group-project, amber=free
- Show the event title and user name on each block
- Current user's events have a subtle border or
highlight to distinguish them
PERMISSIONS:
- All users can see all events
- Only the event owner can edit or delete their events
- Show edit/delete buttons only on the user's own
events
REAL-TIME:
- Use Firestore onSnapshot to listen for changes
- When another user adds/edits/deletes an event,
it updates on screen automatically
Use Tailwind CSS. Import db and auth from
"@/lib/firebase". Use the useAuth() hook.
This is a big prompt! Antigravity may generate the code in multiple steps. Review each step before moving on. If something doesn't work, describe the problem to Antigravity and ask it to fix it.
Checkpoint: The weekly grid displays correctly. You can click a cell, fill in the modal, and see the event appear on the calendar. Check Firestore in the console — the event document should be there.
Test Multi-User
The whole point of this exercise is that multiple users can collaborate on the same planning screen. Let's verify it works.
Set Up Two Sessions
- Open your app in Chrome and sign in as
alice@school.com - Open an incognito window (or use Firefox) and sign in as
bob@school.com - Place both browser windows side by side so you can see both at once
Test Real-Time Sync
- As Alice: Add an event — "Math Lecture" on Monday 9:00–11:00
- Watch Bob's screen: The event should appear within 1–2 seconds without refreshing
- As Bob: Add an event — "Study Group" on Monday 14:00–16:00
- Watch Alice's screen: Bob's event should appear automatically
Test Permissions
- As Bob: Try to edit or delete Alice's event — the edit/delete buttons should not be visible
- As Alice: Edit her own event (e.g., change the title) — the change should appear on Bob's screen
- As Alice: Delete her own event — it should disappear from both screens
Pair up! If you are sitting next to a classmate, both sign in to the same school and try adding events at the same time. This is the most fun way to test real-time sync.
Checkpoint: Two users can sign in, add events, and see each other's updates in real-time. Users cannot edit or delete events that belong to someone else.
Bonus Ideas & Summary
Bonus Challenges
If you have extra time, pick one of these enhancements:
- School Selector — Add a dropdown to switch between schools (each school has its own events sub-collection). This lets the app support multiple classes.
- User Profiles — Store display names and avatar colors in a
userscollection so each person's events have a consistent look. - Drag & Resize — Allow users to drag events to different slots or resize them to change duration.
- Conflict Detection — Highlight time slots where two or more students have overlapping events — useful for scheduling group meetings.
- Export to Calendar — Add a button that exports the week's events as an
.icsfile users can import into Google Calendar or Outlook.
What You Learned
| Concept | What It Does |
|---|---|
| Firebase Auth | Handles user sign-up, sign-in, and session management |
| Firestore | NoSQL database with real-time sync across all clients |
| React Context | Shares auth state across all pages without prop drilling |
| onSnapshot | Listens for real-time changes and updates the UI automatically |
| Authorization | Controls who can edit/delete data based on ownership |