Setup › MDM
Deploy through your MDM
For IT teams with a device console. Push the app, the kiosk lock, and every setting including the room and the credential. An iPad goes from the box to the board with nobody touching it.
Print this page with ⌘P. Links print with their addresses.
Before you start
Three prerequisites, each done once per organization. Bored Room reads the standard Managed App Configuration dictionary (com.apple.configuration.managed); every key is optional, and any key you set is locked on the device.
A. Google: one service account, shared with every room
Full click-by-click in the by-hand guide, sections A and B. Summary:
- Cloud Console › project › enable Google Calendar API › IAM & Admin › Service Accounts › create (no roles) › Keys › Add key › JSON. Keep the file; it's the credential you'll push.
- Admin console › Apps › Google Workspace › Calendar › Sharing settings › External sharing options for secondary calendars › "Share all information, but outsiders cannot change calendars" (or "…and outsiders can change calendars" if you'll enable booking).
- Share each room with the service account email: See all event details, or Make changes to events for booking. Do this in Google Calendar (room › Settings and sharing) or with the Calendar API's
acl.insert(rolereaderorwriter) if you're scripting many rooms. - Collect each room's calendar ID: Admin console › Directory › Buildings and resources › Manage resources › the room › Resource email, e.g.
c_1882c…@resource.calendar.google.com. A spreadsheet of serial, room name, calendar ID is all the per-device data you'll need.
B. Apple Business Manager: licenses
- Apps and Books › Bored Room › quantity › Get. 99¢ per copy.
- Assign the licenses to the location your MDM server token belongs to.
- In the MDM, sync Apps and Books so the app appears in your catalog.
C. MDM: supervision and device settings
- Single App Mode requires supervised iPads. Use Automated Device Enrollment (devices added to Business Manager by the reseller or with Configurator for iPhone) or supervise with Apple Configurator.
- A Restrictions or device-settings payload that turns auto-brightness off, so iPadOS doesn't undo the after-hours dimming. Auto-Lock: Never (Single App Mode's own option covers this too).
- Decide your schedule policy now: always on, or days and hours. If you push none of the hours keys, the default applies: Monday to Friday, 07:00 to 17:00, dark otherwise.
Checklist
- Service account key file in hand; sharing setting changed; every room shared; calendar IDs collected (A)
- Licenses bought, assigned to the MDM's location, synced into the catalog (B)
- Supervision path chosen; auto-brightness-off payload ready; hours policy decided (C)
Configure the MDM
App
- Bundle ID:
com.dmarcantonio.RoomBoard(the App Store name is Bored Room; the bundle ID predates the rename). - Distribution: device-based. The iPads need no Apple ID.
- Automatic updates: on. Remove app on unenrollment: your policy.
Kiosk lock
Push a Single App Mode payload (Jamf: Configuration Profile › Single App Mode; Intune: Device restrictions › Kiosk; Mosyle/Kandji: Kiosk/Single App) targeting com.dmarcantonio.RoomBoard. Suggested options: touch on, sleep/wake button off, volume buttons off, auto-lock disabled.
Managed App Configuration keys
| Key | Type | Value | Where to get it |
|---|---|---|---|
serviceAccountKey | string | The key file's contents, raw JSON or base64. | The .json from Cloud Console › service account › Keys. Base64 it on a Mac with base64 -i key.json | pbcopy. Same value for every iPad. |
calendarId | string | The room's calendar ID. | Admin console › Directory › Buildings and resources › Manage resources › the room › Resource email, e.g. c_1882c…@resource.calendar.google.com. Also under the room's Settings and sharing in Google Calendar › Integrate calendar › Calendar ID. One per iPad. |
roomName | string | Text at the top of the board. | Whatever people call the room. One per iPad. |
pin | string | Exactly 4 digits. | Your choice. One per fleet is fine; it only guards the app's settings. |
allowBooking | boolean | Show "Book now" when the room is free. | Requires "Make changes to events" on the share and the "can change calendars" admin setting. |
showMeetingTitles | boolean | false shows "Meeting" instead of titles. Private meetings never show their title regardless. | Your policy. |
background | string | midnight slate ocean plum charcoal | Your choice. |
font | string | classic rounded serif avenir futura optima | Your choice. |
alwaysOn | boolean | true keeps the board lit around the clock. | Your policy. Leave false to use the days and hours below. |
activeDays | string | Days the board is lit, e.g. Mon,Tue,Wed,Thu,Fri | Three-letter English day names, comma-separated. Any day not listed is dark all day. |
activeHours | string | Hours the board is lit, e.g. 07:00-17:00 | 24-hour clock, 15-minute steps, 24:00 allowed as the end. Outside these hours the screen is black at minimum backlight and wakes for a minute on touch; a meeting in progress keeps it lit. |
If you push none of the three hours keys, the default schedule applies: Monday to Friday, 07:00 to 17:00. Any one of them locks the whole Hours section on the device.
With serviceAccountKey, calendarId, roomName, and pin set, the app skips setup entirely and boots to the board. Setting only some keys is fine; the app asks for the rest on first launch and locks what you pushed.
An AppConfig Community spec file for consoles that import one is at BoredRoom.appconfig.xml.
Example: property list (Jamf, Mosyle, Kandji, most consoles)
Paste as the app's configuration dictionary. Use MDM variables for the per-device values if your console supports them (Jamf: $DEVICENAME, Mosyle/Kandji: device attributes or custom fields), so one profile covers every room.
<dict> <key>serviceAccountKey</key> <string>ewogICJ0eXBlIjogInNlcnZpY2VfYWNjb3VudCIsCiAg…</string> <key>calendarId</key> <string>c_1882ctscth49aga2n3qo5aaud4m2e@resource.calendar.google.com</string> <key>roomName</key> <string>Board Room</string> <key>pin</key> <string>4821</string> <key>allowBooking</key> <true/> <key>showMeetingTitles</key> <true/> <key>background</key> <string>ocean</string> <key>font</key> <string>classic</string> <key>alwaysOn</key> <false/> <key>activeDays</key> <string>Mon,Tue,Wed,Thu,Fri</string> <key>activeHours</key> <string>07:00-18:00</string> </dict>
Example: Intune (iOS app configuration policy, "Use configuration designer")
| Configuration key | Value type | Configuration value |
|---|---|---|
| serviceAccountKey | String | (base64 of key.json) |
| calendarId | String | c_1882c…@resource.calendar.google.com |
| roomName | String | Board Room |
| pin | String | 4821 |
| allowBooking | Boolean | true |
| showMeetingTitles | Boolean | true |
| alwaysOn | Boolean | false |
| activeDays | String | Mon,Tue,Wed,Thu,Fri |
| activeHours | String | 07:00-18:00 |
Intune's "Enter XML data" option accepts the property list above verbatim.
Scoping pattern
One profile per room (or one profile with device variables), scoped to that room's iPad by serial or device group. The service account key and the PIN are identical across rooms; only calendarId and roomName change. A spreadsheet with serial, room name, and calendar ID is all you need to onboard 40 rooms.
Verification
- Push the app and the configuration to one iPad. On launch it should go straight to the board for the configured room.
- Hold the bottom-right corner › PIN › Settings. A banner reads "Some settings are managed by your organization" and managed rows are read-only.
- Create a test meeting in the room; it appears within 60 seconds.
- Push
activeHourswith an end a few minutes away. The board fades to black at that minute; a touch brings it back for a minute. Push the real hours.
Security notes
- The service account key grants exactly what you shared: read (or write) on those room calendars, nothing else. It's stored in the iPad's keychain. Rotate it from Cloud Console (new key, delete old, push the new value); the app picks up the change on next launch.
- No Bored Room servers are involved. The iPad talks to
oauth2.googleapis.comandwww.googleapis.comonly. Allow those if you filter egress. - Full details: privacy policy.
If something's off
- App shows setup instead of the board. One of the four core keys is missing or the dictionary isn't reaching the app. Check the profile is scoped to the device and the bundle ID matches.
- "That file isn't a service account key" at launch. The
serviceAccountKeyvalue is truncated or not valid base64/JSON. Re-paste. - No rooms / 403. The room isn't shared with the service account, or the admin sharing setting is still at free/busy.
- Board shows "Can't read this room's calendar anymore."
calendarIdis wrong or the share was removed. - Board is dark during the day.
activeDaysoractiveHoursis wrong for that iPad's time zone, or the value didn't parse (check the format) and the default Mon–Fri 07:00–17:00 is in effect. - Someone forgot the PIN. Change the
pinvalue in the profile; the app picks it up without a restart. The "Forgot PIN?" button on the device tells them to ask you.
Questions, or a console we haven't covered? hello@boredroom.space.