Developing a Mobile App for Coworking Management
Coworking—multiple space types with different access rules: open zones by subscription, meeting rooms by booking, private offices by long-term contract. Mobile app must cover entire spectrum, plus—become key access (instead of physical cards or door codes).
Meeting Room Booking: Time Slots
Meeting rooms booked for specific times. Main UX challenge—show free slots clearly and handle concurrent bookings:
// Android: time-slots with Jetpack Compose
@Composable
fun TimeSlotPicker(
slots: List<TimeSlot>,
onSlotSelected: (TimeSlot) -> Unit
) {
LazyRow(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
items(slots) { slot ->
TimeSlotChip(
startTime = slot.startTime,
endTime = slot.endTime,
isAvailable = slot.status == SlotStatus.AVAILABLE,
isSelected = slot.isSelected,
onClick = {
if (slot.status == SlotStatus.AVAILABLE) onSlotSelected(slot)
}
)
}
}
}
Slots load via GET /rooms/{roomId}/slots?date=2024-09-21. Poll interval with open booking screen—30 seconds, for instant reaction or WebSocket.
Digital Access via Mobile Key
Main feature of modern coworkings—smartphone instead of RFID card. Three ways:
QR on door—app shows dynamic QR (refreshes 30 seconds), static reader scans. Simplest.
NFC Emulation (Host Card Emulation on Android)—phone emulates RFID card. User applies phone to reader.
// Android: HCE for access
class AccessHCEService : HostApduService() {
override fun processCommandApdu(commandApdu: ByteArray, extras: Bundle?): ByteArray {
val selectAid = byteArrayOf(0x00, 0xA4.toByte(), 0x04, 0x00)
return if (commandApdu.startsWith(selectAid)) {
val accessToken = accessRepository.getCurrentToken()
accessToken.toByteArray() + byteArrayOf(0x90.toByte(), 0x00)
} else {
byteArrayOf(0x6F, 0x00) // unknown command
}
}
override fun onDeactivated(reason: Int) { }
}
HCE works without Apple Pay NFC reader—only Android NFC stack. iOS equivalent—Core NFC with NFCNDEFReaderSession, but card writing/emulation blocked on iOS. So iOS—QR or Bluetooth BLE.
Bluetooth BLE—locks with BLE chip (Salto, Abloy popular). App sends encrypted command to lock:
import CoreBluetooth
class BLELockManager: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
func openLock(peripheral: CBPeripheral, accessToken: String) {
guard let characteristic = lockCharacteristic else { return }
let payload = buildAccessPayload(token: accessToken)
peripheral.writeValue(payload, for: characteristic, type: .withResponse)
}
func peripheral(_ peripheral: CBPeripheral,
didWriteValueFor characteristic: CBCharacteristic,
error: Error?) {
if error == nil {
hapticFeedback.notificationOccurred(.success)
// Door opened
}
}
}
Subscriptions and Deduction
Coworking subscription—hours or days package. Deduction on each visit:
- Hourly subscription: time in/time out, deduct
ceil(minutes / 60)hours - Daily subscription: one day for any visit within 24h
- Unlimited: only check expiry
Balance updates real-time—via push after session close. If balance runs out mid-day—offer buy-more directly from notification.
Resident and Guest System
Long-term residents have permanent access and extended rights (locker storage, dedicated printer). Guests—one-time access via QR, which resident generates for colleague from app.
Guest QR—limited: specific zones only, specific date, single entry max:
def generate_guest_qr(
host_user_id: str,
zones: list[str],
valid_date: date
) -> str:
payload = {
"type": "GUEST",
"hostId": host_user_id,
"zones": zones,
"validDate": valid_date.isoformat(),
"singleUse": True,
"token": secrets.token_urlsafe(16)
}
return sign_and_encode(payload, private_key)
Timeline Estimates
Basic version (space catalog, meeting room booking, QR access, subscriptions): 5–7 weeks. BLE integration with specific locks—another 1–2 weeks depending on manufacturer. Pricing is calculated individually.







