Set up student access
Room Sharing lets your students read your live captions on their own devices. It runs on a free Google Firebase project that you create and control, so your class's data stays private and the whole thing stays free. You only do this once.
About 10 minutes · No coding · Browser onlyCreate a Firebase project
Go to console.firebase.google.com and sign in with a Google account (your personal one is fine).
Click Create a project and give it any name, such as Classroom Captions.
Turn on anonymous sign-in
This lets student devices connect without anyone logging in or creating an account.
- In the left sidebar, under Product categories, click Security.
- Click Authentication, then Get started.
- Choose Anonymous from the list of sign-in providers.
- Toggle it to Enable, then click Save.
Create the Realtime Database
- In the left sidebar, under Product categories, click Databases & Storage.
- Click Realtime Database, then Create Database.
- Pick the location closest to you and continue.
- When asked about security rules, start in locked mode. You'll paste the real rules next.
Paste in the security rules
These rules keep students from injecting fake captions or seeing each other's data. They run on Google's servers, so they can't be bypassed.
- On the Realtime Database page, click the Rules tab.
- Select everything in the box and delete it.
- Copy the rules below and paste them in.
- Click Publish.
{
"rules": {
".read": false,
".write": false,
"rooms": {
"$roomCode": {
".read": "data.child('active').val() === true && data.child('expiresAt').val() > now",
"ownerUid": { ".validate": "newData.isString() && newData.val().length > 0" },
"createdAt": { ".validate": "newData.isNumber()" },
"expiresAt": { ".validate": "newData.isNumber()" },
"active": { ".validate": "newData.isBoolean()" },
"type": { ".validate": "newData.isString() && newData.val() === 'main'" },
".write": "(!data.exists() && auth != null && newData.child('ownerUid').val() === auth.uid && newData.child('expiresAt').val() <= (now + 28800001)) || (data.exists() && data.child('ownerUid').val() === auth.uid)",
"captions": {
".read": "data.parent().child('active').val() === true && data.parent().child('expiresAt').val() > now",
"$pushId": {
".write": "auth != null && data.parent().parent().child('ownerUid').val() === auth.uid",
".validate": "newData.hasChildren(['text','timestamp'])",
"text": { ".validate": "newData.isString() && newData.val().length <= 5000" },
"timestamp": { ".validate": "newData.isNumber()" },
"translations": { ".validate": "newData.hasChildren() || newData.val() === null" },
"$other": { ".validate": true }
}
},
"connections": {
"$connUid": {
".write": "auth != null && $connUid === auth.uid && data.parent().parent().child('active').val() === true",
".validate": "newData.hasChild('lastSeen')",
"joinedAt": { ".validate": "newData.isNumber()" },
"lastSeen": { ".validate": "newData.isNumber()" },
"$other": { ".validate": false }
}
},
"$other": { ".validate": false }
}
},
"accommodationRooms": {
"$accommodationCode": {
".read": "data.child('active').val() === true && data.child('expiresAt').val() > now",
"ownerUid": { ".validate": "newData.isString() && newData.val().length > 0" },
"createdAt": { ".validate": "newData.isNumber()" },
"expiresAt": { ".validate": "newData.isNumber()" },
"active": { ".validate": "newData.isBoolean()" },
"type": { ".validate": "newData.isString() && newData.val() === 'accommodation'" },
".write": "(!data.exists() && auth != null && newData.child('ownerUid').val() === auth.uid && newData.child('expiresAt').val() <= (now + 28800001)) || (data.exists() && data.child('ownerUid').val() === auth.uid)",
"connections": {
"$connUid": {
".write": "auth != null && $connUid === auth.uid && data.parent().parent().child('active').val() === true",
".validate": "newData.hasChild('lastSeen')",
"joinedAt": { ".validate": "newData.isNumber()" },
"lastSeen": { ".validate": "newData.isNumber()" },
"$other": { ".validate": false }
}
},
"$other": { ".validate": false }
}
}
}
}
Get your configuration
- Near the top of the left sidebar, click Settings (the gear), then General.
- Scroll to Your apps and click the web icon </> (angle brackets, not the iOS or Android icons) to register a web app.
- Give it any nickname and click Register app. Leave Also set up Firebase Hosting unchecked.
Firebase shows an Add Firebase SDK screen. Ignore the npm and <script> options. Just find the block that starts with const firebaseConfig:
const firebaseConfig = {
apiKey: "AIzaSy...",
authDomain: "your-project.firebaseapp.com",
databaseURL: "https://your-project-default-rtdb.firebaseio.com",
projectId: "your-project",
storageBucket: "your-project.appspot.com",
messagingSenderId: "1234567890",
appId: "1:1234:web:abcd"
};
Paste it into the extension
- Open the extension's Settings & styling page and find the Room Sharing section.
- Paste your configuration into the Firebase configuration box and click Save settings.
The extension checks your configuration when you save and tells you if anything looks off. You won't need to touch Firebase again.
Name your class and share the code
In the same Settings page, open Share with your students and give your class a name students will recognize, like Mr. Leatherwood, Chemistry. The name travels with your join code, so students who have several teachers can tell your class apart in their list.
Then copy your join code (or the styled invite for Canvas / Classroom) and post it where your students will see it. It's the same code all year.
That's it
Start captions and your students who joined with your code will see them live, each in the language they pick. Need to set up AI Mode too? See Connect your OpenAI account.