Let's Learn Firebase!
If you want to create a Jamstack app quickly, Firebase is a great option. In this episode, David East teaches us how to get started with Firebase to build powerful apps on the Jamstack!
Links & Resources
Click to expand the full transcript
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
JASON LENGSTORF: Hello, everyone. And, welcome to another episode of Learn With Jason. Today, we have David East.
DAVID EAST: Thank you for having me. I'm a big fan of this show, so when you asked me to come on, I was like, "yes! I've made it!" (Laughter). I'm pretty stoked.
JASON LENGSTORF: I've been talking about Firebase with my team, actually. I work with people who are big fans of Firebase. They really like the API.
DAVID EAST: They are great people.
JASON LENGSTORF: My experience with Firebase is superlimited. I worked on a project once, with Sarah, and she did all the Firebase. I worked on the code around Firebase. I've never actually implemented it. People love it. I hear so many developers say they really like this experience. So I'm really excited to dig into it.
I want to talk about you. Could you give us a background on who you are?
DAVID EAST: So, I'm David East. I'm a developer advocate at Firebase. I I actually realized the other day I've been doing Firebase longer than I've done any other job in my life. Six and a half years. In tech industry, that's when you get your gold watch. (Laughter). In tech industry, it's six years. I've been waiting for Google to send me a watch, but they I haven't seen it. But, you know.
JASON LENGSTORF: That's a long time. I feel like, now, if you cross two years, it's, like, you've really you've stayed there for a long time.
DAVID EAST: That's what I thought. Remember, just, like, before, being at Firebase for the first year, it was at Google and I had only worked at small companies before. My very first job, out of school, I was the very first intern for this very small contracting firm and they were very tightknit. It was me and a handful of other people. And then I went to another company that was 20someodd people. Firebase was smaller when I joined. I was the 16th cumulative employee. And then at Google, I was like, oh, my gosh! There's more people in this elevator than I've been in an office before.
JASON LENGSTORF: How big cause Firebase when it got acquired?
DAVID EAST: I think I always forget. 2324 people.
JASON LENGSTORF: Wow! That's a ride. That's that's pretty intense.
Your coworker pools grows by 100,000%?
DAVID EAST: We came in, for the first couple months or so, it was just the 23 of us. Nothing really changed. We just got more food and, like, free coffee. So, that was we were like and the Firebase office was, like, only a couple blocks away from the Google office so they were like, you're here today, you're going to be over there tomorrow. You took an extra bus stop and then I was there and then, like, first day, though, it's kind of cool because, like, Google does their big company meeting weekly company meeting every Thursday and they announced that we oh, we acquired Firebase and I had my Firebase TShirt on. For that 15minute period of time, everyone's like, good job, welcome. (Laughter).
JASON LENGSTORF: Oh, that's great. Well, cool. Yeah, so, I I'm not going to lie. Firebase is always it's been a little mysterious to me. Sometimes I hear Firebase talked about as a user management system. Sometimes I hear it talked about as a database. Sometimes I hear it talked about as an app framework. If you're trying to describe it to someone, how do you talk about Firebase?
DAVID EAST: I'm so happy you asked me this question because this is, like well, it's my job. But also, I have a great answer for it. I, like, rehearsed this for every time I give a talk because it's like you've seen the intro to my generic meetup talk. Okay. Enough leading into it. (Laughter). Basically, yeah, like, I tell people, if you scroll through Firebase.Google.com/products, there's 19 things that Firebase does. I could take you through a slideshow where it's like, this is Firebase for X and Firebase for Z. It kind of feels like I'm showing you my vacation photos and you're like, oh! I don't get it. This is boring. Firebase is 19 different things but you don't need to do all 19 things. You may only need to do one thing. It's about building fast. You can get to production fast. You can build an auth system fast. You can get to scale. Firebase Store is really fast. You go from, like, not having like, you have some client app that's not signing in users or not syncing data in realtime or not A/B testing and you get that feature like that. That is the goal. Within five minutes, you should see something happening and it's cloudconnected, serverless even working on serverless, you know what I'm talking about.
JASON LENGSTORF: I do. I do. Yeah.
DAVID EAST: The whole goal is to make it very accessible and easy to get started with.
JASON LENGSTORF: Excellent. I'm superexcited. However, I think we haven't had a chance to talk. I have no idea what to build today. Chat, we need your help. What should we build today with Firebase? Like, it sounds like we're kind of just open field here. We can think of anything. So, is there something that you wanted to show up, in particular, David?
DAVID EAST: Um, I think if we're going to the biggest bang for our buck, always the nice, magical, easy to get started experience is using Firebase Auth, signin a user data and use that to sign into Firestore. That is the first layer of business. Then if you kind of, like, get past that checkpoint oh, that was fast then we can, I don't know, use cloud storage and, like and upload files. I don't know. There's a lot of things we can do.
One of my favorite things to do is use Remote Config to store CSS. It's a key value system with superpowers. You have a key that's admin user and the value could just be you can have multiple values associated with it, based upon a condition. So, like, 50% of users get this so that's good for A/B testing. If they're from this location, so, I store CSS in it and inject the CSS into the page based upon different values. A lot of them nonsensical, it makes it a lot of fun. There's lots of different stuff. Analytics, performance.
JASON LENGSTORF: Let's make a quick app where we can register and sign up and then we can post our favorite Corgi photos. This is going to be a trust exercise, chat, because you're going to have to be good people because I swear to God, we will never do anything fun on the show again if you abuse my trust here. (Laughter).
DAVID EAST: You need to use an ML APIs that tells you. (Laughter).
JASON LENGSTORF: Does Firebase do that?
DAVID EAST: I think Google Cloud does.
JASON LENGSTORF: So, we can build that and maybe what I'll do is before we look at user submissions, I'll review them offscreen, just in case you hackers. You dirty hackers. Occasionally, they become hackers. (Laughter). I'm going to switch us over to pair programming view. Let's do a quick shoutout to our sponsors. We've got live captioning by White Coat Captioning. We really appreciate it. That is made possible by Netlify, Fauna, Sanity and Auth0, who all pitch in to make this show more accessible to more people. If you'd like to follow the live captioning, it is lwj.dev/live. Go follow David on on the Twitter because you'll get lots of good information there.
DAVID EAST: The Twitter. I have 13.9k followers and, like, I'm never a big, like, person with Twitter followers. I'm always like, oh, that's cool. People listen. But I dislike deeply the number 13 and so I've been sitting there for so long. I'm so close. I just need, like hover over it.
JASON LENGSTORF: 13 of you, go follow David right now.
DAVID EAST: I would really appreciate not seeing the number 13 anymore. 1.9,000 of you unfollow me. I'm just asking not to see 13 anymore.
JASON LENGSTORF: Can we roll it over while we're on this stream? There's three more. Ten more of you, go follow David. Let's make this happen. Where you at? 91.
DAVID EAST: Is this like those oldschool, 1990s
JASON LENGSTORF: '92.
DAVID EAST: I'm going to have to do this more often.
JASON LENGSTORF: Let's talk about Firebase. I'm not kidding, chat, get over there and make it happen.
Let's talk about Firebase and see how we get started. It looks like I'm logged in and I'm logging in good, that's account I want to be logged in on. I'm going to click this "get started" button.
DAVID EAST: I don't know through the flow, through, like, the main thing because I just, you know, all the codes actually I don't know what that means. I've heard the kids say it. So, I do you could click "get started." Yes! Jason, your show is great! Do you need something from me?
JASON LENGSTORF: Look at you go!
(Laughter). Yeah, thank you, chat. You've done a great service today.
DAVID EAST: It's made my day. So (Laughter).
JASON LENGSTORF: Okay. Oh, I've built things on here.
DAVID EAST: Also, your email. (Laughter).
JASON LENGSTORF: You know what this one is? My partner, Marisa, built this. I wonder if this is still alive?
[Music playing]. Yes! She built this. Marisa built this thing that it allows you to write emails to your clients. So, like, if you okay. A client didn't respond to an email about a missed deadline. So, you go in here and you click it oh, wait. So, you have to actually fill out the whole template. I got ahead of myself. So, I'm Jason. You're my client. I can take a call today. Let's do it in the morning. Uhhhh, it's been a week. (Laughter). Look at this! Now, it's this very professional email template that you can use to send to your client. But, yeah, it's how good is this? It's got all these professional wordings. Marisa needs to do more with this. It's so good. Let's share that with the chat. That's a good one. And that's built by Marisa Morby.
DAVID EAST: I love stuff like that because messaging is one of those things you really have to, like you know, when you write something, your motion like, you're too stoked. Of course, we all know what it's like if you're too angry. If you're superhyped about something, everyone's like, "whoa! Slow down there, Dave!"
JASON LENGSTORF: Slow down there, Dave. You're getting a little ahead of yourself.
I'm going to start a new project and our new project is going to be "Corgi photo gallery.
DAVID EAST: I'm going to give you a pro tip here. Don't do anything crazy. Also, wait. Scroll down. You are negative 1 projects away.
JASON LENGSTORF: Oh, no!
DAVID EAST: You must have had a bunch of cloud products. We have a limit of, like, 11. But cloud a Firebase project and a Google Cloud project is a same thing. It just really is the same thing.
JASON LENGSTORF: Let me log into another account then. I'll be right back. I'll do this offscreen.
DAVID EAST: Yeah. That's a good idea. I did once, however I gave a talk
DAVID EAST: I was unveiling Angular 2, when it was still called that. I don't know why they let me give that talk. I was cycling through my tabs and I cycled through my Google email tab and I was less than six months at the company. I remember just being like, oh, my gosh, I just leaked my email. I got it cut out, so it was fine. But then I actually looked at the email, it was literally like the most mundane list of emails. It was literally people being like, hey, we're going to have lunch at 12:30 instead of 12:00 today. I wonder what life of a Googler's email is like? They'd be like, that's not very interesting.
JASON LENGSTORF: Top secret: We're getting cake!
DAVID EAST: There's muffins in the micro kitchen.
JASON LENGSTORF: When I was at IBM, we had Slack and there were multiple channels dedicated to where to find the free food. All the interns and firstyear hires didn't eat food. I think they only scavenged food and roamed between buildings.
DAVID EAST: Google's communication is like, "what free food should we go to today?"
I've always found it just to be unreal, the amount of free food at Google. 20%, which is parttime working on the Angular team, they used to be next to the caf called Masa, which did Mexican food and I loved it. Because it's like going to Chipotle. I remember going down, one day because I usually worked in San Francisco, I lived in Mountain View. Everyone would be like, oh, no! Not Masa, because they'd go every day.
Anyways, your project name, this is important. So do you see at the bottom, there's that ID? There's your name and your ID. The ID's superimportant. This is your this gives you a short URL for whatever REST APIs. I like to see how short or snazzy I can get it. I thought I saw "Corgiphoto" is available. This will be in all of your URLs, if you create a REST API. Corgi so, I do this all the time. I will literally spend an hour being, like, oh, I need the name to be right. "Corgi Photo" is a good one. Pro tip, spend time on your Firebase ID.
JASON LENGSTORF: Dev advocacy is a very fun job and I'm superhappy to hear you're interested in it. I hope we're helpful in not turning you away with our silliness. (Laughter). No, this is a lot of fun. Do I need to do something else here? Select parent resource?
DAVID EAST: Click that. I think you need to be in an org oh, okay. It's because you're logged in. It's because you're logged in with our Netlify Corps that we're off to a bad start.
JASON LENGSTORF: Just don't tell them that we're doing that.
DAVID EAST: That's fine. (Laughter).
JASON LENGSTORF: I'm going to get an email about this. (Laughter).
DAVID EAST: If you have a corps thing, there's all these different permissions and your #enterprise.
This is cool, this is setting up Google Analytics. We have this big screen because of how we have our big integration Google Analytics. If you're coming from an old Google Analytics property, we have a screen to let you know that, hey, Google Analytics is a part of this. In this case, it's fine because you're coming in fresh. People who are not coming in fresh
JASON LENGSTORF: Would be sad, gotcha.
DAVID EAST: So I'd just create a new account here.
JASON LENGSTORF: Good call. Let's do that.
DAVID EAST: "Corgi photo" or "Learn With Jason." This is all GDPR stuff.
JASON LENGSTORF: I have created a project.
DAVID EAST: This goes out sends all these REST APIs. We call this Fire Console. I used to work on this for a good, solid year or so. The amount of REST APIs that are firing out. I make it sound like there's 100, it's four.
JASON LENGSTORF: That's a nice, little animation. I wasn't even paying attention to the fact that we were waiting.
DAVID EAST: We have an amazing UX team and they are all about the animations.
So, now we are so, the first thing you want to do, now, is you got the little code bracket for "web" next to the iOS and Android button. You click that thing. And then, now, I just call this I usually call this "default." You can call it whatever you want. For web, this is less important. You click "register app now." And, for web, it's a little less important. There's a couple resources where this is important. We will get this this how do I want you to do this? All right. Leave this screen open and let's now finally open up the Code Editor. You want this config and everything we'll do after the fact so I probably want you to have this config readily see your auth domain and your storage bucket and your database is all "Corgiphoto." I'm all about the vanity. (Laughter).
JASON LENGSTORF: All right. So, let's get in here and then I'm going to initialize this and then let's open it up in an editor. We've got an empty folder and we are ready to do whatever it is we need to do.
DAVID EAST: What can we do? Let's start with we're going to make this file, so, how do you want to make this? What is your are you, like are you digging any specific framework? Are you, like, just feeling like document.queryselectorall?
JASON LENGSTORF: Let's stick with plain HTML.
DAVID EAST: Document I like when you bind document.queryselector to the document and you store it to $, and it looks like jQuery.
JASON LENGSTORF: Good. Let's do that.
DAVID EAST: It's a really bad jQuery, but jQuery, nonetheless.
JASON LENGSTORF: Wait,.bind?
DAVID EAST: Now it will return it to a function to the document. (Laughter).
JASON LENGSTORF: This is wonderful.
DAVID EAST: This is modern development. (Laughter).
JASON LENGSTORF: And I love it, too, because now we'll just be able to this is such a throwback for me, like, we'll just be, like, give me all the links.
So, now, we've got we've got jQuery installed. I'm ready. We need to build, like, an H1 "share your Corgi photos."
DAVID EAST: That's a proper H1, too. This is just semantic HTML.
JASON LENGSTORF: It is, indeed.
Then we've got probably a section or yeah, a section. And we can call this "photos." And then, like, this is where I'm going to need your help because I'm not 100% sure how much Firebase is going to do for us versus how much we're going to be writing ourselves.
DAVID EAST: So, any DOMrelated stuff, that's not browserAPI specific, but DOMspecific, Firebase is not going to have any opinion about that. We have some libraries that are much more addon, but the core of Firebase doesn't do anything with view manipulation. So, what we will need to do is add in Firebase scripts, which is back in that there's a good section for you to copy, that's why I wanted you to leave that open so we could have something readily to copy into. We'll use this from the CDN and then we'll just initialize in a script belowhand. So, that script, right there, the top one, yeah, just do this top one right there. Yeah.
JASON LENGSTORF: Okay.
DAVID EAST: And so
JASON LENGSTORF: You want this in the head?
DAVID EAST: Put this in the body. So that way, the scripts put it at the bottom of the body because we could defer this script, but then you can can't defer embedded scripts so things could get murky. We want to make sure we have access to Window.Firebase.
JASON LENGSTORF: Got it.
DAVID EAST: So, let's just start with this for now. So, go down below window.$, and let's initialize a Firebase app. This is sort of like the core this is like your container of of your all of your Firebases stuff. So, if you create a variable, like "Firebase app." I like that, canst. "I canst do it today." (Laughter). You can say "window.Firebase.
JASON LENGSTORF: Is it capital?
DAVID EAST: Lowercase "firebase." And.initialapp. Then go back and we're going to copy that snippet. See that config? You I usually just copy into POJO.
JASON LENGSTORF: Okay. And then you said POJO. What's POJO?
JASON LENGSTORF: Thank you for the tip on using Emit for the fullbody.
We've got jQuery and we've got Firebase. (Laughter).
JASON LENGSTORF: If we do something like right. If we do something like that, it actually means something slightly different than if we do this. And it's just I don't know. I try, as hard as I can, to never use this because it's so, so hard to keep that straight in your head. There are good resources that I'm not remembering right now, that explain how context work.
Chat, I don't know if you remember any of these.
DAVID EAST: I'm completely doing this from memory.
Your feeling is correct.
As a little bit of just reassurance over all this configuration you just put in a lot of people are like, huuuuh, because it feels like private keys. It doesn't help that we have a key called "API key." When we see something named that, we think it's private. But in this case, it's not private. None of this stuff is insecure to put in your app. They're all client IDs and the things that make your Firebase code or your Firebase backend insecure, it's not this. This is not there's a whole security role, which if we have time, I can show you. You write a language we have. You annotate in your spots who has access to what, to see who's the loggedin user. This is all configuration that points to all these different Firebase things, not all of them are needed all the time because you're probably not going to use messenger ID, that's for push notifications. Some of them are important, API key, project ID is needed and ID. It's a couple bytes.
JASON LENGSTORF: Sure, yeah.
DAVID EAST: Now we have a Firebase app and what this does for you is nothing because all
All we have is just a Firebase app. We need so, Firebase app when we import other services, it'll augment it and provide it on it. You do "app.blah." As you include more scripts, you get more "blah." That's the technical term for it now. If you scroll up to where you included the Firebase app, if you just kind of duplicate that script and instead of "app," change it to "off." That's the pattern across all of this. Gstatic is Google CDN. There's the version number. We'll do a "firestore." Include "firestore" in there now because we'll forget it otherwise. It's one of those things I'm going be like, what do you mean it's not defined?
Now, let's go down to below the config and let's write some code.
JASON LENGSTORF: I'm going to collapse this.
DAVID EAST: It's not going to give you the bottom because there you go. I do that all the time. So, now let's get an instance of auth. Do a "canst auth equals." I'm not going to stop with that, by the way.
We have an auth instance and it's a singleton behind the scene. But this gives us access to all these methods on auth. We can log users in. We probably need a button click, I would guess, just to make this thing work. So, I would add a login and a logout button and we'll make that work.
And naturally, this is actually going to fail when we do it but I know it's going to fail and that's a part of the learning lesson, because this is Learn With Jason.
JASON LENGSTORF: Exactly. And now we get to use jQuery.
DAVID EAST: I miss jQuery. If you go early, like 20112012, I have screencasts about jQuery.
DAVID EAST: I remember the moment I did the "$, slide down." (Laughter). Someone wrote "jQuery's a gateway drug." Very true. The next thing you know you're covered in V DOM. (Laughter).
JASON LENGSTORF: I mean, that's not wrong. (Laughter). I got login and logout. So I'm going to need to attach something to these, right?
DAVID EAST: Yes. So, let's do adamant listeners. And we'll listen to the clicks. We'll just do "login" for now. Do the gets to the event. Doesn't matter, it doesn't need the event.
JASON LENGSTORF: Is it like this?
DAVID EAST: Do a callback function.
JASON LENGSTORF: I see where you're coming from.
DAVID EAST: Someone's like, it should work. I'm like, it should. But when it doesn't, it doesn't.
So, then inside here, we're going to call "auth.signinI." Let's see if you can do this. I failed on this. Spell "anonymously." Do "A." That's the whole thing. Congratulations, Jason, you progress to the next round.
JASON LENGSTORF: I, indeed, won a spelling bee, when I was a young child. (Laughter).
DAVID EAST: I went really far to represent, for my whole grade. And I lost on the very last word. I can't even remember what it was. It was very simple and my brain was like, we're done here. That's enough words. (Laughter).
JASON LENGSTORF: Do I have to pass any parameters?
DAVID EAST: Nope. So, this, right here, does return a promise. But, we don't have to use it because the way that so Firebase Auth will provide you a bunch of different ways to signin your users. This one's the easiest one to use and it's the coolest one, too. You can sign in with Google, Facebook, Twitter, GitHub, Microsoft. Email password, email link, phone number. Anonymous Auth is sessionbased. What's cool about this is you can just log somebody in and it just works. And then actually, if they want to upgrade their account, you can link them with a permanent account so all their information gets returned.
The better way of managing authentication state is to go to, like, line 44. We're going to write a callback function function that takes a callback." Auth.onoffstatechanged." And then do "user" for the param of the error function. This is the realtime auth state. So, if the user logs in, boom, it'll fire off. If there's no user logged in so, if no user logs in if no user is logged in, that is, it will fire with "null." So, like, you can listen to that and know that nobody's logged in yet.
If you're used to Redux, it's like dispatching login and your reducer.
JASON LENGSTORF: Am I good to run this? You said it's not going to work yet.
DAVID EAST: It's not going to work, but I know why that whole bind thing is always precarious, too.
JASON LENGSTORF: It's running on 8080. All right.
DAVID EAST: Let's open up the Dev Tools. We got an error. That's good, I think. What does it say?
JASON LENGSTORF: Let's see "on/off stat change."
DAVID EAST: We could add that method, if it's easier for you. (Laughter).
JASON LENGSTORF: We got a "null," which means we're not logged in, right?
DAVID EAST: Click "login."
JASON LENGSTORF: It tried to post to Identity Toolkit and we got an error.
DAVID EAST: You have to go into the console and explicitly enable this as an auth permission. You don't want people to be able to just log in to your projects. If you go back to your Firebase dashboard console, click "continue to console." Click "develop." Then the first one is "authentication." Now, we don't have any users yet. If you click "signin method," here will be the list of all the things you can do. If you scroll to the bottom Apple Signin. Now toggle that and click "save." Now, it'll work. "Null" still.
JASON LENGSTORF: Logged in. I like that it logs
DAVID EAST: I believe it's still closure compiled through. It's all written in typescript. I'm not sure. But, basically, it's closurecompiled so you're going to get those crazy ones. On the prototype, you'll see a couple ones that are real properties and stuff.
Basically, one of the UID is the important one because UIDs unique identifier that is what you use I use that to associate data against a user, which is a great segue to start with I guess we could do it if we're going to do Corgi photos, we should probably do storage, first.
JASON LENGSTORF: Yeah. I was going to look at the we can do it from, like, Unsplash or something, too. Let me get the actually art. So, I just want to see what's coming back. Here's what we get back in the JSON web token. There's that same user ID. I think that's the same one, at least. RB8. So, your user ID comes back. We've got expiration times. We've got an audience so we can see which app this is coming from. And then we get a little bit of information, where the signin provider came from. If we're not anonymous, we could get additional details, like their email.
DAVID EAST: If you signin with Google, you'd get more passback, too. With the social or OAuth, you can request more for that screen.
JASON LENGSTORF: Nice. Nice. Cool. Very cool. What I think we can do is, let's just let people store Unsplash photos because that will help with avoiding the trolliness of it. We'll be safe, but also, it'll be it'll be something that we can unleash the chat on at the end. Thank you for the sub. No one's tried burying us in the "boop."
DAVID EAST: I was really excited about the booping. On your website, I was like yes!
JASON LENGSTORF: Here they go. Here they go. They're getting motivated.
I've set up this and then I think the next thing that we want to do is we want to allow I think we could just allow someone to share the URL and then we can take that URL and
DAVID EAST: Just render it.
JASON LENGSTORF: Maybe for safety, we'll do a domain check for Unsplash.
DAVID EAST: All right. So, if you want to do a domain check okay. So oh, you want to just share the URL.
JASON LENGSTORF: And we can do clientside, I think we'll be okay.
DAVID EAST: I was thinking about the actual binary storage of it. If we're going to rely on Unsplash, we'll let them do the hard work. Click on "database." And now you have a choice. I'm going to make it for you. But, we have two not one, but two databases. We have the Cloud Firestore and the Database. When people say, I've used Firebase. They're talking about the Realtime Database.
JASON LENGSTORF: David is the adult supervision. (Laughter).
DAVID EAST: I am.
JASON LENGSTORF: Okay. So, is it possible, since we're building this and we know we're going to be validating to make sure that people aren't being evil, if we use the realtime database, can we have these photos show up as people add them?
DAVID EAST: Both of these databases are realtime. Realtime Database has a lower latency. But Cloud Firestore is still realtime. But, honestly, like, for this case, it doesn't really matter. Cloud Firestore has better querying and better offline support. And I mean, they're very I would use Cloud Firestore, just because we'll have a yeah, let's just use Cloud Firestore. Honestly, they're both great. Click on "start in test mode" for now. I guess it doesn't matter. This is security roles or us deciding who has access to what parts of your database and we're saying, okay, for now, people can write to this database, but not after that 30day period of time. So, if you forget to ever secure your database, that whole thing expires and we lock it down.
JASON LENGSTORF: In this case, I actually feel like what we would want is once we ship this, I feel like we can let this run kind of it's going to be a demon on learnwithjason.dev. If we can make it work, that would be great.
DAVID EAST: We can make it work. I would start in test mode, just for now, and we'll fix that at the end.
JASON LENGSTORF: Got it.
DAVID EAST: You want to know your data structure, first. This is fine, but it in U.S. Central. This is just where you want it, in this case it's not depending on where you are, it's a really big deal. But in this case, it's not that big of a deal. Just reducing latency.
JASON LENGSTORF: If you have strict GDPR.
DAVID EAST: Exactly. For our case, you know, we try to be GDPRcompliant with Corgi Photo, but it's hard, you know?
JASON LENGSTORF: We've got our security rules and here we go. We have a database.
DAVID EAST: So if you click "start collection," you can write "photos." You can call it "Corgis." Click "next." And then if you click "auto ID," it'll show you the auto ID.
And, so now, you set your so, you just want a string for your URL and then we would just you'll have to submit some type of value, though, just to allow it to save. So, you can just say "blah" for now. It doesn't matter right now.
JASON LENGSTORF: I mean, should I throw in
DAVID EAST: That's a good one. I was looking at that one myself. I was like, like at that! That's either the maid of honor, best man, that Corgi had a very important date. (Laughter). This is so, the so, Cloud Firestore is a NoSQL database. This is about as easy as it can get. Let's add an extra field. What you're going to want to do when you save, you're going to want to write "UID." And you can paste it for your anonymous one. Paste that in and now string is fine for this one. Yeah. Actually, we can do this really quick. Go to "rules."
JASON LENGSTORF: "Rules."
DAVID EAST: This is security rules. You write these in the console. But most people do it in Source Control and then we have, like, commands to upload it to the console. These run every single time data gets saved. It has to pass this. It's a bit like routematching if you're writing a router. You can probably yeah. So, you want to keep that one. But you can probably delete all the comments. This is just letting you know, you know we try to take security very seriously.
So, this match/documents**, this is saying every collection is going to follow this rule, which is allow reading and writing if the time of the request that comes in is, you know, less than this timestamp of the future.
JASON LENGSTORF: Got it. August 22nd.
DAVID EAST: So this is for people who open up who created something, maybe something on Code Pen and then they don't ever right rules to it and people start doing bad stuff to it. We set this up so eventually we lock it down. We try to do our best effort to secure things even if you, yourself, aren't doing it. We're going to secure it now. We're going to be good, secure people.
So, you can delete the whole "match//*" and underneath that, we're going to do "match/corgis."
JASON LENGSTORF: I'm going to do "match/corgis."
Now, say "allow write if auth." Watch what happens when you write "auth." Do "auth.." and then "UID." And then say, "= =." So, it is "request.resource.data.UID." And that's it.
JASON LENGSTORF: I did something wrong because it's giving me an error. Invalid variable name.
DAVID EAST: Unhover it off. It should be off. Let me look this up really quick. You're not doing anything wrong. Wait, is it "auth.UID." Is that a semicolon or a colon above it?
JASON LENGSTORF: It is a semicolon.
DAVID EAST: You have that right. "Allow write if
JASON LENGSTORF: I think that Auth isn't
DAVID EAST: It is not. Here, I'm going to go pull up one of my projects, really quick, to be like, what's going on here? So, fortunately, I've done so many livestreams, as well, so when things don't work, I'm like, okay, that happened again.
JASON LENGSTORF: That's the required attitude around here. Like, it's going to break. Let's figure it out.
DAVID EAST: The first time it failed on stage, I immediately bombed out. It's recorded. You can see my face go, "what." Martin said, "it's on line 44."
JASON LENGSTORF: I would never get anything done without the chat.
DAVID EAST: It's "request.auth." Auth is the old version for Realtime Database. I mixed the two. It's like learning two different languages and speaking them both in the same sentence.
JASON LENGSTORF: So I publish this, we're ready?
DAVID EAST: Yes. Just to have some fun, if you where'd your sidebar go? So go to click on that sidebar. Down, you see, there's "rules playground." That's your old version. We provide version control. So, if you hover to the left and go down to
JASON LENGSTORF: I completely missed that.
DAVID EAST: That's fine. There's a lot going on. So, this allows us to test what's going on. So, this gives you some confidence. You could say "get corgis."
JASON LENGSTORF: It likes like it's going to force me to do that. Beta default. Documents there. That works.
DAVID EAST: After "/corgis," run it.
JASON LENGSTORF: Denied. Oh, I did "documents."
DAVID EAST: You just need to say "corgis." But I think it needs to be oh, but it has to be to the document level. That's why. Do "/corgis/1." "Corgis" is a collection level. Only put in "/corgi/1."
JASON LENGSTORF: 0hhhhhh, I understand. Is it because I'm not using the an actual ID, like, there's nothing there?
DAVID EAST: "Allow read" is true so this should work. I'm superstitious here. Get rid of the leading slash. All right. Now, run it again. It should give you more information. Is it because, like, the thing is I wonder if it's because the screen is, like, constrained so it's not showing? It will actually highlight where it failed. I'm going to write this in my console to see what's going on. I messed this up so I need to test this on my own. "Allow write if UID is equal to request.resource.data.UID." That should work. I'm going to publish on this one, which I shouldn't do, but I'm going to do anyways.
When you do something live, you can't go silent.
JASON LENGSTORF: Yeah, you got to keep talking.
DAVID EAST: No dead air.
I wrote "math," instead of "match." So, I got "read denied," as well. Why is that? I feel like let's see here. Should work. For some reason
JASON LENGSTORF: Is it maybe like, should we just try the actual
DAVID EAST: Yeah, let's try the actual one. I'm doing something really obvious right now. If anyone sees what I'm doing, they can fix it. It's just because I'm live and that's the only reason.
JASON LENGSTORF: Josh is suggesting that maybe we need one of those bracketed
DAVID EAST: Oh, yes! Thank you, Josh. We need a route param. Yes, thank you, Josh! That is obvious. So, you need it in "Match." Match.corgis/curlybracket.
JASON LENGSTORF: Over here, I do a "1"? Hey!
DAVID EAST: Josh, you're the real hero here!
JASON LENGSTORF: See, the chat, always here to bail us out.
DAVID EAST: Really, it's very true.
You can even check the authentication and you can test that. But we spent a lot of time here so we can move on to writing more code.
JASON LENGSTORF: Okay. Let's do it.
DAVID EAST: We did security, first. That's a bestpractice with Firebase and we did it first.
So, now what we want to do we included Firestore, so we're good there. Let's create a listener. So, we will say let's see here...where you have, like, "auth," do "canstdbfirestore." We are going to create a reference and create a collection reference. Do, like "canstcorgiscall." Or "call," as in "Col." Do "db.collection." And then collection is a function. And then just do "corgis."
JASON LENGSTORF: Okay.
DAVID EAST: So now we have a reference. So, this allows us to read, listen, manipulate data at this location.
So now below this, if you write "corgiscol.onsnapshot," and then we'll take it to the callback function where the parameter is "snap" or "snapshot." And so what this is, is this is an object that wraps over the data, at this location, and so this is a collection snapshot, as well. I think the official type is called, like, "query snapshot." But, basically, snapshot contains lots of helper functions and metadata. You can actually get not just the data, but you can get, like, what is changed in that dataset so things have been added, removed, updated, modified. You can do really cool Reduxstyle things.
In this case, we just want to get the data. We're going to say "canstcorgis." "Corgis" is the Latin pronunciation.
JASON LENGSTORF: I think it's the foambased spaceship they use to travel through time. (Laughter).
DAVID EAST: You can say "snapshot.docs." This will contain an array of document snapshots, not the actual data. You say ".map," because it's an array. Within here, "d" or "doc" as the callback function. It's kind of terse on one line. I guess it's just my preference. And so we're going to return object out of this, so do the parenthesis and then do "ID:Doc.ID."
JASON LENGSTORF: Is this a function?
DAVID EAST: No, just a property. And then spread over "docdocdata." It's slightlyexpensive so it gets saved as a function. So, the data and the ID are not together unless you explicitly put them together in the database. Because it's easy to put them together, I keep them separate.
If you "console.log."
JASON LENGSTORF: Let's start by making sure we have data. That seems like a better way to work through this. So, we're going to log "corgis."
DAVID EAST: Corgis. There you go. What else would you log?
So, now if you do a refresh
JASON LENGSTORF: There is a corgis. And there is the user ID and there is the image. So, we're in good shape. We're in great shape.
DAVID EAST: Every time someone updates that's why it's a callback. Every time someone updates, you'll get another corgis.
JASON LENGSTORF: If I go to the data and I add another document
DAVID EAST: You can add another document, you could add a field. You could do a ton of things and it would work.
JASON LENGSTORF: Let's make this happen.
DAVID EAST: That's the magic here. That's the oohhhhhh!
JASON LENGSTORF: I need the URL. Let's grab another corgis.
DAVID EAST: That looks like a good boy.
JASON LENGSTORF: I think this is an extremely good boy.
DAVID EAST: Now if you save it and then you go
JASON LENGSTORF: Now it's already updated, so that all happened.
DAVID EAST: Boom!
JASON LENGSTORF: Oohhhh, that's really cool.
DAVID EAST: What's better than one corgis? Two Corgis.
JASON LENGSTORF: I'm going to use the Template API, which I love.
[Music playing]. This is the photo template and inside of this, we are going to have a div, that's going to be our photo and then we're going to set the image source to be "empty." And we'll need an alt I guess that's not going to be great. This is not going to be the most accessible thing. We should probably have more fields.
DAVID EAST: Your alt could be "corgi" and it would be 50% of the way there.
JASON LENGSTORF: I'm going to get the template, which would be the jQuery Photo Template is what I called that, I believe.
And then, in here, for each Corgi, we will be able to let's see...we just get it as a straight array for each Corgi. Element will be "template.content.clonenodetrue and that gives us a fresh DOM element we can work on.
Inside of that, we can do the image will be "image.queryselectorimage." And then we can set image.source to "corgi.URL." We'll say "Corgi." Then, we can do what did we call this one up here? "Photos.append child." This is going to go poorly for us because we're going to need to let's see, how do we want to do this?
DAVID EAST: You could do it as a fragment. I think templates and fragments don't play well together though.
JASON LENGSTORF: We can just check if we can set the ID and, like well there are several ways.
DAVID EAST: You can do Corgi. You can do oh, I see what you're saying.
JASON LENGSTORF: Element ID equals Corgi.ID and then we could basically say, like, if document.queryselector or getelement.bycorgi.id and return so we only do it once.
DAVID EAST: Yes. Yes. You wouldn't get updates this way, but that's fine.
JASON LENGSTORF: We can empty it every time we rerender and maybe that's the way we should do it this time?
DAVID EAST: Let's do it like this, just to see things painted for now. One thing there's we can actually there there's actually a way I talked about so, where you see snapshot.docs. There's snapshot.docchanges. You can partition the array so you can get, like, each one by all the changes, all the removals, modifications and I usually pass those into methods that say, oh, add these ones, remove these ones and then modify these ones.
JASON LENGSTORF: Okay. So
DAVID EAST: You can clear it for now.
JASON LENGSTORF: This is not, like
DAVID EAST: This is completely productionready. Stamp of approval by Jason. (Laughter).
JASON LENGSTORF: We're going to empty our photo array and redraw all of the Corgis in there. And so, what we've done is we've created a little template for it and our template is going to just have a photo and that's all. And then, we're going to put in the the source and the alt and then we'll drop that into Photos, which I've now got a reference to so I don't need to query it twice.
DAVID EAST: Oh, yeah. Nice.
JASON LENGSTORF: Let's give this a shot and see what happens. That's working and then with a little bit of
DAVID EAST: That is a good boy. (Laughter).
JASON LENGSTORF: Just a tiny bit of style here. We'll do photos. We'll set a max width of, let's say, 90. We'll set display grid. We can do a grid template columns, repeat autofill
DAVID EAST: I didn't know we were going to get fancy here today, Jason. (Laughter).
JASON LENGSTORF: We can set a gap of 30 pixels.
DAVID EAST: I do love Grid.
JASON LENGSTORF: We need photos image to be width 100%.
DAVID EAST: Oh, yeah.
JASON LENGSTORF: Okay. That's not bad. I want to do one more thing, though, which is to make these line up right. So, I'm going to take oh, this needs to be a class. Okay. So, divclassphoto. And then, photo, itself, I'm going to make objectfitcover. I think that's how that works?
DAVID EAST: Yeah. I think yes.
JASON LENGSTORF: Wait. Does it need to go on the image itself?
DAVID EAST: Oh.
JASON LENGSTORF: I know this works. Display block.
DAVID EAST: Images will be inline by default.
JASON LENGSTORF: All right. I'm doing something wrong.
DAVID EAST: It might be because of your Grid. Did you do template columns or template rows?
JASON LENGSTORF: I did template columns.
DAVID EAST: When you hovered over the grid display, it said "1, 2."
JASON LENGSTORF: That's what I want.
DAVID EAST: I thought you were trying to stack them.
JASON LENGSTORF: Oh, oh, I think I need to make the images height 100%, too.
DAVID EAST: There we go. I thought you were trying to stack and so I was like, oh, well, that's yes.
JASON LENGSTORF: Look at it go. All right. So, now when we add photos, they will be perfectlysquare and these I should probably make these a little bit smaller. Because I assume when we unleash the chat on this, we're going to get a lot of Corgi photos really fast.
One thing I'm going to add here, we need to validate that the URL came in from Unsplash so what I can do is set up URL=newURLcorgi.URL and then I think we can it's like the path name. Let's just log it and take a look. Do you know this off the top of your head? I use this all the time and I always forget what it is.
DAVID EAST: I'm looking at something really quick, because I think there might be a really cool trick we might be able to do, but I'm not fullycertain. I can't remember the way to do this. Because I think you can do this in I'm not sure now. You can do this with security rules, actually, where we can check that.
JASON LENGSTORF: Oh, that is supercool.
DAVID EAST: I can't remember, off the top of my head, now.
JASON LENGSTORF: If we have extra time, we should do that. We only have about 14 minutes left and I'd love to get this to work. Did something break just now? Images. Host name. Do I need to include the HTTPS? That can't be write. Let's see here. What did I get wrong?
DAVID EAST: Yes, I think we can do a "contains." No, that's the
JASON LENGSTORF: "Images" is what I got wrong. This is the worst security ever, but it'll be okay because for the purposes of this demo it's going to work and then I need to get this thing live. Can I ship this to Netlify?
DAVID EAST: You go ahead, man. This is a collab. This is when two breweries come together and they release a great beer. Limited release.
JASON LENGSTORF: Let's go "get, create, Learn With Jason, Firebase, corgi photos." Let's change this. Checkout. Main. Noooo! Get. Checkout. Main. And then we'll "get push." Main dang it! So, that is done. Netlify init. And we're going to create and configure a new site. We're going to put it on my team. We're going to call the Firebase Corgi Photos. Good. Our build command is "no build command." And the currently directory is what we want to deploy.
So, that's now live and if we open the site...that'll take a second to build, but that'll be that'll be live momentarily. Let's watch it build.
DAVID EAST: I yes. I actually don't know off the top of my head, but I do believe we can do this in security rules. It might be weird you'd probably be very limited to what photos go up. And you probably know this, you can do this with serverless function, as well, when so, Firebase has cloud functions for Firebase so we do triggers whenever documents are updated, created and so when someone creates a Corgi doc, you can look at the URL first and do any sanitation or check on it.
JASON LENGSTORF: Okay. Yeah, that's awesome.
DAVID EAST: You send it to a queue first, so Corgi Queue. And then Corgi Display. You could write the security, it's read publicthrough but it's writeonly by, like, admin.
JASON LENGSTORF: I understand.
DAVID EAST: There's lots of interesting security things to do.
JASON LENGSTORF: Okay. So, now I've created a let me start this up again. Okay. So, this is the that's the live one. Here's the so, now I've got a little form and can we in 10 minutes or less get this thing hooked up so that we can save no photos?
DAVID EAST: Yep. All we need is that photo URL. We already have the collection. We have the collection, so this is going to be easy. Let's listen to the "submit" event.
JASON LENGSTORF: So, I'm going to collapse this one and then down here, we're going to say or, no.
DAVID EAST: Canst.
JASON LENGSTORF: Add event listener. Hell, yeah! Then we're going to get our event and all right. This is a speed run. I'm going to prevent default.
DAVID EAST: Yep. Good one. Default.
JASON LENGSTORF: Default!
Then, we need to get the form data. So, let's get the data. Will be a new form data of event.target.
DAVID EAST: Look at you flexing your APIs.
JASON LENGSTORF: I have the data I have saved and I'm ready to send it to Firebase. So, what do we do next?
DAVID EAST: Go to "corgiscol.add" and then call a function, provide an object. You can just provide URL. And then, you can do we are okay, so we have a bit of a kerfuffle here. Under "canstURL," do "canstuser." And say "auth.capitaluser." And I think this just as a property. And, this is a little finicky because it relies on data I haven't done it this way in awhile. Consolelog the user right below it. If not, we can do a dirty window hack.
JASON LENGSTORF: A dirty window hack. (Laughter).
DAVID EAST: There's something I would do I never do it this way. I usually I usually do everything with RX. But, there's some better ways of doing this.
JASON LENGSTORF: Okay. Let's grab an image address. I know, this one's very regal.
DAVID EAST: I know.
JASON LENGSTORF: I am logged in so I will drop one of these in here and save it. We should see a user logged and theoretically see another photo appear. Chat, I expect you to just Spam the holyheck out of us.
DAVID EAST: I'm not sure though, in the console log, did it log the correct user though?
JASON LENGSTORF: I think so.
DAVID EAST: It's a weird thing to rely on yeah, it did. We're good. It's a weird thing to rely on because it's a synchronous property that gets filled asynchronously. It's kind of like "use when you are very confident you have a logged in user."
JASON LENGSTORF: We are not confident, however, we are very confident that this is a demo and you're going to have to forgive us, chat. What I expect is, here in about 10 seconds, I need you to head over to Unsplash and get a bunch of Corgi photos and drop these right on the site. So, we're ready. Here we go. Do it. Do it.
[Music playing loudly in background]. Yes! Yes! Look at that come in, though. I feel like it's difficult to overstate the coolness of how quickly with screwing around, with making a bunch of jokes, we were able to spinup, very quickly, a fulltime app. Something that is rendering this quickly.
DAVID EAST: And we didn't even secure it. We did secure it, but we didn't do some of the other crazy things. We cut the screencast down, it would be, like, four steps.
JASON LENGSTORF: Yeah, this is really, really fun stuff and I feel like there's probably a lot of nextsteps here. That's not a Corgi, get that out of here. (Laughter). So, I feel like this is a really good intro into how quickly we can get this stuff going, right? We've got some excellent starting points. There are a lot of things we could have done better. I think we could have made the performance of adding the images a little bit better. We can do more with checking the user. We could do a little more with security. But I'm happy. For 90 minutes worth of work, I'm really happy.
DAVID EAST: Let's ship it. Production.
JASON LENGSTORF: You, chat, do you even know what a Corgi is? What is that?
(Laughter). So, David, if people want to take nextsteps, where should they go from here?
DAVID EAST: You notice the photos are updating randomly, we could have added timestamps on them and Firebase has server timestamps. It gets you into querying with Firestore.
Another thing I'm superexcited about is we have a local emulator UI for Firebase services. Part of our CLI, you spinup this emulator and it's all cloudconnected and you can do it locally. You can run Firestore, functions, realtime database, it has a UI on it so it makes development a lot nicer. I just did a whole video about that.
JASON LENGSTORF: How can I link to that?
DAVID EAST: YouTube.com/Firebase. There's me, pointing at you.
JASON LENGSTORF: Look at this guy!
DAVID EAST: It's me. Where is it? Keep scrolling down. Go there it is. There's me. I look very unimpressed in that video. But trust me, I'm very impressed. Here's one right here. I teach you how to get started with a local emulator and I'm a huge fan of it.
JASON LENGSTORF: Beautiful. Let's see how we did. We pushed you over the 14. How
DAVID EAST: That was amazing.
JASON LENGSTORF: Beautiful. Chat, you came through. You really delivered. If you haven't followed David yet, head over there and do it. The code, in this demo, is already public. We can share it right now. So, let's "get browse" and it opened in the wrong window. It's over here. There it is. And, I can share that with you right here.
Everything will be posted on learnwithjason.dev. Today's episode, you'll be able to find it on the site, at this address. It'll be posted tomorrow. If you want to check out what's upcoming, we have Nathaniel coming back to the show. We started building a texttoplay game and we're going to continue work on that. So, if you haven't seen it, go check out Part 1 and once we get on next Tuesday, we're going to have a lot of fun. You'll be texting to vote for things.
On Thursday, we have Brian Robinson coming on and learn how to do plugins for Eleventy. The schedule is incredible. So many people are coming on to teach so many amazing things. Please check out that schedule.
Don't forget, you can add the whole schedule to your Google Calendar. Wait, what's the oh, no, I forget what the thing is. This one, I think? I hope? I hope that works. Here? Yeah, that was it.
Add that to your calendar and it's going to let you know when it comes. It's a lot of fun. David, where should people go if they want to follow you online.
DAVID EAST: I do livestreaming on my YouTube channel. I don't know what my URL is. I don't have the thing. If you search "David East Firebase" I don't know. I'm YouTubesomething?
That's me right there. That one's close to 1,000. So if you want to subscribe
JASON LENGSTORF: Smash that subscribe and ring that bell.
So, go follow that. And, don't forget, you can go get started with Firebase very quickly at Firebase.Google.com.
This was a lot of fun. I feel like there's a whole lot of potential for what we can do here. One more quick shoutout to White Coat Captioning, who's been doing an excellent job making this accessible for us, made possible by Netlify, Fauna, Sanity and Auth0.
Thank you, all, so much for hanging out today. Chat, stay tuned, we are going do raid. David, thank you so much for hanging out and we will catch you next time.
Oh, good timing on that, too. Good. Good. Bye, y'all.
Closed captioning and more are made possible by our sponsors: