LongCut logo

Something fun | Observable Flutter #78

By Flutter

Summary

Topics Covered

  • Serverpod's Anonymous Auth: A Deep Dive
  • Dart's Full Stack Potential: Beyond Flutter
  • Navigating Serverpod Migrations: Friction and Solutions
  • End-to-End Type Safety: Serverpod vs. Django/Express
  • The Nuances of Anonymous Account Merging

Full Transcript

Hello everyone and welcome to another episode of Observable Flutter. My name

is Craig Lebenz and I'm trying to launch this stream for the second time and I'm checking over on the dashboards and okay, I think we are in fact streaming.

Great. Well, it's so lovely to see you all again in 2026. I hope you had as restorative of holidays as I had. I'm

very excited to be back. I'm very

excited to be working on some Flutter stuff together. So, yeah, great to see

stuff together. So, yeah, great to see you all. And I have

you all. And I have not not going through Streamyard today, but I have the chat app that we all made

together. It was a team effort ready to

together. It was a team effort ready to go. So, uh let's see. Oh, wait. I have

go. So, uh let's see. Oh, wait. I have

to switch to the correct window for this to appear because it's not in this OBS overlay. There's always more shuffling

overlay. There's always more shuffling to be done.

Here we are.

Randall wonders what I'm going to be working on today and expects that I too wonder what I'm working on today. And

that is typically correct. But after I made the ambiguous thumbnail, I came up with an idea of what I'm pretty sure I want to work on. and I'll I'll take some

suggestions or ideas from folks. But

what I'm thinking about is I've been working on adding anonymous off to server pod's new O module and

I could basically do that for about an hour and a half kind of proceed on where I've been. So, let me know if anyone has

I've been. So, let me know if anyone has strong feelings for or against seeing a little contribution to server pod. I've

had the good fortune of working with the server pod team a bit to kind of get up and running and figure out how to, you know, how to think about CI and the tests and server pod tests are fairly

complicated.

Um, yeah. So, barring any strong votes against uh I will go with that.

So, as this happens, I'm going to bring this up and um we'll see what we got.

See what we got.

Where's OBS?

Oh, I clicked the wrong button. That's

why what I thought was going to happen didn't happen.

All right.

So, is my chat app something?

Where's that? Oh, yeah. It's the Flutter logo. There it is. There it is. Make an

logo. There it is. There it is. Make an

editing app.

A what editing app? One wonders.

L Creations says that. Oh, do I not have the uh overlay in this one? Oh, no, it does. Okay. All right. So, I'm going to

does. Okay. All right. So, I'm going to pull this up and kind of get situated, but there's still a window for anyone to

come up with a better idea, but absent a better idea. I'm going to contribute to

better idea. I'm going to contribute to Serverbot today and I'll walk folks through what I've done to start us off, if in fact that is

what we go with. And uh and then we'll see and we'll be up and running.

OBS is powerful and with great power comes great responsibility.

That is that is true. OBS is

I I love OBS. Honestly, it's just amazing that something as powerful as OBS exists for free. That's so

incredible.

Uh looking at some of these chat messages. Let's see. So, I vibecoded

messages. Let's see. So, I vibecoded Flutter for terminal applications in Dart.

Um, awesome. What did they do? I'd love

to hear more about that. I have made some terminal commands like organize the raw files of my uh very very very

amateur photography to like delete the raw files of photos that I don't keep.

So, um, I've also dabbled a bit in that world.

Future of Dart outside of Flutter. Well,

we're constantly Oh, wow. Look at this.

Look at the um I just saw that the overlay for that last image was totally not scoped

correctly which was remains one of the big problems in my app and why it's not quite production ready. Um yeah so future of Dart outside of Flutter well

serverside Dart. So, that's a that's an

serverside Dart. So, that's a that's an extremely timely and appropriate question because I'm thinking about doing some uh

some full stack Dart right here. See,

continuing to read some of these chats.

Let's make a mindmap building app. Well,

I basically don't know anything about mind map building uh mind map apps at all. So boy would I not be ready to

all. So boy would I not be ready to build one yet. But I probably should learn. People love mind mapping apps. So

learn. People love mind mapping apps. So

maybe I should get into them. Something

wrong with chats appear on the screen just showing half it. Yeah. Well, that's

something is that the the that is a utility that um

why am I blanking on their name?

Streamyard does quite well is their their logic for the overlay situation is much better.

Mine not not so good. So short messages will render much better when I go straight to Streamyard. Maybe one day we'll have to

Streamyard. Maybe one day we'll have to fix that. Uh all right, looking at more

fix that. Uh all right, looking at more chats. Waiting for Craig to play

chats. Waiting for Craig to play Minecraft on stream and using the redstone dart made by Norbert. Yeah, I'd

love to have Norbert on and talk about that because that's super duper cool.

The Flutter team was sharing around that link. I think it was yesterday.

link. I think it was yesterday.

So, we're also pretty amazed.

Um, all right. So, I think it's time to

all right. So, I think it's time to begin. I'm just going to check a few

begin. I'm just going to check a few things. Make sure I'm not getting any

things. Make sure I'm not getting any chats from backstage folks saying, "You sound terrible. What's wrong with you?"

sound terrible. What's wrong with you?"

But no such chats exist. Okay.

So, and will we see macros and flutter?

Probably not. Not not soon, sadly. Okay.

Make sure I go to the correct screen here. I think I'm going to be on

screen here. I think I'm going to be on the right one. confirming. Yeah. Okay.

So, this is my extremely janky overlay window that you may recall from previous. Oh, chess. That would be fun.

previous. Oh, chess. That would be fun.

Chess would be good.

Uh, I made I I I did make a chess app in Flutter a long time ago. It would be it would be fun to make that more serious.

Like, there's no AI in it. You just play against another person. kind of like hot seat and you can't make illegal moves.

That that was it. And it detects checkmate and fun stuff like that.

There's no no playing against CPU.

All right.

So, first let me pull up the the pull request on server pod. So,

a little backstory here. Server pod is full stack Dart. They have shared server and client side generation so that the

transport layer when your flutter app or your CLI or any whatever your Dart front end is talks to your server, you just call a local function that is magically

routed to the endpoint on the server that you want to invoke and then you return something from that server side uh function and again the transport

layer in reverse is also hidden and back in your front-end Dart code, you're awaiting the result of this function.

Whatever was returned on the server appears magically for you on the client.

Super cool. They have an authorization module because any serious app of course needs to be able to know who is logging in. And that app or sorry, that module

in. And that app or sorry, that module is broken up into multiple different what they call IDPs, identity providers.

Apple, Google, and email being the most common ones. I think they also have a

common ones. I think they also have a pass key one, though I've not really looked at that at all.

Well, what I want to do is add anonymous off, which is obviously a feature in Firebase off, but what I so I could lean on Firebase off for that functionality,

but then I have two O systems and I have to sync users between them and it's unbelievably painful. So I want

unbelievably painful. So I want anonymous off in serverbot and because when so many of you ask for

different features in Flutter, I often will give the somewhat cheeky response of like, well, you can always open a PR, you can always file an issue and work on it. I'm putting my money where my mouth

it. I'm putting my money where my mouth is and I'm doing that with Serverpod.

So let us now uh proceed. So I have made a design document which I believe is open for anyone to look at and yeah so this

is just all of what I'm imagining. I

think a design the design document step here was extremely useful because it allowed everyone to get on the same page about the end state of this feature like

you know where is it going to ultimately go um how do we kind of build with the future in mind and not paint ourselves into corners and all those idioms. So

this is the design document and the currently open PR is basically just phase one and then I have a different PR that begins to work on phase two but

there's lots more that will have to happen for phase two.

So the PR for phase one is nearly complete but I need to rebase some migrations which is currently a source of moderate

friction in server pod but we can do that together and you'll all get to see a little bit of how

to uh you know work with and really massage a server pod project. So that

that's today.

All right.

So, if we look at the files changed of this PR, the diffs are huge, of course, because there's a lot of generated code in here. I did not write 17,000 lines of code.

But if we scroll, nope, I'm actually not. I don't need to look at this tab.

not. I don't need to look at this tab.

Do I know how GitHub works? Have I

developed? Have I developered before? If

we don't leave the default tab at all because why would anybody do that? When

we scroll to the bottom, we'll see that there are some conflicts that have to be resolved because I added migrations, but then I also filed a bug for an enhancement to a different module and

someone on the server pod team fixed that and that added migrations. And now

I have a conflict on migrations. So

that's the first step is to solve that.

Now I'm going to check chat because I haven't looked at it in forever and we'll see what you've all been blaming about. chess would take an hour to just

about. chess would take an hour to just set up. Yeah, it would. But it was super

set up. Yeah, it would. But it was super fun.

Oh, wait. Le chess is written in Flutter and Lotus Chess. I'm not familiar with Lotus Chess. That's interesting. Uh I

Lotus Chess. That's interesting. Uh I

didn't know that my chest was written in Flutter. Yeah, SMS as a IDP is a valid

Flutter. Yeah, SMS as a IDP is a valid IDP not currently in the module.

Okay.

Howdy Egypt. Good to see you.

All right. All right. So, I have the code up and let's look at how migrations in Server Pod work. And admittedly, for

the first few minutes here, Server Pod's not going to look the best because there's, like I said, a little friction around migrations, especially when you need to roll a migration back, which I

have to do to resolve this rebase. If

you don't roll migrations back then there's no friction right. So the first thing is

right. So the first thing is let's see in the server pod off IDP project that's where basically all of

the code that I have been adding is uh has lived and then also in a project specifically to run uh integration tests

against that. So those are the two

against that. So those are the two places. So tests server pod off test and

places. So tests server pod off test and in modules server pod off and then for both of them ultimately in a project

that is like the underscore server part of a server pod situation. So let's do it.

Um I forget. Let's make this big enough.

Is this big enough yet? Should I go a little bigger even? I think I will go bigger. Go bigger or go home. Say the

bigger. Go bigger or go home. Say the

streamers.

So here is that's interesting. What do I not see?

that's interesting. What do I not see?

Oh, resolve in merge editor. I'm not

seeing the actual like big in-your-face conflicts though, so that's interesting.

Uh I see I'm in the middle of a merge.

Yeah, I guess I started thinking about this the other day.

Yeah. Okay. Where did I even leave myself? I think I'm

myself? I think I'm aha.

So, what's going on with this one?

Surprised that I don't have the same issue here, but in the test, we definitely see it. So, my change is the

older one, I believe, which can I read?

Yeah. So, incoming is mine.

Is that right? Was I rebasing? I guess I was rebasing. And this is the

was rebasing. And this is the one that needs to sit below my migration. So if we look at but this is

migration. So if we look at but this is in the test. Why am I not seeing the same thing here? Did I like change something myself? Oh, I did start to

something myself? Oh, I did start to muck with it. But that was invalid, right? Ah, there we go. This makes a lot

right? Ah, there we go. This makes a lot more sense.

So I actually What do I want to do? I

think I want to abort this whole merge. I need to do like a git merge or whatever it is. Get merge

abort or something. Um,

why am I in this directory?

Here we go. Okay, so get merge abort merged files.

Yeah. So, get rebate support.

What's my situation?

I really shouldn't have started mcking with this three days ago and then stopped. Uh, looking at chat again a

stopped. Uh, looking at chat again a little bit here. Oh, get rebase d-upport. Get rebase-up.

d-upport. Get rebase-up.

No rebates in progress.

Where it's like, do you know what you're doing? There we go. Wonderful.

doing? There we go. Wonderful.

Okay. Okay. Okay. So now I'm going to un I deleted this migration which I'm going to ultimately have to do but I'm going to undo that for now. So I'm going to restore these files. Okay. Now I am

ready to delete my migration and then I should be able to merge in uh the real one, the one that needs to

exist before me. So in the server pod repo, we've got this modules directory and then server pod off is where we live. And there's different modules in

live. And there's different modules in here. There's a bridge if you're coming

here. There's a bridge if you're coming from the old O situation core. Pretty

clear what that is. And then IDP is where all the different IDPs live. So if

you don't if you didn't use the old server pod off module, you don't care about migration or bridge. You would

just use core and IDP. So this is where I I have been spending my time and I'm in the underscore server directory in the migrations directory and I added

this migration and if we look at that migration we'll see that it has a V7 uh UU ID function and there is an anonymous

account table and a constraint and you know enters itself into the migrations table all that good stuff.

So, I need to manually back this out, which for my purposes um only means like deleting stuff from my local database

that I'm using because I want to keep using that database. And then uh I will also need to delete these files. And the reason we

have to delete the files is these definition files which I also filed a proposal to basically get rid of because they are the source of this friction.

Shall we now pull up post as one does and look at where am I using this?

I guess it's basically just in the server pod test app. Is this right?

What is my What are my connection credentials here? No, that's not it. Oh,

credentials here? No, that's not it. Oh,

right. I've only set this up on my personal computer. I downloaded I I get

personal computer. I downloaded I I get cloned all of this on my work computer, so I don't have a connection to this yet. All right. Well, that'll be worth

yet. All right. Well, that'll be worth um visiting as well. Well, I'll see.

Okay. So,

um I am going to add a new connection to the local Oh, this means I don't have to delete the table because I'm not on my computer

where I've even added the table. Aha.

Nice. Although I will have to do it later when I return to my personal computer. All right. So, actually this

computer. All right. So, actually this just got easier. So, I can merely delete this whole directory

like this.

And then I need to go into the test directory and get the off test server

migration.

Get the same directory here. Delete it.

And then I was surprised that I didn't see an error in the examples because there's an o examples directory as well.

I think that the bug fixer of the other thing just didn't add their migration to this. So I look at migrations here.

this. So I look at migrations here.

Yeah, they just didn't add it. So that's

okay. I'll fix that, too.

So now I am maybe ready to merge. What

do I What are my open things here? I've

gotten rid of this migration. That is

correct. I'm going to say removes migration in favor of rebased migration.

Love it. I'll now switch back over to um the main branch and make sure I grab everything. Oops. Get checkout main and

everything. Oops. Get checkout main and I'll do a get poll.

And lovely. So now I'll say get checkout add anonymous IDP

that's not what it was called.

Oh goodness.

Okay, back to GitHub we go. What is this branch called?

Anonymous O IDP. I mean, who could have remembered that?

I'll look at some chat real quick here.

Uh tried server pod but it's overkill for you. Hog dominance. Good to see you

for you. Hog dominance. Good to see you hog. Um interesting. I wonder what was

hog. Um interesting. I wonder what was overkill about it for you. I mean if you're not talking to Postgress I think the the value proposition drops off because the OM is really really good.

There's there are definitely other value propositions to server pod like no doubt but to me talking to Postgress is the main one. So, I wonder

main one. So, I wonder um this may clip. I apology. I

apologize. I love Dart, but I'd like to know a good reason to use Serpod over a solution like Django or ExpressJS.

That's an awesome question. I love

Django. I used it for about a decade.

It's awesome. Uh as Randall says, he doesn't want to learn Django or Express.JS. That's a great reason. So if

Express.JS. That's a great reason. So if

you already know Django, then you've got a fair cliff that something else has to exceed before you would stop using, you

know, whatever other tool that you like.

Out of the gate, the shared client generation I was talking about earlier is a huge thing.

Like server pod offers you type safety from a random function in your Flutter app all the way to the database. So

that's type safety over the wire and then type safety on the query.

And you know you get like pseudo type safety with Django as well on the query.

But unless you use kind of a gRPC module and generate some Python bindings and then generate Dart on the front end and like get type safety over the wire that way you won't you just there aren't

really many other ways that I'm aware of to get end to end type safety. So, super

super super cool. Um, server pod, you know, at the risk of talking about their paid product as well, they're also adding like one-click deployments, and that's super awesome. That's kind of in

an alpha beta state right now. Other

folks talking about how yeah, server pod works together cohesively, all that kind of stuff.

Um, continuing to scroll down some chat here.

All right.

Oh, what theme I'm using? Yeah, I love this new theme. It's

Catpuchin. Catpuchin. I'm not really sure how to pronounce it. I like

macchiato and Mocha. I'm currently using Mocha and I really love it. I've been

using Synth Wave for like years, years, and years and years and I recently switched and it's been fun. Okay, so I have pulled and now I'm ready to get

merge main.

I wasn't expecting to still have those conflicts. What are we talking about? I

conflicts. What are we talking about? I

got rid of that. Oh, I didn't delete.

That was the other thing I had to do.

Abort. Sorry. Sorry. Sorry. From the

migration directories. I have to actually delete.

Wait, that's interesting. Wait, what is this migration? Am I like misremembering

this migration? Am I like misremembering something? Oh no. Okay. Wait, wait,

something? Oh no. Okay. Wait, wait,

wait. Yeah. What are you? What are you?

Who are you? What is this?

Another anonymous Hoth.

It existed twice.

Well, that's embarrassing.

Goodbye.

What?

Uh, okay. So,

now let me think. Weird. Don't know what error I made to do that, but I'm sure that was me.

So, okay, I had to deleted that row, which I had to do. So, now I'll go back into the test directory. And

this is probably going to be the same thing. Oh, challenge tracker. No, this

thing. Oh, challenge tracker. No, this

is a real one. This one will definitely not be getting deleted. Did I delete a real thing before? Did I like hallucinate something? I'm really

hallucinate something? I'm really surprised. Okay, so this ends in um

surprised. Okay, so this ends in um 41265.

And if I look at my git history, the folder there is not 401265.

So that was just total user error. Okay,

weird.

But anyway, so in um the tests migration registry, this is where I just delete this line.

Cool. surprised this challenge migration isn't up here, but whatever.

All right, so now I'm going to commit that again and say um more better

migration rebase prep.

Much more better.

Now we should be able to conflict free merge main.

Okay good.

Close that.

All right.

Will Dart ever get better tooling on exceptions, especially in regards to public API documentation on what exception could possibly thrown be thrown from a function method? That is

such a good question and such a uh like big topic in language design. And

right after Randall says, "I hope Dart never requires all exceptions to be listed." Um

listed." Um I know folks who come from languages where exceptions are listed really miss that about Dart, but it is it isn't

going to happen. Now, interestingly,

serverpod wraps everything in an outermost try catch. And when you throw exceptions, which are like registered exceptions with server pod, those

classes get returned and reinstantiated on the front end and get thrown again on the front end. So, you can throw server side exceptions and catch them on the

front end. And that's kind of a nice way

front end. And that's kind of a nice way to use exceptions like again cohesively end to end.

But uh I personally because Dart doesn't lean into exceptions. I try to return union types

exceptions. I try to return union types of like ex success or failure and each function that might throw an exception like contains that exception and doesn't

make it the calling codes problem to try and catch. Now, if you return a union

and catch. Now, if you return a union type, it's still the trying codes problem to unpack that union type and evaluate, you know, which one it is. But

like that's the Dart way to do this. If

you're going to throw if you know that a an exception might be thrown in a certain function, catch it there and convert it into some return type that says like, hey, I failed for this reason. And then your calling code

reason. And then your calling code doesn't, you know, you don't have to like try catches everywhere. You do have unpacking of union types everywhere, though. But in some sense, uh, if you

though. But in some sense, uh, if you don't want every exception to crash your app, you're going to have to do one of those. And that's the dark way.

those. And that's the dark way.

All right, back to serverbot. So, now

that I have done that, and I'm not working with a database here that was muddied up by my migration because that database only exists on my

personal laptop.

I can now uh I'm surprised that merge didn't get squashed. Oh no, I guess there there was

squashed. Oh no, I guess there there was just a lot of commits that I pulled in.

Okay, that's fine. Anyway, um now I can regenerate the migrations and then I'll I'll actually kind of play with the test app and we'll see that it's working

before I submit everything again. Okay,

so I'm going to switch. What's this

directory for? What do you do? What do

you do?

This is the actual thing itself. So here

I should be able to say server pod create migration and we'll get a new folder that'll look a lot like the one I deleted, but it will have the correct definition files.

So server pod create-ash migration and I will now just press enter.

Excellent. So this is right now's time stamp forever immortalized unless this gets deleted again. And if I look in the migrationsql

thing um oh this is a surprise.

I was not expecting that. This is the previous one.

Oh, I'm actually in the test folder. I

thought I was not in the test folder.

I'm in the test folder.

I'm still confused.

I'm not in the test folder.

And yet, what?

Ah. Ah. Ah. Okay. I'm just really, really dumb is the problem. This is the one that was just generated. This is not the one that was generated. So, this is exactly what I should have expected to see if I had a bigger brain. So, okay.

This was what was just generated. And

this migration is going to be my UU ID v7 function again and the anonymous account table. Great. And the one before

account table. Great. And the one before it is the index change. Right. That's

correct.

Great.

And now the migration registry has both of them in the correct order with the right time stamps and all the definition files are valid. Awesome. So now I will

switch over to the test folder which I'll open in a different terminal. So

this will go into test uh off nice server

nice and here I will say server pod create migration.

Awesome.

Is there anything else I need to do? Oh,

yeah. The the off example. I'll make a new terminal for that as well because they're cheap. So, now I'm going to say

they're cheap. So, now I'm going to say example off server.

Yep.

And create migration again.

And that should make some migrations.

Lovely. So, what's this new migration?

This. Yes. Has both.

No, it only has the other one.

Why does this not have the anonymous table?

Why do you not have the anonymous table?

Okay.

H.

What's in here again?

Oh, because this was here and it's out of order.

The funny thing is it actually I don't think this order.

Oh, no. This is like a way earlier thing where I had way more. Is it? Who added

this? Did I add this or did someone else add this? Where's my like get lens?

add this? Where's my like get lens?

What is the date on this? 12:21.

This feels like a day that I was working on this. Did I generate this?

on this. Did I generate this?

Uh, why is git lens not doing anything?

Because it's not installed.

Really increases the difficulty for a extension to do its job.

Who would have thought?

me two weeks ago. Great. That's why it's wrong. You can always tell why

wrong. You can always tell why something's wrong if I made it.

Those things correlate. All right.

Great. So, what I'm going to do now is delete both the old migration I made that is wrong, wrong, wrong, and this new migration that is uh

that I just generated and it's wrong.

And I'm going to delete both of these rows. And now I'm going to create

rows. And now I'm going to create migration again.

And this seems to have bundled them in the same thing.

Oh, there's a lot here.

There's more than I was expecting here.

Not going to lie.

Maybe I didn't do something wrong. Maybe

someone else did something wrong.

Wouldn't that be a change of pace? So,

server pod anonymous ID account. If this

is Oh, wait. No, that I added. So, here

we go. Apple account.

If this is not does not appear here, then we're correct. Oh, and it doesn't.

Interesting. I don't know how this off module worked.

I'm fairly confused, but that's okay.

All right.

So, now I'm going to actually launch the O module and we're going to watch it run.

Looking back in at some chat, people continuing to talk about exceptions.

Is it all handled by Riverpod or server pot or some other other tool? Can you

talk about migrations and how you handle them? Ah yeah yeah yeah okay so um and

them? Ah yeah yeah yeah okay so um and then is are migrations handled by server pod or some other tool? Yeah so that it's all it's all server pod you can see

some answers here in the chat actually all server pod CLI does it. Yep. Yep.

Yep. Yep. So great. Um, and then when you, you know, you have to apply the migrations when you run your app at some point, which of course like if you're deploying to Cloud Run, you don't want

to have d-apply migrations on every wake up because they can kind of get in each other's way. Uh, so there's actually a

other's way. Uh, so there's actually a little bit of thinking about like when you apply the migrations versus you deploy the code versus you have like all your new servers wake up. Always a

little tricky.

So what's the next thing I need to do? I

need to launch the off example app and see it work. That's what I need to do.

So in docker compose I can see here the connection to the development

uh database and this is what I need. So

first I'm going to actually launch this database by saying podman compose.

Podman is just like an open source version of docker up and disconnect or detach or whatever.

So while it thinks I can switch back to Postico and add a new server, which I said I was

going to do earlier, never did. So this

will be server pod off example and the host is localhost and the port we can see right there is 8090 being mapped internally to the typical

Postgress port. And then these are the

Postgress port. And then these are the other values I need. So I'll grab this hot password and the host is definitely localized.

The database is off and the user is Postgress. So I will test that

Postgress. So I will test that connection and it works. Wonderful.

Connect empty database as expected.

So now that all of the Docker containers are running, I can finally say, and what I just warned against as a bad idea in

production is just fine in development.

So I will say dart bin main.dart dash

apply migrations.

And this should wake up and make all of our tables.

which it didn't do. So, password is missing for database. Okay, let me grab this password and that would be in config.

Oh, why don't I have passwords?

Yeah, there it is. Interesting.

Oh, I've made that change locally.

So I will copy uh this is config template to passwords.myl.

Okay. And now we try again.

Still broken. Missing a password for database. So we are

database. So we are Oh, I'm so silly. Oh, that's so silly. I

look at my look at my copy command. Copy

config slash to no config. No config.

So, move passwords to config. And then

it'll keep the file name.

This time, this time it's going to work.

I can feel it.

Okay. It broke for a different reason which is kind of like oh Google client J. Yeah, I don't actually want to do

J. Yeah, I don't actually want to do this. I'm only going to going to not do

this. I'm only going to going to not do that. So that's fine

that. So that's fine because the off example is set up to have configured

Apple and Google login. But I don't really want to go through those trouble that trouble right now because I'm not doing that.

So, is this file?

Whoa.

I'm unfamiliar with what is different about this file.

Okay. Wait, what's in main dart?

And this one. Yeah, it's not using the passwords file. Okay, I won't either

passwords file. Okay, I won't either then.

All right. All right. So, what I need to do here is basically just comment out Google and Apple because I'm not going to configure them and then they are going to rightly complain.

So, there we go. And email, that's fine.

Password. Oh, pass key IDP config.

That's probably fine.

Anonymous config. There we go. That's

what's up. That's new. Now, we have to get rid of this. This is Apple.

All right, that sounds better.

All right, we try again.

Try again.

Look at that. Applied the migrations.

Can't be stopped, folks. Can't stop him.

Can only hope to contain him.

So uh yeah, let's look at this in postco tables and they should include you know there's no app specific tables here because the only thing in this app is

the framework and the off module. So

they're all server pod tables but we have anonymous account.

Boom.

Okay. Now, now for my fourth trick, I will open a new terminal and in this I

can go into examples of flutter and say flutter rund chrome and this

is going to uh I'll think of the words. Yeah, launch

the app and we'll be able to create anonymous accounts and refresh the page and continue to be logged in as those anonymous accounts

and we will see the expected records in the database.

Isn't it fun?

Scanning. Oh, there it is. I was about to say scanning for where the window pops up and it was right in my face.

So, here we go. We've got a new continue without account button at the bottom. So

this whole widget here is the uh what am I thinking? This whole widget is the like signin widget that server pod

provides and you can incrementally turn off things if you like don't use them.

actually a little surprised that Apple and Google didn't get hidden when I removed those things from the server, but it's possible that they

I needed to like run server pod generate again or something. I'm not really sure, but that's not today's headache. So,

when I click this button, nothing happens. Awesome.

nothing happens. Awesome.

What's going on?

Literally nothing happened. Hello.

Wow. It's just totally silent.

So, here's the server running with no output, right? Yeah. No. Okay. Good. And

right? Yeah. No. Okay. Good. And

nothing. Uh.

Huh.

Wasn't expecting that. Um, lib

main.

All right, let's check this out.

Be pretty embarrassing to submit an off PR. try to merge an offbr where the

PR. try to merge an offbr where the button in the main off-the-shelf widget doesn't work.

Okay, so nothing crazy going on here. So

this signin widget is over in the off IDP thing in the Flutter portion. So if

I look here, we've got, you know, yeah, disable is is not set for anonymous, which makes sense because we saw the button. So has anonymous.

button. So has anonymous.

So, if has anonymous, this is our thing.

So, we get into the anonymous sign-in widget and the anonymous sign-in widget should have a button.

Yeah, here it is. So, on pressed controller login. So, let's check out

controller login. So, let's check out the anonymous off controller.

And in the login method, we see I wonder if there's a problem with like this guarded wrapper.

Interesting. Uh

oh, I was Oh, yeah. Okay, this is probably the problem. This is why we test things.

This was a very recent code review that I don't think I actually executed. So

to one day guard against abuse on this, we're planning on adding like app attestation, which you could typically get from Firebase app check,

but you wouldn't want to have Firebase as a dependency just for app check. So

we want to be able to have app attestation in server pod directly. So

that's this anonymous token call thing.

But this bang is giving me some hebiejibbies because I'm not configuring that yet. So now I'm wondering is there like a default noop

function.

So create anonymous is nullable and yeah okay I don't know what on earth anyone was thinking when they had this. So token now could be yeah

had this. So token now could be yeah it's a nullable string. Wonderful. This

is probably better.

So, let's restart the the front end app.

Let's try this again. Continue. Look at

that. Look at that. So, now we go to the database.

Excuse me. Probably should have turned my head in the anonymous table. We have

a record and it points to a user. And critically,

if I refresh the page, we stay logged in.

Nice.

And this button is poorly set up. It someone

who added this to the example would like assumed you were signing in with Google or something. It's like this doesn't

or something. It's like this doesn't make sense for us. And if you uh yeah, sign out, that account is basically gone. So, it does still exist in the

gone. So, it does still exist in the database. It doesn't get deleted, but

database. It doesn't get deleted, but there's no way to recover it. That's the

nature of an anonymous account. So I'll

sign in again. We have a new anonymous account which is extremely exciting. And

if I look at yeah core user, we see that two users have been made. They each had a very exciting empty profile.

I always like to drag the created at time stamp in my database viewer all the way to the right. They each had a token

which is one of these things. Uh,

where's the token table? I don't know.

Oh, session. That's it. Oh, there's only one session. Maybe when I logged out

one session. Maybe when I logged out that session did get deleted. Let's try

that again. Sign out. Yes, that makes sense. Boy, does that actually make

sense. Boy, does that actually make sense.

Okay, so um can we show what guarded does?

Somebody asks. Yeah. So this is honestly a really really really well engineered um

thing this whole off module and there's like no repeated code anywhere. So guarded

is a little closure wrapper down here that uh catches errors and converts them to userfacing errors.

So you might throw you know your server might not understand what server oh like what is a userf facing error uh or it needs to be localized or you know

there's just something exception problems that are not the server's problem and so uh this kind of manages state updates and catches errors and converts them to userfacing errors.

That's what guarded does. Just a custom little thing, but it's all over this app module and and this big widget and it it's a it's a definitely a good pattern.

Um, so yeah, there we are. Now, this is funny. When I look at the stream, I have

funny. When I look at the stream, I have YouTube open so I can just look at chat easily. Um, I'm seeing a video feed

easily. Um, I'm seeing a video feed that's very, very old. So, I don't actually know how the world works. That

is for sure.

Uh F12 for logs. No me says I don't I've never pressed F12 for logs.

Where where would I press that? In what

window?

Uh someone asked is this cure editor?

No, it's anti-gravity which is absolutely my new favorite.

Although somebody's saying anti-gravity slows down my Apple silicon Mac while doing native iOS dev uh Google team please fix interesting. Um so in anti-gravity there

interesting. Um so in anti-gravity there is a way to submit feedback which is where uh settings no maybe

anti-gravity user settings there's a place to submit feedback. Oh here it is bottom left here. So,

open anti-gravity person who's having this problem.

Click this gear. Go into open anti-gravity settings. A new window pops

anti-gravity settings. A new window pops up. Bottom left of that window. Provide

up. Bottom left of that window. Provide

feedback. Here is where you write this slows down my silicon Mac when I do native development. And then uh provide

native development. And then uh provide any other information you can. And

that'll be great. And then attach your logs. I guess this is not a real bug

logs. I guess this is not a real bug because I'm not doing native development. This is not slowing down my

development. This is not slowing down my computer. So, I'm not going to click

computer. So, I'm not going to click submit, but you should.

All right. So, I now think that this is ready to submit. I don't think anything that I

to submit. I don't think anything that I just changed should impact any of the tests that exist for this library or this PR. So, I am going to commit all of

this PR. So, I am going to commit all of this goblygook and push. No, I am not going to commit commenting out

um Apple in Google from server.dart

and I think here I can just revert.

Yeah, I'm going to check out this file.

So revert.

Okay. Yeah, we don't want to commit that uh scanning. This is mostly migration

uh scanning. This is mostly migration nonsense and my one little change here.

So I'm going to commit And now I'm going to say uh rebases migrations commit and push.

Exciting, huh? Exciting stuff.

Do you like well structured software like server pod, spring boot or uh write the whole workflow by yourself? Oh boy,

well ststructured code for sure. There's

Django before similar. Um

it's you got to use you got to use a good framework for sure. You don't want to write it all yourself. You'll be here all day reinventing the wheel. Totally.

Especially with open source things where if you do discover a limitation, you could, you know, fork it or submit a PR or whatever.

Like I've been doing a fair amount of work to add anonymous off to serverbot, but it ain't nothing compared to reinventing Serverbot.

So I'm still way way ahead even though it had a limitation for my purposes.

Okay. So now let's go back to this PR. So this I think these are good.

this PR. So this I think these are good.

Add a new test. Yeah, that's true.

Existing tests. Well, they were before.

We'll see. Uh updated docs. I've not

updated the docs.

All right. So this should have no git.

What? There's another one. Oh, I

needed to run server pod generate.

Yeah. Yeah, I needed to run server pod generate. So, I'll do that and then

generate. So, I'll do that and then push.

Is that right?

Is that the problem? That's probably the problem.

Where is this directory? This is in a test. Didn't have the issue there.

test. Didn't have the issue there.

Surprisingly, why didn't it have the issue there?

Justin off and the example. Interesting.

Okay. So, in the server, I'm going to this is in the example of the server.

I'll say server pod generate.

And then I'm going to do the same in the project itself.

CD modules off IDP server

server pod generate. Oh, the last one didn't even make any changes.

This one did.

Okay. Okay.

Interesting.

Ran server pod generate get push.

Let's see here now. What do we get? It

should presumably still have the mer.

Why?

Wait, why would that be the case? I

wonder if somebody else forgot to run generate. Now, I think they have CI to

generate. Now, I think they have CI to make sure that generate doesn't change anything. All right, I'm going to leave

anything. All right, I'm going to leave this alone for now.

I'll talk with Server Pod team later about figuring out what's going on here.

I don't think that's going to make the best television.

So, instead, let's look at the next PR and the next feature, the next part of phase two. So, we got like phase 2.1

phase two. So, we got like phase 2.1 already in flight and then uh it'll be

time to think about phase 2.2, which is not really spelled out.

What did I even write? I should make sure this is updated. Okay, so new methods will be added to durable IDPS.

That's like not anonymous. A durable IDP is one that you can just log out of and back into, which will attach new providers to the existing O user record.

This user may or may not be anonymous.

Yeah. So this is the part two. That's

what's upcoming next. So before writing new blah blah blah records, the linking flow must first check. Right. So this is all stuff to come next. So I'm going to

call this phase 2.2.

And I'll indent it. Maybe that seems like a thing someone might do. And then

we'll have phase 2.1.

And this is going to add new methods to durable IDPS to look up whether or not a given uh no just the active user whether

or not the active user currently has accounts uh add new methods

to look up whether or not the active user currently has accounts with durable IDPS.

This is required for the front end to conditionally

render like add apple off buttons etc. because of course you don't want to show that button if the user already has Apple and an anonymous user is going to

need to add like one of these things eventually. But even somebody who like

eventually. But even somebody who like maybe came in from email and password off they might one day want to add a pass key or they might want to add Apple or Google uh off. So like I think everybody is going to need this

regardless of whether or not somebody cares about anonymous off. So that is phase 2.1 and I'll add a link to the PR

for that which is somewhere.

Uh it's this one add connected IDPs lookup.

So let's see here. This is um PR.

I guess I'll add this PR for phase one.

I'm not normally this organized.

You should uh not mistake me for this.

You should instead know that I'm a conjurer of cheap tricks.

Oh, wait. Oh, can Oh, yeah. Yeah. Yeah.

Okay. Yeah. This feature is a component of phase 2, right? Okay. Sorry, I

thought I had the wrong tab for a second. Which relates linking IDPs to

second. Which relates linking IDPs to existing accounts.

And there's some maybe bold changes that I'm proposing in this PR, including

adding uh actually let's start to look at how some of the server pod code works and then this will make a little more sense. So

I'm not checking out this PR yet. We're

still on the kind of old PR for just adding anonymous off. and let's look at how this works.

So in IDP server pod um we have

let's close some of these other files in IDP server pod or sorry um underscore server there are in the lib directory this providers folder

which just has these are like barrel files actually so I'll get rid of that and then under source there's There's a providers directory with similar looking

folders and I've added anonymous. So

let's check this out. So to start in server pod you write an endpoint but endpoints are not you know

endpoints are like attached to network stuff and for testing you basically want to pretend the network layer doesn't exist. So kind of the idiomatic thing to

exist. So kind of the idiomatic thing to do in server pod is to immediately delegate to a different function.

And it's kind of funny because you pass this session in. So you know you're only like so separated from HTTP things but

um anyway that's the pattern. So there's

an anonymous IDP class that the endpoint makes use of and the anonymous endpoint merely extends

like generic endpoint. So now let's look at the anonymous IDP class and the anonymous IDP class does not subclass anything which is part of what

I'm proposing to change which is of course a thing that needs to be considered carefully before it's just adopted.

And because there was only one method.

You know, other ones have like a lot of methods and so their classes are more advanced. Anonymous is very simple. You

advanced. Anonymous is very simple. You

just create something. So here we have the login method and it uh you know calls any like

um con functions you configure. So this

one would check for app att testation if you have it and then it ultimately creates an account and you know you're kind of using these other classes that uh again get you kind of further and

further away from the network layer so you can just have isolated unit tests later on or even like isolated integration tests because with server side stuff you want to talk to a database and it's not that useful to

prove to yourself that your code worked absent a database anyway uh create a user profile blah blah blah issue a token. Everything's

exciting. So, this is like how this works. Just for some

works. Just for some or just to kind of close this loop a little bit more, look at email, which is probably the most complicated one

because you got to like get a um verification token sent to your email.

Then you grab that and you put enter the thing in and there's all kinds of security around that. Anyway, so the endpoint for email has more functions.

It ultimately has login, same as the other one. Start registration,

other one. Start registration, verify that code, finish registration, a password reset. Obviously, that's, you know, annoying. Verify the password

know, annoying. Verify the password reset code. It's like this one's way

reset code. It's like this one's way more complicated and it's IDP class has similarly more functions. So, anyway,

that's that. So what I'm proposing in the other PR is that each IDP needs to be able to

answer the question, does a user have an account with this provider? And

what I think makes sense to do is to have an abstract IDP class. Again, this

might be a bad idea. I'm talking about this server pod folks might be like, "Dude, never." and that'll be fine. But

"Dude, never." and that'll be fine. But

my initial naive proposal here is that we have an abstract IDP class that forces all IDPS to a to implement this function has account

and yeah get method was like used for someone else somewhere which is that that part's super simple but anyway because like this would

return the string apple or Google or email or something so dead simple. Um, I

think it was just a limitation of like static methods on abstract classes or static properties on Yeah. Yeah, that's

what it said. Great. Anyway, so if all IDPs are required to have this function which has the exact same signature, then a configured like there could be one

endpoint that loops over all of your configured IDPS and it just calls this method for a given user and is able to return to the front end in one network call. It's like, you know, because you

call. It's like, you know, because you as a server pod developer might add your own IDP. You know, maybe you do want a

own IDP. You know, maybe you do want a password link or SMS or something and that's really important to you and so you add it and you'd probably kind of like this functionality that we're talking

about to be like wired into the O packages single network request to answer the question does which IDPs does the user already have something configured with.

So the only way that you external server pod developer or like me in the future could get your custom IDPS

included in that is if they participate in this contract. So anyway, it's a proposal and then uh you get an endpoint here that basically just figures out what the

accounts are. It's kind of different

accounts are. It's kind of different from anything else. And here we can see that it's going to loop over all of the identity providers. And if any of the

identity providers. And if any of the providers aren't subclassing the IDP, then we'll just kind of note, hey, they're not going to be able to answer this question. But for the other ones,

this question. But for the other ones, we're going to call their has account method and then we can return the answer to that, which I'm apparently having as

a set of strings. So you'd return like Apple, Google, blah blah blah. I don't

think you really want to return more data about those accounts. don't want to like accidentally leak something.

So there's that. And then uh Apple IDP is made to extend it and it implements this method uh has account and it

ultimately just delegates to another thing like we were seeing.

Um so what does have a has account or get account sorry looks like? Oh yeah.

Yeah. So has account is the external facing thing but internally like get account I think makes more sense because internally you'd want to actually see data about it. So get account

merely looks up in the Apple account table like is there something for the authenticated user easy and if you're not authenticated then you don't have an

account.

Uh same for email and same for Google and I I think I added it for pass key as well if I scroll down. Yeah, pass key. I

don't even really know how pass keys work, but that doesn't it's not important because it's consistently abstracted. So, this is the PR that is

abstracted. So, this is the PR that is waiting in the wings.

And now I'm going to look at chat because I haven't done that in forever.

Um, yeah, Randall says, let me get Randall says, "It's hard to know when to delete an anonymous user account." Yeah,

indeed. Um, I mean, I think you probably wouldn't delete the account when someone logs out because like maybe they could call your customer support and rattle off every action they ever took and prove that they were that

account and then you might have some backend process to like restore it for them. But

them. But short of that workflow, you could delete like everything, but then you you would be deleting any work that they did on that account. It would be totally

that account. It would be totally unreoverable. So, be could feel a little

unreoverable. So, be could feel a little harsh.

I'm gonna bring this here. Can everybody

uh look at it while I'm Oh, wow. This

got stuck.

All right. Well, then I'll just uh look at it from YouTube itself and talk about chats, but they won't be able to go up on the screen.

All right. Scrolling up.

Did I take part in the serverbot hackathon? I thought about it, but I was

hackathon? I thought about it, but I was working on this and I have a game that I've been working on, which is like not really hackathon stuff because it's a for real project. So, I didn't want to take on a new thing, but I absolutely

thought about it. I kind of thought about streaming some of it during the holiday break, but instead I played video games. I've gotten into Boulders

video games. I've gotten into Boulders Skate 3.

Whoa, why didn't anyone tell me about this? What a fun game.

this? What a fun game.

Uh, let's see. What else are folks talking about?

Oh yeah. So, deleting users, you mostly Randall says, "You mostly just have to write a job repeating somewhere to delete everything every 10 days or so."

Yeah, especially like if it hasn't logged in in a while or something. Um,

Estidiani says, "Do you have some use cases?" I

don't know what I was talking about when you wrote that. What were the use cases you were asking about?

Or maybe you were talking with Randall.

Uh, Rand says, "Or however long a session makes sense because when a session is gone, it'll never use again."

Yep, makes sense.

Says, "Didn't upgrade to Mac OS Tahoe."

Oh, wait. I thought I had to upgrade. I

think I did. I don't know. I'm not sure if you're talking about me or somebody else, but I was forced to upgrade. I do

regret updating my phone, though. That

I'm I'm on Sequoia. Am I really on Sequoia?

Oh, maybe I was a whole year behind when I had to update.

uh about this Mac.

Sequoa, you guys are right.

I didn't even realize I was behind. It's

not good. You guys, the Do you folks recommend it? I don't like the new iOS

recommend it? I don't like the new iOS version.

I try not to make disliking stuff part of my personality. I I don't run around hating on things very often. Um the

trees, right? Actually, I think I got I was a year behind because I had to update recently. I was on whatever was

update recently. I was on whatever was before Sequoia because I used to have the Flutter background and then the update I got this background and I just didn't think about changing it. Anyway,

I do not like the new iOS version and I had to update that to connect to work things.

I'm so sad about it. I haven't disliked anything that much in a long time.

It is not my thing. Um

anyway, all right. What uh

all right. What uh what what makes sense to do next?

I could begin adding the linking code. So if we go back to the plan, you

code. So if we go back to the plan, you got to stick to the plan of course. New

methods will be added to durable IDPs which attach new O providers to an existing O user record. This may or not may or may not be anonymous. Yeah, this

user may or may not be anonymous.

So before writing and then there's merge conflict and like that's a whole ball of uh wax as well. So let me read what I wrote here. See if it still makes sense.

wrote here. See if it still makes sense.

Before writing these new records, the linking flow must first check for those unique user identifiers in the appropriate database tables. If they

exist, the standard linking flow is aborted and a merge flow is triggered again. And this is why anonymous

again. And this is why anonymous accounts are so painful is this sentence right here. It's actually two sentences.

right here. It's actually two sentences.

If I put on my counting hat, which I was instructed not to do, they say don't don't do the do math on stream. This

merging flow will call a new and optional merge accounts method which a developer would configure and that's how you as a serverod developer would like if the anonymous account took some

actions and you want to persist those and merge them into their other account um you know you handle that here. So the

the user journey that this merge checking is accounting for is let's say like on one device you have an account a proper

email Apple google whatever pass key account with some app using server pod and then on a different device you re you know either redownload the app or

you go to the website or whatever and you take some action before you realize you're not logged in you like take some action that creates It's an anonymous account probably transparently in the background. It's generally how that

background. It's generally how that works. And then you're like, "Oh, wait.

works. And then you're like, "Oh, wait.

Where's all my other stuff? Oh, I'm not logged in." But you like did something

logged in." But you like did something that's important. You know, maybe what

that's important. You know, maybe what you did is throw away, but like maybe it's not. Maybe it was, you know, maybe

it's not. Maybe it was, you know, maybe you like wrote a long document or something and you want it persisted.

So then you're like, "Oh gosh, I got to log in to my account." So you try to log

in to your email account and what basically happens there is during the login flow it realizes like wait a logged in user

is trying to loged in is trying to log in and uh actually you'd probably just see like add I'm not really sure what makes the most sense here because right

you're logged in and the user's mental model is that they're not logged and like they just created an anonymous account on accident and so they're seeing that their other user data isn't present is why anonymous accounts are

such a pain to build but they're very actually user friendly in my opinion.

So, I'm a user. I don't know that I've just created a session. I want to restore my email session.

If I see, you know, I got two buttons that the app could show me. Could say

login with email and password, which would probably make more sense to me, the user, or it could say add email

and passwords to your account, like link email and passwords. And

if I saw that, I would probably think like, well, something's wrong. I don't I wouldn't I don't want to link email and password to my account. I want to go

back to my main account. So, I think probably this is like a thing that an app using anonymous accounts would need to handle. And I don't think it's the

to handle. And I don't think it's the off module's job to figure out kind of which of these buttons to show. But

anyway, obviously comp complexity abounds and then in either rate at some point you're going to

like try to log in again or whatever and you're going to be if you're logging in to email but you're already authenticated and you're anonymous then

like the merge flow kicks in. Or

probably more likely is like Apple and Google because they don't really have a create versus login distinction. and you

just like click the sign in with Google not Apple button and it's just this kind of opaque flow and at the end you're logged in and so that

if I'm a user that's created an an anonymous account I click the button I'm probably less thrown off because the text doesn't seem wrong it just says sign in with Google or Apple or whatever and I'm like yeah that's what I want to

do so I click the button and then the server really has to say like whoa you're logged And so we have one user account, but the Google or Apple

credential that we just received is definitely attached to a different account. So now it's merge time.

account. So now it's merge time.

So it's fun.

Uh Randall says linking doesn't solve the data merge problem. H what uh what are you thinking in that direction,

Randall? What makes that true?

Randall? What makes that true?

So, a lot of things will just not let you say, "I wonder how Reddit has this anonymous off system." A lot of things don't let you take actions until you log

in. So, like if you're anonymous in

in. So, like if you're anonymous in Reddit, can you like a post? Can you

like download a post? Probably not. You

know, normally you are required to um log in before you can take those actions.

I have not visited Reddit unauthenticated in a very long time. So

I don't know what it does.

Uh Sy says, "Is there an option in Surfpopod to convert an anonymous account to a normal one with any of the providers?" So that is exactly what I am

providers?" So that is exactly what I am looking to add because they didn't have anonymous provider so they don't have the conversion thing.

Um let's see.

Uh Randall says, "I realize you'd need data merge anyway, so it would have to be solved already."

I think we're probably both thinking about this clearly, but I'm I'm not quite following the statements you're making.

Do you have any source recommendation for animation in Flutter other than the official videos docs? Uh well, there's probably really darn good third party

explanations of animations. There's also

the Flutter animate package. That's

really good. And there used to be some package that was used to daisy chain animations, but I can't remember what it was called. And last time I looked for

was called. And last time I looked for it, I couldn't find it.

Actually, someone here right now probably knows. Oh, hey. Um, we got

probably knows. Oh, hey. Um, we got actual server pod team members in the chat. So, we're going to have Firebase

chat. So, we're going to have Firebase soon. Nice. There's probably a PR for

soon. Nice. There's probably a PR for that that we could look at and track the progress of.

I would click your message, but my message clicker froze.

Um, let me go back to this.

Let's see if there's a PR for adding Firebase.

All right. may be going by a different name or may not be on the first page of oh I'm on issues.

Never underestimate my ability to do something stupid.

I had Firebase IDP. Look at that. There

it is. This probably a huge project.

Anyway, yeah, this will be uh Oh, I wonder we should maybe make sure our wires are not crossing on

anonymous accounts because Firebase has anonymous accounts as well. And

depending on how this is being implemented, it's probably not going to conflict. I would guess an anonymous

conflict. I would guess an anonymous Firebase account or like an Apple or Google Firebase account. If they look the same to Server Pod, then we'd be

fine.

So, yeah, we should talk about that.

All right. Um,

I don't know if I really think it makes sense to work on this new like the next phase. Right now, it's a

phase. Right now, it's a I like sit down and think very slowly about this.

So, I'm not even sure what I would type.

Randomly said, "So, if I do something as anonymous while I'm still logged in, I'd want to link. There'd be a data merge."

Yeah, I still I think we're probably saying the same thing.

Uh, Predic says, "Hi, I'm Predic. I'm a

Flutter developer. Can you answer a few of my questions?"

Um, well, if you ask them, maybe. And

yeah, as Rand says, there's a Discord and also just yesterday, you missed it, hump day Q&A, but in six more days there'll be another episode probably. So

that's a great place to ask questions.

But if you don't want to wait six days, you can either ask them here or go to the Discord.

Uh it shouldn't conflict since we're using ID tokens to log in. So it's just another provider. Yeah. So that makes

another provider. Yeah. So that makes sense. Doesn't really care about how you

sense. Doesn't really care about how you logged in with Firebase. Yeah, makes

sense. Good. Awesome.

So it's like once you come from Firebase, great. However Firebase

Firebase, great. However Firebase figured out who you are, you know, that was Firebase's problem.

That that that seems good. All right. Uh

well, folks, I think I am going to call it here because way more like slow thinking is required to figure out what I would even type next than I think

would make again like I said earlier, it would make good television. So, I going to call it for now. I do expect to be back next week. I have a couple guests

starting to get lined up into later January, early February, so we'll have some fun topics. Um, let me know what you thought about this episode kind of contributing to an open source

library. I didn't really write a lot of

library. I didn't really write a lot of code. We mostly just talked and I fixed

code. We mostly just talked and I fixed a couple things and like ran some CLI commands. So, it was a different kind of

commands. So, it was a different kind of episode than other ones. But yeah, let me know what you all thought and that'll impact the extent to which I do the same

in the future.

So, uh, thanks everybody and until next time, happy fluttering.

Loading...

Loading video analysis...