SlideShare a Scribd company logo
Rapid Application Development 

with SwiftUI and Firebase
Peter Friese, Developer Advocate, Google
@peterfriese
🔥
Rapid Application Development with SwiftUI and Firebase
Demo 1

Kaffeinated - A coffee tracking app
Rapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and Firebase
SwiftUI
• A declarative way to build your UI

• Everything is a view

• Every SwiftUI view is a struct

• You build UIs by composing views
• Views are a function of their state
Better state management!
struct ContentView: View {
var body: some View {
Text("Hello, World!")
}
}
SwiftUI Views
Demo 2
Building a List From Scratch
Rapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and Firebase
Improve app quality
Crashlytics
Performance
Monitoring
Test Lab
App Distribution
Grow your app
Analytics
Predictions
Cloud
Messaging
Remote
Config
A/B Testing
Dynamic

Links
In-app
Messaging
Build better apps
Auth
Cloud
Functions
Cloud
Firestore
Hosting
ML Kit
Realtime

Database
Cloud
Storage
bit.ly/what-is-firebase
Rapid Application Development with SwiftUI and Firebase
Mobile Databases - The Hard Way
Database MongoDB, Postgres, MySQL, etc
API Server REST API on top of database
Auth Service Protects the API server
Sync Logic REST API calls, caches, etc
SQLite Store data offline
Cross-platform?
You're going to have to write the
same code multiple times!
App DatabaseServer
Rapid Application Development with SwiftUI and Firebase
One-Time FetchesOffline ModeEffortless Syncing
Document
bird_type:
airspeed:
coconut_capacity:
isNative:
icon:
vector:
distances_traveled:
"swallow"
42.733
0.62
false
<binary data>
{x: 36.4255,
y: 25.1442,
z: 18.8816
[42, 39, 12,
42]
Collection
collection("restaurants").
where("city", " ==", "Cairo").
orderBy(“rating”, "desc").limit(10)
Here ya go!
Add Firebase to Your iOS Project
1. Create a new Firebase project

2. Register your iOS app

3. Download configuration file

4. Install the Firebase Cocoapod

5. Call FirebaseApp.configure()
Kaffeinated Data Model
Fetching Data from Firestore
db.collection("coffees").addSnapshotListener { (querySnapshot, error) in
var coffees = [Coffee]()
querySnapshot ?.documents.forEach { document in
let coffeeName = document.data()["name"] as? String ?? ""
let shortDescription = document.data()["shortDescription"] as? String ?? ""
let description = document.data()["description"] as? String ?? ""
let caffeineAmount = document.data()["caffeineAmount"] as? Int ?? 0
let coffee = Coffee(name: coffeeName,
shortDescription: shortDescription,
description: description,
caffeineAmount: caffeineAmount)
coffees.append(coffee)
}
self.coffees = coffees
}
Fetching Data from Firestore
Rapid Application Development with SwiftUI and Firebase
Firestore & Codable
• One of our most-requested and
longest-running feature requests

• Released on October 22nd, 2019

• Makes fetching and writing much
easier
db.collection("coffees").addSnapshotListener { (querySnapshot, error) in
var coffees = [Coffee]()
querySnapshot ?.documents.forEach { document in
let coffeeName = document.data()["name"] as? String ?? ""
let shortDescription = document.data()["shortDescription"] as? String ?? ""
let description = document.data()["description"] as? String ?? ""
let caffeineAmount = document.data()["caffeineAmount"] as? Int ?? 0
let coffee = Coffee(name: coffeeName,
shortDescription: shortDescription,
description: description,
caffeineAmount: caffeineAmount)
coffees.append(coffee)
}
self.coffees = coffees
}
Fetching Data - w/o Codable
// Model
struct Coffee: Codable, Identifiable {
@DocumentID var id: String?
var name: String
var shortDescription: String
var description: String
}
// Elsewhere, fetch our data:
db.collection("coffees").addSnapshotListener { (querySnapshot, error) in
if let querySnapshot = querySnapshot {
self.coffees = querySnapshot.documents.compactMap { document -> Coffee? in
try? document.data(as: Coffee.self)
}
}
}
Fetching Data - w/ Codable
Saving Data to Firestore
let db = Firestore.firestore()
do {
_ = try db.collection(“users/(user.uid)/consumption/")
.addDocument(from: consumption)
}
catch {
print(“Error: (error.localizedDescription).")
}
Saving Data to Firestore
let db = Firestore.firestore()
do {
_ = try db.collection(“users/(user.uid)/consumption/")
.addDocument(from: consumption)
}
catch {
print(“Error: (error.localizedDescription).")
}
Saving Data to Firestore
We didn’t sign in, so what’s
this kind of magic?
Anonymous Auth
Auth.auth().signInAnonymously() { (authResult, error) in
guard let user = authResult ?.user else { return }
let isAnonymous = user.isAnonymous // true
let uid = user.uid
}
Anonymous Auth
let db = Firestore.firestore()
do {
_ = try db.collection(“users/(user.uid)/consumption/")
.addDocument(from: consumption)
}
catch {
print(“Error: (error.localizedDescription).")
}
Saving Data to Firestore
Sign in with Apple
let authUI = FUIAuth.defaultAuthUI()
authUI.shouldAutoUpgradeAnonymousUsers = true
authUI.providers = [
FUIGoogleAuth(),
FUIOAuth.appleAuthProvider()
]
return authUI.authViewController()
Sign in with Apple
Data Flow
Data Flow
• Property

• @State

• @Binding

• @ObservedObject

• @EnvironmentObject

• Sarah Reichelt: SwiftUI Data Flow
(bit.ly/SwiftUIDataFlow)
struct BarsView: View {
let bars: [Bar]
let max: Double
init(bars: [Bar]) {
self.bars = bars
self.max = bars.map { $0.value }.max() ?? 0
}
var body: some View {
GeometryReader { geometry in
HStack(alignment: .bottom, spacing: 0) {
ForEach(self.bars) { bar in
Rectangle()
.fill(bar.color)
.frame(width: 10,
height: CGFloat(bar.value) /
CGFloat(self.max) * geometry.size.height)
Data Flow - Property
struct MainView: View {
@State var selectedTab = 0
@EnvironmentObject var appState: AppState
var body: some View {
TabView(selection: $selectedTab) {
}
}
}
Data Flow - @State
class CoffeeListViewModel: ObservableObject {
@Published var coffees: [Coffee]
}
struct CoffeeListView: View {
@ObservedObject var viewModel: CoffeeListViewModel
var body: some View {
NavigationView {
List(viewModel.coffees) { coffee in
CoffeeCell(coffee: coffee)
}
.navigationBarTitle("Coffees")
}
}
}
Data Flow - @ObservableObject
class AppState: ObservableObject {
@Published var coffees = [Coffee]()
@Published var consumptions = [Consumption]()
}
let appState = AppState()
let contentView = MainView()
window.rootViewController =
UIHostingController(rootView: contentView.environmentObject(appState))
struct MainView: View {
@EnvironmentObject var appState: AppState
var body: some View {
HistoryView(viewModel: HistoryViewModel(consumption: appState.consumptions))
.tabItem { Image(systemName: “chart.bar.fill”)) }
}
}
Data Flow - @EnvironmentObject
Data Flow for Firebase Apps
MainViewAppState
[Coffee]
[Consumption]
User
...
Environment
CoffeeListView
CoffeeListVM
[Coffee]
Firestore
Demo 3
The Final App, Using Firebase
Rapid Application Development with SwiftUI and Firebase
Rapid Application Development with SwiftUI and Firebase
Conclusion
Conclusion
• Achieve great results in a short amount of time

• Documentation a bit lacking

• Great contributions from the community

• A number of things don’t work (yet)

• Fill the gaps with UIViewControllerRepresentable
Conclusion
• Work together well

• No critical issues so far

• Firebase team eager to hear from the community
+
❤
Thanks! Peter Friese, Developer Advocate, Google
@peterfriese
https://peterfriese.dev

https://medium.com/@peterfriese
https://medium.com/firebase-developers

More Related Content

PDF
6 Things You Didn't Know About Firebase Auth
PDF
Search APIs & Universal Links
PDF
Introducing Cardio
PDF
Lecture 11. Microsoft mobile services
PDF
Advanced SharePoint 2010 and 2013 Web Part Development by Rob Windsor - SPTec...
PPTX
01 startoff angularjs
PPTX
Advanced SharePoint Web Part Development
PPTX
Are you getting Sleepy. REST in SharePoint Apps
6 Things You Didn't Know About Firebase Auth
Search APIs & Universal Links
Introducing Cardio
Lecture 11. Microsoft mobile services
Advanced SharePoint 2010 and 2013 Web Part Development by Rob Windsor - SPTec...
01 startoff angularjs
Advanced SharePoint Web Part Development
Are you getting Sleepy. REST in SharePoint Apps

What's hot (20)

PPTX
Data Access Options in SharePoint 2010
PDF
A To-do Web App on Google App Engine
PDF
Usergrid Overview
PPTX
Grails Plugins(Console, DB Migration, Asset Pipeline and Remote pagination)
PDF
Salesforce Lightning Tips & Tricks
PDF
How to Contribute to Apache Usergrid
PDF
HTML5 New and Improved
PDF
Parse cloud code
PPTX
SharePoint 2010 Client-side Object Model
PPTX
Creating a Custom PowerApp Connector using Azure Functions
PPTX
SharePoint 2010 Application Development Overview
PDF
Open Source Mobile Backend on Cassandra
PDF
Try!Swift India 2017: All you need is Swift
PPTX
Lyudmila Zharova: Developing Solutions for SharePoint 2010 Using the Client O...
PPTX
Html indexed db
PDF
Eventbus Library and How Does it Work?
DOCX
SharePoint solution developer exam 70-488
PPTX
Exam 70-488 Developing Microsoft SharePoint Server 2013 Core Solutions Learni...
PPTX
Real World MVC
PDF
Online mobile game server use Firebase realtime aatabase
Data Access Options in SharePoint 2010
A To-do Web App on Google App Engine
Usergrid Overview
Grails Plugins(Console, DB Migration, Asset Pipeline and Remote pagination)
Salesforce Lightning Tips & Tricks
How to Contribute to Apache Usergrid
HTML5 New and Improved
Parse cloud code
SharePoint 2010 Client-side Object Model
Creating a Custom PowerApp Connector using Azure Functions
SharePoint 2010 Application Development Overview
Open Source Mobile Backend on Cassandra
Try!Swift India 2017: All you need is Swift
Lyudmila Zharova: Developing Solutions for SharePoint 2010 Using the Client O...
Html indexed db
Eventbus Library and How Does it Work?
SharePoint solution developer exam 70-488
Exam 70-488 Developing Microsoft SharePoint Server 2013 Core Solutions Learni...
Real World MVC
Online mobile game server use Firebase realtime aatabase
Ad

Similar to Rapid Application Development with SwiftUI and Firebase (20)

PDF
Rapid Application Development with SwiftUI and Firebase
PDF
Building APIs in an easy way using API Platform
PPTX
Chris O'Brien - Best bits of Azure for Office 365/SharePoint developers
PPTX
Going Serverless with Azure Functions
PPTX
Code First with Serverless Azure Functions
PDF
WebNet Conference 2012 - Designing complex applications using html5 and knock...
PPT
jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013
PDF
Medium TechTalk — iOS
PPTX
Basics Of Introduction to ASP.NET Core.pptx
PPTX
Saving Time And Effort With QuickBase Api - Sergio Haro
KEY
OSCON 2011 CouchApps
PDF
Serverless Framework Workshop - Tyler Hendrickson, Chicago/burbs
PDF
Building APIs in an easy way using API Platform
PPTX
Introduction to using jQuery with SharePoint
PDF
WebGUI Developers Workshop
PDF
Seattle StrongLoop Node.js Workshop
PPT
Php frameworks
PDF
Xitrum @ Scala Matsuri Tokyo 2014
PDF
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
PPTX
Introduction to the SharePoint Client Object Model and REST API
Rapid Application Development with SwiftUI and Firebase
Building APIs in an easy way using API Platform
Chris O'Brien - Best bits of Azure for Office 365/SharePoint developers
Going Serverless with Azure Functions
Code First with Serverless Azure Functions
WebNet Conference 2012 - Designing complex applications using html5 and knock...
jsSaturday - PhoneGap and jQuery Mobile for SharePoint 2013
Medium TechTalk — iOS
Basics Of Introduction to ASP.NET Core.pptx
Saving Time And Effort With QuickBase Api - Sergio Haro
OSCON 2011 CouchApps
Serverless Framework Workshop - Tyler Hendrickson, Chicago/burbs
Building APIs in an easy way using API Platform
Introduction to using jQuery with SharePoint
WebGUI Developers Workshop
Seattle StrongLoop Node.js Workshop
Php frameworks
Xitrum @ Scala Matsuri Tokyo 2014
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
Introduction to the SharePoint Client Object Model and REST API
Ad

More from Peter Friese (20)

PDF
Building Reusable SwiftUI Components
PDF
Firebase & SwiftUI Workshop
PDF
Building Reusable SwiftUI Components
PDF
Firebase for Apple Developers - SwiftHeroes
PDF
 +  = ❤️ (Firebase for Apple Developers) at Swift Leeds
PDF
async/await in Swift
PDF
Firebase for Apple Developers
PDF
Building Apps with SwiftUI and Firebase
PDF
Five Things You Didn't Know About Firebase Auth
PDF
Building High-Quality Apps for Google Assistant
PDF
Building Conversational Experiences with Actions on Google
PDF
Building Conversational Experiences with Actions on Google
PDF
What's new in Android Wear 2.0
PDF
Google Fit, Android Wear & Xamarin
PDF
Introduction to Android Wear
PDF
Google Play Services Rock
PDF
Introduction to Android Wear
PDF
Google+ for Mobile Apps on iOS and Android
PDF
Cross-Platform Authentication with Google+ Sign-In
PDF
Bring Back the Fun to Testing Android Apps with Robolectric
Building Reusable SwiftUI Components
Firebase & SwiftUI Workshop
Building Reusable SwiftUI Components
Firebase for Apple Developers - SwiftHeroes
 +  = ❤️ (Firebase for Apple Developers) at Swift Leeds
async/await in Swift
Firebase for Apple Developers
Building Apps with SwiftUI and Firebase
Five Things You Didn't Know About Firebase Auth
Building High-Quality Apps for Google Assistant
Building Conversational Experiences with Actions on Google
Building Conversational Experiences with Actions on Google
What's new in Android Wear 2.0
Google Fit, Android Wear & Xamarin
Introduction to Android Wear
Google Play Services Rock
Introduction to Android Wear
Google+ for Mobile Apps on iOS and Android
Cross-Platform Authentication with Google+ Sign-In
Bring Back the Fun to Testing Android Apps with Robolectric

Recently uploaded (20)

PDF
Softaken Excel to vCard Converter Software.pdf
PPTX
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
PPTX
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
PPTX
Reimagine Home Health with the Power of Agentic AI​
PDF
Wondershare Filmora 15 Crack With Activation Key [2025
PDF
Digital Strategies for Manufacturing Companies
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PDF
Understanding Forklifts - TECH EHS Solution
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
Odoo Companies in India – Driving Business Transformation.pdf
PPTX
ai tools demonstartion for schools and inter college
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Softaken Excel to vCard Converter Software.pdf
Agentic AI Use Case- Contract Lifecycle Management (CLM).pptx
Agentic AI : A Practical Guide. Undersating, Implementing and Scaling Autono...
Reimagine Home Health with the Power of Agentic AI​
Wondershare Filmora 15 Crack With Activation Key [2025
Digital Strategies for Manufacturing Companies
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
How to Choose the Right IT Partner for Your Business in Malaysia
Understanding Forklifts - TECH EHS Solution
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
VVF-Customer-Presentation2025-Ver1.9.pptx
Odoo Companies in India – Driving Business Transformation.pdf
ai tools demonstartion for schools and inter college
Upgrade and Innovation Strategies for SAP ERP Customers
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
Operating system designcfffgfgggggggvggggggggg
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
Which alternative to Crystal Reports is best for small or large businesses.pdf
Adobe Illustrator 28.6 Crack My Vision of Vector Design

Rapid Application Development with SwiftUI and Firebase

  • 1. Rapid Application Development with SwiftUI and Firebase Peter Friese, Developer Advocate, Google @peterfriese 🔥
  • 3. Demo 1 Kaffeinated - A coffee tracking app
  • 6. SwiftUI • A declarative way to build your UI • Everything is a view • Every SwiftUI view is a struct • You build UIs by composing views • Views are a function of their state Better state management!
  • 7. struct ContentView: View { var body: some View { Text("Hello, World!") } } SwiftUI Views
  • 8. Demo 2 Building a List From Scratch
  • 12. Improve app quality Crashlytics Performance Monitoring Test Lab App Distribution Grow your app Analytics Predictions Cloud Messaging Remote Config A/B Testing Dynamic Links In-app Messaging Build better apps Auth Cloud Functions Cloud Firestore Hosting ML Kit Realtime Database Cloud Storage bit.ly/what-is-firebase
  • 14. Mobile Databases - The Hard Way Database MongoDB, Postgres, MySQL, etc API Server REST API on top of database Auth Service Protects the API server Sync Logic REST API calls, caches, etc SQLite Store data offline
  • 15. Cross-platform? You're going to have to write the same code multiple times!
  • 21. collection("restaurants"). where("city", " ==", "Cairo"). orderBy(“rating”, "desc").limit(10) Here ya go!
  • 22. Add Firebase to Your iOS Project 1. Create a new Firebase project 2. Register your iOS app 3. Download configuration file 4. Install the Firebase Cocoapod 5. Call FirebaseApp.configure()
  • 24. Fetching Data from Firestore
  • 25. db.collection("coffees").addSnapshotListener { (querySnapshot, error) in var coffees = [Coffee]() querySnapshot ?.documents.forEach { document in let coffeeName = document.data()["name"] as? String ?? "" let shortDescription = document.data()["shortDescription"] as? String ?? "" let description = document.data()["description"] as? String ?? "" let caffeineAmount = document.data()["caffeineAmount"] as? Int ?? 0 let coffee = Coffee(name: coffeeName, shortDescription: shortDescription, description: description, caffeineAmount: caffeineAmount) coffees.append(coffee) } self.coffees = coffees } Fetching Data from Firestore
  • 27. Firestore & Codable • One of our most-requested and longest-running feature requests • Released on October 22nd, 2019 • Makes fetching and writing much easier
  • 28. db.collection("coffees").addSnapshotListener { (querySnapshot, error) in var coffees = [Coffee]() querySnapshot ?.documents.forEach { document in let coffeeName = document.data()["name"] as? String ?? "" let shortDescription = document.data()["shortDescription"] as? String ?? "" let description = document.data()["description"] as? String ?? "" let caffeineAmount = document.data()["caffeineAmount"] as? Int ?? 0 let coffee = Coffee(name: coffeeName, shortDescription: shortDescription, description: description, caffeineAmount: caffeineAmount) coffees.append(coffee) } self.coffees = coffees } Fetching Data - w/o Codable
  • 29. // Model struct Coffee: Codable, Identifiable { @DocumentID var id: String? var name: String var shortDescription: String var description: String } // Elsewhere, fetch our data: db.collection("coffees").addSnapshotListener { (querySnapshot, error) in if let querySnapshot = querySnapshot { self.coffees = querySnapshot.documents.compactMap { document -> Coffee? in try? document.data(as: Coffee.self) } } } Fetching Data - w/ Codable
  • 30. Saving Data to Firestore
  • 31. let db = Firestore.firestore() do { _ = try db.collection(“users/(user.uid)/consumption/") .addDocument(from: consumption) } catch { print(“Error: (error.localizedDescription).") } Saving Data to Firestore
  • 32. let db = Firestore.firestore() do { _ = try db.collection(“users/(user.uid)/consumption/") .addDocument(from: consumption) } catch { print(“Error: (error.localizedDescription).") } Saving Data to Firestore We didn’t sign in, so what’s this kind of magic?
  • 34. Auth.auth().signInAnonymously() { (authResult, error) in guard let user = authResult ?.user else { return } let isAnonymous = user.isAnonymous // true let uid = user.uid } Anonymous Auth
  • 35. let db = Firestore.firestore() do { _ = try db.collection(“users/(user.uid)/consumption/") .addDocument(from: consumption) } catch { print(“Error: (error.localizedDescription).") } Saving Data to Firestore
  • 36. Sign in with Apple
  • 37. let authUI = FUIAuth.defaultAuthUI() authUI.shouldAutoUpgradeAnonymousUsers = true authUI.providers = [ FUIGoogleAuth(), FUIOAuth.appleAuthProvider() ] return authUI.authViewController() Sign in with Apple
  • 39. Data Flow • Property • @State • @Binding • @ObservedObject • @EnvironmentObject • Sarah Reichelt: SwiftUI Data Flow (bit.ly/SwiftUIDataFlow)
  • 40. struct BarsView: View { let bars: [Bar] let max: Double init(bars: [Bar]) { self.bars = bars self.max = bars.map { $0.value }.max() ?? 0 } var body: some View { GeometryReader { geometry in HStack(alignment: .bottom, spacing: 0) { ForEach(self.bars) { bar in Rectangle() .fill(bar.color) .frame(width: 10, height: CGFloat(bar.value) / CGFloat(self.max) * geometry.size.height) Data Flow - Property
  • 41. struct MainView: View { @State var selectedTab = 0 @EnvironmentObject var appState: AppState var body: some View { TabView(selection: $selectedTab) { } } } Data Flow - @State
  • 42. class CoffeeListViewModel: ObservableObject { @Published var coffees: [Coffee] } struct CoffeeListView: View { @ObservedObject var viewModel: CoffeeListViewModel var body: some View { NavigationView { List(viewModel.coffees) { coffee in CoffeeCell(coffee: coffee) } .navigationBarTitle("Coffees") } } } Data Flow - @ObservableObject
  • 43. class AppState: ObservableObject { @Published var coffees = [Coffee]() @Published var consumptions = [Consumption]() } let appState = AppState() let contentView = MainView() window.rootViewController = UIHostingController(rootView: contentView.environmentObject(appState)) struct MainView: View { @EnvironmentObject var appState: AppState var body: some View { HistoryView(viewModel: HistoryViewModel(consumption: appState.consumptions)) .tabItem { Image(systemName: “chart.bar.fill”)) } } } Data Flow - @EnvironmentObject
  • 44. Data Flow for Firebase Apps MainViewAppState [Coffee] [Consumption] User ... Environment CoffeeListView CoffeeListVM [Coffee] Firestore
  • 45. Demo 3 The Final App, Using Firebase
  • 49. Conclusion • Achieve great results in a short amount of time • Documentation a bit lacking • Great contributions from the community • A number of things don’t work (yet) • Fill the gaps with UIViewControllerRepresentable
  • 50. Conclusion • Work together well • No critical issues so far • Firebase team eager to hear from the community +
  • 51.
  • 52. Thanks! Peter Friese, Developer Advocate, Google @peterfriese https://peterfriese.dev https://medium.com/@peterfriese https://medium.com/firebase-developers