[MUSIC PLAYING] [APPLAUSE] DAVID DEREMER: How's
everybody doing? SETH LADD: Hello. DAVID DEREMER: Good. All right. All right. We made it work. That's right. I'm David. I am a partner at a New York
City-based digital agency called Posse. We work with large brands
and large companies to launch mobile apps. SETH LADD: Hi, everyone. My name is Seth Ladd. I'm a product manager at
Google and I work on Flutter. DAVID DEREMER: So we're
really excited about today. We're here to tell
you about how we've used some of Google's latest
developer technologies to launch a successful
app in the United States in record time. As an agency, at
Posse, we always face incredibly tight deadlines. Our clients are
always pushing us to do more, faster and cheaper. So we're always looking for
cross-platform technologies, special architectures-- like
server-less architectures, like you've been
seeing a lot of today-- to help us do things quicker. Our clients want us
to deliver value, not lines of code or overhead. They don't want us to
reinvent the wheel. So we've been looking
at these technologies, but we always had a
bit of skepticism, a little bit of
lack of confidence in these solutions relative
to the alternatives-- until recently, when
we started working with Flutter and Firebase. SETH LADD: And we're very
glad you found Flutter. At Flutter, our mission
is to help teams build quality apps faster and easier. That's what we're all about. In fact, at Google
for a while now, we've been helping teams
build successful and business-critical apps. So then the question
we asked ourselves is, could we replicate the success
of Flutter outside of Google? So to help us answer that, we
started working with the Google Developer Agency Program, which
is how we met David and Posse. We thought Flutter was a
great fit for agencies, and any team that
wanted to move fast without sacrificing quality,
and needing to reach all users across all of mobile. DAVID DEREMER: When
we dug into Flutter, we finally found a platform we
thought we could really use-- a cross-platform framework that
worked for both iOS and Android to create apps that
felt indistinguishable from native apps, a reactive
coding style that felt really modern and highly productive,
a strongly typed language, which was very important
to our developer team, and a hot reload feature
that, once we saw it, and once we started
using it, drastically increased the efficiency
of our developer team. We were ready to dive
into this technology. But, as an agency, we needed
a client as excited about it as we were. And then it happened-- "Hamilton," the hit Broadway
musical based in New York City, called us up to do an app. And when we told them
about Firebase and Flutter, they were as excited
about this as we were. SETH LADD: Now, for those of
you who don't know, "Hamilton-- The Musical," is a
huge deal in the US. They have a very large and
very passionate fan base. The musical is
constantly sold out. It's nearly impossible to
get tickets to across the US. It's won 11 Grammys, a Pulitzer
Prize, an Emmy, and more. DAVID DEREMER: When the
"Hamilton" team came to us, all they cared about was
creating great experiences for their fans. They just wanted to give the
fans as much as they could. And they had no
internal tech team. So when we talked
to them about how we could do it, the idea of
maintaining two separate code bases for iOS and
Android, or maintaining a fleet of servers-- even on Google
Cloud or something easy like cloud infrastructure--
was really daunting to them. This is a lot of
technology for, basically, a bunch of theater people,
who have no technology experience, to own. So the promise of
cross-platform frameworks and server-less architectures
was really interesting to them. And, most importantly, they had
an incredibly tight deadline. For all the features
they wanted to do, we only had three months. And this deadline
could not be moved. SETH LADD: So, at that
point, the Flutter team was very excited, and,
honestly, a little nervous. Remember, at that time, it
was still early for Flutter. And it hadn't yet
been used for such a prominent, five-star,
consumer-facing app. The "Hamilton" team
had a long list of really important features
and an immovable deadline. So could it work? DAVID DEREMER: And, as if that
pressure wasn't high enough, we got a phone call from the
CEO of "Hamilton," who said, "Hamilton" is really big. The fans love it. We've never failed at anything. And this app will not
be the first time. SETH LADD: So this is
exactly the kind of challenge that our team is looking for. So, of course, we
said, yes, let's do it. The Posse team, the "Hamilton"
team, and the Flutter team devised a plan to execute. Posse would build the
app and design the app to the specifications
requirements of "Hamilton." And the Flutter team
would fix critical bugs and add crucial features
to meet all the use cases and requirements
for the app. DAVID DEREMER: So to give you
an idea of what's in this app and how complicated
it was, there's a whole lot of
features in here-- and, again, three short months. And so there's a lottery. The tickets are
really hard to get. You have to buy them a
year out and after-market they're like $1,000 apiece. So they have this
lottery where you can enter to win $10 tickets. Tens of thousands of people
enter these lotteries every single day. It was the most important
feature of the app. We also built a fully fleshed
out e-commerce experience for you to buy
"Hamilton" merchandise. And, of course, for
that, you need something like an integration with Magento
and some Stripe integrations for process payment-- all done on Firebase
and Cloud Functions. We had a news feed and even
this fun Ham Cam feature, which is basically a custom
camera with overlays, even location-based overlays
that you unlock at the theaters
and other places. A ton of features-- and that's just the
tip of the iceberg. And, again, we had almost
no time to do this. So being able to do this really
quickly and really effectively and beautifully, via
custom-branded design was absolutely essential. But the real question
for this was, could we build an app with
Flutter and with Firebase on this timeline with
all of these features, in a way that the
fans would love it and they would feel that
it was indistinguishable from a native app? SETH LADD: And, yes,
the fans loved it. The media loved it. And both the App Store
and the Play Store both featured the app. DAVID DEREMER: And its uptake
surprised even the "Hamilton" team. Since we launched, we've had
almost a million installs, nearly half a
million active users. We've already taken two
million lottery entries. And we are already one
of the fastest-growing apps on the Google
Cloud Function platform. And we show this to you
say Flutter and Firebase and a lot of these tools
you're seeing here today, they're not just toys. These are real things
that work in production at tremendously high scale. So Flutter and Firebase
are a huge reason that we got this app to
so many fans so quickly. The speed of development
and the features that are given to us
by these tools just really couldn't be
matched for our timeline. So what we want to
do now is, we're going to share some patterns
and some code to show you that you, too, can
use these tools, that you can
accelerate your process and benefit from them
just like we did. And we're going to start
first with Firebase. So Firebase offers
a ton of tools. You may have been to
some talks already today where they're talking
about all the cool ways that you can use Firebase. The really fun
thing about Firebase is that you can use as many
of these things or as few of these things as you want. If you just when you use
Google Analytics, no problem. It's really easy. Just add the SDK, add some
events, you've got analytics. We leaned on it heavily. We used Firebase for
basically everything. So this is new to us. Typically, we built web servers
and complicated web APIs. We only used Firebase
in this application. The authentication product
was one that saved us a tremendous amount of time. You add the SDK. Your authentication strategy's
already pre-baked for you, pretty much-- want to
do email, phone number, Google log-in, anything you
want to do-- it's right there. It's interoperability with
other Google Cloud Services, like Google Cloud
Storage, or Pub/Sub, or all of these
other tools that you have access to with Google
Cloud is really seamless. And it's really
easy to use them. So getting images served
out of Google Cloud Storage was almost trivial
with Firebase. And then there's the
real-time database. You know, it's a
different type of database than probably a lot
of you are used to. But it's real time. And that's something that
our team hadn't really experienced before. We were used to apps
where you make a request, you get a response. The real-time database-- once
you add the Firebase SDK-- it's right there. Your data is live. We're really proud of the
fact that our application doesn't have a single
pull-to-refresh anywhere in the app. What you see is what you
get, live, in real time. But, for us, the real
star of this story was Cloud Functions,
which is relatively new. Before this, we used
Firebase for other pieces, but not really as a
full, complete server. Cloud Functions
gives us the tools we need for this to be
a first-class backend for an app as big as this one. We used it to integrate
with Magento and Stripe APIs and all kinds of
third-party services. We used it to fan out
our data across Firebase. We used it as an API, which
I'll show you in a second. So we have all these
tools with Firebase-- we had the real-time
database, Cloud Functions. And one of the things, when
we were getting started, was, we had to
figure out, how do we make an API out of these tools? We're used to
building out express or rail servers, where
the app makes a request, does some work, you
get your response. You probably all have built APIs
like that before for your apps. We were struggling
with how do we do this. You know, we didn't want
to build a web server, because, you know,
what's the point of a server-less architecture
if you're maintaining servers. And then it hit us. We have this connection already
to our real-time database, the ability to
read and write data in like incredibly fast speeds. And we have Cloud Functions. So we devised this
asynchronous approach, where we use the database
as a connectivity mechanism and Cloud Functions
as our logic, to do the same work
that we'd typically do with a web service. So, as an example,
let's say the app wants to do something, for
instance, enter the lottery. What we do is we
drop a request-- we write a request-- to the Firebase
real-time database. We triggered a cloud
function based on that write. The cloud function does what
we need to do, you know-- checks the user-- we'll show
you some of this in a minute-- but does the work that we
don't want the client to do. We want it to be controlled
and protected on our server. When it's done, it
writes a response back to the real-time database. The database is-- or
the app is listening to this node on the database. And since it's real time, as
soon as we make that response, the app gets it, just
as if your web API responded with some JSON. And there we have it. We have an API. It was incredibly
powerful for us. Once we saw this pattern, not
only was it high-performance, it saved us a ton of time. This app has zero
networking code. We hit zero HTTPS
web APIs at all. Everything is done
through the database. So this was like
mind-blowing to us and saved us a tremendous
amount of time. So to show you
that this is real, and to show you how easy
it is to build an API using the real-time database
and Cloud Functions, we're going to
demo this pattern. This pattern is basically
the same exact pattern we're using in this app, that
tens of thousands and upwards-- we're getting into the hundreds
of thousands-- of users are using every single day. The first thing I wanted to show
you was our package of JSON. The reason I wanted to show
you this is that, on my team, we're always looking to
eliminate as many dependencies as we can. We really only need two
to get this started. We need the Firebase
admin module to talk to the
real-time database-- and do other things--
but pretty much to read and write to
Firebase from our server. And we need our Firebase
functions library to register our functions
and to find our triggers. You may notice that we
actually are doing a few things in our dev dependencies here. We're using TypeScript, which
you'll see, and Webpack. This was a personal
choice of our team, but one that really improved our
efficiency during the process. So how do we create a function? It's incredibly easy. This is just JavaScript-- well,
in this case, it's TypeScript. But, you know, at
the end of the day, you write it just like you
would write any other JavaScript function. You'll notice, again,
there's no node here. There's no express. There's no middleware. There's no body parsers,
nothing like that. All we do is we define
a trigger path-- how we want our
function to be invoked. In this particular
case, since we're doing our request-response
API, we want to on create. When someone adds new
data to our database, at a particular path
that we've defined-- in this case, requests lottery
entry, user ID, push key. When new data is written to
that path in the database, it's going to wake
up our function and do the work
we need it to do. So we've defined this here in
this enter lottery function. So the key thing here is,
why are we doing this? Why do we care? Historically, you might put a
lot of this work in the client side. Or Firebase gives you
direct read-write access from your app into Firebase. But we don't want people to
just be able to drop a lottery entry into the database. That's something
that could be abused. So we want this to be
protected behind our API. When the event fires
and is triggered, it passes this event
into our function. The event has a bunch
of params and data that we can access
from that event. So this is where we can
get from our database path-- we can get
the user ID, we can get the actual
data that the app passes to us in the request when
it saves it in the database. So it behaves kind
of like a web API. But it's just a database write. The next thing we do is we do
some sensitive business logic. These are just
kind of stubbed out for the purposes of the demo. But, you know, maybe we want to
check if the user's eligible, or make sure the
lottery is still open, or do something else that's
private, that we don't want the world to know about. We can do those all here. They're just normal JavaScript. They can be calls
to third party APIs, they can be asynchronous things,
we can send push notifications, save files, whatever
we want to do. But, assuming
everything's OK, we define our entry data object. And then we can save
it out to the database. Now this particular
area of the database-- like our lottery
entries right here-- this is something that is
protected by database rules. Nobody can read
or write to this. It's read-write false. And this is really
important because we only want our systems to be
able to allow people to create a lottery entry. By doing it in this
pattern, we can make sure that our API's safe. Once we're done with that,
and the user has successfully saved their lottery
entry, now we just need to write the response
back to our response node in the database. We have a little helper
function here called respond. We'll, maybe, post
some of this code afterwards, if
anyone's interested. But this just basically
writes our response object with some data-- like
here's your chance ID that was generated through
this, and maybe a message like, hooray, you
won the lottery. We write that back
to the response node. And since the app, after
it made the request, has an active listener
on the response node-- as soon as we make
that write, the app gets the update and the
spinner stops spinning and the app is done. You've entered the lottery. But there's a key point
we want to make here. Unlike a normal web request,
where the connection's open, and until you close that
connection, it's just kind of-- you're
hanging out there, you're waiting for the
response to finish. This is asynchronous. Once we make that
request to the database, the Cloud Function's
running in the background. It's almost totally
detached from the app. So even though we respond
to the app here and we say, hey, you know, hey, you're done. Congrats. We can keep going. Our Cloud Function doesn't
have to stop there. We can do some other
background tasks. Maybe we want to
fan out the data to other areas of the database,
or send a push notification, or do something else. And when we're finally done,
we just return and tell our function we're done. So it's really cool. Again, it saved us a
tremendous amount of time. And there's a few key points
I wanted to highlight here. We called this asynchronous,
database-driven API-- no networking code at all. On our team, we always
end up spending more time than we expect writing
code to interface with some sort of web server-- networking code-- that we don't
like writing, that we have to rewrite all the time, and
it takes a lot of extra time, and our clients
don't care about it. No networking. It was all handled by the
Firebase SDK the second we were able to interact
with our database. The other thing is that there's
no authentication or error handling. Again, all baked in
to the Firebase SDK. It's incredibly
high-scale as well. The Firebase database
scales really nicely. And it has this amazing
real-time performance that we were worried
about, how's this going to work performance-wise? But because it's such a
blazing fast database, the performance has been
really, really amazing. And, perhaps, most importantly
for our client and for us, no servers to maintain. We didn't have to worry about
the type of web server we're using, who's going to
patch the libraries, and all of the operating systems
that our servers are running, and how we're going
to provision this, how are we going to
handle the scale, and how are we
going to auto-scale whenever a lottery opens. Cloud Functions and Firebase
just did it all for us. So Firebase really
worked for us. It was a tremendous
win for the project. But it was only half the story. We also had to craft a
beautiful, custom design for "Hamilton," to really
showcase their brand in an app. And for that, we
turned to Flutter. And I'm going to turn
it over to Seth now, who's going to tell
you a little bit more about how Flutter helped us out. SETH LADD: Great. Thanks, David. So, as we heard
in the beginning, Flutter is a new mobile app SDK
that makes it easier and faster to deliver high-quality apps. At its technical core,
Flutter is a portable renderer and UI toolkit. Now all of these
layers you see here are compiled to native
ARM code for fast startup and predictable performance. But, even more importantly,
this portable renderer is shipped inside of your app. When you deploy your
app via APKs or IPAs, the renderer,
toolkit, and your code are all bundled together
and shipped out. This means that the beautiful
pixels your designers worked so hard on, and the beautiful
UI that your developers built, is the same beautiful experience
your users will get, no matter what OEM version or OS version
they happen to be running. Now, of course, I could
keep telling you about it, but it's much cooler to
show you about Flutter. So let's go to the
demo setup here. OK. We're going to show three
important parts of Flutter, which David and Posse
took advantage of when they built the "Hamilton" app. The first is our
reactive widget library. The second is hot reload. And the third is Flutter Fire. Let's start by looking
at the lottery screen here on these phones. This is an iOS phone. And this is an Android phone. You can see that it's a
beautiful brand-first design. And the colors look
similar down here. So they could deliver a
consistent UI experience across all their users,
across all of mobile. But just because
these look identical doesn't mean that they
have to act identical. Flutter and Posse
know that users on iOS have a particular muscle
memory when they scroll and a particular scrolling
friction on Android that people are used to. And so let's look
at a demo of that. On iOS-- I'm sorry, on Android-- you can see the
over-scroll glow. And on iOS, you get the bounce. So the "Hamilton"
app is beautiful and a consistent
brand experience and still feels very natural
to users on both platforms. OK. So let's pick a piece of this UI
and show you how we built this. We're going to pick the
little blue badge here, the active badge here, to play
with and show you how it works. So let's go to the code here. This is the code for
that active badge. And the first thing
I want you to notice is that it's all code. There's no markup,
there's no XML, there's no other language you
have to learn or build tools for. It's a single language and
a single set of libraries for you to build your
UI, manipulate your UI, and build your business logic. This means you get the power
of code and the power of IDEs like refactoring,
jump to definition, et cetera, when you build all
aspects of that front end. The other thing
I want you to see is that this Lottery State
badge, this active blue box right here, is itself a widget. Widgets and Flutter are the
core basic building blocks of all UI. In fact, widgets themselves
are made out of more widgets. This composition mental model,
this composition architecture, is very powerful. You can recompose
the core widgets that we ship in our toolkit-- things like padding,
things like text-- into more beautiful,
higher-level widgets, which themselves
can be composed. So it's a really good model. Now let's look at what it's
like to actually code this UI. Let's say that we did some
user studies and this blue here may be not working and
maybe the badge is a little too small. So we sit down next to
our designer and they say, what other colors you got? Well, of course-- well,
we have all the colors-- but, of course, we
have code completion, so you can see what
the options are. And let's say we
want to try green. So I'm going to save
it here in the code and jump over to a console here
that's driving these two apps. I'm going to hit r. And-- as it's initializing
the system here. OK, great. It has changed live,
hot reloaded, these UIs to change from blue to green. [APPLAUSE] Thank you. [APPLAUSE] This hot reload system really
enabled Posse and others to iterate very quickly in
their development cycle. But we can do more than
just change colors. Let's change some math here. Let's say we want to change the
size of this button here live. So we're going to go
over and reload here. And-- oh-- oh, no. So what just happened? Well, most of the UI
rendered just fine. But the widget here--
this active widget-- had a syntax error. And, luckily, the
framework said, I can render everything except
that one widget that you had. And I'm going to show
you what that error is. And it even tells me what
the syntax error is, here in the red little box. So, yep, sure enough. It's a syntax error--
forgot to finish. So let's go back here, type r. And in the time it
takes me look back here, we have not only recovered
from a syntax error live, without restarting
the app, but we fixed it, and now it's a lot
bigger for you to see. So, again, this hot reload
dev cycle is really fast. But there's one more aspect
of it that I want to show. Let's tap on this button
a couple of times. And let's add some
state to our app. OK. Hopefully, you can see, I've
tapped each button seven times. State in your app is
like, is a user logged in? Or do I have any
items in the cart? In this case, how many times
have I tapped the button? So we're going to make
another change here. Let's say active-- OK, save-- go back to the
console, hit r for reload. And, boom, right
there-- not only will you get that about a
second hot reload experience, but the state of my
app remained live. So it's a stateful hot reload. This is really
powerful when you want to work in that
one esoteric screen seven levels down in
your app after you log in and add two items to
your cart, et cetera. And you're all the way
down here in your app-- now you can paint
your app to life. You don't have to restart
that flow every time you want to make these changes. Stateful hot reload. Now the next thing
I want to show you is, right now we're
just adding numbers here when I tap the button. But let's make it real. Let's make it connect to
Firebase and those cool Cloud Functions that David
showed us earlier. So Flutter has an
awesome package manager, where you can just
declare your dependencies, get your plug-ins, get
your third-party libraries. And, of course, Firebase
through the Flutter Fire package is a first-class citizen
here in this ecosystem. So it's very easy to
declare this dependency. Now let's go over to the code
that handles this button press. And instead of just
incrementing a counter, we're going to
enter the lottery. Now let's look at the code
for entering the lottery. There's two things
I want to point out. One is these calls to set state. This is a framework feature of
Flutter, where you can easily identify where the state of
your application is changed. It makes it very easy to look
around your code and say, this is where we update the
state or your domain model. Second, it tells Flutter
Framework, rebuild your UI. So this is that reactive
part of the Flutter framework that we're talking about. The second thing I want to show
is post-action, a very cool function that Dave
and his team wrote to encapsulate that async
request-response pattern that we saw earlier,
which triggers Cloud Functions, et cetera. Let's just jump in
here real quick. I just want to
show here a couple of lines of Firebase code. This is normal Firebase code. If you're used to
Firebase, these APIs are going to feel very familiar. It's all brought up into
Flutter for you to access. All right. So we've made a significant
change to our application here. We've added a huge swath
of business logic and code to our app. Now let's do a final hot reload. In about one second,
again, our app is updated. And when I tap this button,
we're now really talking to real-time database, which
really listens for Cloud Functions and really
waits for a response-- all hot-reloaded
and live for you. Come on-- I was-- yes, OK. OK, good. So there's obviously a
lot more cool features to Flutter and Firebase. But, hopefully, you've got
a sense of how fast, fun, and easy it is to
build beautiful UIs and connect it to Firebase. So the question is-- if we
can go back to the slides-- is how did this actually
work for David and his team? DAVID DEREMER: So Flutter
was really, really important. Again, we had a
really tight timeline. And we had a client with
really high demands, both in terms of the
features and the experience we had to deliver. And we wanted to deliver this
beautiful, branded experience across both platforms-- iOS and Android. And we didn't have
time to make sure that every little pixel was
perfect on both platforms. So Flutter really
helped us there-- coding once, seeing the designs,
live on both-- but yet still feeling very natural
and feeling very native. The other thing is that it
allowed us to move really fast and experiment. Our designers were
constantly tweaking things. The client always had new input,
or once they'd get a build, they'd want to change something. So the ability to move
fast and use tools like hot reload to modify that
design in real time saved us a ton of time. Also, in the long run, Flutter
provides an amazing ability to reduce our maintenance costs
and, also, decrease the cost of adding new features. Because every single
time we need to fix a bug or change a design
or add a new feature, we just have to do it one place. And our developers say that
laying out UI with Flutter is significantly faster
than on iOS or Android. And the hot reload, you know-- if you are all mobile developers
here, or if any of you are-- waiting for your application
to recompile and navigate down to where you need to go-- I mean, this is real
money, this is real time. Our clients are paying for
us to develop these apps. So every second our developers
are not waiting for X-code to reload the application,
that's more time we're working on features. And also, because of things
like Flutter Fire and Flutter's plug-in system, and
using tools like Firebase and all of the great resources
we have at our disposal, we spent less time
building plumbing in the technical overhead in
order to make this app work, and more time
working on features. So I'm wondering,
you know, has anyone here faced an incredibly
tough deadline in the work that you do? Have you ever felt
pressure from your bosses or your senior leaders to
ship more features faster? Have you ever had a design team
that wants you to react faster, iterate a design quicker-- I have a new design, can I see
what it looks like on screen? Or perhaps you have
stakeholders in your business that don't want to hear it
about your cool infrastructure solution, or about
the code you've written to optimize this,
that, or the other thing-- they just want to see
new features, you know. What have you done
for me lately? What kind of value are
you adding to our business and to our application? So Flutter and Firebase, for
us, was a tremendous toolkit to deliver on those
needs-- you know, tough time line, branded
design, beautiful experience, complicated features,
protected operations and logic in the back end. And it's really
easy to get started. SETH LADD: That's right. It's less than a minute to
create a Firebase project. And Flutter is open source. You just get Clone or Repo. And we even include a command-- Flutter create-- to
bootstrap your first project. We encourage you to
visit our office hours up on the third floor. And we have instructor-led
trainings for both Firebase and Flutter today and tomorrow. DAVID DEREMER: And we hope that
our talk today inspires you all-- that these aren't just
cool technologies. Real businesses at real scale
are using these out there today to run production code. So we hope that you
can embrace some of the learning
you had here today and go out and try
something amazing. Thank you very much. SETH LADD: Thank you so much. [APPLAUSE] [MUSIC PLAYING]